Example #1
0
  def test_match_node_metadata_to_vcenter_one_node_added_by_ip(self):
    vsphere = VsphereVcenter(vcenter_host="fake_vcenter",
                             vcenter_user="******",
                             vcenter_password="******")

    cluster_metadata = proto_patch_encryption_support(CurieSettings.Cluster)()
    cluster_metadata.cluster_name = "Fake Cluster"
    cluster_metadata.cluster_hypervisor_info.esx_info.SetInParent()
    for index in range(3):  # Add first 3 nodes by hostname to curie metadata
      curr_node = cluster_metadata.cluster_nodes.add()
      curr_node.id = "fake_host_%d" % index
    curr_node = cluster_metadata.cluster_nodes.add()
    curr_node.id = '10.60.5.63'  # Add last node by ip
    vcenter_info = cluster_metadata.cluster_management_server_info.vcenter_info
    vcenter_info.vcenter_host = "fake_vmm_server_address"
    vcenter_info.vcenter_user = "******"
    vcenter_info.vcenter_password = "******"
    vcenter_info.vcenter_datacenter_name = "fake_datacenter"
    vcenter_info.vcenter_cluster_name = "fake_cluster"
    vcenter_info.vcenter_datastore_name = "fake_share_name"
    vcenter_info.vcenter_network_name = "fake_network"
    self.assertEqual(4, len(cluster_metadata.cluster_nodes))

    vsphere.match_node_metadata_to_vcenter(self.m_vim_cluster, cluster_metadata)

    self.assertEqual(4, len(cluster_metadata.cluster_nodes))
    for index, cluster_node in enumerate(cluster_metadata.cluster_nodes):
      self.assertEqual("fake_host_%d" % index, cluster_node.id)
Example #2
0
  def test_fill_cluster_metadata_do_not_include_reporting_fields(self):
    vsphere = VsphereVcenter(vcenter_host="fake_vcenter",
                             vcenter_user="******",
                             vcenter_password="******")

    cluster_metadata = proto_patch_encryption_support(CurieSettings.Cluster)()
    cluster_metadata.cluster_name = "Fake Cluster"
    cluster_metadata.cluster_hypervisor_info.esx_info.SetInParent()
    for index in range(4):
      curr_node = cluster_metadata.cluster_nodes.add()
      curr_node.id = "fake_host_%d" % index
    vcenter_info = cluster_metadata.cluster_management_server_info.vcenter_info
    vcenter_info.vcenter_host = "fake_vmm_server_address"
    vcenter_info.vcenter_user = "******"
    vcenter_info.vcenter_password = "******"
    vcenter_info.vcenter_datacenter_name = "fake_datacenter"
    vcenter_info.vcenter_cluster_name = "fake_cluster"
    vcenter_info.vcenter_datastore_name = "fake_share_name"
    vcenter_info.vcenter_network_name = "fake_network"

    for index, cluster_node in enumerate(cluster_metadata.cluster_nodes):
      self.assertEqual("fake_host_%d" % index, cluster_node.id)
      self.assertEqual(False, cluster_node.HasField("node_hardware"))

    vsphere.fill_cluster_metadata(self.m_vim_cluster, cluster_metadata, False)

    for index, cluster_node in enumerate(cluster_metadata.cluster_nodes):
      self.assertEqual("fake_host_%d" % index, cluster_node.id)
      self.assertEqual(False, cluster_node.HasField("node_hardware"))
Example #3
0
 def test_match_node_metadata_to_vcenter_node_does_not_match(self):
   vsphere = VsphereVcenter(vcenter_host="fake_vcenter",
                            vcenter_user="******",
                            vcenter_password="******")
   self.m_vim_cluster.name = "Fake Cluster"
   cluster_metadata = proto_patch_encryption_support(CurieSettings.Cluster)()
   cluster_metadata.cluster_name = "Fake Cluster"
   cluster_metadata.cluster_hypervisor_info.esx_info.SetInParent()
   for index in range(3):  # Add first 3 nodes by hostname
     curr_node = cluster_metadata.cluster_nodes.add()
     curr_node.id = "fake_host_%d" % index
   curr_node = cluster_metadata.cluster_nodes.add()
   curr_node.id = '10.60.5.222'  # Add last node by ip
   vcenter_info = cluster_metadata.cluster_management_server_info.vcenter_info
   vcenter_info.vcenter_host = "fake_vmm_server_address"
   vcenter_info.vcenter_user = "******"
   vcenter_info.vcenter_password = "******"
   vcenter_info.vcenter_datacenter_name = "fake_datacenter"
   vcenter_info.vcenter_cluster_name = "fake_cluster"
   vcenter_info.vcenter_datastore_name = "fake_share_name"
   vcenter_info.vcenter_network_name = "fake_network"
   self.assertEqual(4, len(cluster_metadata.cluster_nodes))
   with self.assertRaises(CurieTestException) as ar:
     vsphere.match_node_metadata_to_vcenter(self.m_vim_cluster, cluster_metadata)
   self.assertEqual(4, len(cluster_metadata.cluster_nodes))
   self.assertEqual("Node with ID '10.60.5.222' is in the Curie cluster metadata, but not "
                    "found in vSphere cluster 'Fake Cluster'.",
                    str(ar.exception.cause))
Example #4
0
 def test_match_node_metadata_to_vcenter_multiple_node_matches(self):
   vsphere = VsphereVcenter(vcenter_host="fake_vcenter",
                            vcenter_user="******",
                            vcenter_password="******")
   self.m_vim_cluster.name = "Fake Cluster"
   cluster_metadata = proto_patch_encryption_support(CurieSettings.Cluster)()
   cluster_metadata.cluster_name = "Fake Cluster"
   cluster_metadata.cluster_hypervisor_info.esx_info.SetInParent()
   for index in range(3):  # Add first 3 nodes by hostname
     curr_node = cluster_metadata.cluster_nodes.add()
     curr_node.id = "fake_host_%d" % index
   curr_node = cluster_metadata.cluster_nodes.add()
   curr_node.id = '10.60.5.61'  # Add last node by ip
   self.m_vim_cluster.host[0].config.network.vnic[0].spec.ip.ipAddress = '10.60.5.61' # Add repeated address
   vcenter_info = cluster_metadata.cluster_management_server_info.vcenter_info
   vcenter_info.vcenter_host = "fake_vmm_server_address"
   vcenter_info.vcenter_user = "******"
   vcenter_info.vcenter_password = "******"
   vcenter_info.vcenter_datacenter_name = "fake_datacenter"
   vcenter_info.vcenter_cluster_name = "fake_cluster"
   vcenter_info.vcenter_datastore_name = "fake_share_name"
   vcenter_info.vcenter_network_name = "fake_network"
   self.assertEqual(4, len(cluster_metadata.cluster_nodes))
   with self.assertRaises(CurieTestException) as ar:
     vsphere.match_node_metadata_to_vcenter(self.m_vim_cluster, cluster_metadata)
   self.assertEqual(4, len(cluster_metadata.cluster_nodes))
   self.assertEqual("More than one node in the vSphere cluster "
                    "'Fake Cluster' matches node ID '10.60.5.61'. The "
                    "matching nodes are: fake_host_0, fake_host_1.",
                    str(ar.exception.cause))
Example #5
0
 def test_lookup_datastore_does_not_exist(self, m_SmartConnectNoSSL):
   vsphere = VsphereVcenter(vcenter_host="fake_vcenter",
                            vcenter_user="******",
                            vcenter_password="******")
   with vsphere:
     datastore = vsphere.lookup_datastore(self.m_vim_cluster,
                                          "this_is_a_non_existent_datastore")
   self.assertIsNone(datastore)
Example #6
0
 def test_lookup_datastore_mounted_on_all_hosts(self, m_SmartConnectNoSSL):
   vsphere = VsphereVcenter(vcenter_host="fake_vcenter",
                            vcenter_user="******",
                            vcenter_password="******")
   with vsphere:
     datastore = vsphere.lookup_datastore(self.m_vim_cluster,
                                          "fake_datastore")
   self.assertIsInstance(datastore, vim.Datastore)
   self.assertEqual(datastore.name, "fake_datastore")
Example #7
0
 def test_lookup_datastore_host_not_found(self, m_SmartConnectNoSSL):
   vsphere = VsphereVcenter(vcenter_host="fake_vcenter",
                            vcenter_user="******",
                            vcenter_password="******")
   with vsphere:
     with self.assertRaises(CurieTestException) as ar:
       vsphere.lookup_datastore(self.m_vim_cluster,
                                "fake_datastore",
                                "this_is_a_non_existent_host")
   self.assertEqual("Host 'this_is_a_non_existent_host' not found",
                    str(ar.exception))
Example #8
0
 def test_lookup_datastore_not_on_all_hosts(self, m_SmartConnectNoSSL):
   m_some_other_datastore = mock.Mock(spec=vim.Datastore)
   m_some_other_datastore.name = "some_other_datastore"
   self.m_vim_cluster.host[0].datastore = [m_some_other_datastore]
   vsphere = VsphereVcenter(vcenter_host="fake_vcenter",
                            vcenter_user="******",
                            vcenter_password="******")
   with vsphere:
     datastore = vsphere.lookup_datastore(self.m_vim_cluster,
                                          "fake_datastore")
   self.assertIsNone(datastore)
Example #9
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)
Example #10
0
 def __vim_vm_to_curie_vm(self, vim_vm):
     "Returns an object of the appropriate subclass of Vm for 'vim_vm'."
     # On a vSphere cluster, the VM name should be unique on the cluster where
     # the VM resides, so we can just use the VM name as the VM ID.
     vm_id = vim_vm.name
     curie_guest_os_type_value = None
     vim_vm_config = get_optional_vim_attr(vim_vm, "config")
     if vim_vm_config is not None:
         for config_option in vim_vm_config.extraConfig:
             if config_option.key == CURIE_GUEST_OS_TYPE_KEY:
                 curie_guest_os_type_value = config_option.value
                 break
     vm_ip = VsphereVcenter.get_vim_vm_ip_address(vim_vm)
     vim_host = get_optional_vim_attr(vim_vm.runtime, "host")
     if vim_host is not None:
         node_id = vim_host.name
     else:
         node_id = None
     vm_params = VmParams(self, vm_id)
     vm_params.vm_name = vim_vm.name
     vm_params.vm_ip = vm_ip
     vm_params.node_id = node_id
     if curie_guest_os_type_value is None:
         # We use the generic VsphereVm class for all VMs that don't have the
         # curie guest OS type option since non-curie VMs won't have the proper
         # configuration to enable, for example, remote file transfers to/from the
         # VM and remote execution of commands in the VM.
         vm_params.is_cvm = self.__vim_vm_is_nutanix_cvm(vim_vm)
         return VsphereVm(vm_params)
     else:
         CHECK_EQ(curie_guest_os_type_value, "unix")
         return VsphereUnixVm(vm_params)
Example #11
0
 def test_find_datastore_paths_flat(self, m_WaitForTask,
                                      m_SmartConnectNoSSL):
   m_datastore = mock.Mock(spec=vim.Datastore)
   m_task = mock.Mock()
   m_search_result = mock.Mock()
   m_search_result.folderPath = "[rtptest1]"
   m_task.info.result = m_search_result
   m_fileinfo_1 = mock.Mock()
   m_fileinfo_1.path = "__curie_goldimage_1416468224265211271_ubuntu1604_DSS"
   m_fileinfo_2 = mock.Mock()
   m_fileinfo_2.path = "__curie_goldimage_1416468224265211271_ubuntu1604_OLTP"
   m_search_result.file = [m_fileinfo_1, m_fileinfo_2]
   m_datastore.browser.Search.return_value = m_task
   vsphere = VsphereVcenter(vcenter_host="fake_vcenter",
                            vcenter_user="******",
                            vcenter_password="******")
   with vsphere:
     paths = vsphere.find_datastore_paths("__curie_goldimage*", m_datastore)
   self.assertEqual([
     "[rtptest1]__curie_goldimage_1416468224265211271_ubuntu1604_DSS",
     "[rtptest1]__curie_goldimage_1416468224265211271_ubuntu1604_OLTP"],
     paths)
Example #12
0
    def is_ready(self):
        """See 'NodeUtil.is_ready' documentation for further details.

    Confirms node is ready by requesting node's health info from Vsphere
    corresponding to the node.

    Raises:
      CurieTestException: If the VsanNodeUtil's node is not found (passed
                           through from __get_vim_host).
    """
        with VsphereVcenter(
                self.__vcenter_info.vcenter_host,
                self.__vcenter_info.decrypt_field("vcenter_user"),
                self.__vcenter_info.decrypt_field(
                    "vcenter_password")) as vcenter:
            vim_host = self.__get_vim_host(vcenter)
            return self.__vim_host_is_ready(vim_host)
Example #13
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)
Example #14
0
    def update_metadata(self, include_reporting_fields):
        with self._open_vcenter_connection() as vcenter:
            vim_cluster = self._lookup_vim_cluster(vcenter)
            vcenter.fill_cluster_metadata(vim_cluster, self._metadata,
                                          include_reporting_fields)
            vcenter.match_node_metadata_to_vcenter(vim_cluster, self._metadata)

            if (self._metadata.cluster_software_info.HasField("vsan_info")
                    or self._metadata.cluster_software_info.HasField(
                        "generic_info")):

                # TODO (jklein): Clean-up/properly abstract out these checks.
                mgmt_info = self._metadata.cluster_management_server_info
                if mgmt_info.HasField("vcenter_info"):
                    ds_name = mgmt_info.vcenter_info.vcenter_datastore_name
                else:
                    raise CurieTestException("Invalid metadata")
                vim_ds = vcenter.lookup_datastore(vim_cluster, ds_name)
                if vim_ds.summary.type == "vsan":
                    if self._metadata.cluster_software_info.HasField(
                            "generic_info"):
                        self._metadata.cluster_software_info.ClearField(
                            "generic_info")
                        self._metadata.cluster_software_info.vsan_info.SetInParent(
                        )
                else:
                    if self._metadata.cluster_software_info.HasField(
                            "vsan_info"):
                        raise CurieTestException(
                            "Target is not configured for VSAN")

            if include_reporting_fields:
                version_pairs = VsphereVcenter.get_esx_versions(
                    vim_cluster, self._metadata.cluster_nodes)

                esx_versions = [pair[0] for pair in version_pairs]
                esx_builds = [pair[1] for pair in version_pairs]
                self._metadata.cluster_hypervisor_info.esx_info.version.extend(
                    esx_versions)
                self._metadata.cluster_hypervisor_info.esx_info.build.extend(
                    esx_builds)
                cluster_software_info = self._metadata.cluster_software_info
                if cluster_software_info.HasField("nutanix_info"):
                    client = NutanixRestApiClient.from_proto(
                        cluster_software_info.nutanix_info)
                    nutanix_metadata = client.get_nutanix_metadata()
                    if nutanix_metadata.version is not None:
                        cluster_software_info.nutanix_info.version = \
                            nutanix_metadata.version
                    if nutanix_metadata.cluster_uuid is not None:
                        cluster_software_info.nutanix_info.cluster_uuid = \
                            nutanix_metadata.cluster_uuid
                    if nutanix_metadata.cluster_incarnation_id is not None:
                        cluster_software_info.nutanix_info.cluster_incarnation_id = \
                            nutanix_metadata.cluster_incarnation_id
                elif cluster_software_info.HasField("vsan_info"):
                    pass
                elif cluster_software_info.HasField("generic_info"):
                    pass
                else:
                    raise CurieException(
                        CurieError.kInternalError,
                        "Unsupported software on vSphere cluster, %s" %
                        self._metadata)
        self._node_id_metadata_map = dict([
            (node.id, node) for node in self._metadata.cluster_nodes
        ])
Example #15
0
 def _open_vcenter_connection(self):
     return VsphereVcenter(
         self._vcenter_info.vcenter_host,
         self._vcenter_info.decrypt_field("vcenter_user"),
         self._vcenter_info.decrypt_field("vcenter_password"))
Example #16
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
Example #17
0
 def __vim_vm_is_nutanix_cvm(self, vim_vm):
     "Returns True if the VM 'vim_vm' corresponds to a Nutanix CVM."
     if not self._metadata.cluster_software_info.HasField("nutanix_info"):
         return False
     return VsphereVcenter.vim_vm_is_nutanix_cvm(vim_vm)