Merge branch 'stable-2.11' into stable-2.12
[ganeti-github.git] / lib / hypervisor / hv_kvm / __init__.py
index 0f33d8d..2f22720 100644 (file)
@@ -2,21 +2,30 @@
 #
 
 # Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Google Inc.
+# All rights reserved.
 #
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
 #
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
 #
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 """KVM hypervisor
@@ -35,9 +44,9 @@ import shutil
 import urllib2
 from bitarray import bitarray
 try:
-  import affinity   # pylint: disable=F0401
+  import psutil   # pylint: disable=F0401
 except ImportError:
-  affinity = None
+  psutil = None
 try:
   import fdsend   # pylint: disable=F0401
 except ImportError:
@@ -710,31 +719,6 @@ class KVMHypervisor(hv_base.BaseHypervisor):
     """
     hv_base.ConfigureNIC([pathutils.KVM_IFUP, tap], instance, seq, nic, tap)
 
-  @staticmethod
-  def _VerifyAffinityPackage():
-    if affinity is None:
-      raise errors.HypervisorError("affinity Python package not"
-                                   " found; cannot use CPU pinning under KVM")
-
-  @staticmethod
-  def _BuildAffinityCpuMask(cpu_list):
-    """Create a CPU mask suitable for sched_setaffinity from a list of
-    CPUs.
-
-    See man taskset for more info on sched_setaffinity masks.
-    For example: [ 0, 2, 5, 6 ] will return 101 (0x65, 0..01100101).
-
-    @type cpu_list: list of int
-    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
-    @rtype: int
-    @return: a bit mask of CPU affinities
-
-    """
-    if cpu_list == constants.CPU_PINNING_OFF:
-      return constants.CPU_PINNING_ALL_KVM
-    else:
-      return sum(2 ** cpu for cpu in cpu_list)
-
   @classmethod
   def _SetProcessAffinity(cls, process_id, cpus):
     """Sets the affinity of a process to the given CPUs.
@@ -744,9 +728,15 @@ class KVMHypervisor(hv_base.BaseHypervisor):
     @param cpus: The list of CPUs the process ID may use.
 
     """
-    cls._VerifyAffinityPackage()
-    affinity.set_process_affinity_mask(process_id,
-                                       cls._BuildAffinityCpuMask(cpus))
+    if psutil is None:
+      raise errors.HypervisorError("psutil Python package not"
+                                   " found; cannot use CPU pinning under KVM")
+
+    target_process = psutil.Process(process_id)
+    if cpus == constants.CPU_PINNING_OFF:
+      target_process.set_cpu_affinity(range(psutil.cpu_count()))
+    else:
+      target_process.set_cpu_affinity(cpus)
 
   @classmethod
   def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
@@ -1661,11 +1651,12 @@ class KVMHypervisor(hv_base.BaseHypervisor):
       kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
                       self._InstanceKvmdMonitor(instance.name)])
 
-    # Configure the network now for starting instances and bridged interfaces,
-    # during FinalizeMigration for incoming instances' routed interfaces
+    # 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_BRIDGED):
+          nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_ROUTED):
         continue
       self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
 
@@ -1846,12 +1837,13 @@ class KVMHypervisor(hv_base.BaseHypervisor):
       hvp = instance.hvparams
       security_model = hvp[constants.HV_SECURITY_MODEL]
       use_chroot = hvp[constants.HV_KVM_USE_CHROOT]
-      if use_chroot:
-        raise errors.HotplugError("Disk hotplug is not supported"
-                                  " in case of chroot.")
-      if security_model != constants.HT_SM_NONE:
-        raise errors.HotplugError("Disk Hotplug is not supported in case"
-                                  " security models are used.")
+      if action == constants.HOTPLUG_ACTION_ADD:
+        if use_chroot:
+          raise errors.HotplugError("Disk hotplug is not supported"
+                                    " in case of chroot.")
+        if security_model != constants.HT_SM_NONE:
+          raise errors.HotplugError("Disk Hotplug is not supported in case"
+                                    " security models are used.")
 
     if (dev_type == constants.HOTPLUG_TARGET_NIC and
         action == constants.HOTPLUG_ACTION_ADD and not fdsend):
@@ -2184,8 +2176,8 @@ class KVMHypervisor(hv_base.BaseHypervisor):
       kvm_nics = kvm_runtime[1]
 
       for nic_seq, nic in enumerate(kvm_nics):
-        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
-          # Bridged interfaces have already been configured
+        if nic.nicparams[constants.NIC_MODE] != constants.NIC_MODE_ROUTED:
+          # Bridged/OVS interfaces have already been configured
           continue
         try:
           tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))