aboutsummaryrefslogtreecommitdiffstats
path: root/yardstick
diff options
context:
space:
mode:
Diffstat (limited to 'yardstick')
-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/benchmark/scenarios/compute/unixbench_benchmark.bash2
-rw-r--r--yardstick/benchmark/scenarios/lib/create_sec_group.py40
-rw-r--r--yardstick/benchmark/scenarios/lib/delete_network.py24
-rw-r--r--yardstick/common/exceptions.py24
-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/common/openstack_utils.py125
-rw-r--r--yardstick/common/utils.py5
-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/apiserver/resources/v2/__init__.py0
-rw-r--r--yardstick/tests/unit/apiserver/resources/v2/test_images.py46
-rw-r--r--yardstick/tests/unit/benchmark/contexts/standalone/test_model.py76
-rw-r--r--yardstick/tests/unit/benchmark/contexts/test_heat.py2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_sec_group.py67
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_network.py23
-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
-rw-r--r--yardstick/tests/unit/common/test_openstack_utils.py81
26 files changed, 897 insertions, 163 deletions
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/benchmark/scenarios/compute/unixbench_benchmark.bash b/yardstick/benchmark/scenarios/compute/unixbench_benchmark.bash
index 5a5dbc394..9f1804819 100644
--- a/yardstick/benchmark/scenarios/compute/unixbench_benchmark.bash
+++ b/yardstick/benchmark/scenarios/compute/unixbench_benchmark.bash
@@ -18,7 +18,7 @@ OUTPUT_FILE=/tmp/unixbench-out.log
# run unixbench test
run_unixbench()
{
- cd /opt/tempT/UnixBench/
+ cd /opt/tempT/UnixBench/UnixBench/
./Run $OPTIONS > $OUTPUT_FILE
}
diff --git a/yardstick/benchmark/scenarios/lib/create_sec_group.py b/yardstick/benchmark/scenarios/lib/create_sec_group.py
index 3d1aec9e8..1d2e36488 100644
--- a/yardstick/benchmark/scenarios/lib/create_sec_group.py
+++ b/yardstick/benchmark/scenarios/lib/create_sec_group.py
@@ -7,13 +7,11 @@
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-from __future__ import print_function
-from __future__ import absolute_import
-
import logging
from yardstick.benchmark.scenarios import base
-import yardstick.common.openstack_utils as op_utils
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
LOG = logging.getLogger(__name__)
@@ -26,11 +24,12 @@ class CreateSecgroup(base.Scenario):
def __init__(self, scenario_cfg, context_cfg):
self.scenario_cfg = scenario_cfg
self.context_cfg = context_cfg
- self.options = self.scenario_cfg['options']
+ self.options = self.scenario_cfg["options"]
- self.sg_name = self.options.get("sg_name", "yardstick_sec_group")
- self.description = self.options.get("description", None)
- self.neutron_client = op_utils.get_neutron_client()
+ self.sg_name = self.options["sg_name"]
+ self.description = self.options.get("description", "")
+ self.project_id = self.options.get("project_id")
+ self.shade_client = openstack_utils.get_shade_client()
self.setup_done = False
@@ -45,21 +44,16 @@ class CreateSecgroup(base.Scenario):
if not self.setup_done:
self.setup()
- sg_id = op_utils.create_security_group_full(self.neutron_client,
- sg_name=self.sg_name,
- sg_description=self.description)
-
- if sg_id:
- result.update({"sg_create": 1})
- LOG.info("Create security group successful!")
- else:
+ sg_id = openstack_utils.create_security_group_full(
+ self.shade_client, self.sg_name, sg_description=self.description,
+ project_id=self.project_id)
+ if not sg_id:
result.update({"sg_create": 0})
LOG.error("Create security group failed!")
+ raise exceptions.ScenarioCreateSecurityGroupError
- try:
- keys = self.scenario_cfg.get('output', '').split()
- except KeyError:
- pass
- else:
- values = [sg_id]
- return self._push_to_outputs(keys, values)
+ result.update({"sg_create": 1})
+ LOG.info("Create security group successful!")
+ keys = self.scenario_cfg.get("output", '').split()
+ values = [sg_id]
+ return self._push_to_outputs(keys, values)
diff --git a/yardstick/benchmark/scenarios/lib/delete_network.py b/yardstick/benchmark/scenarios/lib/delete_network.py
index 2e8b595f9..8874e8b1e 100644
--- a/yardstick/benchmark/scenarios/lib/delete_network.py
+++ b/yardstick/benchmark/scenarios/lib/delete_network.py
@@ -10,7 +10,8 @@
import logging
from yardstick.benchmark.scenarios import base
-import yardstick.common.openstack_utils as op_utils
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
LOG = logging.getLogger(__name__)
@@ -24,11 +25,11 @@ class DeleteNetwork(base.Scenario):
def __init__(self, scenario_cfg, context_cfg):
self.scenario_cfg = scenario_cfg
self.context_cfg = context_cfg
- self.options = self.scenario_cfg['options']
+ self.options = self.scenario_cfg["options"]
- self.network_id = self.options.get("network_id", None)
+ self.network_name_or_id = self.options["network_name_or_id"]
- self.shade_client = op_utils.get_shade_client()
+ self.shade_client = openstack_utils.get_shade_client()
self.setup_done = False
@@ -43,12 +44,13 @@ class DeleteNetwork(base.Scenario):
if not self.setup_done:
self.setup()
- status = op_utils.delete_neutron_net(self.shade_client,
- network_id=self.network_id)
- if status:
- result.update({"delete_network": 1})
- LOG.info("Delete network successful!")
- else:
+ status = openstack_utils.delete_neutron_net(self.shade_client,
+ self.network_name_or_id)
+
+ if not status:
result.update({"delete_network": 0})
LOG.error("Delete network failed!")
- return status
+ raise exceptions.ScenarioDeleteNetworkError
+
+ result.update({"delete_network": 1})
+ LOG.info("Delete network successful!")
diff --git a/yardstick/common/exceptions.py b/yardstick/common/exceptions.py
index 439b9cb1b..ec21c335b 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'
@@ -166,3 +182,11 @@ class ScenarioCreateFloatingIPError(YardstickException):
class ScenarioDeleteFloatingIPError(YardstickException):
message = 'Delete Neutron Floating IP Scenario failed'
+
+
+class ScenarioCreateSecurityGroupError(YardstickException):
+ message = 'Create Neutron Security Group Scenario failed'
+
+
+class ScenarioDeleteNetworkError(YardstickException):
+ message = 'Delete Neutron Network Scenario failed'
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/common/openstack_utils.py b/yardstick/common/openstack_utils.py
index 2785230c0..0d6afc54a 100644
--- a/yardstick/common/openstack_utils.py
+++ b/yardstick/common/openstack_utils.py
@@ -625,39 +625,6 @@ def delete_floating_ip(shade_client, floating_ip_id, retry=1):
return False
-def get_security_groups(neutron_client): # pragma: no cover
- try:
- security_groups = neutron_client.list_security_groups()[
- 'security_groups']
- return security_groups
- except Exception: # pylint: disable=broad-except
- log.error("Error [get_security_groups(neutron_client)]")
- return None
-
-
-def get_security_group_id(neutron_client, sg_name): # pragma: no cover
- security_groups = get_security_groups(neutron_client)
- id = ''
- for sg in security_groups:
- if sg['name'] == sg_name:
- id = sg['id']
- break
- return id
-
-
-def create_security_group(neutron_client, sg_name,
- sg_description): # pragma: no cover
- json_body = {'security_group': {'name': sg_name,
- 'description': sg_description}}
- try:
- secgroup = neutron_client.create_security_group(json_body)
- return secgroup['security_group']
- except Exception: # pylint: disable=broad-except
- log.error("Error [create_security_group(neutron_client, '%s', "
- "'%s')]", sg_name, sg_description)
- return None
-
-
def create_security_group_rule(shade_client, secgroup_name_or_id,
port_range_min=None, port_range_max=None,
protocol=None, remote_ip_prefix=None,
@@ -712,42 +679,52 @@ def create_security_group_rule(shade_client, secgroup_name_or_id,
return False
-def create_security_group_full(neutron_client, sg_name,
- sg_description): # pragma: no cover
- sg_id = get_security_group_id(neutron_client, sg_name)
- if sg_id != '':
- log.info("Using existing security group '%s'...", sg_name)
- else:
- log.info("Creating security group '%s'...", sg_name)
- SECGROUP = create_security_group(neutron_client,
- sg_name,
- sg_description)
- if not SECGROUP:
- log.error("Failed to create the security group...")
- return None
+def create_security_group_full(shade_client, sg_name,
+ sg_description, project_id=None):
+ security_group = shade_client.get_security_group(sg_name)
- sg_id = SECGROUP['id']
-
- log.debug("Security group '%s' with ID=%s created successfully.",
- SECGROUP['name'], sg_id)
-
- log.debug("Adding ICMP rules in security group '%s'...", sg_name)
- if not create_security_group_rule(neutron_client, sg_id,
- 'ingress', 'icmp'):
- log.error("Failed to create the security group rule...")
- return None
-
- log.debug("Adding SSH rules in security group '%s'...", sg_name)
- if not create_security_group_rule(
- neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
- log.error("Failed to create the security group rule...")
- return None
-
- if not create_security_group_rule(
- neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
- log.error("Failed to create the security group rule...")
- return None
- return sg_id
+ if security_group:
+ log.info("Using existing security group '%s'...", sg_name)
+ return security_group['id']
+
+ log.info("Creating security group '%s'...", sg_name)
+ try:
+ security_group = shade_client.create_security_group(
+ sg_name, sg_description, project_id=project_id)
+ except (exc.OpenStackCloudException,
+ exc.OpenStackCloudUnavailableFeature) as op_exc:
+ log.error("Error [create_security_group(shade_client, %s, %s)]. "
+ "Exception message: %s", sg_name, sg_description,
+ op_exc.orig_message)
+ return
+
+ log.debug("Security group '%s' with ID=%s created successfully.",
+ security_group['name'], security_group['id'])
+
+ log.debug("Adding ICMP rules in security group '%s'...", sg_name)
+ if not create_security_group_rule(shade_client, security_group['id'],
+ direction='ingress', protocol='icmp'):
+ log.error("Failed to create the security group rule...")
+ shade_client.delete_security_group(sg_name)
+ return
+
+ log.debug("Adding SSH rules in security group '%s'...", sg_name)
+ if not create_security_group_rule(shade_client, security_group['id'],
+ direction='ingress', protocol='tcp',
+ port_range_min='22',
+ port_range_max='22'):
+ log.error("Failed to create the security group rule...")
+ shade_client.delete_security_group(sg_name)
+ return
+
+ if not create_security_group_rule(shade_client, security_group['id'],
+ direction='egress', protocol='tcp',
+ port_range_min='22',
+ port_range_max='22'):
+ log.error("Failed to create the security group rule...")
+ shade_client.delete_security_group(sg_name)
+ return
+ return security_group['id']
# *********************************************
@@ -797,6 +774,18 @@ def delete_image(glance_client, image_id): # pragma: no cover
return True
+def list_images(shade_client=None):
+ if shade_client is None:
+ shade_client = get_shade_client()
+
+ try:
+ return shade_client.list_images()
+ except exc.OpenStackCloudException as o_exc:
+ log.error("Error [list_images(shade_client)]."
+ "Exception message, '%s'", o_exc.orig_message)
+ return False
+
+
# *********************************************
# CINDER
# *********************************************
diff --git a/yardstick/common/utils.py b/yardstick/common/utils.py
index 357f66be8..44cc92a7c 100644
--- a/yardstick/common/utils.py
+++ b/yardstick/common/utils.py
@@ -136,6 +136,11 @@ def source_env(env_file):
p = subprocess.Popen(". %s; env" % env_file, stdout=subprocess.PIPE,
shell=True)
output = p.communicate()[0]
+
+ # sometimes output type would be binary_type, and it don't have splitlines
+ # method, so we need to decode
+ if isinstance(output, six.binary_type):
+ output = encodeutils.safe_decode(output)
env = dict(line.split('=', 1) for line in output.splitlines() if '=' in line)
os.environ.update(env)
return env
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/apiserver/resources/v2/__init__.py b/yardstick/tests/unit/apiserver/resources/v2/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/apiserver/resources/v2/__init__.py
diff --git a/yardstick/tests/unit/apiserver/resources/v2/test_images.py b/yardstick/tests/unit/apiserver/resources/v2/test_images.py
new file mode 100644
index 000000000..ab131eec5
--- /dev/null
+++ b/yardstick/tests/unit/apiserver/resources/v2/test_images.py
@@ -0,0 +1,46 @@
+##############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+import mock
+
+import unittest
+
+from yardstick.tests.unit.apiserver import APITestCase
+from api.resources.v2.images import format_image_info
+
+
+class V2ImagesTestCase(APITestCase):
+ @mock.patch('yardstick.common.openstack_utils.list_images')
+ @mock.patch('yardstick.common.utils.source_env')
+ def test_get(self, _, mock_list_images):
+ if self.app is None:
+ unittest.skip('host config error')
+ return
+
+ single_image = mock.MagicMock()
+ single_image.name = 'yardstick-image'
+ single_image.size = 16384
+ single_image.status = 'active'
+ single_image.updated_at = '2018-04-08'
+
+ mock_list_images.return_value = [single_image]
+ url = 'api/v2/yardstick/images'
+ resp = self._get(url)
+ self.assertEqual(resp.get('status'), 1)
+
+
+class FormatImageInfoTestCase(unittest.TestCase):
+ def test_format_image_info(self):
+ image = mock.MagicMock()
+ image.name = 'yardstick-image'
+ image.size = 1048576
+ image.status = 'active'
+ image.updated_at = '2018-04-08'
+
+ image_dict = format_image_info(image)
+ self.assertEqual(image_dict.get('size'), 1)
diff --git a/yardstick/tests/unit/benchmark/contexts/standalone/test_model.py b/yardstick/tests/unit/benchmark/contexts/standalone/test_model.py
index b1dcee209..7078c89b2 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',
diff --git a/yardstick/tests/unit/benchmark/contexts/test_heat.py b/yardstick/tests/unit/benchmark/contexts/test_heat.py
index 625f97bf4..a40adf5ae 100644
--- a/yardstick/tests/unit/benchmark/contexts/test_heat.py
+++ b/yardstick/tests/unit/benchmark/contexts/test_heat.py
@@ -306,7 +306,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')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_sec_group.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_sec_group.py
index 21158ab17..0477a49d4 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_sec_group.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_sec_group.py
@@ -6,25 +6,54 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
+
+from oslo_utils import uuidutils
import unittest
import mock
-from yardstick.benchmark.scenarios.lib.create_sec_group import CreateSecgroup
-
-
-class CreateSecGroupTestCase(unittest.TestCase):
-
- @mock.patch('yardstick.common.openstack_utils.get_neutron_client')
- @mock.patch('yardstick.common.openstack_utils.create_security_group_full')
- def test_create_sec_group(self, mock_get_neutron_client, mock_create_security_group_full):
- options = {
- 'openstack_paras': {
- 'sg_name': 'yardstick_sec_group',
- 'description': 'security group for yardstick manual VM'
- }
- }
- args = {"options": options}
- obj = CreateSecgroup(args, {})
- obj.run({})
- mock_get_neutron_client.assert_called_once()
- mock_create_security_group_full.assert_called_once()
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import create_sec_group
+
+
+class CreateSecurityGroupTestCase(unittest.TestCase):
+
+ def setUp(self):
+
+ self._mock_create_security_group_full = mock.patch.object(
+ openstack_utils, 'create_security_group_full')
+ self.mock_create_security_group_full = (
+ self._mock_create_security_group_full.start())
+ self._mock_get_shade_client = mock.patch.object(
+ openstack_utils, 'get_shade_client')
+ self.mock_get_shade_client = self._mock_get_shade_client.start()
+ self._mock_log = mock.patch.object(create_sec_group, 'LOG')
+ self.mock_log = self._mock_log.start()
+ self.args = {'options': {'sg_name': 'yardstick_sg'}}
+ self.result = {}
+
+ self.csecgp_obj = create_sec_group.CreateSecgroup(self.args, mock.ANY)
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_create_security_group_full.stop()
+ self._mock_get_shade_client.stop()
+ self._mock_log.stop()
+
+ def test_run(self):
+ _uuid = uuidutils.generate_uuid()
+ self.csecgp_obj.scenario_cfg = {'output': 'id'}
+ self.mock_create_security_group_full.return_value = _uuid
+ output = self.csecgp_obj.run(self.result)
+ self.assertEqual({'sg_create': 1}, self.result)
+ self.assertEqual({'id': _uuid}, output)
+ self.mock_log.info.asset_called_once_with(
+ 'Create security group successful!')
+
+ def test_run_fail(self):
+ self.mock_create_security_group_full.return_value = None
+ with self.assertRaises(exceptions.ScenarioCreateSecurityGroupError):
+ self.csecgp_obj.run(self.result)
+ self.assertEqual({'sg_create': 0}, self.result)
+ self.mock_log.error.assert_called_once_with(
+ 'Create security group failed!')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_network.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_network.py
index aef99ee94..b6dbf4791 100644
--- a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_network.py
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_network.py
@@ -11,7 +11,8 @@ from oslo_utils import uuidutils
import unittest
import mock
-import yardstick.common.openstack_utils as op_utils
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
from yardstick.benchmark.scenarios.lib import delete_network
@@ -19,16 +20,17 @@ class DeleteNetworkTestCase(unittest.TestCase):
def setUp(self):
self._mock_delete_neutron_net = mock.patch.object(
- op_utils, 'delete_neutron_net')
+ openstack_utils, "delete_neutron_net")
self.mock_delete_neutron_net = self._mock_delete_neutron_net.start()
self._mock_get_shade_client = mock.patch.object(
- op_utils, 'get_shade_client')
+ openstack_utils, "get_shade_client")
self.mock_get_shade_client = self._mock_get_shade_client.start()
- self._mock_log = mock.patch.object(delete_network, 'LOG')
+ self._mock_log = mock.patch.object(delete_network, "LOG")
self.mock_log = self._mock_log.start()
- _uuid = uuidutils.generate_uuid()
- self.args = {'options': {'network_id': _uuid}}
- self._del_obj = delete_network.DeleteNetwork(self.args, mock.ANY)
+ self.args = {"options": {"network_name_or_id": (
+ uuidutils.generate_uuid())}}
+ self.result = {}
+ self.del_obj = delete_network.DeleteNetwork(self.args, mock.ANY)
self.addCleanup(self._stop_mock)
@@ -39,11 +41,14 @@ class DeleteNetworkTestCase(unittest.TestCase):
def test_run(self):
self.mock_delete_neutron_net.return_value = True
- self.assertTrue(self._del_obj.run({}))
+ self.assertIsNone(self.del_obj.run(self.result))
+ self.assertEqual({"delete_network": 1}, self.result)
self.mock_log.info.assert_called_once_with(
"Delete network successful!")
def test_run_fail(self):
self.mock_delete_neutron_net.return_value = False
- self.assertFalse(self._del_obj.run({}))
+ with self.assertRaises(exceptions.ScenarioDeleteNetworkError):
+ self.del_obj.run(self.result)
+ self.assertEqual({"delete_network": 0}, self.result)
self.mock_log.error.assert_called_once_with("Delete network failed!")
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')
diff --git a/yardstick/tests/unit/common/test_openstack_utils.py b/yardstick/tests/unit/common/test_openstack_utils.py
index 3b7e8eaa1..f03f2516c 100644
--- a/yardstick/tests/unit/common/test_openstack_utils.py
+++ b/yardstick/tests/unit/common/test_openstack_utils.py
@@ -39,18 +39,17 @@ class DeleteNeutronNetTestCase(unittest.TestCase):
def setUp(self):
self.mock_shade_client = mock.Mock()
- self.mock_shade_client.delete_network = mock.Mock()
def test_delete_neutron_net(self):
self.mock_shade_client.delete_network.return_value = True
output = openstack_utils.delete_neutron_net(self.mock_shade_client,
- 'network_id')
+ 'network_name_or_id')
self.assertTrue(output)
def test_delete_neutron_net_fail(self):
self.mock_shade_client.delete_network.return_value = False
output = openstack_utils.delete_neutron_net(self.mock_shade_client,
- 'network_id')
+ 'network_name_or_id')
self.assertFalse(output)
@mock.patch.object(openstack_utils, 'log')
@@ -58,7 +57,7 @@ class DeleteNeutronNetTestCase(unittest.TestCase):
self.mock_shade_client.delete_network.side_effect = (
exc.OpenStackCloudException('error message'))
output = openstack_utils.delete_neutron_net(self.mock_shade_client,
- 'network_id')
+ 'network_name_or_id')
self.assertFalse(output)
mock_logger.error.assert_called_once()
@@ -264,3 +263,77 @@ class CreateSecurityGroupRuleTestCase(unittest.TestCase):
self.mock_shade_client, self.secgroup_name_or_id)
mock_logger.error.assert_called_once()
self.assertFalse(output)
+
+
+class ListImageTestCase(unittest.TestCase):
+
+ def test_list_images(self):
+ mock_shade_client = mock.MagicMock()
+ mock_shade_client.list_images.return_value = []
+ openstack_utils.list_images(mock_shade_client)
+
+ @mock.patch.object(openstack_utils, 'log')
+ def test_list_images_exception(self, mock_logger):
+ mock_shade_client = mock.MagicMock()
+ mock_shade_client.list_images = mock.MagicMock()
+ mock_shade_client.list_images.side_effect = (
+ exc.OpenStackCloudException('error message'))
+ images = openstack_utils.list_images(mock_shade_client)
+ mock_logger.error.assert_called_once()
+ self.assertFalse(images)
+
+
+class SecurityGroupTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_shade_client = mock.Mock()
+ self.sg_name = 'sg_name'
+ self.sg_description = 'sg_description'
+ self._uuid = uuidutils.generate_uuid()
+
+ def test_create_security_group_full_existing_security_group(self):
+ self.mock_shade_client.get_security_group.return_value = (
+ {'name': 'name', 'id': self._uuid})
+ output = openstack_utils.create_security_group_full(
+ self.mock_shade_client, self.sg_name, self.sg_description)
+ self.mock_shade_client.get_security_group.assert_called_once()
+ self.assertEqual(self._uuid, output)
+
+ @mock.patch.object(openstack_utils, 'log')
+ def test_create_security_group_full_non_existing_security_group(
+ self, mock_logger):
+ self.mock_shade_client.get_security_group.return_value = None
+ self.mock_shade_client.create_security_group.side_effect = (
+ exc.OpenStackCloudException('error message'))
+ output = openstack_utils.create_security_group_full(
+ self.mock_shade_client, self.sg_name, self.sg_description)
+ mock_logger.error.assert_called_once()
+ self.assertIsNone(output)
+
+ @mock.patch.object(openstack_utils, 'create_security_group_rule')
+ @mock.patch.object(openstack_utils, 'log')
+ def test_create_security_group_full_create_rule_fail(
+ self, mock_logger, mock_create_security_group_rule):
+ self.mock_shade_client.get_security_group.return_value = None
+ self.mock_shade_client.create_security_group.return_value = (
+ {'name': 'name', 'id': self._uuid})
+ mock_create_security_group_rule.return_value = False
+ output = openstack_utils.create_security_group_full(
+ self.mock_shade_client, self.sg_name, self.sg_description)
+ mock_create_security_group_rule.assert_called()
+ self.mock_shade_client.delete_security_group(self.sg_name)
+ mock_logger.error.assert_called_once()
+ self.assertIsNone(output)
+
+ @mock.patch.object(openstack_utils, 'create_security_group_rule')
+ def test_create_security_group_full(
+ self, mock_create_security_group_rule):
+ self.mock_shade_client.get_security_group.return_value = None
+ self.mock_shade_client.create_security_group.return_value = (
+ {'name': 'name', 'id': self._uuid})
+ mock_create_security_group_rule.return_value = True
+ output = openstack_utils.create_security_group_full(
+ self.mock_shade_client, self.sg_name, self.sg_description)
+ mock_create_security_group_rule.assert_called()
+ self.mock_shade_client.delete_security_group(self.sg_name)
+ self.assertEqual(self._uuid, output)