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:
@@ -37,6 +37,10 @@ ipam_driver = ipam.IPAM_REGISTRY.get_strategy(ipam.QuarkIpamANY.get_name())
|
|||||||
|
|
||||||
def get_ip_addresses(context, **filters):
|
def get_ip_addresses(context, **filters):
|
||||||
LOG.info("get_ip_addresses for tenant %s" % context.tenant_id)
|
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
|
filters["_deallocated"] = False
|
||||||
addrs = db_api.ip_address_find(context, scope=db_api.ALL, **filters)
|
addrs = db_api.ip_address_find(context, scope=db_api.ALL, **filters)
|
||||||
return [v._make_ip_dict(ip) for ip in addrs]
|
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):
|
def get_ip_address(context, id):
|
||||||
LOG.info("get_ip_address %s for tenant %s" %
|
LOG.info("get_ip_address %s for tenant %s" %
|
||||||
(id, context.tenant_id))
|
(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:
|
if not addr:
|
||||||
raise quark_exceptions.IpAddressNotFound(addr_id=id)
|
raise quark_exceptions.IpAddressNotFound(addr_id=id)
|
||||||
return v._make_ip_dict(addr)
|
return v._make_ip_dict(addr)
|
||||||
@@ -108,9 +114,18 @@ def create_ip_address(context, body):
|
|||||||
if not ip_version:
|
if not ip_version:
|
||||||
raise exceptions.BadRequest(resource="ip_addresses",
|
raise exceptions.BadRequest(resource="ip_addresses",
|
||||||
msg="version is required.")
|
msg="version is required.")
|
||||||
if not network_id:
|
if network_id is None:
|
||||||
raise exceptions.BadRequest(resource="ip_addresses",
|
raise exceptions.BadRequest(resource="ip_addresses",
|
||||||
msg="network_id is required.")
|
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 = []
|
new_addresses = []
|
||||||
ports = []
|
ports = []
|
||||||
@@ -328,10 +343,11 @@ def update_port_for_ip_address(context, ip_id, id, port):
|
|||||||
if not addr:
|
if not addr:
|
||||||
raise quark_exceptions.IpAddressNotFound(addr_id=ip_id)
|
raise quark_exceptions.IpAddressNotFound(addr_id=ip_id)
|
||||||
|
|
||||||
|
require_da = False
|
||||||
ports = addr.ports
|
ports = addr.ports
|
||||||
iptype = addr.address_type
|
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()
|
raise quark_exceptions.PortRequiresDisassociation()
|
||||||
|
|
||||||
new_port = {"port": port_dict}
|
new_port = {"port": port_dict}
|
||||||
|
|||||||
@@ -264,9 +264,9 @@ def _make_ip_dict(address):
|
|||||||
"port_ids": [assoc.port_id
|
"port_ids": [assoc.port_id
|
||||||
for assoc in address["associations"]],
|
for assoc in address["associations"]],
|
||||||
"subnet_id": address["subnet_id"],
|
"subnet_id": address["subnet_id"],
|
||||||
"used_by_tenant_id": address["used_by_tenant_id"],
|
"tenant_id": address["used_by_tenant_id"],
|
||||||
"version": address["version"],
|
"version": address["version"],
|
||||||
"address_type": address['address_type']}
|
"type": address['address_type']}
|
||||||
|
|
||||||
|
|
||||||
def _make_ip_policy_dict(ipp):
|
def _make_ip_policy_dict(ipp):
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ class QuarkSharedIPs(MySqlBaseFunctionalTest):
|
|||||||
network_id=net['id'],
|
network_id=net['id'],
|
||||||
version=4)}
|
version=4)}
|
||||||
ip = ip_api.create_ip_address(self.context, shared_ip)
|
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'])
|
ports_ip = ip_api.get_ports_for_ip_address(self.context, ip['id'])
|
||||||
self.assertEqual(2, len(ports_ip))
|
self.assertEqual(2, len(ports_ip))
|
||||||
@@ -102,7 +102,7 @@ class QuarkSharedIPs(MySqlBaseFunctionalTest):
|
|||||||
network_id=net['id'],
|
network_id=net['id'],
|
||||||
version=4)}
|
version=4)}
|
||||||
ip = ip_api.create_ip_address(self.context, shared_ip)
|
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'])
|
ports_ip = ip_api.get_ports_for_ip_address(self.context, ip['id'])
|
||||||
self.assertEqual(2, len(ports_ip))
|
self.assertEqual(2, len(ports_ip))
|
||||||
@@ -130,7 +130,7 @@ class QuarkSharedIPs(MySqlBaseFunctionalTest):
|
|||||||
network_id=net['id'],
|
network_id=net['id'],
|
||||||
version=4)}
|
version=4)}
|
||||||
ip = ip_api.create_ip_address(self.context, shared_ip)
|
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'])
|
ports_ip = ip_api.get_ports_for_ip_address(self.context, ip['id'])
|
||||||
self.assertEqual(2, len(ports_ip))
|
self.assertEqual(2, len(ports_ip))
|
||||||
@@ -177,12 +177,12 @@ class QuarkSharedIPs(MySqlBaseFunctionalTest):
|
|||||||
self.assertEqual(2, len(ips))
|
self.assertEqual(2, len(ips))
|
||||||
|
|
||||||
filters = dict(device_id='a', service='derp',
|
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)
|
ips = ip_api.get_ip_addresses(self.context, **filters)
|
||||||
self.assertEqual(1, len(ips))
|
self.assertEqual(1, len(ips))
|
||||||
|
|
||||||
filters = dict(device_id='a', service='derp',
|
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)
|
ips = ip_api.get_ip_addresses(self.context, **filters)
|
||||||
self.assertEqual(1, len(ips))
|
self.assertEqual(1, len(ips))
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ class TestIpAddresses(test_quark_plugin.TestQuarkPlugin):
|
|||||||
new_addr.extend([addr_model])
|
new_addr.extend([addr_model])
|
||||||
|
|
||||||
with contextlib.nested(
|
with contextlib.nested(
|
||||||
|
mock.patch("quark.db.api.network_find"),
|
||||||
mock.patch("quark.db.api.port_find"),
|
mock.patch("quark.db.api.port_find"),
|
||||||
mock.patch(
|
mock.patch(
|
||||||
"quark.plugin_modules.ip_addresses.ipam_driver"),
|
"quark.plugin_modules.ip_addresses.ipam_driver"),
|
||||||
@@ -78,7 +79,7 @@ class TestIpAddresses(test_quark_plugin.TestQuarkPlugin):
|
|||||||
mock.patch(
|
mock.patch(
|
||||||
"quark.plugin_modules.ip_addresses"
|
"quark.plugin_modules.ip_addresses"
|
||||||
".validate_ports_on_network_and_same_segment")
|
".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
|
port_find.return_value = port_model
|
||||||
mock_ipam.allocate_ip_address.side_effect = _alloc_ip
|
mock_ipam.allocate_ip_address.side_effect = _alloc_ip
|
||||||
mock_port_associate_ip.side_effect = _port_associate_stub
|
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["network_id"], ip_address["network_id"])
|
||||||
self.assertEqual(response["port_ids"], [port["id"]])
|
self.assertEqual(response["port_ids"], [port["id"]])
|
||||||
self.assertEqual(response["subnet_id"], ip["subnet_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["version"], 4)
|
||||||
self.assertEqual(response["address"], "192.168.1.100")
|
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):
|
def test_create_ip_address_with_port(self):
|
||||||
port = dict(id=1, network_id=2, ip_addresses=[])
|
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,
|
self.plugin.create_ip_address(self.context,
|
||||||
dict(ip_address=ip_address))
|
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._stubs(port=None, addr=None):
|
||||||
with self.assertRaises(exceptions.PortNotFound):
|
with self.assertRaises(exceptions.BadRequest):
|
||||||
ip_address = {'ip_address': {'network_id': 'fake',
|
ip_address = {'ip_address': {'network_id': 'fake',
|
||||||
'device_id': 'fake',
|
|
||||||
'version': 4}}
|
'version': 4}}
|
||||||
self.plugin.create_ip_address(self.context, ip_address)
|
self.plugin.create_ip_address(self.context, ip_address)
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@ class TestIpAddresses(test_quark_plugin.TestQuarkPlugin):
|
|||||||
with self.assertRaises(exceptions.PortNotFound):
|
with self.assertRaises(exceptions.PortNotFound):
|
||||||
ip_address = {
|
ip_address = {
|
||||||
'ip_address': {
|
'ip_address': {
|
||||||
'port_id': 'fake',
|
'port_ids': ['fake'],
|
||||||
'version': 4,
|
'version': 4,
|
||||||
'network_id': 'fake'
|
'network_id': 'fake'
|
||||||
}
|
}
|
||||||
@@ -158,13 +158,14 @@ class TestCreateIpAddressQuotaCheck(test_quark_plugin.TestQuarkPlugin):
|
|||||||
port_model["ip_addresses"].append(addr_model)
|
port_model["ip_addresses"].append(addr_model)
|
||||||
|
|
||||||
with contextlib.nested(
|
with contextlib.nested(
|
||||||
|
mock.patch("quark.db.api.network_find"),
|
||||||
mock.patch("quark.db.api.port_find"),
|
mock.patch("quark.db.api.port_find"),
|
||||||
mock.patch("quark.plugin_modules.ip_addresses.ipam_driver"),
|
mock.patch("quark.plugin_modules.ip_addresses.ipam_driver"),
|
||||||
mock.patch("quark.plugin_modules.ip_addresses.db_api"
|
mock.patch("quark.plugin_modules.ip_addresses.db_api"
|
||||||
".port_associate_ip"),
|
".port_associate_ip"),
|
||||||
mock.patch("quark.plugin_modules.ip_addresses"
|
mock.patch("quark.plugin_modules.ip_addresses"
|
||||||
".validate_ports_on_network_and_same_segment")
|
".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
|
port_find.return_value = port_model
|
||||||
yield
|
yield
|
||||||
|
|
||||||
@@ -200,7 +201,7 @@ class TestQuarkSharedIPAddressCreate(test_quark_plugin.TestQuarkPlugin):
|
|||||||
mock_ipam, *args):
|
mock_ipam, *args):
|
||||||
port = dict(id=1, network_id=2, ip_addresses=[])
|
port = dict(id=1, network_id=2, ip_addresses=[])
|
||||||
ip = dict(id=1, address=3232235876, address_readable="192.168.1.100",
|
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 = models.Port()
|
||||||
port_model.update(port)
|
port_model.update(port)
|
||||||
ip_model = models.IPAddress()
|
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"),
|
ports = [dict(id=1, network_id=2, ip_addresses=[], service="none"),
|
||||||
dict(id=2, 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",
|
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]
|
port_models = [models.Port(**p) for p in ports]
|
||||||
ip_model = models.IPAddress()
|
ip_model = models.IPAddress()
|
||||||
ip_model.update(ip)
|
ip_model.update(ip)
|
||||||
@@ -253,7 +254,7 @@ class TestQuarkSharedIPAddressCreate(test_quark_plugin.TestQuarkPlugin):
|
|||||||
cfg.CONF.set_override('ipam_reuse_after', 100, "QUARK")
|
cfg.CONF.set_override('ipam_reuse_after', 100, "QUARK")
|
||||||
ports = [dict(id=1, network_id=2, ip_addresses=[])]
|
ports = [dict(id=1, network_id=2, ip_addresses=[])]
|
||||||
ip = dict(id=1, address=3232235876, address_readable="192.168.1.100",
|
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]
|
port_models = [models.Port(**p) for p in ports]
|
||||||
ip_model = models.IPAddress()
|
ip_model = models.IPAddress()
|
||||||
ip_model.update(ip)
|
ip_model.update(ip)
|
||||||
@@ -924,36 +925,6 @@ class TestQuarkGetIpAddressPort(test_quark_plugin.TestQuarkPlugin):
|
|||||||
self.assertTrue(mock_port_update.called_once_with(
|
self.assertTrue(mock_port_update.called_once_with(
|
||||||
self.context, 100, port_update))
|
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):
|
def test_update_shared_ip_deactivate(self, mock_dbapi, mock_ipam, *args):
|
||||||
port = dict(id=100, service='compute', network_id=2,
|
port = dict(id=100, service='compute', network_id=2,
|
||||||
backend_key="derp", device_id="y")
|
backend_key="derp", device_id="y")
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ SQLAlchemy>=0.7.8,<=0.9.99
|
|||||||
alembic
|
alembic
|
||||||
oslo.concurrency>=1.6.0
|
oslo.concurrency>=1.6.0
|
||||||
oslo.config>=1.2.0
|
oslo.config>=1.2.0
|
||||||
oslo.db
|
oslo.db==1.12.0
|
||||||
oslo.middleware
|
oslo.middleware
|
||||||
zope.sqlalchemy
|
zope.sqlalchemy
|
||||||
mysql-python
|
mysql-python
|
||||||
|
|||||||
Reference in New Issue
Block a user