def set_boot_order(self, node_name, cd_first=False):
     log.info(
         f"Going to set the following boot order: cd_first: {cd_first}, "
         f"for node: {node_name}")
     node = self.libvirt_connection.lookupByName(node_name)
     current_xml = node.XMLDesc(0)
     xml = minidom.parseString(current_xml.encode("utf-8"))
     self._clean_domain_os_boot_data(xml)
     os_element = xml.getElementsByTagName("os")[0]
     # Set boot elements for hd and cdrom
     first = xml.createElement("boot")
     first.setAttribute("dev", "cdrom" if cd_first else "hd")
     os_element.appendChild(first)
     second = xml.createElement("boot")
     second.setAttribute("dev", "hd" if cd_first else "cdrom")
     os_element.appendChild(second)
     # Apply new machine xml
     dom = self.libvirt_connection.defineXML(xml.toprettyxml())
     if dom is None:
         raise Exception(
             f"Failed to set boot order cdrom first: {cd_first}, for node: {node_name}"
         )
     log.info(
         f"Boot order set successfully: cdrom first: {cd_first}, for node: {node_name}"
     )
Пример #2
0
    def patch(
        self,
        secret: Optional[Secret] = None,
        **kwargs,
    ) -> None:
        body = {"spec": kwargs}
        body["spec"]["platform"] = {"agentBareMetal": {}}

        spec = body["spec"]
        body["spec"].update(self._platform_field)

        if secret:
            spec["pullSecretRef"] = secret.ref.as_dict()

        if "agent_cluster_install_ref" in kwargs:
            spec["clusterInstallRef"] = kwargs[
                "agent_cluster_install_ref"].as_dict()

        self.crd_api.patch_namespaced_custom_object(
            group=consts.HIVE_API_GROUP,
            version=consts.HIVE_API_VERSION,
            plural=self._plural,
            name=self.ref.name,
            namespace=self.ref.namespace,
            body=body,
        )

        log.info("patching cluster deployment %s: %s", self.ref, pformat(body))
Пример #3
0
    def iptables(
        self
    ) -> Callable[[Cluster, List[IptableRule], Optional[List[Node]]], None]:
        rules = []

        def set_iptables_rules_for_nodes(
            cluster: Cluster,
            iptables_rules: List[IptableRule],
            given_nodes=None,
        ):
            given_node_ips = []
            given_nodes = given_nodes or cluster.nodes.nodes

            if cluster.enable_image_download:
                cluster.generate_and_download_infra_env(
                    iso_download_path=cluster.iso_download_path)
            cluster.nodes.start_given(given_nodes)
            for node in given_nodes:
                given_node_ips.append(node.ips[0])
            cluster.nodes.shutdown_given(given_nodes)

            log.info(f"Given node ips: {given_node_ips}")

            for _rule in iptables_rules:
                _rule.add_sources(given_node_ips)
                rules.append(_rule)
                _rule.insert()

        yield set_iptables_rules_for_nodes
        log.info("---TEARDOWN iptables ---")
        for rule in rules:
            rule.delete()
Пример #4
0
def _are_operators_in_status(
    cluster_id: str,
    client: InventoryClient,
    operators: List[MonitoredOperator],
    operators_count: int,
    statuses: List[str],
    fall_on_error_status: bool,
) -> bool:
    log.info(
        "Asked operators to be in one of the statuses from %s and currently operators statuses are %s",
        statuses,
        [(operator.name, operator.status, operator.status_info)
         for operator in operators],
    )

    if fall_on_error_status:
        for operator in operators:
            if operator.status == consts.OperatorStatus.FAILED:
                _Exception = consts.olm_operators.get_exception_factory(
                    operator.name)  # noqa: N806
                raise _Exception(
                    f"Operator {operator.name} status is failed with info {operator.status_info}"
                )

    cluster = client.cluster_get(cluster_id=cluster_id).to_dict()
    log.info("Cluster %s progress info: %s", cluster_id, cluster["progress"])
    if len([operator for operator in operators if operator.status in statuses
            ]) >= operators_count:
        return True

    return False
Пример #5
0
    def wait_for_condition(
        self,
        cond_type: str,
        required_status: str,
        required_reason: Optional[str] = None,
        timeout: Union[int, float] = consts.DEFAULT_WAIT_FOR_CRD_STATE_TIMEOUT,
    ) -> None:
        def _has_required_condition() -> Optional[bool]:
            status, reason, message = self.condition(cond_type=cond_type,
                                                     timeout=0.5)
            log.info(
                f"waiting for condition <{cond_type}> to be in status <{required_status}>. "
                f"actual status is: {status} {reason} {message}")
            if status == required_status:
                if required_reason:
                    return required_reason == reason
                return True
            return False

        log.info(
            "Waiting till cluster will be in condition %s with status: %s "
            "reason: %s",
            cond_type,
            required_status,
            required_reason,
        )

        waiting.wait(
            _has_required_condition,
            timeout_seconds=timeout,
            waiting_for=
            f"cluster {self.ref} condition {cond_type} to be in {required_status}",
            sleep_seconds=10,
            expected_exceptions=waiting.exceptions.TimeoutExpired,
        )
Пример #6
0
def wait_till_at_least_one_host_is_in_stage(
    client,
    cluster_id,
    stages,
    nodes_count=1,
    timeout=consts.CLUSTER_INSTALLATION_TIMEOUT / 2,
    interval=consts.DEFAULT_CHECK_STATUSES_INTERVAL,
):
    log.info(f"Wait till {nodes_count} node is in stage {stages}")
    try:
        waiting.wait(
            lambda: utils.are_host_progress_in_stage(
                client.get_cluster_hosts(cluster_id),
                stages,
                nodes_count,
            ),
            timeout_seconds=timeout,
            sleep_seconds=interval,
            waiting_for=f"Node to be in of the stage {stages}",
        )
    except BaseException:
        hosts = client.get_cluster_hosts(cluster_id)
        log.error(
            f"All nodes stages: "
            f"{[host['progress']['current_stage'] for host in hosts]} "
            f"when waited for {stages}"
        )
        raise
Пример #7
0
    def create(
        self,
        pull_secret_file: str,
        agent_namespace: str,
        base_domain: str = consts.env_defaults.DEFAULT_BASE_DNS_DOMAIN,
        provider_image: str = "",
        hypershift_cpo_image: str = "",
        release_image: str = "",
        ssh_key: str = "",
    ):
        log.info(f"Creating HyperShift cluster {self.name}")
        cmd = (
            f"./bin/hypershift create cluster agent --pull-secret {pull_secret_file} --name {self.name}"
            f" --agent-namespace {agent_namespace} --base-domain {base_domain}"
        )
        if provider_image:
            log.info(f"Using provider image {provider_image}")
            cmd += f" --annotations hypershift.openshift.io/capi-provider-agent-image={provider_image}"
        if hypershift_cpo_image:
            log.info(
                f"Using hypershift control-plane-operator image {hypershift_cpo_image}"
            )
            cmd += f" --control-plane-operator-image={hypershift_cpo_image}"
        if release_image:
            log.info(f"Using release image {release_image}")
            cmd += f" --release-image={release_image}"

        if ssh_key:
            cmd += f" --ssh-key {ssh_key}"

        log.info(f"Create command is: {cmd}")
        utils.run_command_with_output(cmd, cwd=HYPERSHIFT_DIR)
    def shutdown_node(self, node_name: str) -> None:
        log.info(f"Powering off vm {node_name}")

        def shutdown(vm) -> task:
            return vm.PowerOff()

        self.__run_on_vm(node_name, shutdown)
Пример #9
0
    def approve_csrs(kubeconfig_path: str, done: threading.Event):
        log.info(
            "Started background worker to approve CSRs when they appear...")
        while not done.is_set():
            unapproved_csrs = []
            try:
                unapproved_csrs = get_unapproved_csr_names(kubeconfig_path)
            except subprocess.SubprocessError:
                log.debug(
                    "Failed to list csrs. This is usually due to API downtime. Retrying"
                )
            except Exception:
                # We're in a thread so it's a bit awkward to stop everything else...
                # Just continue after logging the unexpected exception
                log.exception("Unknown exception while listing csrs")

            for csr_name in unapproved_csrs:
                log.info(f"Found unapproved CSR {csr_name}, approving...")

                try:
                    approve_csr(kubeconfig_path, csr_name)
                except subprocess.SubprocessError:
                    log.warning(
                        "Failed attempt to approve CSR, this may be due to API downtime. Will retry later"
                    )
                except Exception:
                    # We're in a thread so it's a bit awkward to stop everything else...
                    # Just continue after logging the unexpected exception
                    log.exception(
                        f"Unknown exception while approving the {csr_name} CSR"
                    )

            time.sleep(10)
Пример #10
0
def _are_hosts_in_status(hosts,
                         nodes_count,
                         statuses,
                         status_info="",
                         fall_on_error_status=True):
    hosts_in_status = [
        host for host in hosts
        if (host["status"] in statuses
            and host["status_info"].startswith(status_info))
    ]
    if len(hosts_in_status) >= nodes_count:
        return True
    elif fall_on_error_status and len(
        [host
         for host in hosts if host["status"] == consts.NodesStatus.ERROR]) > 0:
        hosts_in_error = [(i, host["id"], host["requested_hostname"],
                           host["role"], host["status"], host["status_info"])
                          for i, host in enumerate(hosts, start=1)
                          if host["status"] == consts.NodesStatus.ERROR]
        log.error(
            "Some of the hosts are in insufficient or error status. Hosts in error %s",
            hosts_in_error)
        raise InstallationFailedError()

    log.info(
        "Asked hosts to be in one of the statuses from %s and currently hosts statuses are %s",
        statuses,
        host_statuses(hosts),
    )
    return False
Пример #11
0
def wait_till_all_hosts_are_in_status(
    client,
    cluster_id,
    nodes_count,
    statuses,
    status_info="",
    timeout=consts.CLUSTER_INSTALLATION_TIMEOUT,
    fall_on_error_status=True,
    interval=consts.DEFAULT_CHECK_STATUSES_INTERVAL,
):
    log.info("Wait till %s nodes are in one of the statuses %s", nodes_count,
             statuses)

    waiting.wait(
        lambda: _are_hosts_in_status(
            hosts=client.get_cluster_hosts(cluster_id),
            nodes_count=nodes_count,
            statuses=statuses,
            status_info=status_info,
            fall_on_error_status=fall_on_error_status,
        ),
        timeout_seconds=timeout,
        sleep_seconds=interval,
        waiting_for=f"Nodes to be in of the statuses {statuses}",
    )
Пример #12
0
    def set_workers_addresses_by_type(self, tfvars: Any, num_worker_nodes: int,
                                      master_ip_type: str, worker_ip_type: str,
                                      worker_mac_type: str):

        old_worker_ips_list = tfvars[worker_ip_type]
        last_master_addresses = tfvars[master_ip_type][-1]

        if last_master_addresses:
            if old_worker_ips_list:
                worker_starting_ip = ipaddress.ip_address(
                    old_worker_ips_list[-1][0])
            else:
                worker_starting_ip = ipaddress.ip_address(
                    last_master_addresses[0])

            worker_ips_list = old_worker_ips_list + utils.create_ip_address_nested_list(
                num_worker_nodes, worker_starting_ip + 1)
        else:
            log.info(
                "IPv6-only environment. IP addresses are left empty and will be allocated by libvirt "
                "DHCP because of a bug in Terraform plugin")
            worker_ips_list = old_worker_ips_list + utils.create_empty_nested_list(
                num_worker_nodes)

        tfvars[worker_ip_type] = worker_ips_list

        old_worker_mac_addresses = tfvars[worker_mac_type]
        tfvars[
            worker_mac_type] = old_worker_mac_addresses + static_network.generate_macs(
                num_worker_nodes)
 def _set_server_address(self, host_ip):
     host_name = socket.gethostname()
     host_ip = host_ip or socket.gethostbyname(host_name)
     proxy_user_path = f"{self.PROXY_USER}:{self.PROXY_USER_PASS}@" if self.authenticated else ""
     address = f"{proxy_user_path}{host_ip}"
     self.address = f"http://{f'[{address}]' if self._is_ipv6 else address}:{self.port}"
     log.info(f"Proxy server address {self.address}")
Пример #14
0
def get_openshift_version(allow_default=True, client=None) -> str:
    """
    Return the openshift version that needs to be handled
    according to the following process:

    1. In case env var OPENSHIFT_VERSION is defined - return it.
    2. In case env var OPENSHIFT_INSTALL_RELEASE_IMAGE is defined to override the release image -
    extract its OCP version.
    3. In case allow_default is enabled, return the default supported version by assisted-service.
        3.1 If a client is provided, request the versions from the service (supports remote service).
        3.2 Otherwise, Get from the JSON file in assisted-service repository.
    """

    version = get_env("OPENSHIFT_VERSION")
    if version:
        return version

    release_image = os.getenv("OPENSHIFT_INSTALL_RELEASE_IMAGE")

    if release_image:
        log.info(
            f"Using release image to get default openshift version, release_image={release_image}"
        )
        with pull_secret_file() as pull_secret:
            stdout, _, _ = run_command(
                f"oc adm release info '{release_image}' --registry-config '{pull_secret}' -o json |"
                f" jq -r '.metadata.version' | grep -oP '\\d\\.\\d+'",
                shell=True,
            )
        return stdout

    if allow_default:
        return get_default_openshift_version(client)

    return None
Пример #15
0
def wait_till_cluster_is_in_status(
    client,
    cluster_id,
    statuses: List[str],
    timeout=consts.NODES_REGISTERED_TIMEOUT,
    interval=30,
    break_statuses: List[str] = None,
):
    log.info("Wait till cluster %s is in status %s", cluster_id, statuses)
    try:
        if break_statuses:
            statuses += break_statuses
        waiting.wait(
            lambda: is_cluster_in_status(client=client, cluster_id=cluster_id, statuses=statuses),
            timeout_seconds=timeout,
            sleep_seconds=interval,
            waiting_for=f"Cluster to be in status {statuses}",
        )
        if break_statuses and is_cluster_in_status(client, cluster_id, break_statuses):
            raise BaseException(
                f"Stop installation process, " f"cluster is in status {client.cluster_get(cluster_id).status}"
            )
    except BaseException:
        log.error("Cluster status is: %s", client.cluster_get(cluster_id).status)
        raise
Пример #16
0
    def installer_gather(self, ip: str, ssh_key: Path, out_dir: str):
        stdout, stderr, _ret = utils.run_command(
            f"{INSTALLER_BINARY} gather bootstrap --log-level debug --bootstrap {ip} --master {ip} --key {str(ssh_key)}"
        )

        with open(INSTALLER_GATHER_DEBUG_STDOUT, "w") as f:
            f.write(stdout)

        with open(INSTALLER_GATHER_DEBUG_STDERR, "w") as f:
            f.write(stderr)

        matches = re.compile(r'.*logs captured here "(.*)".*').findall(stderr)

        if len(matches) == 0:
            log.warning(
                f"It seems like installer-gather didn't generate any bundles, stderr: {stderr}"
            )
            return

        bundle_file_path, *_ = matches

        log.info(f"Found installer-gather bundle at path {bundle_file_path}")

        utils.run_command_with_output(
            f"tar -xzf {bundle_file_path} -C {out_dir}")
        os.remove(bundle_file_path) if os.path.exists(
            bundle_file_path) else None
Пример #17
0
def verify_logs_uploaded(
    cluster_tar_path,
    expected_min_log_num,
    installation_success,
    verify_control_plane=False,
    check_oc=False,
    verify_bootstrap_errors=False,
):
    assert os.path.exists(
        cluster_tar_path), f"{cluster_tar_path} doesn't exist"

    with TemporaryDirectory() as tempdir:
        with tarfile.open(cluster_tar_path) as tar:
            log.info(f"downloaded logs: {tar.getnames()}")
            assert len(tar.getnames()) >= expected_min_log_num, (
                f"{tar.getnames()} "
                f"logs are less than minimum of {expected_min_log_num}")
            tar.extractall(tempdir)
            for gz in os.listdir(tempdir):
                if "bootstrap" in gz and verify_bootstrap_errors is True:
                    _verify_node_logs_uploaded(tempdir, gz)
                    _verify_bootstrap_logs_uploaded(tempdir, gz,
                                                    installation_success,
                                                    verify_control_plane)
                elif "master" in gz or "worker" in gz:
                    _verify_node_logs_uploaded(tempdir, gz)
                elif "controller" in gz:
                    if check_oc:
                        _verify_oc_logs_uploaded(os.path.join(tempdir, gz))
Пример #18
0
    def get(self) -> Munch:
        asset = self.BASE_ASSET.copy()
        self._verify_asset_fields(asset)

        with utils.file_lock_context(self._lock_file):
            assets_in_use = self._get_assets_in_use_from_assets_file()

            self._fill_allocated_ips_and_bridges_from_assets_file(
                assets_in_use)
            self._fill_allocated_ips_and_bridges_by_interface()
            self._fill_virsh_allocated_ips_and_bridges()

            self._override_ip_networks_values_if_not_free(asset)
            self._override_network_bridges_values_if_not_free(asset)

            self._taken_assets.add(str(asset))
            assets_in_use.append(asset)

            self._dump_all_assets_in_use_to_assets_file(assets_in_use)

        self._allocated_bridges.clear()
        self._allocated_ips_objects.clear()

        log.info("Taken asset: %s", asset)
        return Munch.fromDict(asset)
Пример #19
0
def wait_till_specific_host_is_in_stage(
    client,
    cluster_id: str,
    host_name: str,
    stages: List[str],
    nodes_count: int = 1,
    timeout: int = consts.CLUSTER_INSTALLATION_TIMEOUT / 2,
    interval: int = 5,
):
    log.info(f"Wait till {host_name} host is in stage {stages}")
    try:
        waiting.wait(
            lambda: utils.are_host_progress_in_stage(
                [client.get_host_by_name(cluster_id, host_name)],
                stages,
                nodes_count,
            ),
            timeout_seconds=timeout,
            sleep_seconds=interval,
            waiting_for=f"Node to be in of the stage {stages}",
        )
    except BaseException:
        hosts = [client.get_host_by_name(cluster_id, host_name)]
        log.error(
            f"All nodes stages: "
            f"{[host['progress']['current_stage'] for host in hosts]} "
            f"when waited for {stages}"
        )
        raise
Пример #20
0
def main():
    args = handle_arguments()

    if args.sosreport:
        gather_sosreport_data(output_dir=args.dest)

    client = ClientFactory.create_client(
        url=args.inventory_url, timeout=CONNECTION_TIMEOUT, offline_token=get_env("OFFLINE_TOKEN")
    )
    if args.cluster_id:
        cluster = client.cluster_get(args.cluster_id)
        download_cluster_logs(
            client,
            json.loads(json.dumps(cluster.to_dict(), sort_keys=True, default=str)),
            args.dest,
            args.must_gather,
            args.update_by_events,
            pull_secret=args.pull_secret,
        )
    else:
        clusters = get_clusters(client, args.download_all)

        if not clusters:
            log.info("No clusters were found")
            return

        for cluster in clusters:
            if args.download_all or should_download_logs(cluster):
                download_cluster_logs(
                    client, cluster, args.dest, args.must_gather, args.update_by_events, pull_secret=args.pull_secret
                )

        log.info("Cluster installation statuses: %s", dict(Counter(cluster["status"] for cluster in clusters).items()))
Пример #21
0
def is_update_needed(output_folder: str, update_on_events_update: bool,
                     client: InventoryClient, cluster: dict):
    if not os.path.isdir(output_folder):
        return True

    if not update_on_events_update:
        return False

    destination_event_file_path = get_cluster_events_path(
        cluster, output_folder)
    with tempfile.NamedTemporaryFile() as latest_event_tp:
        with SuppressAndLog(assisted_service_client.rest.ApiException):
            client.download_cluster_events(cluster["id"], latest_event_tp.name)

        if filecmp.cmp(destination_event_file_path, latest_event_tp.name):
            latest_event_tp.close()
            log.info(f"no new events found for {destination_event_file_path}")
            need_update = False
        else:
            log.info(
                f"update needed, new events found, deleting {destination_event_file_path}"
            )
            os.remove(destination_event_file_path)
            latest_event_tp.close()
            need_update = True
    return need_update
    def create(
        self,
        cluster_deployment_ref: ObjectReference,
        cluster_cidr: str,
        host_prefix: int,
        service_network: str,
        control_plane_agents: int,
        **kwargs,
    ) -> None:
        body = {
            "apiVersion": f"{self._api_group}/{self._api_version}",
            "kind": self._kind,
            "metadata": self.ref.as_dict(),
            "spec": self._get_spec_dict(
                cluster_deployment_ref=cluster_deployment_ref,
                cluster_cidr=cluster_cidr,
                host_prefix=host_prefix,
                service_network=service_network,
                control_plane_agents=control_plane_agents,
                **kwargs,
            ),
        }

        self.crd_api.create_namespaced_custom_object(
            group=self._api_group,
            version=self._api_version,
            plural=self._plural,
            body=body,
            namespace=self.ref.namespace,
        )

        log.info("created agentclusterinstall %s: %s", self.ref, pformat(body))
Пример #23
0
def wait_till_all_operators_are_in_status(
    client,
    cluster_id,
    operators_count,
    operator_types,
    statuses,
    timeout=consts.CLUSTER_INSTALLATION_TIMEOUT,
    fall_on_error_status=False,
    interval=10,
):
    log.info(
        f"Wait till {operators_count} {operator_types} operators are in one of the statuses {statuses}"
    )

    try:
        waiting.wait(
            lambda: _are_operators_in_status(
                cluster_id,
                client,
                filter_operators_by_type(
                    client.get_cluster_operators(cluster_id), operator_types),
                operators_count,
                statuses,
                fall_on_error_status,
            ),
            timeout_seconds=timeout,
            sleep_seconds=interval,
            waiting_for=
            f"Monitored {operator_types} operators to be in of the statuses {statuses}",
        )
    except BaseException:
        operators = client.get_cluster_operators(cluster_id)
        log.info("All operators: %s", operators)
        raise
Пример #24
0
def start_cluster_installation_rest_api(
        client,
        cluster,
        cluster_id,
        pull_secret,
        kubeconfig_path
):
    log.info("Verifying pull secret")
    verify_pull_secret(
        client=client,
        cluster=cluster,
        pull_secret=pull_secret,
    )
    log.info("Wait till cluster is ready")
    utils.wait_till_cluster_is_in_status(
        client=client,
        cluster_id=cluster_id,
        statuses=[consts.ClusterStatus.READY, consts.ClusterStatus.INSTALLING],
        break_statuses=[consts.ClusterStatus.ERROR],
    )
    cluster = client.cluster_get(cluster_id)
    if cluster.status == consts.ClusterStatus.READY:
        log.info("Install cluster %s", cluster_id)
        _install_cluster(client=client, cluster=cluster)

    else:
        log.info(
            "Cluster is already in installing status, skipping install command"
        )

    log.info("Download kubeconfig-noingress")
    client.download_kubeconfig_no_ingress(
        cluster_id=cluster_id,
        kubeconfig_path=kubeconfig_path,
    )
Пример #25
0
    def create(
        self,
        secret: Secret,
        base_domain: str = consts.env_defaults.DEFAULT_BASE_DNS_DOMAIN,
        agent_cluster_install_ref: Optional[ObjectReference] = None,
        **kwargs,
    ):
        body = {
            "apiVersion": f"{consts.HIVE_API_GROUP}/{consts.HIVE_API_VERSION}",
            "kind": "ClusterDeployment",
            "metadata": self.ref.as_dict(),
            "spec": {
                "clusterName": self.ref.name,
                "baseDomain": base_domain,
                "pullSecretRef": secret.ref.as_dict(),
            },
        }
        body["spec"].update(self._platform_field)

        if agent_cluster_install_ref:
            body["spec"][
                "clusterInstallRef"] = agent_cluster_install_ref.as_dict()

        body["spec"].update(kwargs)
        self.crd_api.create_namespaced_custom_object(
            group=consts.HIVE_API_GROUP,
            version=consts.HIVE_API_VERSION,
            plural=self._plural,
            body=body,
            namespace=self.ref.namespace,
        )

        log.info("created cluster deployment %s: %s", self.ref, pformat(body))
Пример #26
0
    def create(
        self,
        config: dict,
        interfaces: list,
        label: Optional[str] = None,
        **kwargs,
    ) -> None:
        body = {
            "apiVersion": f"{consts.CRD_API_GROUP}/{consts.CRD_API_VERSION}",
            "kind": "NMStateConfig",
            "metadata": {
                "labels": {
                    f"{consts.CRD_API_GROUP}/selector-nmstate-config-name":
                    label,
                },
                **self.ref.as_dict(),
            },
            "spec": {
                "config": config,
                "interfaces": interfaces,
            },
        }
        body["spec"].update(kwargs)
        self.crd_api.create_namespaced_custom_object(
            group=consts.CRD_API_GROUP,
            version=consts.CRD_API_VERSION,
            plural=self._plural,
            body=body,
            namespace=self.ref.namespace,
        )

        log.info("created nmstate config %s: %s", self.ref, pformat(body))
Пример #27
0
    def kube_api_test_prepare_late_binding_infraenv(
        self, kube_api_context: KubeAPIContext, nodes: Nodes, infraenv_config: InfraEnvConfig
    ):
        api_client = kube_api_context.api_client
        spoke_namespace = kube_api_context.spoke_namespace
        infraenv_name = infraenv_config.entity_name.get()
        infraenv_config.iso_download_path = utils.get_iso_download_path(infraenv_name)
        nodes.prepare_nodes()

        spoke_namespace = spoke_namespace
        secret = Secret(api_client, f"{infraenv_name}-secret", spoke_namespace)
        secret.create(pull_secret=infraenv_config.pull_secret)

        ignition_config_override = None

        infra_env = InfraEnv(api_client, f"{infraenv_name}-infra-env", spoke_namespace)
        infra_env.create(
            cluster_deployment=None,
            ignition_config_override=ignition_config_override,
            secret=secret,
            proxy=None,
            ssh_pub_key=infraenv_config.ssh_public_key,
        )

        agents = self.start_nodes(nodes, infra_env, infraenv_config, infraenv_config.is_static_ip)

        log.info("Waiting for agent status verification")
        Agent.wait_for_agents_to_be_ready_for_install(agents)

        return infra_env
Пример #28
0
    def patch(
        self,
        config: dict,
        interfaces: list,
        **kwargs,
    ) -> None:
        body = {"spec": kwargs}

        spec = body["spec"]
        if config:
            spec["config"] = config

        if interfaces:
            spec["interfaces"] = interfaces

        self.crd_api.patch_namespaced_custom_object(
            group=consts.CRD_API_GROUP,
            version=consts.CRD_API_VERSION,
            plural=self._plural,
            name=self.ref.name,
            namespace=self.ref.namespace,
            body=body,
        )

        log.info("patching nmstate config %s: %s", self.ref, pformat(body))
Пример #29
0
    def _set_host_name_from_node(cls, nodes: List[Node], agent: Agent, is_ipv4: bool) -> None:
        """
        Use the MAC address that is listed in the virt node object to find the interface entry
        in the host's inventory and take the host name from there
        The setting of the hostname is required for IPv6 only, because the nodes are booted with
        hostname equal to localhost which is neither unique not legal name for AI host
        """
        if is_ipv4:
            return

        def find_matching_node_and_return_name():
            inventory = agent.status().get("inventory", {})
            for node in nodes:
                for mac_address in node.macs:
                    for interface in inventory.get("interfaces", []):
                        if interface["macAddress"].lower() == mac_address.lower():
                            return node.name

        hostname = waiting.wait(
            find_matching_node_and_return_name,
            timeout_seconds=60,
            sleep_seconds=1,
            waiting_for=f"agent={agent.ref} to find a hostname",
        )
        log.info(f"patching agent {agent.ref} with hostname {hostname}")
        agent.patch(hostname=hostname)
    def _get_domain_ips_and_macs(
            domain: libvirt.virDomain) -> Tuple[List[str], List[str]]:
        interfaces_sources = [
            # getting all DHCP leases IPs
            libvirt.VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE,
            # getting static IPs via ARP
            libvirt.VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP,
        ]

        interfaces = {}
        for addresses_source in interfaces_sources:
            try:
                interfaces.update(
                    **domain.interfaceAddresses(addresses_source))
            except libvirt.libvirtError:
                log.exception(
                    "Got an error while updating domain's network addresses")

        ips = []
        macs = []
        log.debug(f"Host {domain.name()} interfaces are {interfaces}")
        if interfaces:
            for (_, val) in interfaces.items():
                if val["addrs"]:
                    for addr in val["addrs"]:
                        ips.append(addr["addr"])
                        macs.append(val["hwaddr"])
        if ips:
            log.info("Host %s ips are %s", domain.name(), ips)
        if macs:
            log.info("Host %s macs are %s", domain.name(), macs)
        return ips, macs