def discover_nodes_vcenter(arg, ret): """ See 'DiscoveryUtil.handle_nodes_discovery_v2' for info. """ conn_params = arg.mgmt_server.conn_params with VsphereVcenter.from_proto(conn_params) as vcenter: vim_dc = vcenter.lookup_datacenter(arg.cluster_collection.name) for target_cluster in arg.cluster_collection.cluster_vec: vim_cluster = vcenter.lookup_cluster(vim_dc, target_cluster.name) node_coll = ret.node_collection_vec.add() node_coll.cluster_id = vim_cluster.name for vim_node in vim_cluster.host: node = node_coll.node_vec.add() # According to pyVim documentation, the hostname is guaranteed to be # the IP or DNS name for the host. node.id = vim_node.name node.name = vim_node.name node.hypervisor.type = node.hypervisor.kEsx node.hypervisor.version = vcenter.get_esx_versions_for_vim_host( vim_node)[0] # Have already validated that either both fields are set or not. if (arg.oob_info.conn_params.username and arg.oob_info.type != OobInterfaceType.kNone): node.oob_info.CopyFrom(arg.oob_info) node.oob_info.conn_params.address, node.oob_info.vendor = \ DiscoveryUtil.lookup_node_bmc_info(vim_node)
def _update_cluster_version_info_vcenter(cluster_pb): """ See 'DiscoveryUtil.update_cluster_version_info' for info. """ mgmt_info = cluster_pb.cluster_management_server_info.vcenter_info hyp_info = cluster_pb.cluster_hypervisor_info.esx_info with VsphereVcenter.from_proto(mgmt_info) as vcenter: vim_dc = vcenter.lookup_datacenter(mgmt_info.vcenter_datacenter_name) vim_cluster = vcenter.lookup_cluster(vim_dc, mgmt_info.vcenter_cluster_name) if vim_cluster is None: raise CurieException(CurieError.kInvalidParameter, "Cluster not found in specified vCenter") esx_version_pairs = vcenter.get_esx_versions(vim_cluster) hyp_info.version.extend(pair[0] for pair in esx_version_pairs) hyp_info.build.extend(pair[1] for pair in esx_version_pairs) mgmt_info.vcenter_version, mgmt_info.vcenter_build = \ vcenter.get_vcenter_version_info() if cluster_pb.cluster_software_info.HasField("nutanix_info"): cvms = [vim_vm for vim_vm in vcenter.lookup_vms(vim_cluster) if vcenter.vim_vm_is_nutanix_cvm(vim_vm)] if not cvms: raise CurieException( CurieError.kInvalidParameter, "Unable to locate any CVMs on cluster. Is this a Nutanix cluster?") for cvm in cvms: ip = get_optional_vim_attr(cvm.guest, "ipAddress") if ip and CurieUtil.is_ipv4_address(ip): break else: raise CurieException( CurieError.kInvalidParameter, "Unable to locate any CVMs with IPv4 addresses on cluster") software_info = cluster_pb.cluster_software_info.nutanix_info cli = NutanixRestApiClient( ip, software_info.decrypt_field("prism_user"), software_info.decrypt_field("prism_password")) DiscoveryUtil._update_cluster_version_info_nos(cli, cluster_pb)
def update_cluster_virtual_ip(cluster_pb): """ Updates 'prism_host' to correspond to the cluster virtual IP. The 'prism_host' field is set for management and clustering software as appropriate for the target hypervisor. Returns: True if 'prism_host' was updated, else False. Raises: CurieException<kInvalidParameter>: 'cluster_pb' is a Nutanix cluster but does not have a Virtual IP. """ if not cluster_pb.cluster_software_info.HasField("nutanix_info"): return False prism_proto = None ntnx_proto = cluster_pb.cluster_software_info.nutanix_info prism_user = ntnx_proto.decrypt_field("prism_user") prism_password = ntnx_proto.decrypt_field("prism_password") c_uuid = ntnx_proto.cluster_uuid if cluster_pb.cluster_management_server_info.HasField("prism_info"): prism_proto = cluster_pb.cluster_management_server_info.prism_info client = NutanixRestApiClient.from_proto(prism_proto, timeout_secs=10) cluster_json = client.clusters_get(cluster_id=c_uuid) else: cvm_addresses = [] if cluster_pb.cluster_management_server_info.HasField("vmm_info"): vmm_info = cluster_pb.cluster_management_server_info.vmm_info vmm_client = VmmClient(address=vmm_info.vmm_server, username=vmm_info.vmm_user, password=vmm_info.vmm_password) with vmm_client: vms = vmm_client.get_vms(cluster_name=vmm_info.vmm_cluster_name) for vm in vms: if VmmClient.is_nutanix_cvm(vm): if VmmClient.is_powered_on(vm): log.debug("Found CVM '%s' with IPs: %s", vm["name"], vm["ips"]) cvm_addresses.extend(vm["ips"]) else: log.debug("Skipping CVM '%s' because it is not powered on.", vm["name"]) else: node_ids = [node.id for node in cluster_pb.cluster_nodes] # NB: We currently have an asymmetrical input for Prism credentials # depending on whether they're considered as management software or # clustering software. In the latter case, which is when 'nutanix_info' # is set but not 'prism_info', the user is not asked for a Prism host. # In this case, we discover CVMs via vCenter, attempt to connect to Prism # on each in sequence until successful, and then query the virtual IP. mgmt_info = cluster_pb.cluster_management_server_info.vcenter_info with VsphereVcenter.from_proto(mgmt_info) as vcenter: vim_dc = vcenter.lookup_datacenter(mgmt_info.vcenter_datacenter_name) vim_cluster = vcenter.lookup_cluster(vim_dc, mgmt_info.vcenter_cluster_name) for vim_cvm in (vm for vm in vcenter.lookup_vms(vim_cluster) if vcenter.vim_vm_is_nutanix_cvm(vm)): vim_host = get_optional_vim_attr(vim_cvm.runtime, "host") if vim_host: if vim_host.name in node_ids: cvm_address = vcenter.get_vim_vm_ip_address(vim_cvm) if cvm_address: log.debug("Found CVM '%s' with address '%s'" % (vim_cvm.name, cvm_address)) cvm_addresses.append(cvm_address) else: log.debug("Skipping CVM '%s'; Host '%s' is not in the " "metadata" % (vim_cvm.name, vim_host.name)) # We run Nutanix API only against powered on CVMs. if not cvm_addresses: raise CurieTestException( cause="No Nutanix CVMs found.", impact="The cluster virtual IP address can not be discovered.", corrective_action="Please verify that the cluster contains Nutanix " "CVMs, and that they are powered on.", ) for cvm_address in cvm_addresses: client = NutanixRestApiClient(cvm_address, prism_user, prism_password) try: cluster_json = client.clusters_get(cluster_id=c_uuid, max_retries=3) except BaseException: log.warning("Unable to query CVM with IP '%s'", cvm_address, exc_info=True) else: break else: raise CurieTestException( cause="Failed to query Prism on any Nutanix CVM.", impact="The cluster virtual IP address can not be discovered.", corrective_action="Please verify that the Nutanix CVMs on the " "cluster are powered on, and that the network " "connectivity to the CVMs is correct.", ) if "clusterExternalIPAddress" in cluster_json: cluster_name = cluster_json.get("name") cluster_vip = cluster_json["clusterExternalIPAddress"] elif "entities" in cluster_json: cluster_data = cluster_json["entities"][0] cluster_name = cluster_data.get("name") cluster_vip = cluster_data["clusterExternalIPAddress"] else: raise CurieException( CurieError.kInvalidParameter, "Unrecognized response from NutanixRestApiClient.clusters_get") if not cluster_vip: raise CurieException( CurieError.kInvalidParameter, "Cluster '%s' does not appear to be configured with a virtual IP " "(received '%s')" % (cluster_name, cluster_vip)) else: log.debug("Identified Nutanix cluster virtual IP address: '%s'", cluster_vip) ntnx_proto.prism_host = cluster_vip if prism_proto: prism_proto.prism_host = cluster_vip return True