Fixes for shared ips

Fixes JIRA:NCP-1567
Fixes JIRA:NCP-1568
Fixes JIRA:NCP-1569
Fixes JIRA:NCP-1570
This commit is contained in:
Justin Hammond
2015-07-01 11:22:57 -05:00
parent 412bd250cd
commit 39315ff721
5 changed files with 39 additions and 52 deletions

View File

@@ -37,6 +37,10 @@ ipam_driver = ipam.IPAM_REGISTRY.get_strategy(ipam.QuarkIpamANY.get_name())
def get_ip_addresses(context, **filters):
LOG.info("get_ip_addresses for tenant %s" % context.tenant_id)
if not filters:
filters = {}
if 'type' in filters:
filters['address_type'] = filters['type']
filters["_deallocated"] = False
addrs = db_api.ip_address_find(context, scope=db_api.ALL, **filters)
return [v._make_ip_dict(ip) for ip in addrs]
@@ -45,7 +49,9 @@ def get_ip_addresses(context, **filters):
def get_ip_address(context, id):
LOG.info("get_ip_address %s for tenant %s" %
(id, context.tenant_id))
addr = db_api.ip_address_find(context, id=id, scope=db_api.ONE)
filters = {}
filters["_deallocated"] = False
addr = db_api.ip_address_find(context, id=id, scope=db_api.ONE, **filters)
if not addr:
raise quark_exceptions.IpAddressNotFound(addr_id=id)
return v._make_ip_dict(addr)
@@ -108,9 +114,18 @@ def create_ip_address(context, body):
if not ip_version:
raise exceptions.BadRequest(resource="ip_addresses",
msg="version is required.")
if not network_id:
if network_id is None:
raise exceptions.BadRequest(resource="ip_addresses",
msg="network_id is required.")
if network_id == "":
raise exceptions.NetworkNotFound(net_id=network_id)
net = db_api.network_find(context, None, None, None, False,
id=network_id, scope=db_api.ONE)
if not net:
raise exceptions.NetworkNotFound(net_id=network_id)
if not port_ids and not device_ids:
raise exceptions.BadRequest(resource="ip_addresses",
msg="port_ids or device_ids required.")
new_addresses = []
ports = []
@@ -328,10 +343,11 @@ def update_port_for_ip_address(context, ip_id, id, port):
if not addr:
raise quark_exceptions.IpAddressNotFound(addr_id=ip_id)
require_da = False
ports = addr.ports
iptype = addr.address_type
if _shared_ip_and_active(iptype, ports, except_port=id):
if require_da and _shared_ip_and_active(iptype, ports, except_port=id):
raise quark_exceptions.PortRequiresDisassociation()
new_port = {"port": port_dict}

View File

@@ -264,9 +264,9 @@ def _make_ip_dict(address):
"port_ids": [assoc.port_id
for assoc in address["associations"]],
"subnet_id": address["subnet_id"],
"used_by_tenant_id": address["used_by_tenant_id"],
"tenant_id": address["used_by_tenant_id"],
"version": address["version"],
"address_type": address['address_type']}
"type": address['address_type']}
def _make_ip_policy_dict(ipp):

View File

@@ -80,7 +80,7 @@ class QuarkSharedIPs(MySqlBaseFunctionalTest):
network_id=net['id'],
version=4)}
ip = ip_api.create_ip_address(self.context, shared_ip)
self.assertEqual(ip_types.SHARED, ip['address_type'])
self.assertEqual(ip_types.SHARED, ip['type'])
ports_ip = ip_api.get_ports_for_ip_address(self.context, ip['id'])
self.assertEqual(2, len(ports_ip))
@@ -102,7 +102,7 @@ class QuarkSharedIPs(MySqlBaseFunctionalTest):
network_id=net['id'],
version=4)}
ip = ip_api.create_ip_address(self.context, shared_ip)
self.assertEqual(ip_types.SHARED, ip['address_type'])
self.assertEqual(ip_types.SHARED, ip['type'])
ports_ip = ip_api.get_ports_for_ip_address(self.context, ip['id'])
self.assertEqual(2, len(ports_ip))
@@ -130,7 +130,7 @@ class QuarkSharedIPs(MySqlBaseFunctionalTest):
network_id=net['id'],
version=4)}
ip = ip_api.create_ip_address(self.context, shared_ip)
self.assertEqual(ip_types.SHARED, ip['address_type'])
self.assertEqual(ip_types.SHARED, ip['type'])
ports_ip = ip_api.get_ports_for_ip_address(self.context, ip['id'])
self.assertEqual(2, len(ports_ip))
@@ -177,12 +177,12 @@ class QuarkSharedIPs(MySqlBaseFunctionalTest):
self.assertEqual(2, len(ips))
filters = dict(device_id='a', service='derp',
address_type=ip_types.FIXED)
type=ip_types.FIXED)
ips = ip_api.get_ip_addresses(self.context, **filters)
self.assertEqual(1, len(ips))
filters = dict(device_id='a', service='derp',
address_type=ip_types.SHARED)
type=ip_types.SHARED)
ips = ip_api.get_ip_addresses(self.context, **filters)
self.assertEqual(1, len(ips))

View File

@@ -69,6 +69,7 @@ class TestIpAddresses(test_quark_plugin.TestQuarkPlugin):
new_addr.extend([addr_model])
with contextlib.nested(
mock.patch("quark.db.api.network_find"),
mock.patch("quark.db.api.port_find"),
mock.patch(
"quark.plugin_modules.ip_addresses.ipam_driver"),
@@ -78,7 +79,7 @@ class TestIpAddresses(test_quark_plugin.TestQuarkPlugin):
mock.patch(
"quark.plugin_modules.ip_addresses"
".validate_ports_on_network_and_same_segment")
) as (port_find, mock_ipam, mock_port_associate_ip, validate):
) as (net_f, port_find, mock_ipam, mock_port_associate_ip, validate):
port_find.return_value = port_model
mock_ipam.allocate_ip_address.side_effect = _alloc_ip
mock_port_associate_ip.side_effect = _port_associate_stub
@@ -97,10 +98,10 @@ class TestIpAddresses(test_quark_plugin.TestQuarkPlugin):
self.assertEqual(response["network_id"], ip_address["network_id"])
self.assertEqual(response["port_ids"], [port["id"]])
self.assertEqual(response["subnet_id"], ip["subnet_id"])
self.assertEqual(response['address_type'], None)
self.assertEqual(response['type'], None)
self.assertEqual(response["version"], 4)
self.assertEqual(response["address"], "192.168.1.100")
self.assertEqual(response["used_by_tenant_id"], 1)
self.assertEqual(response["tenant_id"], 1)
def test_create_ip_address_with_port(self):
port = dict(id=1, network_id=2, ip_addresses=[])
@@ -125,11 +126,10 @@ class TestIpAddresses(test_quark_plugin.TestQuarkPlugin):
self.plugin.create_ip_address(self.context,
dict(ip_address=ip_address))
def test_create_ip_address_invalid_network_and_device(self):
def test_create_ip_address_invalid_missing_port_and_device_list(self):
with self._stubs(port=None, addr=None):
with self.assertRaises(exceptions.PortNotFound):
with self.assertRaises(exceptions.BadRequest):
ip_address = {'ip_address': {'network_id': 'fake',
'device_id': 'fake',
'version': 4}}
self.plugin.create_ip_address(self.context, ip_address)
@@ -138,7 +138,7 @@ class TestIpAddresses(test_quark_plugin.TestQuarkPlugin):
with self.assertRaises(exceptions.PortNotFound):
ip_address = {
'ip_address': {
'port_id': 'fake',
'port_ids': ['fake'],
'version': 4,
'network_id': 'fake'
}
@@ -158,13 +158,14 @@ class TestCreateIpAddressQuotaCheck(test_quark_plugin.TestQuarkPlugin):
port_model["ip_addresses"].append(addr_model)
with contextlib.nested(
mock.patch("quark.db.api.network_find"),
mock.patch("quark.db.api.port_find"),
mock.patch("quark.plugin_modules.ip_addresses.ipam_driver"),
mock.patch("quark.plugin_modules.ip_addresses.db_api"
".port_associate_ip"),
mock.patch("quark.plugin_modules.ip_addresses"
".validate_ports_on_network_and_same_segment")
) as (port_find, mock_ipam, mock_port_associate_ip, validate):
) as (net_f, port_find, mock_ipam, mock_port_associate_ip, validate):
port_find.return_value = port_model
yield
@@ -200,7 +201,7 @@ class TestQuarkSharedIPAddressCreate(test_quark_plugin.TestQuarkPlugin):
mock_ipam, *args):
port = dict(id=1, network_id=2, ip_addresses=[])
ip = dict(id=1, address=3232235876, address_readable="192.168.1.100",
subnet_id=1, network_id=2, version=4, used_by_tenant_id=1)
subnet_id=1, network_id=2, version=4, tenant_id=1)
port_model = models.Port()
port_model.update(port)
ip_model = models.IPAddress()
@@ -224,7 +225,7 @@ class TestQuarkSharedIPAddressCreate(test_quark_plugin.TestQuarkPlugin):
ports = [dict(id=1, network_id=2, ip_addresses=[], service="none"),
dict(id=2, network_id=2, ip_addresses=[], service="none")]
ip = dict(id=1, address=3232235876, address_readable="192.168.1.100",
subnet_id=1, network_id=2, version=4, used_by_tenant_id=1)
subnet_id=1, network_id=2, version=4, tenant_id=1)
port_models = [models.Port(**p) for p in ports]
ip_model = models.IPAddress()
ip_model.update(ip)
@@ -253,7 +254,7 @@ class TestQuarkSharedIPAddressCreate(test_quark_plugin.TestQuarkPlugin):
cfg.CONF.set_override('ipam_reuse_after', 100, "QUARK")
ports = [dict(id=1, network_id=2, ip_addresses=[])]
ip = dict(id=1, address=3232235876, address_readable="192.168.1.100",
subnet_id=1, network_id=2, version=4, used_by_tenant_id=1)
subnet_id=1, network_id=2, version=4, tenant_id=1)
port_models = [models.Port(**p) for p in ports]
ip_model = models.IPAddress()
ip_model.update(ip)
@@ -924,36 +925,6 @@ class TestQuarkGetIpAddressPort(test_quark_plugin.TestQuarkPlugin):
self.assertTrue(mock_port_update.called_once_with(
self.context, 100, port_update))
def test_fail_to_update_service_with_active_shared_ip(self, mock_dbapi,
mock_ipam, *args):
port = dict(id=100, service='none', network_id=2,
backend_key="derp", device_id="y")
port2 = dict(id=101, service='compute', network_id=2,
backend_key="derp", device_id="x")
ip = dict(id=1, address=3232235876, address_readable="192.168.1.100",
subnet_id=1, network_id=2, version=4, address_type="shared")
port_model = models.Port()
port_model2 = models.Port()
port_model.update(port)
port_model2.update(port2)
ip_model = models.IPAddress()
ip_model.update(ip)
ip_model.ports = [port_model, port_model2]
mock_port_update = patch('quark.plugin_modules.ports.update_port')
self.addCleanup(mock_port_update.stop)
mock_port_update = mock_port_update.start()
mock_dbapi.port_find.return_value = port_model
mock_dbapi.ip_address_find.return_value = ip_model
mock_ipam.allocate_ip_address.side_effect = (
self._alloc_stub(ip_model))
port_update = dict(service='derp')
port_update = {'port': port_update}
qe = quark_exceptions
with self.assertRaises(qe.PortRequiresDisassociation):
self.plugin.update_port_for_ip(self.context, 1, 100, port_update)
def test_update_shared_ip_deactivate(self, mock_dbapi, mock_ipam, *args):
port = dict(id=100, service='compute', network_id=2,
backend_key="derp", device_id="y")

View File

@@ -2,7 +2,7 @@ SQLAlchemy>=0.7.8,<=0.9.99
alembic
oslo.concurrency>=1.6.0
oslo.config>=1.2.0
oslo.db
oslo.db==1.12.0
oslo.middleware
zope.sqlalchemy
mysql-python