コード例 #1
0
 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)
コード例 #8
0
    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)
コード例 #13
0
 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
ファイル: utils.py プロジェクト: mhrivnak/assisted-test-infra
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
ファイル: assets.py プロジェクト: ybettan/assisted-test-infra
    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
コード例 #22
0
    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)
コード例 #30
0
    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