def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
    """Execute a KVM cmd, after completing it with some last minute data.

    @type instance: L{objects.Instance} object
    @param instance: the VM this command acts upon
    @type kvm_runtime: tuple of (list of str, list of L{objects.NIC} objects,
        dict of hypervisor options, list of tuples (L{objects.Disk}, str, str)
    @param kvm_runtime: (kvm command, NICs of the instance, options at startup
        of the instance, [(disk, link_name, uri)..])
    @type incoming: tuple of strings
    @param incoming: (target_host_ip, port) for migration.
    @type kvmhelp: string
    @param kvmhelp: output of kvm --help

    """
    # Small _ExecuteKVMRuntime hv parameters programming howto:
    #  - conf_hvp contains the parameters as configured on ganeti. they might
    #    have changed since the instance started; only use them if the change
    #    won't affect the inside of the instance (which hasn't been rebooted).
    #  - up_hvp contains the parameters as they were when the instance was
    #    started, plus any new parameter which has been added between ganeti
    #    versions: it is paramount that those default to a value which won't
    #    affect the inside of the instance as well.
    conf_hvp = instance.hvparams
    name = instance.name
    self._CheckDown(name)

    self._ClearUserShutdown(instance.name)
    self._StartKvmd(instance.hvparams)

    temp_files = []

    kvm_cmd, kvm_nics, up_hvp, kvm_disks = kvm_runtime
    # the first element of kvm_cmd is always the path to the kvm binary
    kvm_path = kvm_cmd[0]
    up_hvp = objects.FillDict(conf_hvp, up_hvp)

    # We know it's safe to run as a different user upon migration, so we'll use
    # the latest conf, from conf_hvp.
    security_model = conf_hvp[constants.HV_SECURITY_MODEL]
    if security_model == constants.HT_SM_USER:
      kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])

    keymap = conf_hvp[constants.HV_KEYMAP]
    if keymap:
      keymap_path = self._InstanceKeymapFile(name)
      # If a keymap file is specified, KVM won't use its internal defaults. By
      # first including the "en-us" layout, an error on loading the actual
      # layout (e.g. because it can't be found) won't lead to a non-functional
      # keyboard. A keyboard with incorrect keys is still better than none.
      utils.WriteFile(keymap_path, data="include en-us\ninclude %s\n" % keymap)
      kvm_cmd.extend(["-k", keymap_path])

    # We have reasons to believe changing something like the nic driver/type
    # upon migration won't exactly fly with the instance kernel, so for nic
    # related parameters we'll use up_hvp
    tapfds = []
    taps = []
    devlist = self._GetKVMOutput(kvm_path, self._KVMOPT_DEVICELIST)
    if not kvm_nics:
      kvm_cmd.extend(["-net", "none"])
    else:
      features, tap_extra, nic_extra = \
          self._GetNetworkDeviceFeatures(up_hvp, devlist, kvmhelp)
      nic_model = features["driver"]
      kvm_supports_netdev = self._NETDEV_RE.search(kvmhelp)
      for nic_seq, nic in enumerate(kvm_nics):
        tapname, nic_tapfds, nic_vhostfds = \
          OpenTap(features=features, name=self._GenerateKvmTapName(nic))

        tapfds.extend(nic_tapfds)
        tapfds.extend(nic_vhostfds)
        taps.append(tapname)
        tapfd = "%s%s" % ("fds=" if len(nic_tapfds) > 1 else "fd=",
                          ":".join(str(fd) for fd in nic_tapfds))

        if nic_vhostfds:
          vhostfd = "%s%s" % (",vhostfds="
                              if len(nic_vhostfds) > 1 else ",vhostfd=",
                              ":".join(str(fd) for fd in nic_vhostfds))
        else:
          vhostfd = ""

        if kvm_supports_netdev:
          # Non paravirtual NICs hvinfo is empty
          if "id" in nic.hvinfo:
            nic_val = _GenerateDeviceHVInfoStr(nic.hvinfo)
            netdev = nic.hvinfo["id"]
          else:
            nic_val = "%s" % nic_model
            netdev = "netdev%d" % nic_seq
          nic_val += (",netdev=%s,mac=%s%s" % (netdev, nic.mac, nic_extra))
          tap_val = ("type=tap,id=%s,%s%s%s" %
                     (netdev, tapfd, vhostfd, tap_extra))
          kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val])
        else:
          nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq,
                                                         nic.mac, nic_model)
          tap_val = "tap,vlan=%s,%s" % (nic_seq, tapfd)
          kvm_cmd.extend(["-net", tap_val, "-net", nic_val])

    if incoming:
      target, port = incoming
      kvm_cmd.extend(["-incoming", "tcp:%s:%s" % (target, port)])

    # Changing the vnc password doesn't bother the guest that much. At most it
    # will surprise people who connect to it. Whether positively or negatively
    # it's debatable.
    vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
    vnc_pwd = None
    if vnc_pwd_file:
      try:
        vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
      except EnvironmentError, err:
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
                                     % (vnc_pwd_file, err))

    if conf_hvp[constants.HV_KVM_USE_CHROOT]:
      utils.EnsureDirs([(self._InstanceChrootDir(name),
                         constants.SECURE_DIR_MODE)])

    # Automatically enable QMP if version is >= 0.14
    if self._QMP_RE.search(kvmhelp):
      logging.debug("Enabling QMP")
      kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
                      self._InstanceQmpMonitor(instance.name)])
      # Add a second monitor for kvmd
      kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
                      self._InstanceKvmdMonitor(instance.name)])

    # Configure the network now for starting instances and bridged/OVS
    # interfaces, during FinalizeMigration for incoming instances' routed
    # interfaces.
    for nic_seq, nic in enumerate(kvm_nics):
      if (incoming and
          nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_ROUTED):
        continue
      self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])

    bdev_opts = self._GenerateKVMBlockDevicesOptions(up_hvp,
                                                     kvm_disks,
                                                     kvmhelp,
                                                     devlist)
    kvm_cmd.extend(bdev_opts)
    # CPU affinity requires kvm to start paused, so we set this flag if the
    # instance is not already paused and if we are not going to accept a
    # migrating instance. In the latter case, pausing is not needed.
    start_kvm_paused = not (_KVM_START_PAUSED_FLAG in kvm_cmd) and not incoming
    if start_kvm_paused:
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])

    # Note: CPU pinning is using up_hvp since changes take effect
    # during instance startup anyway, and to avoid problems when soft
    # rebooting the instance.
    cpu_pinning = False
    if up_hvp.get(constants.HV_CPU_MASK, None):
      cpu_pinning = True

    if security_model == constants.HT_SM_POOL:
      ss = ssconf.SimpleStore()
      uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
      all_uids = set(uidpool.ExpandUidPool(uid_pool))
      uid = uidpool.RequestUnusedUid(all_uids)
      try:
        username = pwd.getpwuid(uid.GetUid()).pw_name
        kvm_cmd.extend(["-runas", username])
        self._RunKVMCmd(name, kvm_cmd, tapfds)
      except:
        uidpool.ReleaseUid(uid)
        raise
      else:
        uid.Unlock()
        utils.WriteFile(self._InstanceUidFile(name), data=uid.AsStr())
    else:
      self._RunKVMCmd(name, kvm_cmd, tapfds)

    utils.EnsureDirs([(self._InstanceNICDir(instance.name),
                     constants.RUN_DIRS_MODE)])
    for nic_seq, tap in enumerate(taps):
      utils.WriteFile(self._InstanceNICFile(instance.name, nic_seq),
                      data=tap)

    if vnc_pwd:
      change_cmd = "change vnc password %s" % vnc_pwd
      self._CallMonitorCommand(instance.name, change_cmd)

    # Setting SPICE password. We are not vulnerable to malicious passwordless
    # connection attempts because SPICE by default does not allow connections
    # if neither a password nor the "disable_ticketing" options are specified.
    # As soon as we send the password via QMP, that password is a valid ticket
    # for connection.
    spice_password_file = conf_hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]
    if spice_password_file:
      spice_pwd = ""
      try:
        spice_pwd = utils.ReadOneLineFile(spice_password_file, strict=True)
      except EnvironmentError, err:
        raise errors.HypervisorError("Failed to open SPICE password file %s: %s"
                                     % (spice_password_file, err))

      qmp = QmpConnection(self._InstanceQmpMonitor(instance.name))
      qmp.connect()
      arguments = {
          "protocol": "spice",
          "password": spice_pwd,
      }
      qmp.Execute("set_password", arguments)

    for filename in temp_files:
      utils.RemoveFile(filename)

    # If requested, set CPU affinity and resume instance execution
    if cpu_pinning:
      self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK],
                               up_hvp[constants.HV_WORKER_CPU_MASK])

    start_memory = self._InstanceStartupMemory(instance)
    if start_memory < instance.beparams[constants.BE_MAXMEM]:
      self.BalloonInstanceMemory(instance, start_memory)

    if start_kvm_paused:
      # To control CPU pinning, ballooning, and vnc/spice passwords
      # the VM was started in a frozen state. If freezing was not
      # explicitly requested resume the vm status.
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
dataset/ETHPy150Open ganeti/ganeti/lib/hypervisor/hv_kvm/__init__.py/KVMHypervisor._ExecuteKVMRuntime/original