diff --git a/nova/api/openstack/compute/contrib/networks_associate.py b/nova/api/openstack/compute/contrib/networks_associate.py index 4f5bea6ed062..256a5c610333 100644 --- a/nova/api/openstack/compute/contrib/networks_associate.py +++ b/nova/api/openstack/compute/contrib/networks_associate.py @@ -39,6 +39,10 @@ class NetworkAssociateActionController(wsgi.Controller): except exception.NetworkNotFound: msg = _("Network not found") raise exc.HTTPNotFound(explanation=msg) + except NotImplementedError: + msg = _('Disassociate host is not implemented by the configured ' + 'Network API') + raise exc.HTTPNotImplemented(explanation=msg) return exc.HTTPAccepted() @wsgi.action("disassociate_project") @@ -51,6 +55,11 @@ class NetworkAssociateActionController(wsgi.Controller): except exception.NetworkNotFound: msg = _("Network not found") raise exc.HTTPNotFound(explanation=msg) + except NotImplementedError: + msg = _('Disassociate project is not implemented by the ' + 'configured Network API') + raise exc.HTTPNotImplemented(explanation=msg) + return exc.HTTPAccepted() @wsgi.action("associate_host") @@ -64,6 +73,11 @@ class NetworkAssociateActionController(wsgi.Controller): except exception.NetworkNotFound: msg = _("Network not found") raise exc.HTTPNotFound(explanation=msg) + except NotImplementedError: + msg = _('Associate host is not implemented by the configured ' + 'Network API') + raise exc.HTTPNotImplemented(explanation=msg) + return exc.HTTPAccepted() diff --git a/nova/api/openstack/compute/contrib/os_networks.py b/nova/api/openstack/compute/contrib/os_networks.py index cc2c153312b3..241f489c5ca6 100644 --- a/nova/api/openstack/compute/contrib/os_networks.py +++ b/nova/api/openstack/compute/contrib/os_networks.py @@ -77,6 +77,10 @@ class NetworkController(wsgi.Controller): except exception.NetworkNotFound: msg = _("Network not found") raise exc.HTTPNotFound(explanation=msg) + except NotImplementedError: + msg = _('Disassociate network is not implemented by the ' + 'configured Network API') + raise exc.HTTPNotImplemented(explanation=msg) return exc.HTTPAccepted() def show(self, req, id): diff --git a/nova/network/neutronv2/api.py b/nova/network/neutronv2/api.py index ac5b8b68e9b8..eaa3f93142c3 100644 --- a/nova/network/neutronv2/api.py +++ b/nova/network/neutronv2/api.py @@ -94,6 +94,7 @@ update_instance_info_cache = network_api.update_instance_cache_with_nw_info class API(base.Base): """API for interacting with the neutron 2.x API.""" + _sentinel = object() def __init__(self): super(API, self).__init__() @@ -751,6 +752,11 @@ class API(base.Base): """Disassociate a network for client.""" raise NotImplementedError() + def associate(self, context, network_uuid, host=_sentinel, + project=_sentinel): + """Associate a network for client.""" + raise NotImplementedError() + def get_fixed_ip(self, context, id): """Get a fixed ip from the id.""" raise NotImplementedError() diff --git a/nova/tests/api/openstack/compute/contrib/test_networks.py b/nova/tests/api/openstack/compute/contrib/test_networks.py index e8bab4cec167..31437ea37cd8 100644 --- a/nova/tests/api/openstack/compute/contrib/test_networks.py +++ b/nova/tests/api/openstack/compute/contrib/test_networks.py @@ -28,6 +28,7 @@ import nova.context from nova import exception from nova import test from nova.tests.api.openstack import fakes +import nova.utils CONF = cfg.CONF @@ -202,6 +203,7 @@ class NetworksTest(test.NoDBTestCase): self.associate_controller = networks_associate\ .NetworkAssociateActionController(self.fake_network_api) fakes.stub_out_networking(self.stubs) + nova.utils.reset_is_neutron() fakes.stub_out_rate_limiting(self.stubs) @staticmethod @@ -347,3 +349,41 @@ class NetworksTest(test.NoDBTestCase): res_dict = self.controller.create(req, large_network) self.assertEqual(res_dict['network']['cidr'], large_network['network']['cidr']) + + def test_network_neutron_associate_not_implemented(self): + uuid = FAKE_NETWORKS[1]['uuid'] + self.flags(network_api_class='nova.network.neutronv2.api.API') + assoc_ctrl = networks_associate.NetworkAssociateActionController() + + req = fakes.HTTPRequest.blank('/v2/1234/os-networks/%s/action' % uuid) + self.assertRaises(webob.exc.HTTPNotImplemented, + assoc_ctrl._associate_host, + req, uuid, {'associate_host': "TestHost"}) + + def test_network_neutron_disassociate_project_not_implemented(self): + uuid = FAKE_NETWORKS[1]['uuid'] + self.flags(network_api_class='nova.network.neutronv2.api.API') + assoc_ctrl = networks_associate.NetworkAssociateActionController() + + req = fakes.HTTPRequest.blank('/v2/1234/os-networks/%s/action' % uuid) + self.assertRaises(webob.exc.HTTPNotImplemented, + assoc_ctrl._disassociate_project_only, + req, uuid, {'disassociate_project': None}) + + def test_network_neutron_disassociate_host_not_implemented(self): + uuid = FAKE_NETWORKS[1]['uuid'] + self.flags(network_api_class='nova.network.neutronv2.api.API') + assoc_ctrl = networks_associate.NetworkAssociateActionController() + req = fakes.HTTPRequest.blank('/v2/1234/os-networks/%s/action' % uuid) + self.assertRaises(webob.exc.HTTPNotImplemented, + assoc_ctrl._disassociate_host_only, + req, uuid, {'disassociate_host': None}) + + def test_network_neutron_disassociate_not_implemented(self): + uuid = FAKE_NETWORKS[1]['uuid'] + self.flags(network_api_class='nova.network.neutronv2.api.API') + controller = networks.NetworkController() + req = fakes.HTTPRequest.blank('/v2/1234/os-networks/%s/action' % uuid) + self.assertRaises(webob.exc.HTTPNotImplemented, + controller._disassociate_host_and_project, + req, uuid, {'disassociate': None}) diff --git a/nova/tests/network/test_neutronv2.py b/nova/tests/network/test_neutronv2.py index 6add77f0e352..34430e69b40b 100644 --- a/nova/tests/network/test_neutronv2.py +++ b/nova/tests/network/test_neutronv2.py @@ -2091,6 +2091,12 @@ class TestNeutronv2Portbinding(TestNeutronv2Base): api.migrate_instance_finish, self.context, self.instance, migration) + def test_associate_not_implemented(self): + api = neutronapi.API() + self.assertRaises(NotImplementedError, + api.associate, + self.context, 'id') + class TestNeutronv2ExtraDhcpOpts(TestNeutronv2Base): def setUp(self):