WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] cpupools, xend: Add missing file XendCPUP

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] cpupools, xend: Add missing file XendCPUPool.py
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Sat, 24 Apr 2010 06:15:17 -0700
Delivery-date: Sat, 24 Apr 2010 06:16:05 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1272031466 -3600
# Node ID c87ec146229ab2255ecdf005b862b943b1a5112e
# Parent  ffcc927a19a43b347217a49706f035d8718b2707
cpupools, xend: Add missing file XendCPUPool.py

Signed-off-by: Juergen Gross <juergen.gross@xxxxxxxxxxxxxx>
---
 tools/python/xen/xend/XendCPUPool.py |  905 +++++++++++++++++++++++++++++++++++
 1 files changed, 905 insertions(+)

diff -r ffcc927a19a4 -r c87ec146229a tools/python/xen/xend/XendCPUPool.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/python/xen/xend/XendCPUPool.py      Fri Apr 23 15:04:26 2010 +0100
@@ -0,0 +1,905 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#============================================================================
+# Copyright (c) 2009 Fujitsu Technology Solutions.
+#============================================================================
+
+""" CPU Pool support including XEN-API and Legacy API.
+"""
+
+import types
+import threading
+import re
+import xen.lowlevel.xc
+import XendNode
+import XendDomain
+from xen.xend.XendLogging import log
+from xen.xend.XendBase import XendBase
+from xen.xend import XendAPIStore
+from xen.xend.XendConstants import XS_POOLROOT
+from xen.xend import uuid as genuuid
+from xen.xend.XendError import VmError, XendAPIError, PoolError
+from xen.xend.xenstore.xstransact import xstransact
+from xen.util.sxputils import sxp2map, map2sxp
+
+
+XEND_ERROR_INTERNAL             = 'INTERNAL_ERROR'
+XEND_ERROR_UNKOWN_SCHED_POLICY  = 'UNKOWN_SCHED_POLICY'
+XEND_ERROR_BAD_POOL_STATE       = 'POOL_BAD_STATE'
+XEND_ERROR_POOL_PARAM           = 'PARAMETER_ERROR'
+XEND_ERROR_INSUFFICIENT_CPUS    = 'INSUFFICIENT_CPUS'
+XEND_ERROR_POOL_RECONF          = 'POOL_RECONF'
+XEND_ERROR_INVALID_CPU          = 'INVAILD_CPU'
+XEND_ERROR_LAST_CPU_NOT_REM     = 'LAST_CPU_NOT_REMOVEABLE'
+
+
+XEN_SCHEDULER_TO_ID = {
+    'credit2': xen.lowlevel.xc.XEN_SCHEDULER_CREDIT2,
+    'credit' : xen.lowlevel.xc.XEN_SCHEDULER_CREDIT,
+    'sedf'   : xen.lowlevel.xc.XEN_SCHEDULER_SEDF,
+    }
+
+xc = xen.lowlevel.xc.xc()
+
+class XendCPUPool(XendBase):
+    """ CPU Pool management.
+        @ivar pool_lock: Lock to secure modification of pool data
+        @type pool_lock: Rlock
+    """
+
+    pool_lock = threading.RLock()
+
+    def getClass(cls):
+        return "cpu_pool"
+
+    def getAttrRO(cls):
+        attrRO = ['resident_on',
+                  'started_VMs',
+                  'host_CPUs',
+                  'activated',
+                 ]
+        return XendBase.getAttrRO() + attrRO
+
+    def getAttrRW(cls):
+        attrRW = ['name_label',
+                  'name_description',
+                  'auto_power_on',
+                  'ncpu',
+                  'sched_policy',
+                  'proposed_CPUs',
+                  'other_config',
+                 ]
+        return XendBase.getAttrRW() + attrRW
+
+    def getMethods(cls):
+        methods = ['destroy',
+                   'activate',
+                   'deactivate',
+                   'add_host_CPU_live',
+                   'remove_host_CPU_live',
+                   'add_to_proposed_CPUs',
+                   'remove_from_proposed_CPUs',
+                   'add_to_other_config',
+                   'remove_from_other_config',
+                  ]
+        return XendBase.getMethods() + methods
+
+    def getFuncs(cls):
+        funcs = ['create',
+                 'get_by_name_label',
+                ]
+        return XendBase.getFuncs() + funcs
+
+    getClass    = classmethod(getClass)
+    getAttrRO   = classmethod(getAttrRO)
+    getAttrRW   = classmethod(getAttrRW)
+    getMethods  = classmethod(getMethods)
+    getFuncs    = classmethod(getFuncs)
+
+
+    #
+    # XenAPI function calls
+    #
+
+    def create(cls, record):
+        """ Create a new managed pool instance.
+            @param record: attributes of pool
+            @type record:  dict
+            @return: uuid of created pool
+            @rtype:  str
+        """
+        new_uuid = genuuid.createString()
+        XendCPUPool(record, new_uuid)
+        XendNode.instance().save_cpu_pools()
+        return new_uuid
+
+    create = classmethod(create)
+
+
+    def get_by_name_label(cls, name_label):
+        """ Query a Pool(ref) by its name.
+            @return: ref of pool
+            @rtype:  str
+        """
+        cls.pool_lock.acquire()
+        try:
+            return [ inst.get_uuid()
+                     for inst in XendAPIStore.get_all(cls.getClass())
+                     if inst.name_label == name_label
+                   ]
+        finally:
+            cls.pool_lock.release()
+
+    get_by_name_label = classmethod(get_by_name_label)
+
+
+    def get_cpu_pool_by_cpu_ref(cls, host_cpu):
+        """ Query cpu_pool ref the given cpu belongs to.
+            @param host_cpu: ref of host_cpu to lookup
+            @type host_cpu:  str
+            @return: list cpu_pool refs (list contains not more than one 
element)
+            @rtype:  list of str
+        """
+        node = XendNode.instance()
+        cpu_nr = node.get_host_cpu_field(host_cpu, 'number')
+        for pool_rec in xc.cpupool_getinfo():
+            if cpu_nr in pool_rec['cpulist']:
+                # pool found; return the ref
+                return cls.query_pool_ref(pool_rec['cpupool'])
+        return []
+
+    get_cpu_pool_by_cpu_ref = classmethod(get_cpu_pool_by_cpu_ref)
+
+
+    def get_all_managed(cls):
+        """ Query all managed pools.
+            @return: uuids of all managed pools
+            @rtype:  list of str
+        """
+        cls.pool_lock.acquire()
+        try:
+            managed_pools = [ inst.get_uuid()
+                              for inst in XendAPIStore.get_all(cls.getClass())
+                              if inst.is_managed() ]
+        finally:
+            cls.pool_lock.release()
+        return managed_pools
+
+    get_all_managed = classmethod(get_all_managed)
+
+
+    #
+    # XenAPI methods calls
+    #
+
+    def __init__(self, record, new_uuid, managed_pool=True):
+        XendBase.__init__(self, new_uuid, record)
+        try:
+            self._managed = managed_pool
+            self.name_label = None
+
+            name = record.get('name_label', 'Pool-Unnamed')
+            self._checkName(name)
+            self.name_label = name
+            self.name_description = record.get('name_description',
+                                               self.name_label)
+            self.proposed_cpus = [ int(cpu)
+                                   for cpu in record.get('proposed_CPUs', []) ]
+            self.auto_power_on = bool(record.get('auto_power_on', False))
+            self.ncpu = int(record.get('ncpu', 1))
+            self.sched_policy = record.get('sched_policy', '')
+            self.other_config = record.get('other_config', {})
+        except Exception, ex:
+            XendBase.destroy(self)
+            raise ex
+
+
+    def get_resident_on(self):
+        """ Always return uuid of own node.
+            @return: uuid of this node
+            @rytpe:  str
+        """
+        return XendNode.instance().uuid
+
+    def get_started_VMs(self):
+        """ Query all VMs currently assigned to pool.
+            @return: ref of all VMs assigned to pool; if pool is not active,
+                     an empty list will be returned
+            @rtype:  list of str
+        """
+        if self.get_activated():
+            # search VMs related to this pool
+            pool_id = self.query_pool_id()
+            started_VMs = [ vm.get_uuid()
+                            for vm in XendDomain.instance().list('all')
+                            if vm.get_cpu_pool() == pool_id ]
+        else:
+            # pool not active, so it couldn't have any started VMs
+            started_VMs = []
+
+        return started_VMs
+
+    def get_host_CPUs(self):
+        """ Query all cpu refs of this pool currently asisgned .
+            - Read pool id of this pool from xenstore
+            - Read cpu configuration from hypervisor
+            - lookup cpu number -> cpu ref
+            @return: host_cpu refs
+            @rtype:  list of str
+        """
+        if self.get_activated():
+            node = XendNode.instance()
+            pool_id = self.query_pool_id()
+            if pool_id == None:
+                raise PoolError(XEND_ERROR_INTERNAL,
+                                [self.getClass(), 'get_host_CPUs'])
+            cpus = []
+            for pool_rec in xc.cpupool_getinfo():
+                if pool_rec['cpupool'] == pool_id:
+                    cpus = pool_rec['cpulist']
+
+            # query host_cpu ref for any cpu of the pool
+            host_CPUs = [ cpu_ref
+                          for cpu_ref in node.get_host_cpu_refs()
+                          if node.get_host_cpu_field(cpu_ref, 'number')
+                              in cpus ]
+        else:
+            # pool not active, so it couldn't have any assigned cpus
+            host_CPUs = []
+
+        return host_CPUs
+
+    def get_activated(self):
+        """ Query if the pool is registered in XendStore.
+            If pool uuid is not in XenStore, the pool is not activated.
+            @return: True, if activated
+            @rtype:  bool
+        """
+        return self.query_pool_id() != None
+
+    def get_name_label(self):
+        return self.name_label
+
+    def get_name_description(self):
+        return self.name_description
+
+    def get_auto_power_on(self):
+        return self.auto_power_on
+
+    def get_ncpu(self):
+        return self.ncpu
+
+    def get_sched_policy(self):
+        if len(self.sched_policy) == 0:
+            # default scheduler selected
+            return XendNode.instance().get_vcpus_policy()
+        else:
+            return self.sched_policy
+
+    def get_proposed_CPUs(self):
+        return [ str(cpu) for cpu in self.proposed_cpus ]
+
+    def get_other_config(self):
+        return self.other_config
+
+    def set_name_label(self, name_label):
+        self._checkName(name_label)
+        self.name_label = name_label
+        if self._managed:
+            XendNode.instance().save_cpu_pools()
+
+    def set_name_description(self, name_descr):
+        self.name_description = name_descr
+        if self._managed:
+            XendNode.instance().save_cpu_pools()
+
+    def set_auto_power_on(self, auto_power_on):
+        self.auto_power_on = bool(int(auto_power_on))
+        if self._managed:
+            XendNode.instance().save_cpu_pools()
+
+    def set_ncpu(self, ncpu):
+        _ncpu = int(ncpu)
+        if _ncpu < 1:
+            raise PoolError(XEND_ERROR_POOL_PARAM, 'ncpu')
+        self.ncpu = _ncpu
+        if self._managed:
+            XendNode.instance().save_cpu_pools()
+
+    def set_sched_policy(self, sched_policy):
+        if self.get_activated():
+            raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'activated')
+        self.sched_policy = sched_policy
+        if self._managed:
+            XendNode.instance().save_cpu_pools()
+
+    def set_proposed_CPUs(self, proposed_cpus):
+        if self.get_activated():
+            raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'activated')
+        self.proposed_cpus = [ int(cpu) for cpu in proposed_cpus ]
+        if self._managed:
+            XendNode.instance().save_cpu_pools()
+
+    def set_other_config(self, other_config):
+        self.other_config = other_config
+        if self._managed:
+            XendNode.instance().save_cpu_pools()
+
+    def destroy(self):
+        """ In order to destroy a cpu pool, it must be deactivated """
+        self.pool_lock.acquire()
+        try:
+            if self.get_activated():
+                raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'activated')
+            XendBase.destroy(self)
+        finally:
+            self.pool_lock.release()
+        XendNode.instance().save_cpu_pools()
+
+    def activate(self):
+        """ Create pool in hypervisor and add cpus.
+            Preconditions:
+            - pool not already active
+            - enough unbound cpus available
+            Actions:
+            - create pool in hypervisor
+            - select free cpus (preferred from proposed_CPUs list) and bind it 
to
+              the pool
+            - create entries in Xenstore
+        """
+        self.pool_lock.acquire()
+        try:
+            if self.get_activated():
+                raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'activated')
+            sched_policy = self.get_sched_policy()
+            if sched_policy not in XEN_SCHEDULER_TO_ID.keys():
+                raise PoolError(XEND_ERROR_UNKOWN_SCHED_POLICY)
+            unbound_cpus = set(self.unbound_cpus())
+            if len(unbound_cpus) < self.ncpu:
+                raise PoolError(XEND_ERROR_INSUFFICIENT_CPUS,
+                                [str(self.ncpu), str(len(unbound_cpus))])
+
+            # build list of cpu numbers to bind to pool
+            cpu_set = set(self.proposed_cpus).intersection(unbound_cpus)
+            if len(cpu_set) < self.ncpu:
+                pool_cpus = (list(cpu_set) +
+                             list(unbound_cpus.difference(cpu_set)))
+            else:
+                pool_cpus = list(cpu_set)
+            pool_cpus = pool_cpus[0:self.ncpu]
+
+            # create pool in hypervisor
+            pool_id = xc.cpupool_create(
+                sched = XEN_SCHEDULER_TO_ID.get(sched_policy, 0))
+
+            self.update_XS(pool_id)
+            # add cpus
+            for cpu in pool_cpus:
+                xc.cpupool_addcpu(pool_id, cpu)
+
+        finally:
+            self.pool_lock.release()
+
+    def deactivate(self):
+        """ Delete pool in hypervisor
+            Preconditions:
+            - pool is activated
+            - no running VMs in pool
+            Actions:
+            - call hypervisor for deletion
+            - remove path of pool in xenstore
+        """
+        self.pool_lock.acquire()
+        try:
+            if not self.get_activated():
+                raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'deactivated')
+            if len(self.get_started_VMs()) != 0:
+                raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'in use')
+
+            pool_id = self.query_pool_id()
+            # remove cpus from pool
+            cpus = []
+            for pool_rec in xc.cpupool_getinfo():
+                if pool_rec['cpupool'] == pool_id:
+                    cpus = pool_rec['cpulist']
+            for cpu_number in cpus:
+                xc.cpupool_removecpu(pool_id, cpu_number)
+            xc.cpupool_destroy(pool_id)
+
+            # update XenStore
+            xs_path = XS_POOLROOT + "%s/" % pool_id
+            xstransact.Remove(xs_path)
+        finally:
+            self.pool_lock.release()
+
+    def add_host_CPU_live(self, cpu_ref):
+        """ Add cpu to pool, if it is currently not assigned to a pool.
+            @param cpu_ref: reference of host_cpu instance to add
+            @type  cpu_ref: str
+        """
+        if not self.get_activated():
+            raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'deactivated')
+        node = XendNode.instance()
+        number = node.get_host_cpu_field(cpu_ref, 'number')
+
+        self.pool_lock.acquire()
+        try:
+            pool_id = self.query_pool_id()
+            other_pool_ref = self.get_cpu_pool_by_cpu_ref(cpu_ref)
+            if len(other_pool_ref) != 0:
+                raise PoolError(XEND_ERROR_INVALID_CPU,
+                            'cpu already assigned to pool "%s"' % 
other_pool_ref[0])
+            xc.cpupool_addcpu(pool_id, number)
+        finally:
+            self.pool_lock.release()
+
+        if number not in self.proposed_cpus:
+            self.proposed_cpus.append(number)
+        self._update_ncpu(pool_id)
+        if self._managed:
+            XendNode.instance().save_cpu_pools()
+
+    def remove_host_CPU_live(self, cpu_ref):
+        """ Remove cpu from pool.
+            After successfull call, the cpu is free.
+            Remove of the last cpu of the pool is rejected.
+            @param cpu_ref: reference of host_cpu instance to remove
+            @type  cpu_ref: str
+        """
+        if not self.get_activated():
+            raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'deactivated')
+        node = XendNode.instance()
+        number = node.get_host_cpu_field(cpu_ref, 'number')
+
+        self.pool_lock.acquire()
+        try:
+            pool_id = self.query_pool_id()
+            pool_rec = {}
+            for pool in xc.cpupool_getinfo():
+                if pool['cpupool'] == pool_id:
+                    pool_rec = pool
+                    break
+
+            if number in pool_rec['cpulist']:
+                if len(pool_rec['cpulist']) < 2 and pool_rec['n_dom'] > 0:
+                    raise PoolError(XEND_ERROR_LAST_CPU_NOT_REM,
+                                    'could not remove last cpu')
+                xc.cpupool_removecpu(pool_id, number)
+            else:
+                raise PoolError(XEND_ERROR_INVALID_CPU,
+                                'CPU not assigned to pool')
+        finally:
+            self.pool_lock.release()
+
+        if number in self.proposed_cpus:
+            self.proposed_cpus.remove(number)
+        self._update_ncpu(pool_id)
+        if self._managed:
+            XendNode.instance().save_cpu_pools()
+
+    def add_to_proposed_CPUs(self, cpu):
+        if self.get_activated():
+            raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'activated')
+
+        _cpu = int(cpu)
+        if _cpu not in self.proposed_cpus:
+            self.proposed_cpus.append(_cpu)
+            self.proposed_cpus.sort()
+            if self._managed:
+                XendNode.instance().save_cpu_pools()
+
+    def remove_from_proposed_CPUs(self, cpu):
+        if self.get_activated():
+            raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'activated')
+        _cpu = int(cpu)
+        if _cpu in self.proposed_cpus:
+            self.proposed_cpus.remove(_cpu)
+            if self._managed:
+                XendNode.instance().save_cpu_pools()
+
+    def add_to_other_config(self, key, value):
+        self.other_config[key] = value
+        if self._managed:
+            XendNode.instance().save_cpu_pools()
+
+    def remove_from_other_config(self, key):
+        if key in self.other_config:
+            del self.other_config[key]
+        if self._managed:
+            XendNode.instance().save_cpu_pools()
+
+
+    #
+    # Legacy RPC calls
+    #
+    def pool_new(cls, config):
+        try:
+            record = sxp2map(config)
+            if record.has_key('proposed_CPUs') and \
+               not isinstance(record['proposed_CPUs'], types.ListType):
+                record['proposed_CPUs'] = [record['proposed_CPUs']]
+            new_uuid = cls.create(record)
+        except XendAPIError, ex:
+            raise VmError(ex.get_api_error())
+        return new_uuid
+
+    def pool_create(cls, config):
+        try:
+            record = sxp2map(config)
+            if record.has_key('proposed_CPUs') and \
+               not isinstance(record['proposed_CPUs'], types.ListType):
+                record['proposed_CPUs'] = [record['proposed_CPUs']]
+            new_uuid = genuuid.createString()
+            pool = XendCPUPool(record, new_uuid, False)
+            pool.activate()
+        except XendAPIError, ex:
+            raise VmError(ex.get_api_error())
+
+    def pool_start(cls, poolname):
+        pool = cls.lookup_pool(poolname)
+        if not pool:
+            raise VmError('unknown pool %s' % poolname)
+        try:
+            pool.activate()
+        except XendAPIError, ex:
+            raise VmError(ex.get_api_error())
+
+    def pool_list(cls, names):
+        sxprs = []
+        try:
+            node = XendNode.instance()
+            xd = XendDomain.instance()
+            pools = cls.get_all_records()
+            for (pool_uuid, pool_vals) in pools.items():
+                if pool_vals['name_label'] in names or len(names) == 0:
+                    # conv host_cpu refs to cpu number
+                    cpus = [ node.get_host_cpu_field(cpu_ref, 'number')
+                             for cpu_ref in pool_vals['host_CPUs'] ]
+                    cpus.sort()
+                    pool_vals['host_CPU_numbers'] = cpus
+                    # query VMs names. Take in account, that a VM
+                    # returned by get_all_records could be destroy, now
+                    vm_names = [ vm.getName()
+                                 for vm in map(xd.get_vm_by_uuid,
+                                               pool_vals['started_VMs'])
+                                 if vm ]
+                    pool_vals['started_VM_names'] = vm_names
+                    pool_vals['auto_power_on'] = 
int(pool_vals['auto_power_on'])
+                    sxprs += [[pool_uuid] + map2sxp(pool_vals)]
+        except XendAPIError, ex:
+            raise VmError(ex.get_api_error())
+        return sxprs
+
+    def pool_destroy(cls, poolname):
+        pool = cls.lookup_pool(poolname)
+        if not pool:
+            raise VmError('unknown pool %s' % poolname)
+        try:
+            pool.deactivate()
+            if not pool.is_managed():
+                pool.destroy()
+        except XendAPIError, ex:
+            raise VmError(ex.get_api_error())
+
+    def pool_delete(cls, poolname):
+        pool = cls.lookup_pool(poolname)
+        if not pool:
+            raise VmError('unknown pool %s' % poolname)
+        try:
+            pool.destroy()
+        except XendAPIError, ex:
+            raise VmError(ex.get_api_error())
+
+    def pool_cpu_add(cls, poolname, cpu):
+        pool = cls.lookup_pool(poolname)
+        if not pool:
+            raise VmError('unknown pool %s' % poolname)
+        try:
+            cpu_ref = cls._cpu_number_to_ref(int(cpu))
+            if cpu_ref:
+                pool.add_host_CPU_live(cpu_ref)
+            else:
+                raise PoolError(XEND_ERROR_INVALID_CPU,
+                                'CPU unknown')
+        except XendAPIError, ex:
+            raise VmError(ex.get_api_error())
+
+    def pool_cpu_remove(cls, poolname, cpu):
+        pool = cls.lookup_pool(poolname)
+        if not pool:
+            raise VmError('unknown pool %s' % poolname)
+        try:
+            cpu_ref = cls._cpu_number_to_ref(int(cpu))
+            if cpu_ref:
+                pool.remove_host_CPU_live(cpu_ref)
+            else:
+                raise PoolError(XEND_ERROR_INVALID_CPU,
+                                'CPU unknown')
+        except XendAPIError, ex:
+            raise VmError(ex.get_api_error())
+
+    def pool_migrate(cls, domname, poolname):
+        dom = XendDomain.instance()
+        pool = cls.lookup_pool(poolname)
+        if not pool:
+            raise VmError('unknown pool %s' % poolname)
+        dominfo = dom.domain_lookup_nr(domname)
+        if not dominfo:
+            raise VmError('unknown domain %s' % domname)
+        domid = dominfo.getDomid()
+        if domid is not None:
+            if domid == 0:
+                raise VmError('could not move Domain-0')
+            try:
+                cls.move_domain(pool.get_uuid(), domid)
+            except Exception, ex:
+                raise VmError('could not move domain')
+        dominfo.info['pool_name'] = poolname
+        dom.managed_config_save(dominfo)
+
+    pool_new        = classmethod(pool_new)
+    pool_create     = classmethod(pool_create)
+    pool_start      = classmethod(pool_start)
+    pool_list       = classmethod(pool_list)
+    pool_destroy    = classmethod(pool_destroy)
+    pool_delete     = classmethod(pool_delete)
+    pool_cpu_add    = classmethod(pool_cpu_add)
+    pool_cpu_remove = classmethod(pool_cpu_remove)
+    pool_migrate    = classmethod(pool_migrate)
+
+
+    #
+    # methods
+    #
+
+    def is_managed(self):
+        """ Check, if pool is managed.
+            @return: True, if managed
+            @rtype: bool
+        """
+        return self._managed
+
+    def query_pool_id(self):
+        """ Get corresponding pool-id of pool instance from XenStore.
+            @return: pool id or None
+            @rytpe:  int
+        """
+        self.pool_lock.acquire()
+        try:
+            for pool_id in xstransact.List(XS_POOLROOT):
+                uuid = xstransact.Read(XS_POOLROOT + "%s/" % pool_id, 'uuid')
+                if uuid == self.get_uuid():
+                    return int(pool_id)
+        finally:
+            self.pool_lock.release()
+
+        return None
+
+    def update_XS(self, pool_id):
+        """ Write (or update) data in xenstore taken from instance.
+            @param pool_id: Pool id to build path to pool data in xenstore
+            @type  pool_id: int
+        """
+        self.pool_lock.acquire()
+        try:
+            xs_path = XS_POOLROOT + "%s/" % pool_id
+            xs_entries = { 'uuid' : self.get_uuid(),
+                           'name' : self.name_label,
+                           'description' : self.name_description
+                         }
+            xstransact.Mkdir(xs_path)
+            xstransact.Mkdir(xs_path, 'other_config')
+            xstransact.Write(xs_path, xs_entries)
+            xstransact.Write('%s%s' % (xs_path, 'other_config'),
+                             self.other_config)
+        finally:
+            self.pool_lock.release()
+
+    def _update_ncpu(self, pool_id):
+        for pool_rec in xc.cpupool_getinfo():
+            if pool_rec['cpupool'] == pool_id:
+                self.ncpu = len(pool_rec['cpulist'])
+
+    def _checkName(self, name):
+        """ Check if a pool name is valid. Valid names contain alphabetic
+            characters, digits, or characters in '_-.:/+'.
+            The same name cannot be used for more than one pool at the same
+            time.
+            @param name: name
+            @type name:  str
+            @raise: PoolError if invalid
+        """
+        if name is None or name == '':
+            raise PoolError(XEND_ERROR_POOL_PARAM, 'Missing Pool Name')
+        if not re.search(r'^[A-Za-z0-9_\-\.\:\/\+]+$', name):
+            raise PoolError(XEND_ERROR_POOL_PARAM, 'Invalid Pool Name')
+
+        pool = self.lookup_pool(name)
+        if pool and pool.get_uuid() != self.get_uuid():
+            raise PoolError(XEND_ERROR_POOL_PARAM,
+                'Pool name "%s" already exists' % name)
+
+
+    #
+    # class methods
+    #
+
+    def recreate_active_pools(cls):
+        """ Read active pool config from hypervisor and create pool instances.
+            - Query pool ids and assigned CPUs from hypervisor.
+            - Query additional information for any pool from xenstore.
+              If an entry for a pool id is missing in xenstore, it will be
+              recreated with a new uuid and generic name (this is an error 
case)
+            - Create an XendCPUPool instance for any pool id
+            Function have to be called after recreation of managed pools.
+        """
+        log.debug('recreate_active_pools')
+
+        for pool_rec in xc.cpupool_getinfo():
+            pool = pool_rec['cpupool']
+
+            # read pool data from xenstore
+            path = XS_POOLROOT + "%s/" % pool
+            uuid = xstransact.Read(path, 'uuid')
+            if not uuid:
+                # xenstore entry missing / invaild; create entry with new uuid
+                uuid = genuuid.createString()
+                name = "Pool-%s" % pool
+                try:
+                    inst = XendCPUPool( { 'name_label' : name }, uuid, False )
+                    inst.update_XS(pool)
+                except PoolError, ex:
+                    # log error and skip domain
+                    log.error('cannot recreate pool %s; skipping (reason: %s)' 
\
+                        % (name, ex))
+            else:
+                (name, descr) = xstransact.Read(path, 'name', 'description')
+                other_config = {}
+                for key in xstransact.List(path + 'other_config'):
+                    other_config[key] = xstransact.Read(
+                        path + 'other_config/%s' % key)
+
+                # check existance of pool instance
+                inst = XendAPIStore.get(uuid, cls.getClass())
+                if inst:
+                    # update attributes of existing instance
+                    inst.name_label = name
+                    inst.name_description = descr
+                    inst.other_config = other_config
+                else:
+                    # recreate instance
+                    try:
+                        inst = XendCPUPool(
+                            { 'name_label' : name,
+                              'name_description' : descr,
+                              'other_config' : other_config,
+                              'proposed_CPUs' : pool_rec['cpulist'],
+                              'ncpu' : len(pool_rec['cpulist']),
+                            },
+                            uuid, False )
+                    except PoolError, ex:
+                        # log error and skip domain
+                        log.error(
+                            'cannot recreate pool %s; skipping (reason: %s)' \
+                            % (name, ex))
+
+    recreate_active_pools = classmethod(recreate_active_pools)
+
+
+    def recreate(cls, record, current_uuid):
+        """ Recreate a pool instance while xend restart.
+            @param record: attributes of pool
+            @type record:  dict
+            @param current_uuid: uuid of pool to create
+            @type current_uuid:  str
+        """
+        XendCPUPool(record, current_uuid)
+
+    recreate = classmethod(recreate)
+
+
+    def autostart_pools(cls):
+        """ Start managed pools that are marked as autostart pools.
+            Function is called after recreation of managed domains while
+            xend restart.
+        """
+        cls.pool_lock.acquire()
+        try:
+            for inst in XendAPIStore.get_all(cls.getClass()):
+                if inst.is_managed() and inst.auto_power_on and \
+                   inst.query_pool_id() == None:
+                    inst.activate()
+        finally:
+            cls.pool_lock.release()
+
+    autostart_pools = classmethod(autostart_pools)
+
+
+    def move_domain(cls, pool_ref, domid):
+        cls.pool_lock.acquire()
+        try:
+            pool = XendAPIStore.get(pool_ref, cls.getClass())
+            pool_id = pool.query_pool_id()
+
+            xc.cpupool_movedomain(pool_id, domid)
+        finally:
+            cls.pool_lock.release()
+
+    move_domain = classmethod(move_domain)
+
+
+    def query_pool_ref(cls, pool_id):
+        """ Get pool ref by pool id.
+            Take the ref from xenstore.
+            @param pool_id:
+            @type  pool_id: int
+            @return: ref
+            @rtype:  str
+        """
+        uuid = xstransact.Read(XS_POOLROOT + "%s/" % pool_id, 'uuid')
+        if uuid:
+            return [uuid]
+        else:
+            return []
+
+    query_pool_ref = classmethod(query_pool_ref)
+
+
+    def lookup_pool(cls, id_or_name):
+        """ Search XendCPUPool instance with given id_or_name.
+            @param id_or_name: pool id or pool nameto search
+            @type id_or_name:  [int, str]
+            @return: instane or None if not found
+            @rtype:  XendCPUPool
+        """
+        pool_uuid = None
+        try:
+            pool_id = int(id_or_name)
+            # pool id given ?
+            pool_uuid = cls.query_pool_ref(pool_id)
+            if not pool_uuid:
+                # not found -> search name
+                pool_uuid = cls.get_by_name_label(id_or_name)
+        except ValueError:
+            # pool name given
+            pool_uuid = cls.get_by_name_label(id_or_name)
+
+        if len(pool_uuid) > 0:
+            return XendAPIStore.get(pool_uuid[0], cls.getClass())
+        else:
+            return None
+
+    lookup_pool = classmethod(lookup_pool)
+
+
+    def _cpu_number_to_ref(cls, number):
+        node = XendNode.instance()
+        for cpu_ref in node.get_host_cpu_refs():
+            if node.get_host_cpu_field(cpu_ref, 'number') == number:
+                return cpu_ref
+        return None
+
+    _cpu_number_to_ref = classmethod(_cpu_number_to_ref)
+
+
+    def unbound_cpus(cls):
+        """ Build list containing the numbers of all cpus not bound to a pool.
+            Info is taken from Hypervisor.
+            @return: list of cpu numbers
+            @rytpe:  list of int
+        """
+        return xc.cpupool_freeinfo()
+
+    unbound_cpus = classmethod(unbound_cpus)
+

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] cpupools, xend: Add missing file XendCPUPool.py, Xen patchbot-unstable <=