aboutsummaryrefslogtreecommitdiffstats
path: root/yardstick
diff options
context:
space:
mode:
Diffstat (limited to 'yardstick')
-rw-r--r--yardstick/benchmark/contexts/heat.py3
-rw-r--r--yardstick/benchmark/contexts/standalone/model.py42
-rw-r--r--yardstick/benchmark/contexts/standalone/ovs_dpdk.py7
-rw-r--r--yardstick/benchmark/contexts/standalone/sriov.py7
-rw-r--r--yardstick/common/ansible_common.py2
-rw-r--r--yardstick/common/exceptions.py16
-rw-r--r--yardstick/common/messaging/__init__.py36
-rw-r--r--yardstick/common/messaging/consumer.py85
-rw-r--r--yardstick/common/messaging/payloads.py53
-rw-r--r--yardstick/common/messaging/producer.py70
-rw-r--r--yardstick/tests/functional/common/messaging/__init__.py0
-rw-r--r--yardstick/tests/functional/common/messaging/test_messaging.py99
-rw-r--r--yardstick/tests/unit/benchmark/contexts/standalone/test_model.py78
-rw-r--r--yardstick/tests/unit/benchmark/contexts/test_heat.py11
-rw-r--r--yardstick/tests/unit/common/messaging/__init__.py0
-rw-r--r--yardstick/tests/unit/common/messaging/test_consumer.py54
-rw-r--r--yardstick/tests/unit/common/messaging/test_payloads.py46
-rw-r--r--yardstick/tests/unit/common/messaging/test_producer.py46
18 files changed, 617 insertions, 38 deletions
diff --git a/yardstick/benchmark/contexts/heat.py b/yardstick/benchmark/contexts/heat.py
index 0d1dfb86f..0964b7baf 100644
--- a/yardstick/benchmark/contexts/heat.py
+++ b/yardstick/benchmark/contexts/heat.py
@@ -7,9 +7,6 @@
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-from __future__ import absolute_import
-from __future__ import print_function
-
import collections
import logging
import os
diff --git a/yardstick/benchmark/contexts/standalone/model.py b/yardstick/benchmark/contexts/standalone/model.py
index f18d090d8..4d43f2611 100644
--- a/yardstick/benchmark/contexts/standalone/model.py
+++ b/yardstick/benchmark/contexts/standalone/model.py
@@ -232,14 +232,40 @@ class Libvirt(object):
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))
-
- return image
+ def create_snapshot_qemu(connection, index, base_image):
+ """Create the snapshot image for a VM using a base 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, vm_name, index):
diff --git a/yardstick/benchmark/contexts/standalone/ovs_dpdk.py b/yardstick/benchmark/contexts/standalone/ovs_dpdk.py
index 30b685eec..b9e66a481 100644
--- a/yardstick/benchmark/contexts/standalone/ovs_dpdk.py
+++ b/yardstick/benchmark/contexts/standalone/ovs_dpdk.py
@@ -20,6 +20,7 @@ import re
import time
from yardstick import ssh
+from yardstick.network_services.utils import get_nsb_option
from yardstick.benchmark.contexts.base import Context
from yardstick.benchmark.contexts.standalone import model
from yardstick.common import exceptions
@@ -55,7 +56,8 @@ class OvsDpdkContext(Context):
self.file_path = None
self.sriov = []
self.first_run = True
- self.dpdk_devbind = ''
+ self.dpdk_devbind = os.path.join(get_nsb_option('bin_path'),
+ 'dpdk-devbind.py')
self.vm_names = []
self.nfvi_host = []
self.nodes = []
@@ -260,9 +262,6 @@ class OvsDpdkContext(Context):
return
self.connection = ssh.SSH.from_node(self.host_mgmt)
- self.dpdk_devbind = utils.provision_tool(
- self.connection,
- os.path.join(utils.get_nsb_option('bin_path'), 'dpdk-devbind.py'))
# Check dpdk/ovs version, if not present install
self.check_ovs_dpdk_env()
diff --git a/yardstick/benchmark/contexts/standalone/sriov.py b/yardstick/benchmark/contexts/standalone/sriov.py
index 5db419e6a..95472fdda 100644
--- a/yardstick/benchmark/contexts/standalone/sriov.py
+++ b/yardstick/benchmark/contexts/standalone/sriov.py
@@ -19,7 +19,6 @@ import collections
from yardstick import ssh
from yardstick.network_services.utils import get_nsb_option
-from yardstick.network_services.utils import provision_tool
from yardstick.benchmark.contexts.base import Context
from yardstick.benchmark.contexts.standalone import model
from yardstick.network_services.utils import PciAddress
@@ -38,7 +37,8 @@ class SriovContext(Context):
self.file_path = None
self.sriov = []
self.first_run = True
- self.dpdk_devbind = ''
+ self.dpdk_devbind = os.path.join(get_nsb_option('bin_path'),
+ 'dpdk-devbind.py')
self.vm_names = []
self.nfvi_host = []
self.nodes = []
@@ -79,9 +79,6 @@ class SriovContext(Context):
return
self.connection = ssh.SSH.from_node(self.host_mgmt)
- self.dpdk_devbind = provision_tool(
- self.connection,
- os.path.join(get_nsb_option("bin_path"), "dpdk-devbind.py"))
# Todo: NFVi deploy (sriov, vswitch, ovs etc) based on the config.
model.StandaloneContextHelper.install_req_libs(self.connection)
diff --git a/yardstick/common/ansible_common.py b/yardstick/common/ansible_common.py
index 38d2dd7c2..ca5a110e2 100644
--- a/yardstick/common/ansible_common.py
+++ b/yardstick/common/ansible_common.py
@@ -514,7 +514,7 @@ class AnsibleCommon(object):
parser.add_section('defaults')
parser.set('defaults', 'host_key_checking', 'False')
- cfg_path = os.path.join(directory, 'setup.cfg')
+ cfg_path = os.path.join(directory, 'ansible.cfg')
with open(cfg_path, 'w') as f:
parser.write(f)
diff --git a/yardstick/common/exceptions.py b/yardstick/common/exceptions.py
index 734706191..bc16cab8f 100644
--- a/yardstick/common/exceptions.py
+++ b/yardstick/common/exceptions.py
@@ -64,6 +64,11 @@ class YardstickBannedModuleImported(YardstickException):
message = 'Module "%(module)s" cannnot be imported. Reason: "%(reason)s"'
+class PayloadMissingAttributes(YardstickException):
+ message = ('Error instantiating a Payload class, missing attributes: '
+ '%(missing_attributes)s')
+
+
class HeatTemplateError(YardstickException):
"""Error in Heat during the stack deployment"""
message = ('Error in Heat during the creation of the OpenStack stack '
@@ -112,6 +117,17 @@ class LibvirtCreateError(YardstickException):
message = 'Error creating the virtual machine. Error: %(error)s.'
+class LibvirtQemuImageBaseImageNotPresent(YardstickException):
+ message = ('Error creating the qemu image for %(vm_image)s. Base image: '
+ '%(base_image)s. Base image not present in execution host or '
+ 'remote host.')
+
+
+class LibvirtQemuImageCreateError(YardstickException):
+ message = ('Error creating the qemu image for %(vm_image)s. Base image: '
+ '%(base_image)s. Error: %(error)s.')
+
+
class ScenarioConfigContextNameNotFound(YardstickException):
message = 'Context name "%(context_name)s" not found'
diff --git a/yardstick/common/messaging/__init__.py b/yardstick/common/messaging/__init__.py
new file mode 100644
index 000000000..f0f012ec3
--- /dev/null
+++ b/yardstick/common/messaging/__init__.py
@@ -0,0 +1,36 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# MQ is statically configured:
+# - MQ service: RabbitMQ
+# - user/password: yardstick/yardstick
+# - host:port: localhost:5672
+MQ_USER = 'yardstick'
+MQ_PASS = 'yardstick'
+MQ_SERVICE = 'rabbit'
+SERVER = 'localhost'
+PORT = 5672
+TRANSPORT_URL = (MQ_SERVICE + '://' + MQ_USER + ':' + MQ_PASS + '@' + SERVER +
+ ':' + str(PORT) + '/')
+
+# RPC server.
+RPC_SERVER_EXECUTOR = 'threading'
+
+# Topics.
+RUNNER = 'runner'
+
+# Methods.
+# RUNNER methods:
+RUNNER_INFO = 'runner_info'
+RUNNER_LOOP = 'runner_loop'
diff --git a/yardstick/common/messaging/consumer.py b/yardstick/common/messaging/consumer.py
new file mode 100644
index 000000000..24ec6f184
--- /dev/null
+++ b/yardstick/common/messaging/consumer.py
@@ -0,0 +1,85 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import abc
+import logging
+
+from oslo_config import cfg
+import oslo_messaging
+import six
+
+from yardstick.common import messaging
+
+
+LOG = logging.getLogger(__name__)
+
+
+@six.add_metaclass(abc.ABCMeta)
+class NotificationHandler(object):
+ """Abstract class to define a endpoint object for a MessagingConsumer"""
+
+ def __init__(self, _id, ctx_pids, queue):
+ self._id = _id
+ self._ctx_pids = ctx_pids
+ self._queue = queue
+
+
+@six.add_metaclass(abc.ABCMeta)
+class MessagingConsumer(object):
+ """Abstract class to implement a MQ consumer
+
+ This abstract class allows a class implementing this interface to receive
+ the messages published by a `MessagingNotifier`.
+ """
+
+ def __init__(self, topic, pids, endpoints, fanout=True):
+ """Init function.
+
+ :param topic: (string) MQ exchange topic
+ :param pids: (list of int) list of PIDs of the processes implementing
+ the MQ Notifier which will be in the message context
+ :param endpoints: (list of class) list of classes implementing the
+ methods (see `MessagingNotifier.send_message) used by
+ the Notifier
+ :param fanout: (bool) MQ clients may request that a copy of the message
+ be delivered to all servers listening on a topic by
+ setting fanout to ``True``, rather than just one of them
+ :returns: `MessagingConsumer` class object
+ """
+
+ self._pids = pids
+ self._endpoints = endpoints
+ self._transport = oslo_messaging.get_rpc_transport(
+ cfg.CONF, url=messaging.TRANSPORT_URL)
+ self._target = oslo_messaging.Target(topic=topic, fanout=fanout,
+ server=messaging.SERVER)
+ self._server = oslo_messaging.get_rpc_server(
+ self._transport, self._target, self._endpoints,
+ executor=messaging.RPC_SERVER_EXECUTOR,
+ access_policy=oslo_messaging.DefaultRPCAccessPolicy)
+
+ def start_rpc_server(self):
+ """Start the RPC server."""
+ if self._server:
+ self._server.start()
+
+ def stop_rpc_server(self):
+ """Stop the RPC server."""
+ if self._server:
+ self._server.stop()
+
+ def wait(self):
+ """Wait for message processing to complete (blocking)."""
+ if self._server:
+ self._server.wait()
diff --git a/yardstick/common/messaging/payloads.py b/yardstick/common/messaging/payloads.py
new file mode 100644
index 000000000..d29d79808
--- /dev/null
+++ b/yardstick/common/messaging/payloads.py
@@ -0,0 +1,53 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import abc
+
+import six
+
+from yardstick.common import exceptions
+
+
+@six.add_metaclass(abc.ABCMeta)
+class Payload(object):
+ """Base Payload class to transfer data through the MQ service"""
+
+ REQUIRED_FIELDS = {'version'}
+
+ def __init__(self, **kwargs):
+ """Init method
+
+ :param kwargs: (dictionary) attributes and values of the object
+ :returns: Payload object
+ """
+
+ if not all(req_field in kwargs for req_field in self.REQUIRED_FIELDS):
+ _attrs = set(kwargs) - self.REQUIRED_FIELDS
+ missing_attributes = ', '.join(str(_attr) for _attr in _attrs)
+ raise exceptions.PayloadMissingAttributes(
+ missing_attributes=missing_attributes)
+
+ for name, value in kwargs.items():
+ setattr(self, name, value)
+
+ self._fields = set(kwargs.keys())
+
+ def obj_to_dict(self):
+ """Returns a dictionary with the attributes of the object"""
+ return {field: getattr(self, field) for field in self._fields}
+
+ @classmethod
+ def dict_to_obj(cls, _dict):
+ """Returns a Payload object built from the dictionary elements"""
+ return cls(**_dict)
diff --git a/yardstick/common/messaging/producer.py b/yardstick/common/messaging/producer.py
new file mode 100644
index 000000000..b6adc0c17
--- /dev/null
+++ b/yardstick/common/messaging/producer.py
@@ -0,0 +1,70 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import abc
+import logging
+import os
+
+from oslo_config import cfg
+import oslo_messaging
+import six
+
+from yardstick.common import messaging
+
+
+LOG = logging.getLogger(__name__)
+
+
+@six.add_metaclass(abc.ABCMeta)
+class MessagingProducer(object):
+ """Abstract class to implement a MQ producer
+
+ This abstract class allows a class implementing this interface to publish
+ messages in a message queue.
+ """
+
+ def __init__(self, topic, pid=os.getpid(), fanout=True):
+ """Init function.
+
+ :param topic: (string) MQ exchange topic
+ :param pid: (int) PID of the process implementing this MQ Notifier
+ :param fanout: (bool) MQ clients may request that a copy of the message
+ be delivered to all servers listening on a topic by
+ setting fanout to ``True``, rather than just one of them
+ :returns: `MessagingNotifier` class object
+ """
+ self._topic = topic
+ self._pid = pid
+ self._fanout = fanout
+ self._transport = oslo_messaging.get_rpc_transport(
+ cfg.CONF, url=messaging.TRANSPORT_URL)
+ self._target = oslo_messaging.Target(topic=topic, fanout=fanout,
+ server=messaging.SERVER)
+ self._notifier = oslo_messaging.RPCClient(self._transport,
+ self._target)
+
+ def send_message(self, method, payload):
+ """Send a cast message, that will invoke a method without blocking.
+
+ The cast() method is used to invoke an RPC method that does not return
+ a value. cast() RPC requests may be broadcast to all Servers listening
+ on a given topic by setting the fanout Target property to ``True``.
+
+ :param methos: (string) method name, that must be implemented in the
+ consumer endpoints
+ :param payload: (subclass `Payload`) payload content
+ """
+ self._notifier.cast({'pid': self._pid},
+ method,
+ **payload.obj_to_dict())
diff --git a/yardstick/tests/functional/common/messaging/__init__.py b/yardstick/tests/functional/common/messaging/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/functional/common/messaging/__init__.py
diff --git a/yardstick/tests/functional/common/messaging/test_messaging.py b/yardstick/tests/functional/common/messaging/test_messaging.py
new file mode 100644
index 000000000..99874343b
--- /dev/null
+++ b/yardstick/tests/functional/common/messaging/test_messaging.py
@@ -0,0 +1,99 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import multiprocessing
+import time
+
+from yardstick.common.messaging import consumer
+from yardstick.common.messaging import payloads
+from yardstick.common.messaging import producer
+from yardstick.tests.functional import base
+
+
+TOPIC = 'topic_MQ'
+METHOD_INFO = 'info'
+
+
+class DummyPayload(payloads.Payload):
+ REQUIRED_FIELDS = {'version', 'data'}
+
+
+class DummyEndpoint(consumer.NotificationHandler):
+
+ def info(self, ctxt, **kwargs):
+ if ctxt['pid'] in self._ctx_pids:
+ self._queue.put('ID {}, data: {}, pid: {}'.format(
+ self._id, kwargs['data'], ctxt['pid']))
+
+
+class DummyConsumer(consumer.MessagingConsumer):
+
+ def __init__(self, _id, ctx_pids, queue):
+ self._id = _id
+ endpoints = [DummyEndpoint(_id, ctx_pids, queue)]
+ super(DummyConsumer, self).__init__(TOPIC, ctx_pids, endpoints)
+
+
+class DummyProducer(producer.MessagingProducer):
+ pass
+
+
+def _run_consumer(_id, ctx_pids, queue):
+ _consumer = DummyConsumer(_id, ctx_pids, queue)
+ _consumer.start_rpc_server()
+ _consumer.wait()
+
+
+class MessagingTestCase(base.BaseFunctionalTestCase):
+
+ @staticmethod
+ def _terminate_consumers(num_consumers, processes):
+ for i in range(num_consumers):
+ processes[i].terminate()
+
+ def test_run_five_consumers(self):
+ output_queue = multiprocessing.Queue()
+ num_consumers = 10
+ ctx_1 = 100001
+ ctx_2 = 100002
+ producers = [DummyProducer(TOPIC, pid=ctx_1),
+ DummyProducer(TOPIC, pid=ctx_2)]
+
+ processes = []
+ for i in range(num_consumers):
+ processes.append(multiprocessing.Process(
+ name='consumer_{}'.format(i),
+ target=_run_consumer,
+ args=(i, [ctx_1, ctx_2], output_queue)))
+ processes[i].start()
+ self.addCleanup(self._terminate_consumers, num_consumers, processes)
+
+ time.sleep(2) # Let consumers to create the listeners
+ for producer in producers:
+ for message in ['message 0', 'message 1']:
+ producer.send_message(METHOD_INFO,
+ DummyPayload(version=1, data=message))
+
+ time.sleep(2) # Let consumers attend the calls
+ output = []
+ while not output_queue.empty():
+ output.append(output_queue.get(True, 1))
+
+ self.assertEqual(num_consumers * 4, len(output))
+ msg_template = 'ID {}, data: {}, pid: {}'
+ for i in range(num_consumers):
+ for ctx in [ctx_1, ctx_2]:
+ for message in ['message 0', 'message 1']:
+ msg = msg_template.format(i, message, ctx)
+ self.assertIn(msg, output)
diff --git a/yardstick/tests/unit/benchmark/contexts/standalone/test_model.py b/yardstick/tests/unit/benchmark/contexts/standalone/test_model.py
index b1dcee209..72e684a68 100644
--- a/yardstick/tests/unit/benchmark/contexts/standalone/test_model.py
+++ b/yardstick/tests/unit/benchmark/contexts/standalone/test_model.py
@@ -13,11 +13,11 @@
# limitations under the License.
import copy
-import mock
import os
-import unittest
import uuid
+import mock
+import unittest
from xml.etree import ElementTree
from yardstick import ssh
@@ -172,14 +172,70 @@ class ModelLibvirtTestCase(unittest.TestCase):
interface_address.get('function'))
def test_create_snapshot_qemu(self):
- result = "/var/lib/libvirt/images/0.qcow2"
- with mock.patch("yardstick.ssh.SSH") as ssh:
- ssh_mock = mock.Mock(autospec=ssh.SSH)
- ssh_mock.execute = \
- mock.Mock(return_value=(0, "a", ""))
- ssh.return_value = ssh_mock
- image = model.Libvirt.create_snapshot_qemu(ssh_mock, "0", "ubuntu.img")
- self.assertEqual(image, result)
+ self.mock_ssh.execute = mock.Mock(return_value=(0, 0, 0))
+ index = 1
+ vm_image = '/var/lib/libvirt/images/%s.qcow2' % index
+ base_image = '/tmp/base_image'
+
+ model.Libvirt.create_snapshot_qemu(self.mock_ssh, index, base_image)
+ self.mock_ssh.execute.assert_has_calls([
+ mock.call('rm -- "%s"' % vm_image),
+ mock.call('test -r %s' % base_image),
+ mock.call('qemu-img create -f qcow2 -o backing_file=%s %s' %
+ (base_image, vm_image))
+ ])
+
+ @mock.patch.object(os.path, 'basename', return_value='base_image')
+ @mock.patch.object(os.path, 'normpath')
+ @mock.patch.object(os, 'access', return_value=True)
+ def test_create_snapshot_qemu_no_image_remote(self,
+ mock_os_access, mock_normpath, mock_basename):
+ self.mock_ssh.execute = mock.Mock(
+ side_effect=[(0, 0, 0), (1, 0, 0), (0, 0, 0), (0, 0, 0)])
+ index = 1
+ vm_image = '/var/lib/libvirt/images/%s.qcow2' % index
+ base_image = '/tmp/base_image'
+ mock_normpath.return_value = base_image
+
+ model.Libvirt.create_snapshot_qemu(self.mock_ssh, index, base_image)
+ self.mock_ssh.execute.assert_has_calls([
+ mock.call('rm -- "%s"' % vm_image),
+ mock.call('test -r %s' % base_image),
+ mock.call('mv -- "/tmp/%s" "%s"' % ('base_image', base_image)),
+ mock.call('qemu-img create -f qcow2 -o backing_file=%s %s' %
+ (base_image, vm_image))
+ ])
+ mock_os_access.assert_called_once_with(base_image, os.R_OK)
+ mock_normpath.assert_called_once_with(base_image)
+ mock_basename.assert_has_calls([mock.call(base_image)])
+ self.mock_ssh.put_file.assert_called_once_with(base_image,
+ '/tmp/base_image')
+
+ @mock.patch.object(os, 'access', return_value=False)
+ def test_create_snapshot_qemu_no_image_local(self, mock_os_access):
+ self.mock_ssh.execute = mock.Mock(side_effect=[(0, 0, 0), (1, 0, 0)])
+ base_image = '/tmp/base_image'
+
+ with self.assertRaises(exceptions.LibvirtQemuImageBaseImageNotPresent):
+ model.Libvirt.create_snapshot_qemu(self.mock_ssh, 3, base_image)
+ mock_os_access.assert_called_once_with(base_image, os.R_OK)
+
+ def test_create_snapshot_qemu_error_qemuimg_command(self):
+ self.mock_ssh.execute = mock.Mock(
+ side_effect=[(0, 0, 0), (0, 0, 0), (1, 0, 0)])
+ index = 1
+ vm_image = '/var/lib/libvirt/images/%s.qcow2' % index
+ base_image = '/tmp/base_image'
+
+ with self.assertRaises(exceptions.LibvirtQemuImageCreateError):
+ model.Libvirt.create_snapshot_qemu(self.mock_ssh, index,
+ base_image)
+ self.mock_ssh.execute.assert_has_calls([
+ mock.call('rm -- "%s"' % vm_image),
+ mock.call('test -r %s' % base_image),
+ mock.call('qemu-img create -f qcow2 -o backing_file=%s %s' %
+ (base_image, vm_image))
+ ])
@mock.patch.object(model.Libvirt, 'pin_vcpu_for_perf', return_value='4,5')
@mock.patch.object(model.Libvirt, 'create_snapshot_qemu',
@@ -422,7 +478,7 @@ class OvsDeployTestCase(unittest.TestCase):
def setUp(self):
self._mock_ssh = mock.patch.object(ssh, 'SSH')
- self.mock_ssh = self._mock_ssh .start()
+ self.mock_ssh = self._mock_ssh.start()
self.ovs_deploy = model.OvsDeploy(self.mock_ssh,
'/tmp/dpdk-devbind.py',
self.OVS_DETAILS)
diff --git a/yardstick/tests/unit/benchmark/contexts/test_heat.py b/yardstick/tests/unit/benchmark/contexts/test_heat.py
index 625f97bf4..1d491fe60 100644
--- a/yardstick/tests/unit/benchmark/contexts/test_heat.py
+++ b/yardstick/tests/unit/benchmark/contexts/test_heat.py
@@ -229,7 +229,7 @@ class HeatContextTestCase(unittest.TestCase):
self.assertRaises(y_exc.HeatTemplateError,
self.test_context.deploy)
- mock_path_exists.assert_called_once()
+ mock_path_exists.assert_called()
mock_resources_template.assert_called_once()
@mock.patch.object(os.path, 'exists', return_value=False)
@@ -254,7 +254,7 @@ class HeatContextTestCase(unittest.TestCase):
'yardstick/resources/files/yardstick_key-',
self.test_context._name_task_id])
mock_genkeys.assert_called_once_with(key_filename)
- mock_path_exists.assert_called_once_with(key_filename)
+ mock_path_exists.assert_any_call(key_filename)
@mock.patch.object(heat, 'HeatTemplate')
@mock.patch.object(os.path, 'exists', return_value=False)
@@ -280,7 +280,7 @@ class HeatContextTestCase(unittest.TestCase):
'yardstick/resources/files/yardstick_key-',
self.test_context._name])
mock_genkeys.assert_called_once_with(key_filename)
- mock_path_exists.assert_called_once_with(key_filename)
+ mock_path_exists.assert_any_call(key_filename)
@mock.patch.object(heat, 'HeatTemplate')
@mock.patch.object(os.path, 'exists', return_value=False)
@@ -296,7 +296,6 @@ class HeatContextTestCase(unittest.TestCase):
self.test_context._flags.no_setup = True
self.test_context.template_file = '/bar/baz/some-heat-file'
self.test_context.get_neutron_info = mock.MagicMock()
-
self.test_context.deploy()
mock_retrieve_stack.assert_called_once_with(self.test_context._name)
@@ -306,7 +305,7 @@ class HeatContextTestCase(unittest.TestCase):
'yardstick/resources/files/yardstick_key-',
self.test_context._name])
mock_genkeys.assert_called_once_with(key_filename)
- mock_path_exists.assert_called_once_with(key_filename)
+ mock_path_exists.assert_any_call(key_filename)
@mock.patch.object(heat, 'HeatTemplate', return_value='heat_template')
@mock.patch.object(heat.HeatContext, '_add_resources_to_template')
@@ -334,7 +333,7 @@ class HeatContextTestCase(unittest.TestCase):
'yardstick/resources/files/yardstick_key-',
self.test_context._name_task_id])
mock_genkeys.assert_called_once_with(key_filename)
- mock_path_exists.assert_called_with(key_filename)
+ mock_path_exists.assert_any_call(key_filename)
mock_call_gen_keys = mock.call.gen_keys(key_filename)
mock_call_add_resources = (
diff --git a/yardstick/tests/unit/common/messaging/__init__.py b/yardstick/tests/unit/common/messaging/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/common/messaging/__init__.py
diff --git a/yardstick/tests/unit/common/messaging/test_consumer.py b/yardstick/tests/unit/common/messaging/test_consumer.py
new file mode 100644
index 000000000..612dcaecd
--- /dev/null
+++ b/yardstick/tests/unit/common/messaging/test_consumer.py
@@ -0,0 +1,54 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import mock
+from oslo_config import cfg
+import oslo_messaging
+
+from yardstick.common import messaging
+from yardstick.common.messaging import consumer
+from yardstick.tests.unit import base as ut_base
+
+
+class TestEndPoint(object):
+ def action_1(self):
+ pass
+
+
+class _MessagingConsumer(consumer.MessagingConsumer):
+ pass
+
+
+class MessagingConsumerTestCase(ut_base.BaseUnitTestCase):
+
+ def test__init(self):
+ with mock.patch.object(oslo_messaging, 'get_rpc_server') as \
+ mock_get_rpc_server, \
+ mock.patch.object(oslo_messaging, 'get_rpc_transport') as \
+ mock_get_rpc_transport, \
+ mock.patch.object(oslo_messaging, 'Target') as \
+ mock_Target:
+ mock_get_rpc_transport.return_value = 'test_rpc_transport'
+ mock_Target.return_value = 'test_Target'
+
+ _MessagingConsumer('test_topic', 'test_pid', [TestEndPoint],
+ fanout=True)
+ mock_get_rpc_transport.assert_called_once_with(
+ cfg.CONF, url=messaging.TRANSPORT_URL)
+ mock_Target.assert_called_once_with(
+ topic='test_topic', fanout=True, server=messaging.SERVER)
+ mock_get_rpc_server.assert_called_once_with(
+ 'test_rpc_transport', 'test_Target', [TestEndPoint],
+ executor=messaging.RPC_SERVER_EXECUTOR,
+ access_policy=oslo_messaging.DefaultRPCAccessPolicy)
diff --git a/yardstick/tests/unit/common/messaging/test_payloads.py b/yardstick/tests/unit/common/messaging/test_payloads.py
new file mode 100644
index 000000000..00ec220c9
--- /dev/null
+++ b/yardstick/tests/unit/common/messaging/test_payloads.py
@@ -0,0 +1,46 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from yardstick.common import exceptions
+from yardstick.common.messaging import payloads
+from yardstick.tests.unit import base as ut_base
+
+
+class _DummyPayload(payloads.Payload):
+ REQUIRED_FIELDS = {'version', 'key1', 'key2'}
+
+
+class PayloadTestCase(ut_base.BaseUnitTestCase):
+
+ def test__init(self):
+ payload = _DummyPayload(version=1, key1='value1', key2='value2')
+ self.assertEqual(1, payload.version)
+ self.assertEqual('value1', payload.key1)
+ self.assertEqual('value2', payload.key2)
+ self.assertEqual(3, len(payload._fields))
+
+ def test__init_missing_required_fields(self):
+ with self.assertRaises(exceptions.PayloadMissingAttributes):
+ _DummyPayload(key1='value1', key2='value2')
+
+ def test_obj_to_dict(self):
+ payload = _DummyPayload(version=1, key1='value1', key2='value2')
+ payload_dict = payload.obj_to_dict()
+ self.assertEqual({'version': 1, 'key1': 'value1', 'key2': 'value2'},
+ payload_dict)
+
+ def test_dict_to_obj(self):
+ _dict = {'version': 2, 'key1': 'value100', 'key2': 'value200'}
+ payload = _DummyPayload.dict_to_obj(_dict)
+ self.assertEqual(set(_dict.keys()), payload._fields)
diff --git a/yardstick/tests/unit/common/messaging/test_producer.py b/yardstick/tests/unit/common/messaging/test_producer.py
new file mode 100644
index 000000000..0289689dc
--- /dev/null
+++ b/yardstick/tests/unit/common/messaging/test_producer.py
@@ -0,0 +1,46 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import mock
+from oslo_config import cfg
+import oslo_messaging
+
+from yardstick.common import messaging
+from yardstick.common.messaging import producer
+from yardstick.tests.unit import base as ut_base
+
+
+class _MessagingProducer(producer.MessagingProducer):
+ pass
+
+
+class MessagingProducerTestCase(ut_base.BaseUnitTestCase):
+
+ def test__init(self):
+ with mock.patch.object(oslo_messaging, 'RPCClient') as \
+ mock_RPCClient, \
+ mock.patch.object(oslo_messaging, 'get_rpc_transport') as \
+ mock_get_rpc_transport, \
+ mock.patch.object(oslo_messaging, 'Target') as \
+ mock_Target:
+ mock_get_rpc_transport.return_value = 'test_rpc_transport'
+ mock_Target.return_value = 'test_Target'
+
+ _MessagingProducer('test_topic', 'test_pid', fanout=True)
+ mock_get_rpc_transport.assert_called_once_with(
+ cfg.CONF, url=messaging.TRANSPORT_URL)
+ mock_Target.assert_called_once_with(
+ topic='test_topic', fanout=True, server=messaging.SERVER)
+ mock_RPCClient.assert_called_once_with('test_rpc_transport',
+ 'test_Target')