Add existing_network context

This context lets you use existing networks that have already been
created instead of creating new networks with Rally. This is useful
when, for instance, you are using Neutron with a dumb router that is
not capable of creating new networks on the fly.

Change-Id: I3718dba57145c3e64237dcb758cdcf3505e000dd
This commit is contained in:
Chris St. Pierre 2015-07-23 15:40:57 -05:00
parent 12b1abd86d
commit 7eb81c91ba
4 changed files with 165 additions and 9 deletions

View File

@ -0,0 +1,53 @@
# All Rights Reserved.
#
# 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 rally.common.i18n import _
from rally.common import log as logging
from rally.common import utils
from rally import consts
from rally import osclients
from rally.plugins.openstack.wrappers import network as network_wrapper
from rally.task import context
LOG = logging.getLogger(__name__)
@context.configure(name="existing_network", order=349)
class ExistingNetwork(context.Context):
"""This context supports using existing networks in Rally.
This context should be used on a deployment with existing users.
"""
CONFIG_SCHEMA = {
"type": "object",
"$schema": consts.JSON_SCHEMA,
"additionalProperties": False
}
@utils.log_task_wrapper(LOG.info, _("Enter context: `existing_network`"))
def setup(self):
for user, tenant_id in utils.iterate_per_tenants(
self.context.get("users", [])):
net_wrapper = network_wrapper.wrap(
osclients.Clients(user["endpoint"]),
self.config)
self.context["tenants"][tenant_id]["networks"] = (
net_wrapper.list_networks())
@utils.log_task_wrapper(LOG.info, _("Exit context: `existing_network`"))
def cleanup(self):
"""Networks were not created by Rally, so nothing to do."""

View File

@ -112,6 +112,21 @@ class NovaNetworkWrapper(NetworkWrapper):
cidr = generate_cidr(start_cidr=self.start_cidr)
return cidr
def _marshal_network_object(self, net_obj):
"""Convert a Network object to a dict.
This helps keep return values from the NovaNetworkWrapper
compatible with those from NeutronWrapper.
:param net_obj: The Network object to convert to a dict
"""
return {"id": net_obj.id,
"cidr": net_obj.cidr,
"name": net_obj.label,
"status": "ACTIVE",
"external": False,
"tenant_id": net_obj.project_id}
def create_network(self, tenant_id, **kwargs):
"""Create network.
@ -123,18 +138,14 @@ class NovaNetworkWrapper(NetworkWrapper):
label = utils.generate_random_name("rally_net_")
network = self.client.networks.create(
tenant_id=tenant_id, cidr=cidr, label=label)
return {"id": network.id,
"cidr": network.cidr,
"name": network.label,
"status": "ACTIVE",
"external": False,
"tenant_id": tenant_id}
return self._marshal_network_object(network)
def delete_network(self, network):
return self.client.networks.delete(network["id"])
def list_networks(self):
return self.client.networks.list()
return [self._marshal_network_object(n)
for n in self.client.networks.list()]
def create_floating_ip(self, ext_network=None, **kwargs):
"""Allocate a floating ip from the given nova-network pool

View File

@ -0,0 +1,81 @@
# All Rights Reserved.
#
# 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 rally.plugins.openstack.context import existing_network
from tests.unit import test
CTX = "rally.plugins.openstack.context"
class ExistingNetworkTestCase(test.TestCase):
def setUp(self):
super(ExistingNetworkTestCase, self).setUp()
self.config = mock.MagicMock()
self.context = {
"task": mock.MagicMock(),
"users": [
{"id": 1,
"tenant_id": "tenant1",
"endpoint": mock.Mock()},
{"id": 2,
"tenant_id": "tenant2",
"endpoint": mock.Mock()},
],
"tenants": {
"tenant1": {},
"tenant2": {},
},
"config": {
"existing_network": self.config
},
}
@mock.patch("rally.osclients.Clients")
@mock.patch("rally.plugins.openstack.wrappers.network.wrap")
def test_setup(self, mock_network_wrap, mock_clients):
networks = [mock.Mock(), mock.Mock(), mock.Mock()]
net_wrappers = {
"tenant1": mock.Mock(
**{"list_networks.return_value": networks[0:2]}),
"tenant2": mock.Mock(
**{"list_networks.return_value": networks[2:]})
}
mock_network_wrap.side_effect = [net_wrappers["tenant1"],
net_wrappers["tenant2"]]
existing_network.ExistingNetwork(self.context).setup()
mock_clients.assert_has_calls([
mock.call(u["endpoint"]) for u in self.context["users"]])
mock_network_wrap.assert_has_calls([
mock.call(mock_clients.return_value, self.config),
mock.call(mock_clients.return_value, self.config)])
for net_wrapper in net_wrappers.values():
net_wrapper.list_networks.assert_called_once_with()
self.assertDictEqual(
self.context["tenants"],
{
"tenant1": {"networks": networks[0:2]},
"tenant2": {"networks": networks[2:]},
}
)
def test_cleanup(self):
# NOTE(stpierre): Test that cleanup is not abstract
existing_network.ExistingNetwork({"task": mock.MagicMock()}).cleanup()

View File

@ -30,6 +30,8 @@ class NovaNetworkWrapperTestCase(test.TestCase):
class Net(object):
def __init__(self, **kwargs):
if "tenant_id" in kwargs:
kwargs["project_id"] = kwargs.pop("tenant_id")
self.__dict__.update(kwargs)
def get_wrapper(self, *skip_cidrs, **kwargs):
@ -88,9 +90,18 @@ class NovaNetworkWrapperTestCase(test.TestCase):
def test_list_networks(self):
service = self.get_wrapper()
service.client.networks.list.return_value = "foo_list"
service.client.networks.list.reset_mock()
self.assertEqual(service.list_networks(), "foo_list")
service.client.networks.list.return_value = [
self.Net(id="foo_id", project_id="foo_tenant", cidr="foo_cidr",
label="foo_label"),
self.Net(id="bar_id", project_id="bar_tenant", cidr="bar_cidr",
label="bar_label")]
expected = [
{"id": "foo_id", "cidr": "foo_cidr", "name": "foo_label",
"status": "ACTIVE", "external": False, "tenant_id": "foo_tenant"},
{"id": "bar_id", "cidr": "bar_cidr", "name": "bar_label",
"status": "ACTIVE", "external": False, "tenant_id": "bar_tenant"}]
self.assertEqual(expected, service.list_networks())
service.client.networks.list.assert_called_once_with()
def test__get_floating_ip(self):