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__)
@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, XML config: %s', cfg)
+ status, _, error = connection.execute('virsh create %s' % cfg)
+ if status:
+ raise exceptions.LibvirtCreateError(error=error)
@staticmethod
def virsh_destroy_vm(vm_name, connection):
- connection.execute("virsh destroy %s" % vm_name)
+ LOG.info('VM destroy, VM name: %s', vm_name)
+ status, _, error = connection.execute('virsh destroy %s' % vm_name)
+ if status:
+ LOG.warning('Error destroying VM %s. Error: %s', vm_name, error)
@staticmethod
def _add_interface_address(interface, pci_address):
return vm_pci
@classmethod
- def add_ovs_interface(cls, vpath, port_num, vpci, vports_mac, xml):
+ def add_ovs_interface(cls, vpath, port_num, vpci, vports_mac, xml_str):
"""Add a DPDK OVS 'interface' XML node in 'devices' node
<devices>
vhost_path = ('{0}/var/run/openvswitch/dpdkvhostuser{1}'.
format(vpath, port_num))
- root = ET.parse(xml)
+ root = ET.fromstring(xml_str)
pci_address = PciAddress(vpci.strip())
device = root.find('devices')
cls._add_interface_address(interface, pci_address)
- root.write(xml)
+ return ET.tostring(root)
@classmethod
- def add_sriov_interfaces(cls, vm_pci, vf_pci, vf_mac, xml):
+ def add_sriov_interfaces(cls, vm_pci, vf_pci, vf_mac, xml_str):
"""Add a SR-IOV 'interface' XML node in 'devices' node
<devices>
-sr_iov-how_sr_iov_libvirt_works
"""
- root = ET.parse(xml)
+ root = ET.fromstring(xml_str)
device = root.find('devices')
interface = ET.SubElement(device, 'interface')
pci_vm_address = PciAddress(vm_pci.strip())
cls._add_interface_address(interface, pci_vm_address)
- root.write(xml)
+ return ET.tostring(root)
@staticmethod
- def create_snapshot_qemu(connection, index, vm_image):
- # build snapshot image
- image = "/var/lib/libvirt/images/%s.qcow2" % index
- connection.execute("rm %s" % image)
- qemu_template = "qemu-img create -f qcow2 -o backing_file=%s %s"
- connection.execute(qemu_template % (vm_image, image))
+ def create_snapshot_qemu(connection, index, base_image):
+ """Create the snapshot image for a VM using a base image
- return image
+ :param connection: SSH connection to the remote host
+ :param index: index of the VM to be spawn
+ :param base_image: path of the VM base image in the remote host
+ :return: snapshot image path
+ """
+ vm_image = '/var/lib/libvirt/images/%s.qcow2' % index
+ connection.execute('rm -- "%s"' % vm_image)
+ status, _, _ = connection.execute('test -r %s' % base_image)
+ if status:
+ if not os.access(base_image, os.R_OK):
+ raise exceptions.LibvirtQemuImageBaseImageNotPresent(
+ vm_image=vm_image, base_image=base_image)
+ # NOTE(ralonsoh): done in two steps to avoid root permission
+ # issues.
+ LOG.info('Copy %s from execution host to remote host', base_image)
+ file_name = os.path.basename(os.path.normpath(base_image))
+ connection.put_file(base_image, '/tmp/%s' % file_name)
+ status, _, error = connection.execute(
+ 'mv -- "/tmp/%s" "%s"' % (file_name, base_image))
+ if status:
+ raise exceptions.LibvirtQemuImageCreateError(
+ vm_image=vm_image, base_image=base_image, error=error)
+
+ LOG.info('Convert image %s to %s', base_image, vm_image)
+ qemu_cmd = ('qemu-img create -f qcow2 -o backing_file=%s %s' %
+ (base_image, vm_image))
+ status, _, error = connection.execute(qemu_cmd)
+ if status:
+ raise exceptions.LibvirtQemuImageCreateError(
+ vm_image=vm_image, base_image=base_image, error=error)
+ return vm_image
@classmethod
- def build_vm_xml(cls, connection, flavor, cfg, vm_name, index):
+ def build_vm_xml(cls, connection, flavor, vm_name, index):
+ """Build the XML from the configuration parameters"""
memory = flavor.get('ram', '4096')
extra_spec = flavor.get('extra_specs', {})
cpu = extra_spec.get('hw:cpu_cores', '2')
socket=socket, threads=threads,
vm_image=image, cpuset=cpuset, cputune=cputune)
- write_file(cfg, vm_xml)
-
- return [vcpu, mac]
+ return vm_xml, mac
@staticmethod
def update_interrupts_hugepages_perf(connection):
cpuset = "%s,%s" % (cores, threads)
return cpuset
+ @classmethod
+ def write_file(cls, file_name, xml_str):
+ """Dump a XML string to a file"""
+ root = ET.fromstring(xml_str)
+ et = ET.ElementTree(element=root)
+ et.write(file_name, encoding='utf-8', method='xml')
+
class StandaloneContextHelper(object):
""" This class handles all the common code for standalone