X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=yardstick%2Fbenchmark%2Fcontexts%2Fstandalone%2Fmodel.py;h=30170832afbfba5adb165a70abc7b4dd74d867c1;hb=3d13a4e3a2a593cee37d55638d0c1e49cec1dea7;hp=4491660e0c043bca87d9d80073ba62e041e79532;hpb=5721849f3f08c2c1c89354341115c834e510b3d6;p=yardstick.git diff --git a/yardstick/benchmark/contexts/standalone/model.py b/yardstick/benchmark/contexts/standalone/model.py index 4491660e0..30170832a 100644 --- a/yardstick/benchmark/contexts/standalone/model.py +++ b/yardstick/benchmark/contexts/standalone/model.py @@ -16,11 +16,9 @@ from __future__ import absolute_import import os import re import time -import glob import uuid import random import logging -import itertools import errno from netaddr import IPNetwork @@ -30,20 +28,22 @@ from yardstick import ssh from yardstick.common.constants import YARDSTICK_ROOT_PATH from yardstick.common.yaml_loader import yaml_load from yardstick.network_services.utils import PciAddress +from yardstick.network_services.helpers.cpu import CpuSysCores from yardstick.common.utils import write_file LOG = logging.getLogger(__name__) VM_TEMPLATE = """ - {vm_name} + {vm_name} {random_uuid} {memory} {memory} - {vcpu} + {vcpu} + {cputune} hvm @@ -80,7 +80,13 @@ VM_TEMPLATE = """ - + + + + + + + """ WAIT_FOR_BOOT = 30 @@ -95,33 +101,63 @@ class Libvirt(object): cmd_template = "virsh list --name | grep -i %s" status = connection.execute(cmd_template % vm_name)[0] if status == 0: - LOG.info("VM '%s' is already present.. destroying" % vm_name) + LOG.info("VM '%s' is already present... destroying", vm_name) connection.execute("virsh destroy %s" % vm_name) @staticmethod def virsh_create_vm(connection, cfg): err = connection.execute("virsh create %s" % cfg)[0] - LOG.info("VM create status: %s" % (err)) + LOG.info("VM create status: %s", err) @staticmethod def virsh_destroy_vm(vm_name, connection): connection.execute("virsh destroy %s" % vm_name) @staticmethod - def add_interface_address(interface, pci_address): + def _add_interface_address(interface, pci_address): + """Add a PCI 'address' XML node + +
+ + Refence: https://software.intel.com/en-us/articles/ + configure-sr-iov-network-virtual-functions-in-linux-kvm + """ vm_pci = ET.SubElement(interface, 'address') vm_pci.set('type', 'pci') - vm_pci.set('domain', '0x%s' % pci_address.domain) - vm_pci.set('bus', '0x%s' % pci_address.bus) - vm_pci.set('slot', '0x%s' % pci_address.slot) - vm_pci.set('function', '0x%s' % pci_address.function) + vm_pci.set('domain', '0x{}'.format(pci_address.domain)) + vm_pci.set('bus', '0x{}'.format(pci_address.bus)) + vm_pci.set('slot', '0x{}'.format(pci_address.slot)) + vm_pci.set('function', '0x{}'.format(pci_address.function)) return vm_pci @classmethod def add_ovs_interface(cls, vpath, port_num, vpci, vports_mac, xml): - vhost_path = '{0}/var/run/openvswitch/dpdkvhostuser{1}' + """Add a DPDK OVS 'interface' XML node in 'devices' node + + + + + + + + + +
+ + ... + + + Reference: http://docs.openvswitch.org/en/latest/topics/dpdk/ + vhost-user/ + """ + + vhost_path = ('{0}/var/run/openvswitch/dpdkvhostuser{1}'. + format(vpath, port_num)) root = ET.parse(xml) - pci_address = PciAddress.parse_address(vpci.strip(), multi_line=True) + pci_address = PciAddress(vpci.strip()) device = root.find('devices') interface = ET.SubElement(device, 'interface') @@ -131,7 +167,7 @@ class Libvirt(object): source = ET.SubElement(interface, 'source') source.set('type', 'unix') - source.set('path', vhost_path.format(vpath, port_num)) + source.set('path', vhost_path) source.set('mode', 'client') model = ET.SubElement(interface, 'model') @@ -143,14 +179,35 @@ class Libvirt(object): host = ET.SubElement(driver, 'host') host.set('mrg_rxbuf', 'off') - cls.add_interface_address(interface, pci_address) + cls._add_interface_address(interface, pci_address) root.write(xml) @classmethod - def add_sriov_interfaces(cls, vm_pci, vf_pci, vfmac, xml): + def add_sriov_interfaces(cls, vm_pci, vf_pci, vf_mac, xml): + """Add a SR-IOV 'interface' XML node in 'devices' node + + + + +
+ + +
+ + ... + + + Reference: https://access.redhat.com/documentation/en-us/ + red_hat_enterprise_linux/6/html/ + virtualization_host_configuration_and_guest_installation_guide/ + sect-virtualization_host_configuration_and_guest_installation_guide + -sr_iov-how_sr_iov_libvirt_works + """ + root = ET.parse(xml) - pci_address = PciAddress.parse_address(vf_pci.strip(), multi_line=True) device = root.find('devices') interface = ET.SubElement(device, 'interface') @@ -158,18 +215,14 @@ class Libvirt(object): interface.set('type', 'hostdev') mac = ET.SubElement(interface, 'mac') - mac.set('address', vfmac) - source = ET.SubElement(interface, 'source') + mac.set('address', vf_mac) - addr = ET.SubElement(source, "address") - addr.set('domain', "0x0") - addr.set('bus', "{0}".format(pci_address.bus)) - addr.set('function', "{0}".format(pci_address.function)) - addr.set('slot', "0x{0}".format(pci_address.slot)) - addr.set('type', "pci") + source = ET.SubElement(interface, 'source') + pci_address = PciAddress(vf_pci.strip()) + cls._add_interface_address(source, pci_address) - pci_vm_address = PciAddress.parse_address(vm_pci.strip(), multi_line=True) - cls.add_interface_address(interface, pci_vm_address) + pci_vm_address = PciAddress(vm_pci.strip()) + cls._add_interface_address(interface, pci_vm_address) root.write(xml) @@ -192,7 +245,10 @@ class Libvirt(object): threads = extra_spec.get('hw:cpu_threads', '2') vcpu = int(cpu) * int(threads) numa_cpus = '0-%s' % (vcpu - 1) + hw_socket = flavor.get('hw_socket', '0') + cpuset = Libvirt.pin_vcpu_for_perf(connection, hw_socket) + cputune = extra_spec.get('cputune', '') mac = StandaloneContextHelper.get_mac_address(0x00) image = cls.create_snapshot_qemu(connection, index, flavor.get("images", None)) @@ -203,51 +259,29 @@ class Libvirt(object): memory=memory, vcpu=vcpu, cpu=cpu, numa_cpus=numa_cpus, socket=socket, threads=threads, - vm_image=image) + vm_image=image, cpuset=cpuset, cputune=cputune) write_file(cfg, vm_xml) return [vcpu, mac] - @staticmethod - def split_cpu_list(cpu_list): - if not cpu_list: - return [] - - ranges = cpu_list.split(',') - bounds = ([int(b) for b in r.split('-')] for r in ranges) - range_objects = \ - (range(bound[0], bound[1] + 1 if len(bound) == 2 - else bound[0] + 1) for bound in bounds) - - return sorted(itertools.chain.from_iterable(range_objects)) - - @classmethod - def get_numa_nodes(cls): - nodes_sysfs = glob.iglob("/sys/devices/system/node/node*") - nodes = {} - for node_sysfs in nodes_sysfs: - num = os.path.basename(node_sysfs).replace("node", "") - with open(os.path.join(node_sysfs, "cpulist")) as cpulist_file: - cpulist = cpulist_file.read().strip() - nodes[num] = cls.split_cpu_list(cpulist) - LOG.info("nodes: {0}".format(nodes)) - return nodes - @staticmethod def update_interrupts_hugepages_perf(connection): connection.execute("echo 1 > /sys/module/kvm/parameters/allow_unsafe_assigned_interrupts") connection.execute("echo never > /sys/kernel/mm/transparent_hugepage/enabled") @classmethod - def pin_vcpu_for_perf(cls, connection, vm_name, cpu): - nodes = cls.get_numa_nodes() - num_nodes = len(nodes) - vcpi_pin_template = "virsh vcpupin {0} {1} {2}" - for i in range(0, int(cpu)): - core = nodes[str(num_nodes - 1)][i % len(nodes[str(num_nodes - 1)])] - connection.execute(vcpi_pin_template.format(vm_name, i, core)) - cls.update_interrupts_hugepages_perf(connection) + def pin_vcpu_for_perf(cls, connection, socket='0'): + threads = "" + sys_obj = CpuSysCores(connection) + soc_cpu = sys_obj.get_core_socket() + sys_cpu = int(soc_cpu["cores_per_socket"]) + socket = str(socket) + cores = "%s-%s" % (soc_cpu[socket][0], soc_cpu[socket][sys_cpu - 1]) + if int(soc_cpu["thread_per_core"]) > 1: + threads = "%s-%s" % (soc_cpu[socket][sys_cpu], soc_cpu[socket][-1]) + cpuset = "%s,%s" % (cores, threads) + return cpuset class StandaloneContextHelper(object): @@ -258,7 +292,8 @@ class StandaloneContextHelper(object): super(StandaloneContextHelper, self).__init__() @staticmethod - def install_req_libs(connection, extra_pkgs=[]): + def install_req_libs(connection, extra_pkgs=None): + extra_pkgs = extra_pkgs or [] pkgs = ["qemu-kvm", "libvirt-bin", "bridge-utils", "numactl", "fping"] pkgs.extend(extra_pkgs) cmd_template = "dpkg-query -W --showformat='${Status}\\n' \"%s\"|grep 'ok installed'" @@ -266,9 +301,6 @@ class StandaloneContextHelper(object): if connection.execute(cmd_template % pkg)[0]: connection.execute("apt-get update") connection.execute("apt-get -y install %s" % pkg) - else: - # all installed - return @staticmethod def get_kernel_module(connection, pci, driver): @@ -305,7 +337,7 @@ class StandaloneContextHelper(object): 'interface': str(interface), 'driver': driver }) - LOG.info("{0}".format(networks)) + LOG.info(networks) return networks @@ -374,7 +406,7 @@ class StandaloneContextHelper(object): while not mgmtip and times: connection.execute("fping -c 1 -g %s > /dev/null 2>&1" % cidr) out = connection.execute("ip neighbor | grep '%s'" % mac)[1] - LOG.info("fping -c 1 -g %s > /dev/null 2>&1" % cidr) + LOG.info("fping -c 1 -g %s > /dev/null 2>&1", cidr) if out.strip(): mgmtip = str(out.split(" ")[0]).strip() client = ssh.SSH.from_node(node, overrides={"ip": mgmtip})