Exemplo n.º 1
0
  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)
Exemplo n.º 2
0
  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)
Exemplo n.º 3
0
  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