def validate(self): self.spec.validate() if self.spec.placement.hosts: explicit_hostnames = { h.hostname for h in self.spec.placement.hosts } unknown_hosts = explicit_hostnames.difference( set(self.get_hosts_func())) if unknown_hosts: raise OrchestratorValidationError( f'Cannot place {self.spec.one_line_str()} on {unknown_hosts}: Unknown hosts' ) if self.spec.placement.host_pattern: pattern_hostnames = self.spec.placement.filter_matching_hosts( self.get_hosts_func) if not pattern_hostnames: raise OrchestratorValidationError( f'Cannot place {self.spec.one_line_str()}: No matching hosts' ) if self.spec.placement.label: label_hostnames = self.get_hosts_func( label=self.spec.placement.label) if not label_hostnames: raise OrchestratorValidationError( f'Cannot place {self.spec.one_line_str()}: No matching ' f'hosts for label {self.spec.placement.label}')
def validate(self) -> None: self.spec.validate() if self.spec.placement.count == 0: raise OrchestratorValidationError( f'<count> can not be 0 for {self.spec.one_line_str()}') if self.spec.placement.hosts: explicit_hostnames = { h.hostname for h in self.spec.placement.hosts } unknown_hosts = explicit_hostnames.difference( set(self.get_hostnames())) if unknown_hosts: raise OrchestratorValidationError( f'Cannot place {self.spec.one_line_str()} on {", ".join(sorted(unknown_hosts))}: Unknown hosts' ) if self.spec.placement.host_pattern: pattern_hostnames = self.spec.placement.filter_matching_hostspecs( self.hosts) if not pattern_hostnames: raise OrchestratorValidationError( f'Cannot place {self.spec.one_line_str()}: No matching hosts' ) if self.spec.placement.label: label_hosts = self.hosts_by_label(self.spec.placement.label) if not label_hosts: raise OrchestratorValidationError( f'Cannot place {self.spec.one_line_str()}: No matching ' f'hosts for label {self.spec.placement.label}')
def get_candidates(self) -> List[DaemonPlacement]: if self.spec.placement.hosts: ls = [ DaemonPlacement(hostname=h.hostname, network=h.network, name=h.name, port=self.port_start) for h in self.spec.placement.hosts ] elif self.spec.placement.label: ls = [ DaemonPlacement(hostname=x.hostname, port=self.port_start) for x in self.hosts_by_label(self.spec.placement.label) ] elif self.spec.placement.host_pattern: ls = [ DaemonPlacement(hostname=x, port=self.port_start) for x in self.spec.placement.filter_matching_hostspecs(self.hosts) ] elif (self.spec.placement.count is not None or self.spec.placement.count_per_host is not None): ls = [ DaemonPlacement(hostname=x.hostname, port=self.port_start) for x in self.hosts ] else: raise OrchestratorValidationError( "placement spec is empty: no hosts, no label, no pattern, no count" ) if self.filter_new_host: old = ls.copy() ls = [h for h in ls if self.filter_new_host(h.hostname)] for h in list(set(old) - set(ls)): logger.info( f"Filtered out host {h.hostname}: could not verify host allowed virtual ips" ) logger.debug('Filtered %s down to %s' % (old, ls)) # shuffle for pseudo random selection # gen seed off of self.spec to make shuffling deterministic seed = hash(self.spec.service_name()) random.Random(seed).shuffle(ls) return ls
def get_candidates(self) -> List[HostPlacementSpec]: if self.spec.placement.hosts: return self.spec.placement.hosts elif self.spec.placement.label: return [ HostPlacementSpec(x, '', '') for x in self.get_hosts_func(label=self.spec.placement.label) ] elif self.spec.placement.host_pattern: return [ HostPlacementSpec(x, '', '') for x in self.spec.placement.filter_matching_hosts(self.get_hosts_func) ] if self.spec.placement.count is None: raise OrchestratorValidationError( "placement spec is empty: no hosts, no label, no pattern, no count" ) # backward compatibility: consider an empty placements to be the same pattern = * return [HostPlacementSpec(x, '', '') for x in self.get_hosts_func()]
def get_candidates(self) -> List[HostPlacementSpec]: if self.spec.placement.hosts: return self.spec.placement.hosts elif self.spec.placement.label: return [ HostPlacementSpec(x.hostname, '', '') for x in self.hosts_by_label(self.spec.placement.label) ] elif self.spec.placement.host_pattern: return [ HostPlacementSpec(x, '', '') for x in self.spec.placement.filter_matching_hostspecs(self.hosts) ] # If none of the above and also no <count> if self.spec.placement.count is None: raise OrchestratorValidationError( "placement spec is empty: no hosts, no label, no pattern, no count" ) # backward compatibility: consider an empty placements to be the same pattern = * return [HostPlacementSpec(x.hostname, '', '') for x in self.hosts]
def get_candidates(self) -> List[DaemonPlacement]: if self.spec.placement.hosts: ls = [ DaemonPlacement(daemon_type=self.primary_daemon_type, hostname=h.hostname, network=h.network, name=h.name, ports=self.ports_start) for h in self.spec.placement.hosts ] elif self.spec.placement.label: ls = [ DaemonPlacement(daemon_type=self.primary_daemon_type, hostname=x.hostname, ports=self.ports_start) for x in self.hosts_by_label(self.spec.placement.label) ] elif self.spec.placement.host_pattern: ls = [ DaemonPlacement(daemon_type=self.primary_daemon_type, hostname=x, ports=self.ports_start) for x in self.spec.placement.filter_matching_hostspecs(self.hosts) ] elif (self.spec.placement.count is not None or self.spec.placement.count_per_host is not None): ls = [ DaemonPlacement(daemon_type=self.primary_daemon_type, hostname=x.hostname, ports=self.ports_start) for x in self.hosts ] else: raise OrchestratorValidationError( "placement spec is empty: no hosts, no label, no pattern, no count" ) # allocate an IP? if self.spec.networks: orig = ls.copy() ls = [] for p in orig: ip = self.find_ip_on_host(p.hostname, self.spec.networks) if ip: ls.append( DaemonPlacement(daemon_type=self.primary_daemon_type, hostname=p.hostname, network=p.network, name=p.name, ports=p.ports, ip=ip)) else: logger.debug( f'Skipping {p.hostname} with no IP in network(s) {self.spec.networks}' ) if self.filter_new_host: old = ls.copy() ls = [] for h in old: if self.filter_new_host(h.hostname): ls.append(h) if len(old) > len(ls): logger.debug('Filtered %s down to %s' % (old, ls)) # now that we have the list of nodes candidates based on the configured # placement, let's shuffle the list for node pseudo-random selection. For this, # we generate a seed from the service name and we use to shuffle the candidates. # This makes shuffling deterministic for the same service name. seed = int( hashlib.sha1(self.spec.service_name().encode('utf-8')).hexdigest(), 16) % (2**32) # truncate result to 32 bits final = sorted(ls) random.Random(seed).shuffle(final) return final
def get_candidates(self) -> List[DaemonPlacement]: if self.spec.placement.hosts: ls = [ DaemonPlacement(daemon_type=self.primary_daemon_type, hostname=h.hostname, network=h.network, name=h.name, ports=self.ports_start) for h in self.spec.placement.hosts ] elif self.spec.placement.label: ls = [ DaemonPlacement(daemon_type=self.primary_daemon_type, hostname=x.hostname, ports=self.ports_start) for x in self.hosts_by_label(self.spec.placement.label) ] elif self.spec.placement.host_pattern: ls = [ DaemonPlacement(daemon_type=self.primary_daemon_type, hostname=x, ports=self.ports_start) for x in self.spec.placement.filter_matching_hostspecs(self.hosts) ] elif (self.spec.placement.count is not None or self.spec.placement.count_per_host is not None): ls = [ DaemonPlacement(daemon_type=self.primary_daemon_type, hostname=x.hostname, ports=self.ports_start) for x in self.hosts ] else: raise OrchestratorValidationError( "placement spec is empty: no hosts, no label, no pattern, no count" ) # allocate an IP? if self.spec.networks: orig = ls.copy() ls = [] for p in orig: ip = self.find_ip_on_host(p.hostname, self.spec.networks) if ip: ls.append( DaemonPlacement(daemon_type=self.primary_daemon_type, hostname=p.hostname, network=p.network, name=p.name, ports=p.ports, ip=ip)) else: logger.debug( f'Skipping {p.hostname} with no IP in network(s) {self.spec.networks}' ) if self.filter_new_host: old = ls.copy() ls = [] for h in old: if self.filter_new_host(h.hostname): ls.append(h) if len(old) > len(ls): logger.debug('Filtered %s down to %s' % (old, ls)) # shuffle for pseudo random selection # gen seed off of self.spec to make shuffling deterministic seed = int( hashlib.sha1(self.spec.service_name().encode('utf-8')).hexdigest(), 16) % (2**32) final = sorted(ls) random.Random(seed).shuffle(final) return ls