--- /dev/null
+class ZoneEPs:
+ def __init__(self):
+ self.endpoints = set()
+
+ def add(self, ep):
+ if not ep:
+ return
+
+ self.endpoints.add(ep)
+
+ def diff(self, zep):
+ return list(self.endpoints.difference(zep.endpoints))
+
+ def get_all(self):
+ for ep in self.endpoints:
+ yield ep
+
+
+
+class RealmEPs:
+ def __init__(self):
+ self.zones = {}
+
+ def add(self, zone, ep = None):
+ if not zone:
+ return
+
+ z = self.zones.get(zone)
+ if not z:
+ z = ZoneEPs()
+ self.zones[zone] = z
+
+ z.add(ep)
+
+ def diff(self, rep):
+ result = {}
+ for z, zep in rep.zones.items():
+ myzep = self.zones.get(z)
+ if not myzep:
+ continue
+
+
+ d = myzep.diff(zep)
+ if len(d) > 0:
+ result[z] = myzep.diff(zep)
+
+ return result
+
+ def get_all(self):
+ for z, zep in self.zones.items():
+ eps = []
+ for ep in zep.get_all():
+ eps.append(ep)
+ yield z, eps
+
+
+
+class RealmsEPs:
+ def __init__(self):
+ self.realms = {}
+
+ def add(self, realm, zone = None, ep = None):
+ if not realm:
+ return
+
+ r = self.realms.get(realm)
+ if not r:
+ r = RealmEPs()
+ self.realms[realm] = r
+
+ r.add(zone, ep)
+
+ def diff(self, rep):
+ result = {}
+
+ for r, rep in rep.realms.items():
+ myrealm = self.realms.get(r)
+ if not myrealm:
+ continue
+
+ d = myrealm.diff(rep)
+ if d:
+ result[r] = d
+
+ return result
+
+ def get_all(self):
+ result = {}
+ for r, rep in self.realms.items():
+ zs = {}
+ for z, eps in rep.get_all():
+ zs[z] = eps
+
+ result[r] = zs
+
+ return result
+
+
return HandleCommandResult(retval=retval, stdout=out, stderr=err)
+ @CLICommand('rgw realm reconcile', perm='rw')
+ def _cmd_rgw_realm_reconcile(self,
+ realm_name : Optional[str] = None,
+ zonegroup_name: Optional[str] = None,
+ zone_name: Optional[str] = None,
+ update: Optional[bool] = False):
+ """Bootstrap new rgw zone that syncs with existing zone"""
+
+ try:
+ retval, out, err = RGWAM(self.env).realm_reconcile(realm_name, zonegroup_name,
+ zone_name, update)
+ except RGWAMException as e:
+ self.log.error('cmd run exception: (%d) %s' % (e.retcode, e.message))
+ return (e.retcode, e.message, e.stderr)
+
+ return HandleCommandResult(retval=retval, stdout=out, stderr=err)
+
def shutdown(self) -> None:
"""
This method is called by the mgr when the module needs to shut
from urllib.parse import urlparse
from .types import RGWAMException, RGWAMCmdRunException, RGWPeriod, RGWUser, RealmToken
+from .diff import RealmsEPs
from ceph.deployment.service_spec import RGWSpec
class RealmOp:
def __init__(self, env : EnvArgs):
self.env = env
+
+ def list(self):
+ ze = ZoneEnv(self.env)
+
+ params = [ 'realm',
+ 'list' ]
+
+ return RGWAdminJSONCmd(ze).run(params)
+
def get(self, realm : EntityKey = None):
return (0, success_message, '')
+
+ def _get_daemon_eps(self, realm_name = None, zonegroup_name = None, zone_name = None):
+ # get running daemons info
+ service_name = None
+ if realm_name and zone_name:
+ service_name = 'rgw.%s.%s' % (realm_name, zone_name)
+
+ daemon_type = 'rgw'
+ daemon_id = None
+ hostname = None
+ refresh = True
+
+ completion = self.env.mgr.list_daemons(service_name,
+ daemon_type,
+ daemon_id=daemon_id,
+ host=hostname,
+ refresh=refresh)
+
+ daemons = orchestrator.raise_if_exception(completion)
+
+ rep = RealmsEPs()
+
+ for s in daemons:
+ for p in s.ports:
+ svc_id = s.service_id()
+ l = svc_id.split('.')
+ if len(l) < 2:
+ log.error('ERROR: service id cannot be parsed: (svc_id=%s)' % svc_id)
+ continue
+
+ svc_realm = l[0]
+ svc_zone = l[1]
+
+ if realm_name and svc_realm != realm_name:
+ log.debug('skipping realm %s' % svc_realm)
+ continue
+
+ if zone_name and svc_zone != zone_name:
+ log.debug('skipping zone %s' % svc_zone)
+ continue
+
+ ep = 'http://%s:%d' % (s.hostname, p) # ssl?
+
+ rep.add(svc_realm, svc_zone, ep)
+
+ return rep
+
+
+
+ def _get_rgw_eps(self, realm_name = None, zonegroup_name = None, zone_name = None):
+ rep = RealmsEPs()
+
+ try:
+ realm_list_ret = self.realm_op().list()
+ except RGWAMException as e:
+ raise RGWAMException('failed to list realms', e)
+
+ realms = realm_list_ret.get('realms') or []
+
+ zones_map = {}
+
+ for realm in realms:
+ if realm_name and realm != realm_name:
+ log.debug('skipping realm %s' % realm)
+ continue
+
+ period_info = self.period_op().get(EntityName(realm))
+
+ period = RGWPeriod(period_info)
+
+ zones_map[realm] = {}
+
+ for zg in period.iter_zonegroups():
+ if zonegroup_name and zg.name != zonegroup_name:
+ log.debug('skipping zonegroup %s' % zg.name)
+ continue
+
+ for zone in zg.iter_zones():
+ if zone_name and zone.name != zone_name:
+ log.debug('skipping zone %s' % zone.name)
+ continue
+
+ zones_map[realm][zone.name] = zg.name
+
+ if len(zone.endpoints) == 0:
+ rep.add(realm, zone.name, None)
+ continue
+
+ for ep in zone.endpoints:
+ rep.add(realm, zone.name, ep)
+
+ return (rep, zones_map)
+
+ def realm_reconcile(self, realm_name = None, zonegroup_name = None, zone_name = None, update = False):
+
+ daemon_rep = self._get_daemon_eps(realm_name, zonegroup_name, zone_name)
+
+ rgw_rep, zones_map = self._get_rgw_eps(realm_name, zonegroup_name, zone_name)
+
+ diff = daemon_rep.diff(rgw_rep)
+
+ diffj = json.dumps(diff)
+
+ if not update:
+ return (0, diffj, '')
+
+ for realm, realm_diff in diff.items():
+ for zone, endpoints in realm_diff.items():
+
+ zg = zones_map[realm][zone]
+
+ try:
+ zone_info = self.zone_op().modify(EntityName(zone), EntityName(zg), endpoints = ','.join(diff[realm][zone]))
+ except RGWAMException as e:
+ raise RGWAMException('failed to modify zone', e)
+
+ try:
+ period_info = self.period_op().update(EntityName(realm), EntityName(zg), EntityName(zone), True)
+ except RGWAMException as e:
+ raise RGWAMException('failed to update period', e)
+
+ return (0, 'Updated: ' + diffj, '')
+
+
def run_radosgw(self, port = None, log_file = None, debug_ms = None, debug_rgw = None):
fe_cfg = 'beast'