[dts] [PATCH v2 04/19] Add a module to manage the host resource

Jiajia, Sun sunx.jiajia at intel.com
Fri May 22 11:03:57 CEST 2015


From: sjiajiax <sunx.jiajia at intel.com>

Added module: framework/virt_resource.py

Signed-off-by: sjiajiax <sunx.jiajia at intel.com>
---
 framework/virt_resource.py | 490 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 490 insertions(+)
 create mode 100644 framework/virt_resource.py

diff --git a/framework/virt_resource.py b/framework/virt_resource.py
new file mode 100644
index 0000000..ce60751
--- /dev/null
+++ b/framework/virt_resource.py
@@ -0,0 +1,490 @@
+#!/usr/bin/python
+# BSD LICENSE
+#
+# Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#   * Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+#   * 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.
+#   * Neither the name of Intel Corporation nor the names of its
+#     contributors may be used to endorse or promote products derived
+#     from this software without specific prior written permission.
+#
+# 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
+# OWNER 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.
+from random import randint
+
+from utils import get_obj_funcs
+
+INIT_FREE_PORT = 6060
+
+
+class VirtResource(object):
+
+    """
+    Class handle dut resource, like cpu, memory, net devices
+    """
+
+    def __init__(self, dut):
+        self.dut = dut
+
+        self.cores = [int(core['thread']) for core in dut.cores]
+        # initialized unused cores
+        self.unused_cores = self.cores[:]
+        # initialized used cores
+        self.used_cores = [-1] * len(self.unused_cores)
+
+        self.ports_info = dut.ports_info
+        # initialized unused ports
+        self.ports = [port['pci'] for port in dut.ports_info]
+        self.unused_ports = self.ports[:]
+        # initialized used ports
+        self.used_ports = ['unused'] * len(self.unused_ports)
+
+        # initialized vf ports
+        self.vfs_info = []
+        self.vfs = []
+        self.unused_vfs = []
+        self.used_vfs = []
+
+        # save allocated cores and related vm
+        self.allocated_info = {}
+
+    def __port_used(self, pci):
+        index = self.ports.index(pci)
+        self.used_ports[index] = pci
+        self.unused_ports[index] = 'used'
+
+    def __port_unused(self, pci):
+        index = self.ports.index(pci)
+        self.unused_ports[index] = pci
+        self.used_ports[index] = 'unused'
+
+    def __port_on_socket(self, pci, socket):
+        for port in self.ports_info:
+            if port['pci'] == pci:
+                if socket is -1:
+                    return True
+
+                if port['numa'] == socket:
+                    return True
+                else:
+                    return False
+
+        return False
+
+    def __vf_used(self, pci):
+        index = self.vfs.index(pci)
+        self.used_vfs[index] = pci
+        self.unused_vfs[index] = 'used'
+
+    def __vf_unused(self, pci):
+        index = self.vfs.index(pci)
+        self.used_vfs[index] = 'unused'
+        self.unused_vfs[index] = pci
+
+    def __core_used(self, core):
+        core = int(core)
+        index = self.cores.index(core)
+        self.used_cores[index] = core
+        self.unused_cores[index] = -1
+
+    def __core_unused(self, core):
+        core = int(core)
+        index = self.cores.index(core)
+        self.unused_cores[index] = core
+        self.used_cores[index] = -1
+
+    def __core_on_socket(self, core, socket):
+        for dut_core in self.dut.cores:
+            if int(dut_core['thread']) == core:
+                if socket is -1:
+                    return True
+
+                if int(dut_core['socket']) == socket:
+                    return True
+                else:
+                    return False
+
+        return False
+
+    def __core_isused(self, core):
+        index = self.cores.index(core)
+        if self.used_cores[index] != -1:
+            return True
+        else:
+            return False
+
+    def reserve_cpu(self, coremask=''):
+        """
+        Reserve dpdk used cpus by mask
+        """
+        val = int(coremask, base=16)
+        cpus = []
+        index = 0
+        while val != 0:
+            if val & 0x1:
+                cpus.append(index)
+
+            val = val >> 1
+            index += 1
+
+        for cpu in cpus:
+            self.__core_used(cpu)
+
+    def alloc_cpu(self, vm='', number=-1, socket=-1, corelist=None):
+        """
+        There're two options for request cpu resouce for vm.
+        If number is not -1, just allocate cpu from not used cores.
+        If list is not None, will allocate cpu after checked.
+        """
+        cores = []
+
+        if vm == '':
+            print "Alloc cpu request vitual machine name!!!"
+            return cores
+
+        if number != -1:
+            for core in self.unused_cores:
+                if core != -1 and number != 0:
+                    if self.__core_on_socket(core, socket) is True:
+                        self.__core_used(core)
+                        cores.append(str(core))
+                        number = number - 1
+            if number != 0:
+                print "Can't allocated requested cpu!!!"
+
+        if corelist is not None:
+            for core in corelist:
+                if self.__core_isused(int(core)) is True:
+                    print "Core %s has been used!!!" % core
+                else:
+                    if self.__core_on_socket(int(core), socket) is True:
+                        self.__core_used(int(core))
+                        cores.append(core)
+
+        if vm not in self.allocated_info:
+            self.allocated_info[vm] = {}
+
+        self.allocated_info[vm]['cores'] = cores
+        return cores
+
+    def __vm_has_resource(self, vm, resource=''):
+        if vm == '':
+            self.dut.logger.info("VM name cannt be NULL!!!")
+            raise Exception("VM name cannt be NULL!!!")
+        if vm not in self.allocated_info:
+            self.dut.logger.info(
+                "There is no resource allocated to VM [%s]." % vm)
+            return False
+        if resource == '':
+            return True
+        if resource not in self.allocated_info[vm]:
+            self.dut.logger.info(
+                "There is no resource [%s] allocated to VM [%s] " %
+                (resource, vm))
+            return False
+        return True
+
+    def free_cpu(self, vm):
+        if self.__vm_has_resource(vm, 'cores'):
+            for core in self.allocated_info[vm]['cores']:
+                self.__core_unused(core)
+            self.allocated_info[vm].pop('cores')
+
+    def alloc_pf(self, vm='', number=-1, socket=-1, pflist=[]):
+        """
+        There're two options for request pf devices for vm.
+        If number is not -1, just allocate pf device from not used pfs.
+        If list is not None, will allocate pf devices after checked.
+        """
+        ports = []
+
+        if number != -1:
+            for pci in self.unused_ports:
+                if pci != 'unused' and number != 0:
+                    if self.__port_on_socket(pci, socket) is True:
+                        self.__port_used(pci)
+                        ports.append(pci)
+                        number = number - 1
+            if number != 0:
+                print "Can't allocated requested PF devices!!!"
+
+        if pflist is not None:
+            for pci in pflist:
+                if self.__port_isused(pci) is True:
+                    print "Port %s has been used!!!" % pci
+                else:
+                    if self.__port_on_socket(pci, socket) is True:
+                        self.__port_used(core)
+                        ports.append(core)
+
+        if vm not in self.allocated_info:
+            self.allocated_info[vm] = {}
+
+        self.allocated_info[vm]['ports'] = ports
+        return ports
+
+    def free_pf(self, vm):
+        if self.__vm_has_resource(vm, 'ports'):
+            for pci in self.allocated_info[vm]['ports']:
+                self.__port_unused(pci)
+            self.allocated_info[vm].pop('ports')
+
+    def alloc_vf_from_pf(self, vm='', pf_pci='', number=-1, vflist=[]):
+        """
+        There're two options for request vf devices of pf device.
+        If number is not -1, just allocate vf device from not used vfs.
+        If list is not None, will allocate vf devices after checked.
+        """
+        vfs = []
+        if vm == '':
+            print "Alloc VF request vitual machine name!!!"
+            return vfs
+
+        if pf_pci == '':
+            print "Alloc VF request PF pci address!!!"
+            return vfs
+
+        for vf_info in self.vfs_info:
+            if vf_info['pf_pci'] == pf_pci:
+                if vf_info['pci'] in vflist:
+                    vfs.append(vf_info['pci'])
+                    continue
+
+                if number > 0:
+                    vfs.append(vf_info['pci'])
+                    number = number - 1
+
+        for vf in vfs:
+            self.__vf_used(vf)
+
+        if vm not in self.allocated_info:
+            self.allocated_info[vm] = {}
+
+        self.allocated_info[vm]['vfs'] = vfs
+        return vfs
+
+    def free_vf(self, vm):
+        if self.__vm_has_resource(vm, 'vfs'):
+            for pci in self.allocated_info[vm]['vfs']:
+                self.__vf_unused(pci)
+            self.allocated_info[vm].pop('vfs')
+
+    def add_vf_on_pf(self, pf_pci='', vflist=[]):
+        """
+        Add vf devices generated by specified pf devices.
+        """
+        # add vfs into vf info list
+        vfs = []
+        for vf in vflist:
+            if vf not in self.vfs:
+                self.vfs_info.append({'pci': vf, 'pf_pci': pf_pci})
+                vfs.append(vf)
+        used_vfs = ['unused'] * len(vflist)
+        self.unused_vfs += vfs
+        self.used_vfs += used_vfs
+        self.vfs += vfs
+
+    def del_vf_on_pf(self, pf_pci='', vflist=[]):
+        """
+        Remove vf devices generated by specified pf devices.
+        """
+        vfs = []
+        for vf in vflist:
+            for vfs_info in self.vfs_info:
+                if vfs_info['pci'] == vf:
+                    vfs.append(vf)
+
+        for vf in vfs:
+            try:
+                index = self.vfs.index(vf)
+            except:
+                continue
+            del self.vfs_info[index]
+            del self.unused_vfs[index]
+            del self.used_vfs[index]
+            del self.vfs[index]
+
+    def alloc_port(self, vm=''):
+        """
+        Allocate unused host port for vm
+        """
+        if vm == '':
+            print "Alloc host port request vitual machine name!!!"
+            return None
+
+        port_start = INIT_FREE_PORT + randint(1, 100)
+        port_step = randint(1, 10)
+        port = None
+        count = 20
+        while True:
+            if self.dut.check_port_occupied(port_start) is False:
+                port = port_start
+                break
+            count -= 1
+            if count < 0:
+                print 'No available port on the host!!!'
+                break
+            port_start += port_step
+
+        if vm not in self.allocated_info:
+            self.allocated_info[vm] = {}
+
+        self.allocated_info[vm]['hostport'] = port
+        return port
+
+    def free_port(self, vm):
+        if self.__vm_has_resource(vm, 'hostport'):
+            self.allocated_info[vm].pop('hostport')
+
+    def alloc_vnc_num(self, vm=''):
+        """
+        Allocate unused host VNC display number for VM.
+        """
+        if vm == '':
+            print "Alloc vnc display number request vitual machine name!!!"
+            return None
+
+        max_vnc_display_num = self.dut.get_maximal_vnc_num()
+        free_vnc_display_num = max_vnc_display_num + 1
+
+        if vm not in self.allocated_info:
+            self.allocated_info[vm] = {}
+
+        self.allocated_info[vm]['vnc_display_num'] = free_vnc_display_num
+
+        return free_vnc_display_num
+
+    def free_vnc_num(self, vm):
+        if self.__vm_has_resource(vm, 'vnc_display_num'):
+            self.allocated_info[vm].pop('vnc_display_num')
+
+    def free_all_resource(self, vm):
+        """
+        Free all resource VM has been allocated.
+        """
+        self.free_port(vm)
+        self.free_vnc_num(vm)
+        self.free_vf(vm)
+        self.free_pf(vm)
+        self.free_cpu(vm)
+
+        if self.__vm_has_resource(vm):
+            self.allocated_info.pop(vm)
+
+    def get_cpu_on_vm(self, vm=''):
+        """
+        Return core list on specifid VM.
+        """
+        if vm in self.allocated_info:
+            if "cores" in self.allocated_info[vm]:
+                return self.allocated_info[vm]['cores']
+
+    def get_vfs_on_vm(self, vm=''):
+        """
+        Return vf device list on specifid VM.
+        """
+        if vm in self.allocated_info:
+            if 'vfs' in self.allocated_info[vm]:
+                return self.allocated_info[vm]['vfs']
+
+    def get_pfs_on_vm(self, vm=''):
+        """
+        Return pf device list on specifid VM.
+        """
+        if vm in self.allocated_info:
+            if 'ports' in self.allocated_info[vm]:
+                return self.allocated_info[vm]['ports']
+
+
+class simple_dut(object):
+
+    def __init__(self):
+        self.ports_info = []
+        self.cores = []
+
+    def check_port_occupied(self, port):
+        return False
+
+if __name__ == "__main__":
+    dut = simple_dut()
+    dut.cores = [{'thread': '1', 'socket': '0'}, {'thread': '2', 'socket': '0'},
+                 {'thread': '3', 'socket': '0'}, {'thread': '4', 'socket': '0'},
+                 {'thread': '5', 'socket': '0'}, {'thread': '6', 'socket': '0'},
+                 {'thread': '7', 'socket': '1'}, {'thread': '8', 'socket': '1'},
+                 {'thread': '9', 'socket': '1'}, {'thread': '10', 'socket': '1'},
+                 {'thread': '11', 'socket': '1'}, {'thread': '12', 'socket': '1'}]
+
+    dut.ports_info = [{'intf': 'p786p1', 'source': 'cfg', 'mac': '90:e2:ba:69:e5:e4',
+                       'pci': '08:00.0', 'numa': 0, 'ipv6': 'fe80::92e2:baff:fe69:e5e4',
+                       'peer': 'IXIA:6.5', 'type': '8086:10fb'},
+                      {'intf': 'p786p2', 'source': 'cfg', 'mac': '90:e2:ba:69:e5:e5',
+                       'pci': '08:00.1', 'numa': 0, 'ipv6': 'fe80::92e2:baff:fe69:e5e5',
+                       'peer': 'IXIA:6.6', 'type': '8086:10fb'},
+                      {'intf': 'p787p1', 'source': 'cfg', 'mac': '90:e2:ba:69:e5:e6',
+                       'pci': '84:00.0', 'numa': 1, 'ipv6': 'fe80::92e2:baff:fe69:e5e6',
+                       'peer': 'IXIA:6.7', 'type': '8086:10fb'},
+                      {'intf': 'p787p2', 'source': 'cfg', 'mac': '90:e2:ba:69:e5:e7',
+                       'pci': '84:00.1', 'numa': 1, 'ipv6': 'fe80::92e2:baff:fe69:e5e7',
+                       'peer': 'IXIA:6.8', 'type': '8086:10fb'}]
+
+    virt_pool = VirtResource(dut)
+    print "Alloc two PF devices on socket 1 from VM"
+    print virt_pool.alloc_pf(vm='test1', number=2, socket=1)
+
+    virt_pool.add_vf_on_pf(pf_pci='08:00.0', vflist=[
+                           '08:10.0', '08:10.2', '08:10.4', '08:10.6'])
+    virt_pool.add_vf_on_pf(pf_pci='08:00.1', vflist=[
+                           '08:10.1', '08:10.3', '08:10.5', '08:10.7'])
+    print "Add VF devices to resource pool"
+    print virt_pool.vfs_info
+
+    print "Alloc VF device from resource pool"
+    print virt_pool.alloc_vf_from_pf(vm='test1', pf_pci='08:00.0', number=2)
+    print virt_pool.used_vfs
+    print "Alloc VF device from resource pool"
+    print virt_pool.alloc_vf_from_pf(vm='test2', pf_pci='08:00.1', vflist=['08:10.3', '08:10.5'])
+    print virt_pool.used_vfs
+
+    print "Del VF devices from resource pool"
+    virt_pool.del_vf_on_pf(pf_pci='08:00.0', vflist=['08:10.4', '08:10.2'])
+    print virt_pool.vfs_info
+
+    virt_pool.reserve_cpu('e')
+    print "Reserve three cores from resource pool"
+    print virt_pool.unused_cores
+    print "Alloc two cores on socket1 for VM-test1"
+    print virt_pool.alloc_cpu(vm="test1", number=2, socket=1)
+    print "Alloc two cores in list for VM-test2"
+    print virt_pool.alloc_cpu(vm="test2", corelist=['4', '5'])
+    print "Alloc two cores for VM-test3"
+    print virt_pool.alloc_cpu(vm="test3", number=2)
+    print "Alloc port for VM-test1"
+    print virt_pool.alloc_port(vm='test1')
+    print "Alloc information after allcated"
+    print virt_pool.allocated_info
+
+    print "Get cores on VM-test1"
+    print virt_pool.get_cpu_on_vm("test1")
+    print "Get pfs on VM-test1"
+    print virt_pool.get_pfs_on_vm("test1")
+    print "Get vfs on VM-test2"
+    print virt_pool.get_vfs_on_vm("test2")
-- 
1.9.3



More information about the dts mailing list