def get_daemons_by_type(self, service_type: str, host: str = '') -> List[orchestrator.DaemonDescription]: assert service_type not in ['keepalived', 'haproxy'] result = [] # type: List[orchestrator.DaemonDescription] for h, dm in self.daemons.items(): if host and h != host: continue for name, d in dm.items(): if d.daemon_type in service_to_daemon_types(service_type): result.append(d) return result
def get_daemons_by_type( self, service_type: str, host: str = '') -> List[orchestrator.DaemonDescription]: assert service_type not in ['keepalived', 'haproxy'] daemons = self.daemons[host].values() if host else self._get_daemons() return [ d for d in daemons if d.daemon_type in service_to_daemon_types(service_type) ]
def _apply_service(self, spec: ServiceSpec) -> bool: """ Schedule a service. Deploy new daemons or remove old ones, depending on the target label and count specified in the placement. """ self.mgr.migration.verify_no_migration() service_type = spec.service_type service_name = spec.service_name() if spec.unmanaged: self.log.debug('Skipping unmanaged service %s' % service_name) return False if spec.preview_only: self.log.debug('Skipping preview_only service %s' % service_name) return False self.log.debug('Applying service %s spec' % service_name) self._apply_service_config(spec) if service_type == 'osd': self.mgr.osd_service.create_from_spec(cast(DriveGroupSpec, spec)) # TODO: return True would result in a busy loop # can't know if daemon count changed; create_from_spec doesn't # return a solid indication return False svc = self.mgr.cephadm_services[service_type] daemons = self.mgr.cache.get_daemons_by_service(service_name) public_network = None if service_type == 'mon': out = str(self.mgr.get_foreign_ceph_option('mon', 'public_network')) if '/' in out: public_network = out.strip() self.log.debug('mon public_network is %s' % public_network) def matches_network(host): # type: (str) -> bool if not public_network: return False # make sure we have 1 or more IPs for that network on that # host return len(self.mgr.cache.networks[host].get(public_network, [])) > 0 def virtual_ip_allowed(host): # type: (str) -> bool # Verify that it is possible to use Virtual IPs in the host try: if self.mgr.cache.facts[host]['kernel_parameters']['net.ipv4.ip_nonlocal_bind'] == '0': return False except KeyError: return False return True ha = HostAssignment( spec=spec, hosts=self.mgr._hosts_with_daemon_inventory(), daemons=daemons, filter_new_host=matches_network if service_type == 'mon' else virtual_ip_allowed if service_type == 'ha-rgw' else None, allow_colo=svc.allow_colo(), ) try: all_slots, slots_to_add, daemons_to_remove = ha.place() self.log.debug('Add %s, remove %s' % (slots_to_add, daemons_to_remove)) except OrchestratorError as e: self.log.error('Failed to apply %s spec %s: %s' % ( spec.service_name(), spec, e)) self.mgr.events.for_service(spec, 'ERROR', 'Failed to apply: ' + str(e)) return False r = None # sanity check final_count = len(daemons) + len(slots_to_add) - len(daemons_to_remove) if service_type in ['mon', 'mgr'] and final_count < 1: self.log.debug('cannot scale mon|mgr below 1)') return False # add any? did_config = False self.log.debug('Hosts that will receive new daemons: %s' % slots_to_add) self.log.debug('Daemons that will be removed: %s' % daemons_to_remove) if service_type == 'ha-rgw': spec = self.update_ha_rgw_definitive_hosts(spec, all_slots, slots_to_add) for slot in slots_to_add: for daemon_type in service_to_daemon_types(service_type): daemon_id = self.mgr.get_unique_name( daemon_type, slot.hostname, daemons, prefix=spec.service_id, forcename=slot.name) if not did_config: svc.config(spec, daemon_id) did_config = True daemon_spec = svc.make_daemon_spec( slot.hostname, daemon_id, slot.network, spec, daemon_type=daemon_type, ports=[slot.port] if slot.port else None ) self.log.debug('Placing %s.%s on host %s' % ( daemon_type, daemon_id, slot.hostname)) try: daemon_spec = svc.prepare_create(daemon_spec) self._create_daemon(daemon_spec) r = True except (RuntimeError, OrchestratorError) as e: self.mgr.events.for_service(spec, 'ERROR', f"Failed while placing {daemon_type}.{daemon_id}" f"on {slot.hostname}: {e}") # only return "no change" if no one else has already succeeded. # later successes will also change to True if r is None: r = False continue # add to daemon list so next name(s) will also be unique sd = orchestrator.DaemonDescription( hostname=slot.hostname, daemon_type=daemon_type, daemon_id=daemon_id, ) daemons.append(sd) # remove any? def _ok_to_stop(remove_daemons: List[orchestrator.DaemonDescription]) -> bool: daemon_ids = [d.daemon_id for d in remove_daemons] assert None not in daemon_ids # setting force flag retains previous behavior r = svc.ok_to_stop(cast(List[str], daemon_ids), force=True) return not r.retval while daemons_to_remove and not _ok_to_stop(daemons_to_remove): # let's find a subset that is ok-to-stop daemons_to_remove.pop() for d in daemons_to_remove: r = True # NOTE: we are passing the 'force' flag here, which means # we can delete a mon instances data. assert d.hostname is not None self._remove_daemon(d.name(), d.hostname) if r is None: r = False return r