def test_parse_placement_specs_raises(test_input): with pytest.raises(ServiceSpecValidationError): PlacementSpec.from_string(test_input)
def describe_service( self, service_type: Optional[str] = None, service_name: Optional[str] = None, refresh: bool = False) -> List[orchestrator.ServiceDescription]: now = datetime.datetime.utcnow() # CephCluster cl = self.rook_cluster.rook_api_get("cephclusters/{0}".format( self.rook_cluster.rook_env.cluster_name)) self.log.debug('CephCluster %s' % cl) image_name = cl['spec'].get('cephVersion', {}).get('image', None) num_nodes = len(self.rook_cluster.get_node_names()) spec = {} if service_type == 'mon' or service_type is None: spec['mon'] = orchestrator.ServiceDescription( spec=ServiceSpec( 'mon', placement=PlacementSpec(count=cl['spec'].get( 'mon', {}).get('count', 1), ), ), size=cl['spec'].get('mon', {}).get('count', 1), container_image_name=image_name, last_refresh=now, ) if service_type == 'mgr' or service_type is None: spec['mgr'] = orchestrator.ServiceDescription( spec=ServiceSpec( 'mgr', placement=PlacementSpec.from_string('count:1'), ), size=1, container_image_name=image_name, last_refresh=now, ) if not cl['spec'].get('crashCollector', {}).get('disable', False): spec['crash'] = orchestrator.ServiceDescription( spec=ServiceSpec( 'crash', placement=PlacementSpec.from_string('*'), ), size=num_nodes, container_image_name=image_name, last_refresh=now, ) if service_type == 'mds' or service_type is None: # CephFilesystems all_fs = self.rook_cluster.rook_api_get("cephfilesystems/") self.log.debug('CephFilesystems %s' % all_fs) for fs in all_fs.get('items', []): svc = 'mds.' + fs['metadata']['name'] if svc in spec: continue # FIXME: we are conflating active (+ standby) with count active = fs['spec'].get('metadataServer', {}).get('activeCount', 1) total_mds = active if fs['spec'].get('metadataServer', {}).get('activeStandby', False): total_mds = active * 2 spec[svc] = orchestrator.ServiceDescription( spec=ServiceSpec( service_type='mds', service_id=fs['metadata']['name'], placement=PlacementSpec(count=active), ), size=total_mds, container_image_name=image_name, last_refresh=now, ) if service_type == 'rgw' or service_type is None: # CephObjectstores all_zones = self.rook_cluster.rook_api_get("cephobjectstores/") self.log.debug('CephObjectstores %s' % all_zones) for zone in all_zones.get('items', []): rgw_realm = zone['metadata']['name'] rgw_zone = rgw_realm svc = 'rgw.' + rgw_realm + '.' + rgw_zone if svc in spec: continue active = zone['spec']['gateway']['instances'] if 'securePort' in zone['spec']['gateway']: ssl = True port = zone['spec']['gateway']['securePort'] else: ssl = False port = zone['spec']['gateway']['port'] or 80 spec[svc] = orchestrator.ServiceDescription( spec=RGWSpec( service_id=rgw_realm + '.' + rgw_zone, rgw_realm=rgw_realm, rgw_zone=rgw_zone, ssl=ssl, rgw_frontend_port=port, placement=PlacementSpec(count=active), ), size=active, container_image_name=image_name, last_refresh=now, ) if service_type == 'nfs' or service_type is None: # CephNFSes all_nfs = self.rook_cluster.rook_api_get("cephnfses/") self.log.warning('CephNFS %s' % all_nfs) for nfs in all_nfs.get('items', []): nfs_name = nfs['metadata']['name'] svc = 'nfs.' + nfs_name if svc in spec: continue active = nfs['spec'].get('server', {}).get('active') spec[svc] = orchestrator.ServiceDescription( spec=NFSServiceSpec( service_id=nfs_name, pool=nfs['spec']['rados']['pool'], namespace=nfs['spec']['rados'].get('namespace', None), placement=PlacementSpec(count=active), ), size=active, last_refresh=now, ) for dd in self._list_daemons(): if dd.service_name() not in spec: continue service = spec[dd.service_name()] service.running += 1 if not service.container_image_id: service.container_image_id = dd.container_image_id if not service.container_image_name: service.container_image_name = dd.container_image_name if service.last_refresh is None or not dd.last_refresh or dd.last_refresh < service.last_refresh: service.last_refresh = dd.last_refresh if service.created is None or dd.created is None or dd.created < service.created: service.created = dd.created return [v for k, v in spec.items()]
def test_parse_placement_specs(test_input, expected): ret = PlacementSpec.from_string(test_input) assert str(ret) == expected
def describe_service( self, service_type: Optional[str] = None, service_name: Optional[str] = None, refresh: bool = False) -> List[orchestrator.ServiceDescription]: now = datetime_now() # CephCluster cl = self.rook_cluster.rook_api_get("cephclusters/{0}".format( self.rook_cluster.rook_env.cluster_name)) self.log.debug('CephCluster %s' % cl) image_name = cl['spec'].get('cephVersion', {}).get('image', None) num_nodes = len(self.rook_cluster.get_node_names()) spec = {} if service_type == 'mon' or service_type is None: spec['mon'] = orchestrator.ServiceDescription( spec=ServiceSpec( 'mon', placement=PlacementSpec(count=cl['spec'].get( 'mon', {}).get('count', 1), ), ), size=cl['spec'].get('mon', {}).get('count', 1), container_image_name=image_name, last_refresh=now, ) if service_type == 'mgr' or service_type is None: spec['mgr'] = orchestrator.ServiceDescription( spec=ServiceSpec( 'mgr', placement=PlacementSpec.from_string('count:1'), ), size=1, container_image_name=image_name, last_refresh=now, ) if (service_type == 'crash' or service_type is None and not cl['spec'].get( 'crashCollector', {}).get('disable', False)): spec['crash'] = orchestrator.ServiceDescription( spec=ServiceSpec( 'crash', placement=PlacementSpec.from_string('*'), ), size=num_nodes, container_image_name=image_name, last_refresh=now, ) if service_type == 'mds' or service_type is None: # CephFilesystems all_fs = self.rook_cluster.get_resource("cephfilesystems") for fs in all_fs: svc = 'mds.' + fs['metadata']['name'] if svc in spec: continue # FIXME: we are conflating active (+ standby) with count active = fs['spec'].get('metadataServer', {}).get('activeCount', 1) total_mds = active if fs['spec'].get('metadataServer', {}).get('activeStandby', False): total_mds = active * 2 spec[svc] = orchestrator.ServiceDescription( spec=ServiceSpec( service_type='mds', service_id=fs['metadata']['name'], placement=PlacementSpec(count=active), ), size=total_mds, container_image_name=image_name, last_refresh=now, ) if service_type == 'rgw' or service_type is None: # CephObjectstores all_zones = self.rook_cluster.get_resource("cephobjectstores") for zone in all_zones: svc = 'rgw.' + zone['metadata']['name'] if svc in spec: continue active = zone['spec']['gateway']['instances'] if 'securePort' in zone['spec']['gateway']: ssl = True port = zone['spec']['gateway']['securePort'] else: ssl = False port = zone['spec']['gateway']['port'] or 80 rgw_zone = zone['spec'].get('zone', {}).get('name') or None spec[svc] = orchestrator.ServiceDescription( spec=RGWSpec( service_id=zone['metadata']['name'], rgw_zone=rgw_zone, ssl=ssl, rgw_frontend_port=port, placement=PlacementSpec(count=active), ), size=active, container_image_name=image_name, last_refresh=now, ) if service_type == 'nfs' or service_type is None: # CephNFSes all_nfs = self.rook_cluster.get_resource("cephnfses") nfs_pods = self.rook_cluster.describe_pods('nfs', None, None) for nfs in all_nfs: if nfs['spec']['rados']['pool'] != NFS_POOL_NAME: continue nfs_name = nfs['metadata']['name'] svc = 'nfs.' + nfs_name if svc in spec: continue active = nfs['spec'].get('server', {}).get('active') creation_timestamp = datetime.datetime.strptime( nfs['metadata']['creationTimestamp'], '%Y-%m-%dT%H:%M:%SZ') spec[svc] = orchestrator.ServiceDescription( spec=NFSServiceSpec( service_id=nfs_name, placement=PlacementSpec(count=active), ), size=active, last_refresh=now, running=len([ 1 for pod in nfs_pods if pod['labels']['ceph_nfs'] == nfs_name ]), created=creation_timestamp.astimezone( tz=datetime.timezone.utc)) if service_type == 'osd' or service_type is None: # OSDs # FIXME: map running OSDs back to their respective services... # the catch-all unmanaged all_osds = self.rook_cluster.get_osds() svc = 'osd' spec[svc] = orchestrator.ServiceDescription( spec=DriveGroupSpec( unmanaged=True, service_type='osd', ), size=len(all_osds), last_refresh=now, running=sum(osd.status.phase == 'Running' for osd in all_osds)) # drivegroups for name, dg in self._drive_group_map.items(): spec[f'osd.{name}'] = orchestrator.ServiceDescription( spec=dg, last_refresh=now, size=0, running=0, ) if service_type == 'rbd-mirror' or service_type is None: # rbd-mirrors all_mirrors = self.rook_cluster.get_resource("cephrbdmirrors") for mirror in all_mirrors: logging.warn(mirror) mirror_name = mirror['metadata']['name'] svc = 'rbd-mirror.' + mirror_name if svc in spec: continue spec[svc] = orchestrator.ServiceDescription( spec=ServiceSpec( service_id=mirror_name, service_type="rbd-mirror", placement=PlacementSpec(count=1), ), size=1, last_refresh=now, ) for dd in self._list_daemons(): if dd.service_name() not in spec: continue service = spec[dd.service_name()] service.running += 1 if not service.container_image_id: service.container_image_id = dd.container_image_id if not service.container_image_name: service.container_image_name = dd.container_image_name if service.last_refresh is None or not dd.last_refresh or dd.last_refresh < service.last_refresh: service.last_refresh = dd.last_refresh if service.created is None or dd.created is None or dd.created < service.created: service.created = dd.created return [v for k, v in spec.items()]
def test_parse_placement_specs(test_input, expected): ret = PlacementSpec.from_string(test_input) assert str(ret) == expected assert PlacementSpec.from_string( ret.pretty_str()) == ret, f'"{ret.pretty_str()}" != "{test_input}"'
def test_bad_placements(placement): try: s = PlacementSpec.from_string(placement.split(' ')) assert False except ServiceSpecValidationError as e: pass
def describe_service(self, service_type=None, service_name=None, refresh=False): now = datetime.datetime.utcnow() # CephCluster cl = self.rook_cluster.rook_api_get( "cephclusters/{0}".format(self.rook_cluster.rook_env.cluster_name)) self.log.debug('CephCluster %s' % cl) image_name = cl['spec'].get('cephVersion', {}).get('image', None) num_nodes = len(self.rook_cluster.get_node_names()) spec = {} spec['mon'] = orchestrator.ServiceDescription( service_name='mon', spec=ServiceSpec( 'mon', placement=PlacementSpec( count=cl['spec'].get('mon', {}).get('count', 1), ), ), size=cl['spec'].get('mon', {}).get('count', 1), container_image_name=image_name, last_refresh=now, ) spec['mgr'] = orchestrator.ServiceDescription( service_name='mgr', spec=ServiceSpec( 'mgr', placement=PlacementSpec.from_string('count:1'), ), size=1, container_image_name=image_name, last_refresh=now, ) if not cl['spec'].get('crashCollector', {}).get('disable', False): spec['crash'] = orchestrator.ServiceDescription( service_name='crash', spec=ServiceSpec( 'crash', placement=PlacementSpec.from_string('all:true'), ), size=num_nodes, container_image_name=image_name, last_refresh=now, ) # CephFilesystems all_fs = self.rook_cluster.rook_api_get( "cephfilesystems/") self.log.debug('CephFilesystems %s' % all_fs) for fs in all_fs.get('items', []): svc = 'mds.' + fs['metadata']['name'] if svc in spec: continue # FIXME: we are conflating active (+ standby) with count active = fs['spec'].get('metadataServer', {}).get('activeCount', 1) total_mds = active if fs['spec'].get('metadataServer', {}).get('activeStandby', False): total_mds = active * 2 spec[svc] = orchestrator.ServiceDescription( service_name=svc, spec=ServiceSpec( svc, placement=PlacementSpec(count=active), ), size=total_mds, container_image_name=image_name, last_refresh=now, ) # FIXME: CephObjectstores for dd in self._list_daemons(): if dd.service_name() not in spec: continue spec[dd.service_name()].running += 1 return [v for k, v in spec.items()]