aboutsummaryrefslogtreecommitdiffstats
path: root/yardstick/benchmark/contexts/standalone/model.py
diff options
context:
space:
mode:
Diffstat (limited to 'yardstick/benchmark/contexts/standalone/model.py')
-rw-r--r--yardstick/benchmark/contexts/standalone/model.py156
1 files changed, 91 insertions, 65 deletions
diff --git a/yardstick/benchmark/contexts/standalone/model.py b/yardstick/benchmark/contexts/standalone/model.py
index 4491660e0..85ae14b1d 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,6 +28,7 @@ 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__)
@@ -43,7 +42,8 @@ VM_TEMPLATE = """
<memoryBacking>
<hugepages />
</memoryBacking>
- <vcpu placement="static">{vcpu}</vcpu>
+ <vcpu cpuset='{cpuset}'>{vcpu}</vcpu>
+ {cputune}
<os>
<type arch="x86_64" machine="pc-i440fx-utopic">hvm</type>
<boot dev="hd" />
@@ -95,33 +95,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
+
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x08'
+ function='0x0'/>
+
+ 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
+
+ <devices>
+ <interface type='vhostuser'>
+ <mac address='00:00:00:00:00:01'/>
+ <source type='unix' path='/usr/local/var/run/openvswitch/
+ dpdkvhostuser0' mode='client'/>
+ <model type='virtio'/>
+ <driver queues='4'>
+ <host mrg_rxbuf='off'/>
+ </driver>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x03'
+ function='0x0'/>
+ </interface>
+ ...
+ </devices>
+
+ 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 +161,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 +173,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
+
+ <devices>
+ <interface type='hostdev' managed='yes'>
+ <source>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x03'
+ function='0x0'/>
+ </source>
+ <mac address='52:54:00:6d:90:02'>
+ <address type='pci' domain='0x0000' bus='0x02' slot='0x04'
+ function='0x1'/>
+ </interface>
+ ...
+ </devices>
+
+ 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 +209,15 @@ 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')
+ addr = ET.SubElement(source, 'address')
+ pci_address = PciAddress(vf_pci.strip())
+ cls._add_interface_address(addr, 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 +240,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 +254,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):
@@ -266,9 +295,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 +331,7 @@ class StandaloneContextHelper(object):
'interface': str(interface),
'driver': driver
})
- LOG.info("{0}".format(networks))
+ LOG.info(networks)
return networks
@@ -374,7 +400,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})