forked from vitalif/vitastor
Fix vitastor-disk purge (now it works)
parent
b9b50ab4cc
commit
8e12285629
|
@ -164,14 +164,14 @@ Purge Vitastor OSD(s) on specified device(s). Uses `vitastor-cli rm-osd` to chec
|
|||
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.
|
||||
Requires `vitastor-cli`, `sfdisk` and `partprobe` (from parted) utilities.
|
||||
|
||||
## read-sb
|
||||
|
||||
`vitastor-disk read-sb [--force] <device>`
|
||||
|
||||
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.
|
||||
`--force` allows to ignore validation errors.
|
||||
|
||||
## write-sb
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ throttle_target_mbs, throttle_target_parallelism, throttle_threshold_us.
|
|||
возможности удаления без потери данных и для удаления OSD из etcd. Опции `--force`
|
||||
и `--allow-data-loss` служат для обхода данной защиты в случае необходимости.
|
||||
|
||||
Команде требуются утилиты `vitastor-cli` и `wipefs`.
|
||||
Команде требуются утилиты `vitastor-cli`, `sfdisk` и `partprobe` (из состава parted).
|
||||
|
||||
## read-sb
|
||||
|
||||
|
@ -176,7 +176,7 @@ throttle_target_mbs, throttle_target_parallelism, throttle_threshold_us.
|
|||
Прочитать суперблок OSD с диска `<device>` и вывести его в формате JSON.
|
||||
|
||||
Опция `--force` позволяет читать суперблок, даже если он считается некорректным
|
||||
из-за того, что не ссылается на устройство, с которого прочитан.
|
||||
из-за ошибок валидации.
|
||||
|
||||
## write-sb
|
||||
|
||||
|
|
|
@ -115,11 +115,11 @@ static const char *help_text =
|
|||
" 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"
|
||||
" Requires `vitastor-cli`, `sfdisk` and `partprobe` (from parted) utilities.\n"
|
||||
"\n"
|
||||
"vitastor-disk read-sb [--force] <device>\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 ignore validation errors.\n"
|
||||
"\n"
|
||||
"vitastor-disk write-sb <device>\n"
|
||||
" Read JSON from STDIN and write it into Vitastor OSD superblock on <device>.\n"
|
||||
|
|
|
@ -109,7 +109,6 @@ struct disk_tool_t
|
|||
int write_sb(std::string device);
|
||||
int exec_osd(std::string device);
|
||||
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 purge_devices(const std::vector<std::string> & devices);
|
||||
|
||||
|
@ -141,3 +140,4 @@ int write_zero(int fd, uint64_t offset, uint64_t size);
|
|||
json11::Json read_parttable(std::string dev);
|
||||
uint64_t dev_size_from_parttable(json11::Json pt);
|
||||
uint64_t free_from_parttable(json11::Json pt);
|
||||
int fix_partition_type(std::string dev_by_uuid);
|
||||
|
|
|
@ -61,6 +61,11 @@ int disk_tool_t::prepare_one(std::map<std::string, std::string> options, int is_
|
|||
fprintf(stderr, "%s already contains Vitastor OSD superblock, not creating OSD without --force\n", dev.c_str());
|
||||
return 1;
|
||||
}
|
||||
if (fix_partition_type(dev) != 0)
|
||||
{
|
||||
fprintf(stderr, "%s has incorrect type and we failed to change it to Vitastor type\n", dev.c_str());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto dev: std::vector<std::string>{"data", "meta", "journal"})
|
||||
|
@ -317,7 +322,8 @@ json11::Json disk_tool_t::add_partitions(vitastor_dev_info_t & devinfo, std::vec
|
|||
{
|
||||
script += "+ "+size+" "+std::string(VITASTOR_PART_TYPE)+"\n";
|
||||
}
|
||||
if (shell_exec({ "sfdisk", "--force", devinfo.path }, script, NULL, NULL) != 0)
|
||||
std::string out;
|
||||
if (shell_exec({ "sfdisk", "--no-reread", "--force", devinfo.path }, script, &out, NULL) != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to add %lu partition(s) with sfdisk\n", sizes.size());
|
||||
return {};
|
||||
|
@ -351,7 +357,8 @@ json11::Json disk_tool_t::add_partitions(vitastor_dev_info_t & devinfo, std::vec
|
|||
{
|
||||
iter++;
|
||||
// Run partprobe
|
||||
if (iter > 1 || (r = shell_exec({ "partprobe", devinfo.path }, "", NULL, NULL)) != 0)
|
||||
std::string out;
|
||||
if (iter > 1 || (r = shell_exec({ "partprobe", devinfo.path }, "", &out, NULL)) != 0)
|
||||
{
|
||||
fprintf(
|
||||
stderr, iter == 1 && r == 255
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "disk_tool.h"
|
||||
#include "rw_blocking.h"
|
||||
#include "str_util.h"
|
||||
|
||||
struct __attribute__((__packed__)) vitastor_disk_superblock_t
|
||||
{
|
||||
|
@ -123,7 +124,7 @@ uint32_t disk_tool_t::write_osd_superblock(std::string device, json11::Json para
|
|||
return sb_size;
|
||||
}
|
||||
|
||||
json11::Json disk_tool_t::read_osd_superblock(std::string device, bool expect_exist, bool ignore_nonref)
|
||||
json11::Json disk_tool_t::read_osd_superblock(std::string device, bool expect_exist, bool ignore_errors)
|
||||
{
|
||||
vitastor_disk_superblock_t *sb = NULL;
|
||||
uint8_t *buf = NULL;
|
||||
|
@ -144,7 +145,7 @@ json11::Json disk_tool_t::read_osd_superblock(std::string device, bool expect_ex
|
|||
goto ex;
|
||||
}
|
||||
sb = (vitastor_disk_superblock_t*)buf;
|
||||
if (sb->magic != VITASTOR_DISK_MAGIC)
|
||||
if (sb->magic != VITASTOR_DISK_MAGIC && !ignore_errors)
|
||||
{
|
||||
if (expect_exist)
|
||||
fprintf(stderr, "Invalid OSD superblock on %s: magic number mismatch\n", device.c_str());
|
||||
|
@ -172,7 +173,7 @@ json11::Json disk_tool_t::read_osd_superblock(std::string device, bool expect_ex
|
|||
}
|
||||
sb = (vitastor_disk_superblock_t*)buf;
|
||||
}
|
||||
if (sb->crc32c != crc32c(0, &sb->size, sb->size - ((uint8_t*)&sb->size - buf)))
|
||||
if (sb->crc32c != crc32c(0, &sb->size, sb->size - ((uint8_t*)&sb->size - buf)) && !ignore_errors)
|
||||
{
|
||||
if (expect_exist)
|
||||
fprintf(stderr, "Invalid OSD superblock on %s: crc32 mismatch\n", device.c_str());
|
||||
|
@ -186,14 +187,14 @@ json11::Json disk_tool_t::read_osd_superblock(std::string device, bool expect_ex
|
|||
goto ex;
|
||||
}
|
||||
// Validate superblock
|
||||
if (!osd_params["osd_num"].uint64_value())
|
||||
if (!osd_params["osd_num"].uint64_value() && !ignore_errors)
|
||||
{
|
||||
if (expect_exist)
|
||||
fprintf(stderr, "OSD superblock on %s lacks osd_num\n", device.c_str());
|
||||
osd_params = json11::Json();
|
||||
goto ex;
|
||||
}
|
||||
if (osd_params["data_device"].string_value() == "")
|
||||
if (osd_params["data_device"].string_value() == "" && !ignore_errors)
|
||||
{
|
||||
if (expect_exist)
|
||||
fprintf(stderr, "OSD superblock on %s lacks data_device\n", device.c_str());
|
||||
|
@ -226,7 +227,7 @@ json11::Json disk_tool_t::read_osd_superblock(std::string device, bool expect_ex
|
|||
{
|
||||
device_type = "journal";
|
||||
}
|
||||
else if (!ignore_nonref)
|
||||
else if (!ignore_errors)
|
||||
{
|
||||
if (expect_exist)
|
||||
fprintf(stderr, "Invalid OSD superblock on %s: does not refer to the device itself\n", device.c_str());
|
||||
|
@ -253,29 +254,19 @@ int disk_tool_t::systemd_start_stop_osds(const std::vector<std::string> & cmd, c
|
|||
fprintf(stderr, "Device path is missing\n");
|
||||
return 1;
|
||||
}
|
||||
std::vector<uint64_t> osd_numbers;
|
||||
std::vector<std::string> svcs;
|
||||
for (auto & device: devices)
|
||||
{
|
||||
json11::Json sb = read_osd_superblock(device);
|
||||
if (!sb.is_null())
|
||||
{
|
||||
osd_numbers.push_back(sb["params"]["osd_num"].uint64_value());
|
||||
svcs.push_back("vitastor-osd@"+sb["params"]["osd_num"].as_string());
|
||||
}
|
||||
}
|
||||
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())
|
||||
if (!svcs.size())
|
||||
{
|
||||
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;
|
||||
argv.push_back((char*)"systemctl");
|
||||
for (auto & s: cmd)
|
||||
|
@ -316,8 +307,7 @@ int disk_tool_t::exec_osd(std::string device)
|
|||
argv[i] = (char*)argstr[i].c_str();
|
||||
}
|
||||
argv[argstr.size()] = NULL;
|
||||
execvpe(osd_binary.c_str(), argv, environ);
|
||||
return 0;
|
||||
return execvpe(osd_binary.c_str(), argv, environ);
|
||||
}
|
||||
|
||||
static int check_disabled_cache(std::string dev)
|
||||
|
@ -404,7 +394,12 @@ int disk_tool_t::purge_devices(const std::vector<std::string> & devices)
|
|||
return 1;
|
||||
}
|
||||
// Disable & stop OSDs
|
||||
if (call_systemctl({ "disable", "--now" }, osd_numbers) != 0)
|
||||
std::vector<std::string> systemctl_cli = { "systemctl", "disable", "--now" };
|
||||
for (auto osd_num: osd_numbers)
|
||||
{
|
||||
systemctl_cli.push_back("vitastor-osd@"+std::to_string(osd_num));
|
||||
}
|
||||
if (shell_exec(systemctl_cli, "", NULL, NULL) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
@ -464,7 +459,38 @@ int disk_tool_t::purge_devices(const std::vector<std::string> & devices)
|
|||
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);
|
||||
auto uuid_to_del = strtolower(sb["params"][dev_type+"_device"].string_value().substr(22));
|
||||
auto parent_dev = get_parent_device(dev);
|
||||
if (parent_dev == "" || parent_dev == dev)
|
||||
{
|
||||
fprintf(stderr, "Failed to delete partition %s: failed to find parent device\n", dev.c_str());
|
||||
continue;
|
||||
}
|
||||
auto pt = read_parttable("/dev/"+parent_dev);
|
||||
if (!pt.is_object())
|
||||
continue;
|
||||
json11::Json::array newpt = pt["partitions"].array_items();
|
||||
for (int i = 0; i < newpt.size(); i++)
|
||||
{
|
||||
if (strtolower(newpt[i]["uuid"].string_value()) == uuid_to_del)
|
||||
{
|
||||
auto old_part = newpt[i];
|
||||
newpt.erase(newpt.begin()+i, newpt.begin()+i+1);
|
||||
vitastor_dev_info_t devinfo = {
|
||||
.path = "/dev/"+parent_dev,
|
||||
.pt = json11::Json::object{ { "partitions", newpt } },
|
||||
};
|
||||
add_partitions(devinfo, {});
|
||||
struct stat st;
|
||||
if (stat(old_part["node"].string_value().c_str(), &st) == 0 ||
|
||||
errno != ENOENT)
|
||||
{
|
||||
std::string out;
|
||||
shell_exec({ "partprobe", "/dev/"+parent_dev }, "", &out, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,42 +38,6 @@ static std::map<std::string, std::string> read_vitastor_unit(std::string unit)
|
|||
return r;
|
||||
}
|
||||
|
||||
static int fix_partition_type(std::string dev_by_uuid)
|
||||
{
|
||||
auto uuid = strtolower(dev_by_uuid.substr(dev_by_uuid.rfind('/')+1));
|
||||
std::string parent_dev = get_parent_device(realpath_str(dev_by_uuid, false));
|
||||
if (parent_dev == "")
|
||||
return 1;
|
||||
auto pt = read_parttable("/dev/"+parent_dev);
|
||||
if (pt.is_null())
|
||||
return 1;
|
||||
std::string script = "label: gpt\n\n";
|
||||
for (const auto & part: pt["partitions"].array_items())
|
||||
{
|
||||
bool this_part = (strtolower(part["uuid"].string_value()) == uuid);
|
||||
if (this_part && strtolower(part["type"].string_value()) == "e7009fac-a5a1-4d72-af72-53de13059903")
|
||||
{
|
||||
// Already correct type
|
||||
return 0;
|
||||
}
|
||||
script += part["node"].string_value()+": ";
|
||||
bool first = true;
|
||||
for (const auto & kv: part.object_items())
|
||||
{
|
||||
if (kv.first != "node")
|
||||
{
|
||||
script += (first ? "" : ", ")+kv.first+"="+
|
||||
(kv.first == "type" && this_part
|
||||
? "e7009fac-a5a1-4d72-af72-53de13059903"
|
||||
: (kv.second.is_string() ? kv.second.string_value() : kv.second.dump()));
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
script += "\n";
|
||||
}
|
||||
return shell_exec({ "sfdisk", "--no-reread", "--force", "/dev/"+parent_dev }, script, NULL, NULL);
|
||||
}
|
||||
|
||||
int disk_tool_t::upgrade_simple_unit(std::string unit)
|
||||
{
|
||||
if (stoull_full(unit) != 0)
|
||||
|
|
|
@ -239,7 +239,8 @@ int shell_exec(const std::vector<std::string> & cmd, const std::string & in, std
|
|||
{
|
||||
// Child
|
||||
dup2(child_stdin[0], 0);
|
||||
dup2(child_stdout[1], 1);
|
||||
if (out)
|
||||
dup2(child_stdout[1], 1);
|
||||
if (err)
|
||||
dup2(child_stderr[1], 2);
|
||||
close(child_stdin[0]);
|
||||
|
@ -250,9 +251,7 @@ int shell_exec(const std::vector<std::string> & cmd, const std::string & in, std
|
|||
close(child_stderr[1]);
|
||||
char *argv[cmd.size()+1];
|
||||
for (int i = 0; i < cmd.size(); i++)
|
||||
{
|
||||
argv[i] = (char*)cmd[i].c_str();
|
||||
}
|
||||
argv[cmd.size()] = NULL;
|
||||
execvp(argv[0], argv);
|
||||
std::string full_cmd;
|
||||
|
@ -354,3 +353,40 @@ uint64_t free_from_parttable(json11::Json pt)
|
|||
free *= pt["sectorsize"].uint64_value();
|
||||
return free;
|
||||
}
|
||||
|
||||
int fix_partition_type(std::string dev_by_uuid)
|
||||
{
|
||||
auto uuid = strtolower(dev_by_uuid.substr(dev_by_uuid.rfind('/')+1));
|
||||
std::string parent_dev = get_parent_device(realpath_str(dev_by_uuid, false));
|
||||
if (parent_dev == "")
|
||||
return 1;
|
||||
auto pt = read_parttable("/dev/"+parent_dev);
|
||||
if (pt.is_null() || pt.is_bool())
|
||||
return 1;
|
||||
std::string script = "label: gpt\n\n";
|
||||
for (const auto & part: pt["partitions"].array_items())
|
||||
{
|
||||
bool this_part = (strtolower(part["uuid"].string_value()) == uuid);
|
||||
if (this_part && strtolower(part["type"].string_value()) == "e7009fac-a5a1-4d72-af72-53de13059903")
|
||||
{
|
||||
// Already correct type
|
||||
return 0;
|
||||
}
|
||||
script += part["node"].string_value()+": ";
|
||||
bool first = true;
|
||||
for (const auto & kv: part.object_items())
|
||||
{
|
||||
if (kv.first != "node")
|
||||
{
|
||||
script += (first ? "" : ", ")+kv.first+"="+
|
||||
(kv.first == "type" && this_part
|
||||
? "e7009fac-a5a1-4d72-af72-53de13059903"
|
||||
: (kv.second.is_string() ? kv.second.string_value() : kv.second.dump()));
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
script += "\n";
|
||||
}
|
||||
std::string out;
|
||||
return shell_exec({ "sfdisk", "--no-reread", "--force", "/dev/"+parent_dev }, script, &out, NULL);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue