diff --git a/neutron/plugins/cisco/n1kv/n1kv_client.py b/neutron/plugins/cisco/n1kv/n1kv_client.py index d7ccab1e58..662199df3b 100644 --- a/neutron/plugins/cisco/n1kv/n1kv_client.py +++ b/neutron/plugins/cisco/n1kv/n1kv_client.py @@ -383,7 +383,12 @@ class Client(object): 'portProfile': policy_profile['name'], 'portProfileId': policy_profile['id'], 'tenantId': port['tenant_id'], + 'portId': port['id'], + 'macAddress': port['mac_address'], } + if port.get('fixed_ips'): + body['ipAddress'] = port['fixed_ips'][0]['ip_address'] + body['subnetId'] = port['fixed_ips'][0]['subnet_id'] return self._post(self.vm_networks_path, body=body) @@ -406,6 +411,7 @@ class Client(object): 'macAddress': port['mac_address']} if port.get('fixed_ips'): body['ipAddress'] = port['fixed_ips'][0]['ip_address'] + body['subnetId'] = port['fixed_ips'][0]['subnet_id'] return self._post(self.ports_path % vm_network_name, body=body) diff --git a/neutron/plugins/cisco/n1kv/n1kv_neutron_plugin.py b/neutron/plugins/cisco/n1kv/n1kv_neutron_plugin.py index 1e657d3cff..028808b9f2 100644 --- a/neutron/plugins/cisco/n1kv/n1kv_neutron_plugin.py +++ b/neutron/plugins/cisco/n1kv/n1kv_neutron_plugin.py @@ -867,7 +867,6 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2, n1kvclient.create_vm_network(port, vm_network_name, policy_profile) - n1kvclient.create_n1kv_port(port, vm_network_name) else: vm_network_name = vm_network['name'] n1kvclient = n1kv_client.Client() diff --git a/neutron/tests/unit/cisco/n1kv/fake_client.py b/neutron/tests/unit/cisco/n1kv/fake_client.py new file mode 100755 index 0000000000..12a36e60b0 --- /dev/null +++ b/neutron/tests/unit/cisco/n1kv/fake_client.py @@ -0,0 +1,71 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2014 Cisco Systems, Inc. +# +# 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. +# +# @author: Abhishek Raut, Cisco Systems Inc. +# @author: Sourabh Patwardhan, Cisco Systems Inc. + +from neutron.openstack.common import log as logging +from neutron.plugins.cisco.common import cisco_exceptions +from neutron.plugins.cisco.n1kv.n1kv_client import Client as n1kv_client + +LOG = logging.getLogger(__name__) + +_resource_metadata = {'port': ['id', 'macAddress', 'ipAddress', 'subnetId'], + 'vmnetwork': ['name', 'networkSegmentId', + 'networkSegment', 'portProfile', + 'portProfileId', 'tenantId', + 'portId', 'macAddress', + 'ipAddress', 'subnetId']} + + +class TestClient(n1kv_client): + + def __init__(self, **kwargs): + self.broken = False + self.inject_params = False + super(TestClient, self).__init__() + + def _do_request(self, method, action, body=None, headers=None): + if self.broken: + raise cisco_exceptions.VSMError(reason='VSM:Internal Server Error') + if self.inject_params and body: + body['invalidKey'] = 'catchMeIfYouCan' + if method == 'POST': + return _validate_resource(action, body) + + +class TestClientInvalidRequest(TestClient): + + def __init__(self, **kwargs): + super(TestClientInvalidRequest, self).__init__() + self.inject_params = True + + +def _validate_resource(action, body=None): + if body: + body_set = set(body.keys()) + else: + return + if 'vm-network' in action and 'port' not in action: + vmnetwork_set = set(_resource_metadata['vmnetwork']) + if body_set - vmnetwork_set: + raise cisco_exceptions.VSMError(reason='Invalid Request') + elif 'port' in action: + port_set = set(_resource_metadata['port']) + if body_set - port_set: + raise cisco_exceptions.VSMError(reason='Invalid Request') + else: + return diff --git a/neutron/tests/unit/cisco/n1kv/test_n1kv_plugin.py b/neutron/tests/unit/cisco/n1kv/test_n1kv_plugin.py index ac96a6d2be..0891ab80eb 100644 --- a/neutron/tests/unit/cisco/n1kv/test_n1kv_plugin.py +++ b/neutron/tests/unit/cisco/n1kv/test_n1kv_plugin.py @@ -16,6 +16,7 @@ # # @author: Juergen Brendel, Cisco Systems Inc. # @author: Abhishek Raut, Cisco Systems Inc. +# @author: Sourabh Patwardhan, Cisco Systems Inc. from mock import patch @@ -33,6 +34,7 @@ from neutron.plugins.cisco.extensions import network_profile from neutron.plugins.cisco.n1kv import n1kv_client from neutron.plugins.cisco.n1kv import n1kv_neutron_plugin from neutron.tests.unit import _test_extension_portbindings as test_bindings +from neutron.tests.unit.cisco.n1kv import fake_client from neutron.tests.unit import test_api_v2 from neutron.tests.unit import test_db_plugin as test_plugin @@ -471,6 +473,36 @@ class TestN1kvPorts(test_plugin.TestPortsV2, # Port update should fail to update policy profile id. self.assertEqual(res.status_int, 400) + def test_create_first_port_invalid_parameters_fail(self): + """Test parameters for first port create sent to the VSM.""" + profile_obj = self._make_test_policy_profile(name='test_profile') + with self.network() as network: + client_patch = patch(n1kv_client.__name__ + ".Client", + new=fake_client.TestClientInvalidRequest) + client_patch.start() + data = {'port': {n1kv.PROFILE_ID: profile_obj.id, + 'tenant_id': self.tenant_id, + 'network_id': network['network']['id'], + }} + port_req = self.new_create_request('ports', data) + res = port_req.get_response(self.api) + self.assertEqual(res.status_int, 500) + client_patch.stop() + + def test_create_next_port_invalid_parameters_fail(self): + """Test parameters for subsequent port create sent to the VSM.""" + with self.port() as port: + client_patch = patch(n1kv_client.__name__ + ".Client", + new=fake_client.TestClientInvalidRequest) + client_patch.start() + data = {'port': {n1kv.PROFILE_ID: port['port']['n1kv:profile_id'], + 'tenant_id': port['port']['tenant_id'], + 'network_id': port['port']['network_id']}} + port_req = self.new_create_request('ports', data) + res = port_req.get_response(self.api) + self.assertEqual(res.status_int, 500) + client_patch.stop() + class TestN1kvNetworks(test_plugin.TestNetworksV2, N1kvPluginTestCase):