forked from vitalif/vitastor
Implement vitastor-disk purge command
parent
0d8625f92d
commit
b9b50ab4cc
|
@ -14,6 +14,7 @@ It supports the following commands:
|
||||||
- [upgrade-simple](#upgrade-simple)
|
- [upgrade-simple](#upgrade-simple)
|
||||||
- [resize](#resize)
|
- [resize](#resize)
|
||||||
- [start/stop/restart/enable/disable](#start/stop/restart/enable/disable)
|
- [start/stop/restart/enable/disable](#start/stop/restart/enable/disable)
|
||||||
|
- [purge](#purge)
|
||||||
- [read-sb](#read-sb)
|
- [read-sb](#read-sb)
|
||||||
- [write-sb](#write-sb)
|
- [write-sb](#write-sb)
|
||||||
- [udev](#udev)
|
- [udev](#udev)
|
||||||
|
@ -155,11 +156,22 @@ Commands are passed to `systemctl` with `vitastor-osd@<num>` units as arguments.
|
||||||
|
|
||||||
When `--now` is added to enable/disable, OSDs are also immediately started/stopped.
|
When `--now` is added to enable/disable, OSDs are also immediately started/stopped.
|
||||||
|
|
||||||
|
## purge
|
||||||
|
|
||||||
|
`vitastor-disk purge [--force] [--allow-data-loss] <device> [device2 device3 ...]`
|
||||||
|
|
||||||
|
Purge Vitastor OSD(s) on specified device(s). Uses `vitastor-cli rm-osd` to check
|
||||||
|
if deletion is possible without data loss and to actually remove metadata from etcd.
|
||||||
|
`--force` and `--allow-data-loss` options may be used to ignore safety check results.
|
||||||
|
|
||||||
|
Requires `vitastor-cli` and `wipefs` utilities.
|
||||||
|
|
||||||
## read-sb
|
## read-sb
|
||||||
|
|
||||||
`vitastor-disk read-sb <device>`
|
`vitastor-disk read-sb [--force] <device>`
|
||||||
|
|
||||||
Try to read Vitastor OSD superblock from `<device>` and print it in JSON format.
|
Try to read Vitastor OSD superblock from `<device>` and print it in JSON format.
|
||||||
|
`--force` allows to bypass "does not refer to the device itself" errors.
|
||||||
|
|
||||||
## write-sb
|
## write-sb
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ vitastor-disk - инструмент командной строки для уп
|
||||||
- [upgrade-simple](#upgrade-simple)
|
- [upgrade-simple](#upgrade-simple)
|
||||||
- [resize](#resize)
|
- [resize](#resize)
|
||||||
- [start/stop/restart/enable/disable](#start/stop/restart/enable/disable)
|
- [start/stop/restart/enable/disable](#start/stop/restart/enable/disable)
|
||||||
|
- [purge](#purge)
|
||||||
- [read-sb](#read-sb)
|
- [read-sb](#read-sb)
|
||||||
- [write-sb](#write-sb)
|
- [write-sb](#write-sb)
|
||||||
- [udev](#udev)
|
- [udev](#udev)
|
||||||
|
@ -158,12 +159,25 @@ throttle_target_mbs, throttle_target_parallelism, throttle_threshold_us.
|
||||||
Когда к командам включения/выключения добавляется параметр `--now`, OSD также сразу
|
Когда к командам включения/выключения добавляется параметр `--now`, OSD также сразу
|
||||||
запускаются/останавливаются.
|
запускаются/останавливаются.
|
||||||
|
|
||||||
|
## purge
|
||||||
|
|
||||||
|
`vitastor-disk purge [--force] [--allow-data-loss] <device> [device2 device3 ...]`
|
||||||
|
|
||||||
|
Удалить OSD на заданном диске/дисках. Использует `vitastor-cli rm-osd` для проверки
|
||||||
|
возможности удаления без потери данных и для удаления OSD из etcd. Опции `--force`
|
||||||
|
и `--allow-data-loss` служат для обхода данной защиты в случае необходимости.
|
||||||
|
|
||||||
|
Команде требуются утилиты `vitastor-cli` и `wipefs`.
|
||||||
|
|
||||||
## read-sb
|
## read-sb
|
||||||
|
|
||||||
`vitastor-disk read-sb <device>`
|
`vitastor-disk read-sb [--force] <device>`
|
||||||
|
|
||||||
Прочитать суперблок OSD с диска `<device>` и вывести его в формате JSON.
|
Прочитать суперблок OSD с диска `<device>` и вывести его в формате JSON.
|
||||||
|
|
||||||
|
Опция `--force` позволяет читать суперблок, даже если он считается некорректным
|
||||||
|
из-за того, что не ссылается на устройство, с которого прочитан.
|
||||||
|
|
||||||
## write-sb
|
## write-sb
|
||||||
|
|
||||||
`vitastor-disk write-sb <device>`
|
`vitastor-disk write-sb <device>`
|
||||||
|
|
|
@ -150,15 +150,9 @@ struct rm_osd_t
|
||||||
else if (!is_dataloss && !is_warning && dry_run)
|
else if (!is_dataloss && !is_warning && dry_run)
|
||||||
error += "OSDs can be deleted without data loss.\n";
|
error += "OSDs can be deleted without data loss.\n";
|
||||||
result.text = error;
|
result.text = error;
|
||||||
if (is_dataloss && !force_dataloss || is_warning && !force_warning)
|
if (dry_run || is_dataloss && !force_dataloss || is_warning && !force_warning)
|
||||||
{
|
{
|
||||||
result.err = EBUSY;
|
result.err = is_dataloss || is_warning ? EBUSY : 0;
|
||||||
state = 100;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (dry_run)
|
|
||||||
{
|
|
||||||
result.err = 0;
|
|
||||||
state = 100;
|
state = 100;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,6 +110,13 @@ static const char *help_text =
|
||||||
" Commands are passed to systemctl with vitastor-osd@<num> units as arguments.\n"
|
" Commands are passed to systemctl with vitastor-osd@<num> units as arguments.\n"
|
||||||
" When --now is added to enable/disable, OSDs are also immediately started/stopped.\n"
|
" When --now is added to enable/disable, OSDs are also immediately started/stopped.\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
"vitastor-disk purge [--force] [--allow-data-loss] <device> [device2 device3 ...]\n"
|
||||||
|
" Purge Vitastor OSD(s) on specified device(s). Uses vitastor-cli rm-osd to check\n"
|
||||||
|
" if deletion is possible without data loss and to actually remove metadata from etcd.\n"
|
||||||
|
" --force and --allow-data-loss options may be used to ignore safety check results.\n"
|
||||||
|
" \n"
|
||||||
|
" Requires `vitastor-cli` and `wipefs` utilities.\n"
|
||||||
|
"\n"
|
||||||
"vitastor-disk read-sb [--force] <device>\n"
|
"vitastor-disk read-sb [--force] <device>\n"
|
||||||
" Try to read Vitastor OSD superblock from <device> and print it in JSON format.\n"
|
" Try to read Vitastor OSD superblock from <device> and print it in JSON format.\n"
|
||||||
" --force allows to bypass \"does not refer to the device itself\" errors.\n"
|
" --force allows to bypass \"does not refer to the device itself\" errors.\n"
|
||||||
|
@ -213,6 +220,10 @@ int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
self.options["force"] = "1";
|
self.options["force"] = "1";
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(argv[i], "--allow-data-loss"))
|
||||||
|
{
|
||||||
|
self.options["allow_data_loss"] = "1";
|
||||||
|
}
|
||||||
else if (argv[i][0] == '-' && argv[i][1] == '-')
|
else if (argv[i][0] == '-' && argv[i][1] == '-')
|
||||||
{
|
{
|
||||||
char *key = argv[i]+2;
|
char *key = argv[i]+2;
|
||||||
|
@ -345,6 +356,10 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
return self.systemd_start_stop_osds(systemd_cmd, std::vector<std::string>(cmd.begin()+1, cmd.end()));
|
return self.systemd_start_stop_osds(systemd_cmd, std::vector<std::string>(cmd.begin()+1, cmd.end()));
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(cmd[0], "purge"))
|
||||||
|
{
|
||||||
|
return self.purge_devices(std::vector<std::string>(cmd.begin()+1, cmd.end()));
|
||||||
|
}
|
||||||
else if (!strcmp(cmd[0], "exec-osd"))
|
else if (!strcmp(cmd[0], "exec-osd"))
|
||||||
{
|
{
|
||||||
if (cmd.size() != 2)
|
if (cmd.size() != 2)
|
||||||
|
|
|
@ -108,8 +108,10 @@ struct disk_tool_t
|
||||||
int read_sb(std::string device);
|
int read_sb(std::string device);
|
||||||
int write_sb(std::string device);
|
int write_sb(std::string device);
|
||||||
int exec_osd(std::string device);
|
int exec_osd(std::string device);
|
||||||
int systemd_start_stop_osds(std::vector<std::string> cmd, std::vector<std::string> devices);
|
int systemd_start_stop_osds(const std::vector<std::string> & cmd, const std::vector<std::string> & devices);
|
||||||
|
int call_systemctl(const std::vector<std::string> & cmd, const std::vector<uint64_t> & osd_numbers);
|
||||||
int pre_exec_osd(std::string device);
|
int pre_exec_osd(std::string device);
|
||||||
|
int purge_devices(const std::vector<std::string> & devices);
|
||||||
|
|
||||||
json11::Json read_osd_superblock(std::string device, bool expect_exist = true, bool ignore_nonref = false);
|
json11::Json read_osd_superblock(std::string device, bool expect_exist = true, bool ignore_nonref = false);
|
||||||
uint32_t write_osd_superblock(std::string device, json11::Json params);
|
uint32_t write_osd_superblock(std::string device, json11::Json params);
|
||||||
|
|
|
@ -246,26 +246,36 @@ ex:
|
||||||
return osd_params;
|
return osd_params;
|
||||||
}
|
}
|
||||||
|
|
||||||
int disk_tool_t::systemd_start_stop_osds(std::vector<std::string> cmd, std::vector<std::string> devices)
|
int disk_tool_t::systemd_start_stop_osds(const std::vector<std::string> & cmd, const std::vector<std::string> & devices)
|
||||||
{
|
{
|
||||||
if (!devices.size())
|
if (!devices.size())
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Device path is missing\n");
|
fprintf(stderr, "Device path is missing\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
std::vector<std::string> svcs;
|
std::vector<uint64_t> osd_numbers;
|
||||||
for (auto & device: devices)
|
for (auto & device: devices)
|
||||||
{
|
{
|
||||||
json11::Json sb = read_osd_superblock(device);
|
json11::Json sb = read_osd_superblock(device);
|
||||||
if (!sb.is_null())
|
if (!sb.is_null())
|
||||||
{
|
{
|
||||||
svcs.push_back("vitastor-osd@"+sb["params"]["osd_num"].as_string());
|
osd_numbers.push_back(sb["params"]["osd_num"].uint64_value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!svcs.size())
|
return call_systemctl(cmd, osd_numbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
int disk_tool_t::call_systemctl(const std::vector<std::string> & cmd, const std::vector<uint64_t> & osd_numbers)
|
||||||
|
{
|
||||||
|
if (!osd_numbers.size())
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
std::vector<std::string> svcs;
|
||||||
|
for (auto osd_num: osd_numbers)
|
||||||
|
{
|
||||||
|
svcs.push_back("vitastor-osd@"+std::to_string(osd_num));
|
||||||
|
}
|
||||||
std::vector<char*> argv;
|
std::vector<char*> argv;
|
||||||
argv.push_back((char*)"systemctl");
|
argv.push_back((char*)"systemctl");
|
||||||
for (auto & s: cmd)
|
for (auto & s: cmd)
|
||||||
|
@ -362,3 +372,104 @@ int disk_tool_t::pre_exec_osd(std::string device)
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int disk_tool_t::purge_devices(const std::vector<std::string> & devices)
|
||||||
|
{
|
||||||
|
std::vector<uint64_t> osd_numbers;
|
||||||
|
json11::Json::array superblocks;
|
||||||
|
for (auto & device: devices)
|
||||||
|
{
|
||||||
|
json11::Json sb = read_osd_superblock(device);
|
||||||
|
if (!sb.is_null())
|
||||||
|
{
|
||||||
|
uint64_t osd_num = sb["params"]["osd_num"].uint64_value();
|
||||||
|
osd_numbers.push_back(osd_num);
|
||||||
|
superblocks.push_back(sb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!osd_numbers.size())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
std::vector<std::string> rm_osd_cli = { "vitastor-cli", "rm-osd" };
|
||||||
|
for (auto osd_num: osd_numbers)
|
||||||
|
{
|
||||||
|
rm_osd_cli.push_back(std::to_string(osd_num));
|
||||||
|
}
|
||||||
|
// Check for data loss
|
||||||
|
rm_osd_cli.push_back("--dry-run");
|
||||||
|
std::string dry_run_ignore_stdout;
|
||||||
|
if (shell_exec(rm_osd_cli, "", &dry_run_ignore_stdout, NULL) != 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// Disable & stop OSDs
|
||||||
|
if (call_systemctl({ "disable", "--now" }, osd_numbers) != 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// Remove OSD metadata
|
||||||
|
rm_osd_cli.pop_back();
|
||||||
|
if (options["force"] != "")
|
||||||
|
{
|
||||||
|
rm_osd_cli.push_back("--force");
|
||||||
|
}
|
||||||
|
else if (options["allow_data_loss"] != "")
|
||||||
|
{
|
||||||
|
rm_osd_cli.push_back("--allow-data-loss");
|
||||||
|
}
|
||||||
|
if (shell_exec(rm_osd_cli, "", NULL, NULL) != 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// Destroy OSD superblocks
|
||||||
|
uint8_t *buf = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, 4096);
|
||||||
|
for (auto & sb: superblocks)
|
||||||
|
{
|
||||||
|
for (auto dev_type: std::vector<std::string>{ "data", "meta", "journal" })
|
||||||
|
{
|
||||||
|
auto dev = sb["real_"+dev_type+"_device"].string_value();
|
||||||
|
if (dev != "")
|
||||||
|
{
|
||||||
|
int fd = -1, r = open(dev.c_str(), O_DIRECT|O_RDWR);
|
||||||
|
if (r >= 0)
|
||||||
|
{
|
||||||
|
fd = r;
|
||||||
|
r = read_blocking(fd, buf, 4096);
|
||||||
|
if (r == 4096)
|
||||||
|
{
|
||||||
|
// Clear magic and CRC
|
||||||
|
memset(buf, 0, 12);
|
||||||
|
r = lseek64(fd, 0, 0);
|
||||||
|
if (r == 0)
|
||||||
|
{
|
||||||
|
r = write_blocking(fd, buf, 4096);
|
||||||
|
if (r == 4096)
|
||||||
|
r = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fd >= 0)
|
||||||
|
close(fd);
|
||||||
|
if (r != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to clear OSD %lu %s device %s superblock: %s\n",
|
||||||
|
sb["params"]["osd_num"].uint64_value(), dev_type.c_str(), dev.c_str(), strerror(errno));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "OSD %lu %s device %s superblock cleared\n",
|
||||||
|
sb["params"]["osd_num"].uint64_value(), dev_type.c_str(), dev.c_str());
|
||||||
|
}
|
||||||
|
if (sb["params"][dev_type+"_device"].string_value().substr(0, 22) == "/dev/disk/by-partuuid/")
|
||||||
|
{
|
||||||
|
// Delete the partition itself
|
||||||
|
shell_exec({ "wipefs", "-af", dev }, "", NULL, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
buf = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ fi
|
||||||
sleep 1
|
sleep 1
|
||||||
kill -9 $OSD4_PID
|
kill -9 $OSD4_PID
|
||||||
sleep 1
|
sleep 1
|
||||||
build/src/vitastor-cli --etcd_address $ETCD_URL rm-osd 4
|
build/src/vitastor-cli --etcd_address $ETCD_URL rm-osd --force 4
|
||||||
|
|
||||||
sleep 2
|
sleep 2
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue