Ejemplo n.º 1
0
    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}')
Ejemplo n.º 2
0
    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}')
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
 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()]
Ejemplo n.º 5
0
 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]
Ejemplo n.º 6
0
    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
Ejemplo n.º 7
0
    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