summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Authors2
-rw-r--r--nova/compute/api.py10
-rw-r--r--nova/compute/manager.py12
-rw-r--r--nova/exception.py4
-rw-r--r--nova/network/api.py8
-rw-r--r--nova/network/manager.py28
-rw-r--r--nova/tests/api/openstack/contrib/test_multinic_xs.py10
-rw-r--r--nova/tests/test_network.py33
-rw-r--r--nova/virt/driver.py4
9 files changed, 94 insertions, 17 deletions
diff --git a/Authors b/Authors
index d2b1b627c..2e50cfbe0 100644
--- a/Authors
+++ b/Authors
@@ -1,4 +1,5 @@
Alex Meade <alex.meade@rackspace.com>
+Alexander Sakhnov <asakhnov@mirantis.com>
Andrey Brindeyev <abrindeyev@griddynamics.com>
Andy Smith <code@term.ie>
Andy Southgate <andy.southgate@citrix.com>
@@ -64,6 +65,7 @@ Masanori Itoh <itoumsn@nttdata.co.jp>
Matt Dietz <matt.dietz@rackspace.com>
Michael Gundlach <michael.gundlach@rackspace.com>
Mike Scherbakov <mihgen@gmail.com>
+Mohammed Naser <mnaser@vexxhost.com>
Monsyne Dragon <mdragon@rackspace.com>
Monty Taylor <mordred@inaugust.com>
MORITA Kazutaka <morita.kazutaka@gmail.com>
diff --git a/nova/compute/api.py b/nova/compute/api.py
index edd1a4d64..432658bbb 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -901,8 +901,14 @@ class API(base.Base):
def add_fixed_ip(self, context, instance_id, network_id):
"""Add fixed_ip from specified network to given instance."""
self._cast_compute_message('add_fixed_ip_to_instance', context,
- instance_id,
- network_id)
+ instance_id,
+ params=dict(network_id=network_id))
+
+ @scheduler_api.reroute_compute("remove_fixed_ip")
+ def remove_fixed_ip(self, context, instance_id, address):
+ """Remove fixed_ip from specified network to given instance."""
+ self._cast_compute_message('remove_fixed_ip_from_instance', context,
+ instance_id, params=dict(address=address))
#TODO(tr3buchet): how to run this in the correct zone?
def add_network_to_project(self, context, project_id):
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 91a604934..c627d2985 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -842,6 +842,18 @@ class ComputeManager(manager.SchedulerDependentManager):
@exception.wrap_exception
@checks_instance_lock
+ def remove_fixed_ip_from_instance(self, context, instance_id, address):
+ """Calls network_api to remove existing fixed_ip from instance
+ by injecting the altered network info and resetting
+ instance networking.
+ """
+ self.network_api.remove_fixed_ip_from_instance(context, instance_id,
+ address)
+ self.inject_network_info(context, instance_id)
+ self.reset_network(context, instance_id)
+
+ @exception.wrap_exception
+ @checks_instance_lock
def pause_instance(self, context, instance_id):
"""Pause an instance on this host."""
context = context.elevated()
diff --git a/nova/exception.py b/nova/exception.py
index a6776b64f..988940d6a 100644
--- a/nova/exception.py
+++ b/nova/exception.py
@@ -377,6 +377,10 @@ class FixedIpNotFoundForInstance(FixedIpNotFound):
message = _("Instance %(instance_id)s has zero fixed ips.")
+class FixedIpNotFoundForSpecificInstance(FixedIpNotFound):
+ message = _("Instance %(instance_id)s doesn't have fixed ip '%(ip)s'.")
+
+
class FixedIpNotFoundForVirtualInterface(FixedIpNotFound):
message = _("Virtual interface %(vif_id)s has zero associated fixed ips.")
diff --git a/nova/network/api.py b/nova/network/api.py
index b2b96082b..70b1099f0 100644
--- a/nova/network/api.py
+++ b/nova/network/api.py
@@ -156,6 +156,14 @@ class API(base.Base):
{'method': 'add_fixed_ip_to_instance',
'args': args})
+ def remove_fixed_ip_from_instance(self, context, instance_id, address):
+ """Removes a fixed ip from instance from specified network."""
+ args = {'instance_id': instance_id,
+ 'address': address}
+ rpc.cast(context, FLAGS.network_topic,
+ {'method': 'remove_fixed_ip_from_instance',
+ 'args': args})
+
def add_network_to_project(self, context, project_id):
"""Force adds another network to a project."""
rpc.cast(context, FLAGS.network_topic,
diff --git a/nova/network/manager.py b/nova/network/manager.py
index d7ac460ae..824e8d24d 100644
--- a/nova/network/manager.py
+++ b/nova/network/manager.py
@@ -124,10 +124,11 @@ class RPCAllocateFixedIP(object):
used since they share code to RPC.call allocate_fixed_ip on the
correct network host to configure dnsmasq
"""
- def _allocate_fixed_ips(self, context, instance_id, networks):
+ def _allocate_fixed_ips(self, context, instance_id, networks, **kwargs):
"""Calls allocate_fixed_ip once for each network."""
green_pool = greenpool.GreenPool()
+ vpn = kwargs.pop('vpn')
for network in networks:
if network['host'] != self.host:
# need to call allocate_fixed_ip to correct network host
@@ -136,13 +137,14 @@ class RPCAllocateFixedIP(object):
args = {}
args['instance_id'] = instance_id
args['network_id'] = network['id']
+ args['vpn'] = vpn
green_pool.spawn_n(rpc.call, context, topic,
{'method': '_rpc_allocate_fixed_ip',
'args': args})
else:
# i am the correct host, run here
- self.allocate_fixed_ip(context, instance_id, network)
+ self.allocate_fixed_ip(context, instance_id, network, vpn=vpn)
# wait for all of the allocates (if any) to finish
green_pool.waitall()
@@ -371,13 +373,14 @@ class NetworkManager(manager.SchedulerDependentManager):
instance_id = kwargs.pop('instance_id')
project_id = kwargs.pop('project_id')
type_id = kwargs.pop('instance_type_id')
+ vpn = kwargs.pop('vpn')
admin_context = context.elevated()
LOG.debug(_("network allocations for instance %s"), instance_id,
context=context)
networks = self._get_networks_for_instance(admin_context, instance_id,
project_id)
self._allocate_mac_addresses(context, instance_id, networks)
- self._allocate_fixed_ips(admin_context, instance_id, networks)
+ self._allocate_fixed_ips(admin_context, instance_id, networks, vpn=vpn)
return self.get_instance_nw_info(context, instance_id, type_id)
def deallocate_for_instance(self, context, **kwargs):
@@ -489,6 +492,16 @@ class NetworkManager(manager.SchedulerDependentManager):
networks = [self.db.network_get(context, network_id)]
self._allocate_fixed_ips(context, instance_id, networks)
+ def remove_fixed_ip_from_instance(self, context, instance_id, address):
+ """Removes a fixed ip from an instance from specified network."""
+ fixed_ips = self.db.fixed_ip_get_by_instance(context, instance_id)
+ for fixed_ip in fixed_ips:
+ if fixed_ip['address'] == address:
+ self.deallocate_fixed_ip(context, address)
+ return
+ raise exception.FixedIpNotFoundForSpecificInstance(
+ instance_id=instance_id, ip=address)
+
def allocate_fixed_ip(self, context, instance_id, network, **kwargs):
"""Gets a fixed ip from the pool."""
# TODO(vish): when this is called by compute, we can associate compute
@@ -646,7 +659,7 @@ class NetworkManager(manager.SchedulerDependentManager):
'address': address,
'reserved': reserved})
- def _allocate_fixed_ips(self, context, instance_id, networks):
+ def _allocate_fixed_ips(self, context, instance_id, networks, **kwargs):
"""Calls allocate_fixed_ip once for each network."""
raise NotImplementedError()
@@ -693,7 +706,7 @@ class FlatManager(NetworkManager):
timeout_fixed_ips = False
- def _allocate_fixed_ips(self, context, instance_id, networks):
+ def _allocate_fixed_ips(self, context, instance_id, networks, **kwargs):
"""Calls allocate_fixed_ip once for each network."""
for network in networks:
self.allocate_fixed_ip(context, instance_id, network)
@@ -701,7 +714,7 @@ class FlatManager(NetworkManager):
def deallocate_fixed_ip(self, context, address, **kwargs):
"""Returns a fixed ip to the pool."""
super(FlatManager, self).deallocate_fixed_ip(context, address,
- **kwargs)
+ **kwargs)
self.db.fixed_ip_disassociate(context, address)
def setup_compute_network(self, context, instance_id):
@@ -750,7 +763,7 @@ class FlatDHCPManager(FloatingIP, RPCAllocateFixedIP, NetworkManager):
self.driver.ensure_bridge(network['bridge'],
network['bridge_interface'])
- def allocate_fixed_ip(self, context, instance_id, network):
+ def allocate_fixed_ip(self, context, instance_id, network, **kwargs):
"""Allocate flat_network fixed_ip, then setup dhcp for this network."""
address = super(FlatDHCPManager, self).allocate_fixed_ip(context,
instance_id,
@@ -812,6 +825,7 @@ class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager):
address = self.db.fixed_ip_associate_pool(context,
network['id'],
instance_id)
+
vif = self.db.virtual_interface_get_by_instance_and_network(context,
instance_id,
network['id'])
diff --git a/nova/tests/api/openstack/contrib/test_multinic_xs.py b/nova/tests/api/openstack/contrib/test_multinic_xs.py
index 484cd1c17..b0a9f7676 100644
--- a/nova/tests/api/openstack/contrib/test_multinic_xs.py
+++ b/nova/tests/api/openstack/contrib/test_multinic_xs.py
@@ -50,9 +50,8 @@ class FixedIpTest(test.TestCase):
fakes.stub_out_auth(self.stubs)
self.stubs.Set(compute.api.API, "add_fixed_ip",
compute_api_add_fixed_ip)
- # TODO(Vek): Fails until remove_fixed_ip() added
- # self.stubs.Set(compute.api.API, "remove_fixed_ip",
- # compute_api_remove_fixed_ip)
+ self.stubs.Set(compute.api.API, "remove_fixed_ip",
+ compute_api_remove_fixed_ip)
self.context = context.get_admin_context()
def tearDown(self):
@@ -98,9 +97,8 @@ class FixedIpTest(test.TestCase):
req.headers['content-type'] = 'application/json'
resp = req.get_response(fakes.wsgi_app())
- # TODO(Vek): Fails until remove_fixed_ip() added
- # self.assertEqual(resp.status_int, 202)
- # self.assertEqual(last_remove_fixed_ip, ('test_inst', '10.10.10.1'))
+ self.assertEqual(resp.status_int, 202)
+ self.assertEqual(last_remove_fixed_ip, ('test_inst', '10.10.10.1'))
def test_remove_fixed_ip_no_address(self):
global last_remove_fixed_ip
diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py
index 6d5166019..b09021e13 100644
--- a/nova/tests/test_network.py
+++ b/nova/tests/test_network.py
@@ -16,6 +16,7 @@
# under the License.
from nova import db
+from nova import exception
from nova import flags
from nova import log as logging
from nova import test
@@ -238,3 +239,35 @@ class VlanNetworkTestCase(test.TestCase):
self.assertRaises(ValueError, self.network.create_networks, None,
num_networks=100, vlan_start=1,
cidr='192.168.0.1/24', network_size=100)
+
+
+class CommonNetworkTestCase(test.TestCase):
+
+ class FakeNetworkManager(network_manager.NetworkManager):
+ """This NetworkManager doesn't call the base class so we can bypass all
+ inherited service cruft and just perform unit tests.
+ """
+
+ class FakeDB:
+ def fixed_ip_get_by_instance(self, context, instance_id):
+ return [dict(address='10.0.0.0'), dict(address='10.0.0.1'),
+ dict(address='10.0.0.2')]
+
+ def __init__(self):
+ self.db = self.FakeDB()
+ self.deallocate_called = None
+
+ def deallocate_fixed_ip(self, context, address):
+ self.deallocate_called = address
+
+ def test_remove_fixed_ip_from_instance(self):
+ manager = self.FakeNetworkManager()
+ manager.remove_fixed_ip_from_instance(None, 99, '10.0.0.1')
+
+ self.assertEquals(manager.deallocate_called, '10.0.0.1')
+
+ def test_remove_fixed_ip_from_instance_bad_input(self):
+ manager = self.FakeNetworkManager()
+ self.assertRaises(exception.FixedIpNotFoundForSpecificInstance,
+ manager.remove_fixed_ip_from_instance,
+ None, 99, 'bad input')
diff --git a/nova/virt/driver.py b/nova/virt/driver.py
index 3c4a073bf..178279d31 100644
--- a/nova/virt/driver.py
+++ b/nova/virt/driver.py
@@ -197,7 +197,7 @@ class ComputeDriver(object):
def reset_network(self, instance):
"""reset networking for specified instance"""
- raise NotImplementedError()
+ pass
def ensure_filtering_rules_for_instance(self, instance_ref):
"""Setting up filtering rules and waiting for its completion.
@@ -244,7 +244,7 @@ class ComputeDriver(object):
def inject_network_info(self, instance, nw_info):
"""inject network info for specified instance"""
- raise NotImplementedError()
+ pass
def poll_rescued_instances(self, timeout):
"""Poll for rescued instances"""