Implemented DELETE and GET /mac_address_ranges/<uuid>
* Added exceptions.MacAddressRangeNotFound, exceptions.MacAddressRangeInUse * Implemented tests for plugin.get_mac_address_range * Implemented tests for plugin.delete_mac_address_range
This commit is contained in:
@@ -61,10 +61,12 @@ class MacAddressRangesController(wsgi.Controller):
|
|||||||
|
|
||||||
def show(self, request, id):
|
def show(self, request, id):
|
||||||
context = request.context
|
context = request.context
|
||||||
tenant_id = id
|
return {"mac_address_range":
|
||||||
if not tenant_id:
|
self._plugin.get_mac_address_range(context, id)}
|
||||||
raise webob.exc.HTTPBadRequest('invalid tenant')
|
|
||||||
return self._plugin.get_mac_address_range(context, id)
|
def delete(self, request, id, **kwargs):
|
||||||
|
context = request.context
|
||||||
|
return self._plugin.delete_mac_address_range(context, id)
|
||||||
|
|
||||||
|
|
||||||
class Mac_address_ranges(object):
|
class Mac_address_ranges(object):
|
||||||
|
|||||||
@@ -252,6 +252,10 @@ def mac_address_range_create(context, **range_dict):
|
|||||||
return new_range
|
return new_range
|
||||||
|
|
||||||
|
|
||||||
|
def mac_address_range_delete(context, mac_address_range):
|
||||||
|
context.session.delete(mac_address_range)
|
||||||
|
|
||||||
|
|
||||||
def mac_address_update(context, mac, **kwargs):
|
def mac_address_update(context, mac, **kwargs):
|
||||||
mac.update(kwargs)
|
mac.update(kwargs)
|
||||||
context.session.add(mac)
|
context.session.add(mac)
|
||||||
|
|||||||
@@ -306,7 +306,8 @@ class MacAddress(BASEV2, models.HasTenant):
|
|||||||
__tablename__ = "quark_mac_addresses"
|
__tablename__ = "quark_mac_addresses"
|
||||||
address = sa.Column(sa.BigInteger(), primary_key=True)
|
address = sa.Column(sa.BigInteger(), primary_key=True)
|
||||||
mac_address_range_id = sa.Column(
|
mac_address_range_id = sa.Column(
|
||||||
sa.String(36), sa.ForeignKey("quark_mac_address_ranges.id"),
|
sa.String(36),
|
||||||
|
sa.ForeignKey("quark_mac_address_ranges.id", ondelete="CASCADE"),
|
||||||
nullable=False)
|
nullable=False)
|
||||||
deallocated = sa.Column(sa.Boolean())
|
deallocated = sa.Column(sa.Boolean())
|
||||||
deallocated_at = sa.Column(sa.DateTime())
|
deallocated_at = sa.Column(sa.DateTime())
|
||||||
@@ -319,6 +320,11 @@ class MacAddressRange(BASEV2, models.HasId):
|
|||||||
first_address = sa.Column(sa.BigInteger(), nullable=False)
|
first_address = sa.Column(sa.BigInteger(), nullable=False)
|
||||||
last_address = sa.Column(sa.BigInteger(), nullable=False)
|
last_address = sa.Column(sa.BigInteger(), nullable=False)
|
||||||
next_auto_assign_mac = sa.Column(sa.BigInteger(), nullable=False)
|
next_auto_assign_mac = sa.Column(sa.BigInteger(), nullable=False)
|
||||||
|
allocated_macs = orm.relationship(MacAddress,
|
||||||
|
primaryjoin='and_(MacAddressRange.id=='
|
||||||
|
'MacAddress.mac_address_range_id, '
|
||||||
|
'MacAddress.deallocated!=1)',
|
||||||
|
backref="mac_address_range")
|
||||||
|
|
||||||
|
|
||||||
class Network(BASEV2, models.HasTenant, models.HasId):
|
class Network(BASEV2, models.HasTenant, models.HasId):
|
||||||
|
|||||||
@@ -5,6 +5,14 @@ class InvalidMacAddressRange(exceptions.QuantumException):
|
|||||||
message = _("Invalid MAC address range %(cidr)s.")
|
message = _("Invalid MAC address range %(cidr)s.")
|
||||||
|
|
||||||
|
|
||||||
|
class MacAddressRangeNotFound(exceptions.NotFound):
|
||||||
|
message = _("MAC address range %(mac_address_range_id) not found.")
|
||||||
|
|
||||||
|
|
||||||
|
class MacAddressRangeInUse(exceptions.InUse):
|
||||||
|
message = _("MAC address range %(mac_address_range_id) in use.")
|
||||||
|
|
||||||
|
|
||||||
class RouteNotFound(exceptions.NotFound):
|
class RouteNotFound(exceptions.NotFound):
|
||||||
message = _("Route %(route_id)s not found.")
|
message = _("Route %(route_id)s not found.")
|
||||||
|
|
||||||
|
|||||||
@@ -893,6 +893,27 @@ class Plugin(quantum_plugin_base_v2.QuantumPluginBaseV2,
|
|||||||
|
|
||||||
return self._make_port_dict(port)
|
return self._make_port_dict(port)
|
||||||
|
|
||||||
|
def get_mac_address_range(self, context, id, fields=None):
|
||||||
|
"""Retrieve a mac_address_range.
|
||||||
|
|
||||||
|
: param context: quantum api request context
|
||||||
|
: param id: UUID representing the network to fetch.
|
||||||
|
: param fields: a list of strings that are valid keys in a
|
||||||
|
network dictionary as listed in the RESOURCE_ATTRIBUTE_MAP
|
||||||
|
object in quantum/api/v2/attributes.py. Only these fields
|
||||||
|
will be returned.
|
||||||
|
"""
|
||||||
|
LOG.info("get_mac_address_range %s for tenant %s fields %s" %
|
||||||
|
(id, context.tenant_id, fields))
|
||||||
|
|
||||||
|
mac_address_range = db_api.mac_address_range_find(
|
||||||
|
context, id=id, scope=db_api.ONE)
|
||||||
|
|
||||||
|
if not mac_address_range:
|
||||||
|
raise quark_exceptions.MacAddressRangeNotFound(
|
||||||
|
mac_address_range_id=id)
|
||||||
|
return self._make_mac_range_dict(mac_address_range)
|
||||||
|
|
||||||
def get_mac_address_ranges(self, context):
|
def get_mac_address_ranges(self, context):
|
||||||
LOG.info("get_mac_address_ranges for tenant %s" % context.tenant_id)
|
LOG.info("get_mac_address_ranges for tenant %s" % context.tenant_id)
|
||||||
ranges = db_api.mac_address_range_find(context)
|
ranges = db_api.mac_address_range_find(context)
|
||||||
@@ -930,6 +951,26 @@ class Plugin(quantum_plugin_base_v2.QuantumPluginBaseV2,
|
|||||||
prefix_int = int(prefix, base=16)
|
prefix_int = int(prefix, base=16)
|
||||||
return cidr, prefix_int, prefix_int + mask_size
|
return cidr, prefix_int, prefix_int + mask_size
|
||||||
|
|
||||||
|
def _delete_mac_address_range(self, context, mac_address_range):
|
||||||
|
if mac_address_range.allocated_macs:
|
||||||
|
raise quark_exceptions.MacAddressRangeInUse(
|
||||||
|
mac_address_range_id=mac_address_range["id"])
|
||||||
|
db_api.mac_address_range_delete(context, mac_address_range)
|
||||||
|
|
||||||
|
def delete_mac_address_range(self, context, id):
|
||||||
|
"""Delete a mac_address_range.
|
||||||
|
|
||||||
|
: param context: quantum api request context
|
||||||
|
: param id: UUID representing the mac_address_range to delete.
|
||||||
|
"""
|
||||||
|
LOG.info("delete_mac_address_range %s for tenant %s" %
|
||||||
|
(id, context.tenant_id))
|
||||||
|
mar = db_api.mac_address_range_find(context, id=id, scope=db_api.ONE)
|
||||||
|
if not mar:
|
||||||
|
raise quark_exceptions.MacAddressRangeNotFound(
|
||||||
|
mac_address_range_id=id)
|
||||||
|
self._delete_mac_address_range(context, mar)
|
||||||
|
|
||||||
def get_route(self, context, id):
|
def get_route(self, context, id):
|
||||||
LOG.info("get_route %s for tenant %s" % (id, context.tenant_id))
|
LOG.info("get_route %s for tenant %s" % (id, context.tenant_id))
|
||||||
route = db_api.route_find(context, id=id)
|
route = db_api.route_find(context, id=id)
|
||||||
|
|||||||
@@ -1466,16 +1466,28 @@ class TestQuarkGetMacAddressRanges(TestQuarkPlugin):
|
|||||||
def _stubs(self, mac_range):
|
def _stubs(self, mac_range):
|
||||||
db_mod = "quark.db.api"
|
db_mod = "quark.db.api"
|
||||||
with mock.patch("%s.mac_address_range_find" % db_mod) as mar_find:
|
with mock.patch("%s.mac_address_range_find" % db_mod) as mar_find:
|
||||||
mar_find.return_value = [mac_range]
|
mar_find.return_value = mac_range
|
||||||
yield
|
yield
|
||||||
|
|
||||||
def test_find_mac_ranges(self):
|
def test_find_mac_ranges(self):
|
||||||
mar = dict(id=1, cidr="AA:BB:CC/24")
|
mar = dict(id=1, cidr="AA:BB:CC/24")
|
||||||
with self._stubs(mar):
|
with self._stubs([mar]):
|
||||||
res = self.plugin.get_mac_address_ranges(self.context)
|
res = self.plugin.get_mac_address_ranges(self.context)
|
||||||
self.assertEqual(res[0]["id"], mar["id"])
|
self.assertEqual(res[0]["id"], mar["id"])
|
||||||
self.assertEqual(res[0]["cidr"], mar["cidr"])
|
self.assertEqual(res[0]["cidr"], mar["cidr"])
|
||||||
|
|
||||||
|
def test_find_mac_range(self):
|
||||||
|
mar = dict(id=1, cidr="AA:BB:CC/24")
|
||||||
|
with self._stubs(mar):
|
||||||
|
res = self.plugin.get_mac_address_range(self.context, 1)
|
||||||
|
self.assertEqual(res["id"], mar["id"])
|
||||||
|
self.assertEqual(res["cidr"], mar["cidr"])
|
||||||
|
|
||||||
|
def test_find_mac_range_fail(self):
|
||||||
|
with self._stubs(None):
|
||||||
|
with self.assertRaises(quark_exceptions.MacAddressRangeNotFound):
|
||||||
|
self.plugin.get_mac_address_range(self.context, 1)
|
||||||
|
|
||||||
|
|
||||||
class TestQuarkCreateMacAddressRanges(TestQuarkPlugin):
|
class TestQuarkCreateMacAddressRanges(TestQuarkPlugin):
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
@@ -1537,6 +1549,40 @@ class TestQuarkCreateMacAddressRanges(TestQuarkPlugin):
|
|||||||
cidr, first, last = self.plugin._to_mac_range("F0-0-BAR")
|
cidr, first, last = self.plugin._to_mac_range("F0-0-BAR")
|
||||||
|
|
||||||
|
|
||||||
|
class TestQuarkDeleteMacAddressRanges(TestQuarkPlugin):
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def _stubs(self, mac_range):
|
||||||
|
db_mod = "quark.db.api"
|
||||||
|
with contextlib.nested(
|
||||||
|
mock.patch("%s.mac_address_range_find" % db_mod),
|
||||||
|
mock.patch("%s.mac_address_range_delete" % db_mod),
|
||||||
|
) as (mar_find, mar_delete):
|
||||||
|
mar_find.return_value = mac_range
|
||||||
|
yield mar_delete
|
||||||
|
|
||||||
|
def test_mac_address_range_delete_not_found(self):
|
||||||
|
with self._stubs(None):
|
||||||
|
with self.assertRaises(quark_exceptions.MacAddressRangeNotFound):
|
||||||
|
self.plugin.delete_mac_address_range(self.context, 1)
|
||||||
|
|
||||||
|
def test_mac_address_range_delete_in_use(self):
|
||||||
|
mar = mock.MagicMock()
|
||||||
|
mar.id = 1
|
||||||
|
mar.allocated_macs = 1
|
||||||
|
with self._stubs(mar):
|
||||||
|
with self.assertRaises(quark_exceptions.MacAddressRangeInUse):
|
||||||
|
self.plugin.delete_mac_address_range(self.context, 1)
|
||||||
|
|
||||||
|
def test_mac_address_range_delete_success(self):
|
||||||
|
mar = mock.MagicMock()
|
||||||
|
mar.id = 1
|
||||||
|
mar.allocated_macs = 0
|
||||||
|
with self._stubs(mar) as mar_delete:
|
||||||
|
resp = self.plugin.delete_mac_address_range(self.context, 1)
|
||||||
|
self.assertIsNone(resp)
|
||||||
|
mar_delete.assert_called_once_with(self.context, mar)
|
||||||
|
|
||||||
|
|
||||||
class TestQuarkGetRoutes(TestQuarkPlugin):
|
class TestQuarkGetRoutes(TestQuarkPlugin):
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def _stubs(self, routes):
|
def _stubs(self, routes):
|
||||||
|
|||||||
Reference in New Issue
Block a user