Skip to content

Instantly share code, notes, and snippets.

@h0hmj
Last active November 28, 2023 07:01
Show Gist options
  • Save h0hmj/288c4cd6753d571c186e2b81eaa14edb to your computer and use it in GitHub Desktop.
Save h0hmj/288c4cd6753d571c186e2b81eaa14edb to your computer and use it in GitHub Desktop.
fix curveadm cluster after migration
import os
import yaml
import sqlite3
class CurveadmHostsHandler:
def __init__(self):
self.data = None
def load(self, path=None):
if path is not None:
with open(path, "r") as fd:
self.data = yaml.safe_load(fd)
os.system("curveadm hosts show > /tmp/hosts.yaml")
with open("/tmp/hosts.yaml", "r") as fd:
self.data = yaml.safe_load(fd)
def dump(self, path):
if self.data is None:
raise Exception("load hosts first")
with open(path, "w") as fd:
yaml.safe_dump(self.data, fd)
def commit(self, path):
os.system(f'echo "yes"| curveadm hosts commit {path}')
def add_host(self, host_alias, hostname):
if self.data is None:
raise Exception("load hosts first")
hosts = self.data["hosts"]
for host in hosts:
if host["host"] == host_alias:
if host["hostname"] == hostname:
return
else:
raise Exception("host alias already exist with different hostname")
hosts.append({"host": host_alias, "hostname": hostname})
class CurveadmClusterHandler:
def __init__(self, db_path, name):
self.topo = None
self.name = name
self.id = None
self.uuid = None
self.db_path = db_path
self.db_connection = sqlite3.connect(self.db_path)
self.db_cursor = self.db_connection.cursor()
result = self.db_cursor.execute(
f'SELECT id,uuid,topology FROM clusters WHERE name="{self.name}"'
).fetchone()
if result is None:
raise Exception("cluster not exist")
else:
self.id, self.uuid, self.topo = result
self.topo = yaml.safe_load(self.topo)
def __calculate_service_id(
self, uuid, service_name, host_alias, host_index, instance_index
):
import hashlib
m = hashlib.md5()
print(f"{uuid}_{service_name}_{host_alias}_{host_index}_{instance_index}")
m.update(
f"{uuid}_{service_name}_{host_alias}_{host_index}_{instance_index}".encode(
"utf-8"
)
)
return str(m.hexdigest())
def add_service(self, service_name, host_alias, instance_num, container_ids):
if len(container_ids) != instance_num:
raise Exception("container_ids num not match instance_num")
# todo: check variable
services = self.topo[f"{service_name}_services"]
instances = services["deploy"]
host_index = len(instances)
for instance in instances:
host = instance["host"]
if host_alias == host:
print(
f"service {service_name}.{host_alias} already exist in topo, skip"
)
return
instances.append({"host": host_alias, "instances": instance_num})
for i in range(instance_num):
service_id = self.__calculate_service_id(
self.uuid, service_name, host_alias, host_index, i
)
self.db_cursor.execute(
f'INSERT INTO containers (id, cluster_id, container_id) VALUES ("{service_id[:12]}", {self.id}, "{container_ids[i]}") ON CONFLICT (id) DO NOTHING'
)
self.db_cursor.execute(
"UPDATE clusters SET topology = ? WHERE name = ?",
(yaml.safe_dump(self.topo), "test"),
)
self.db_connection.commit()
# usage example, backup your curveadm db first
# tool target: fix curveadm hosts and cluster topology to match your real cluster
# 1. add hosts
hosts = CurveadmHostsHandler()
hosts.load()
hosts.add_host("vm4", "192.168.16.32")
hosts.add_host("vm5", "192.168.16.35")
hosts.add_host("vm6", "192.168.16.36")
hosts.dump("/tmp/hosts_mod.yaml")
hosts.commit("/tmp/hosts_mod.yaml")
# 2. add services
# full container id get from docker ps --no-trunc
cluster = CurveadmClusterHandler("/root/.curveadm/data/curveadm.db", "test")
cluster.add_service("etcd", "vm4", 1, ["-"])
cluster.add_service("etcd", "vm5", 1, ["-"])
cluster.add_service("etcd", "vm6", 1, ["-"])
cluster.add_service("mds", "vm4", 1, ["-"])
cluster.add_service("mds", "vm5", 1, ["-"])
cluster.add_service("mds", "vm6", 1, ["-"])
cluster.add_service("metaserver", "vm4", 3, ["-", "-", "-"])
cluster.add_service("metaserver", "vm5", 3, ["-", "-", "-"])
cluster.add_service("metaserver", "vm6", 3, ["-", "-", "-"])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment