Pulls Mac Address Range plugin support out
Refactors the quark plugin by moving Mac Address Ranges and associated tests into separate submodules. Also includes a hack for a pretty heinous bug. Check out https://github.com/jkoelker/quark/issues/130 for details.
This commit is contained in:
@@ -125,11 +125,8 @@ class QuarkIpam(object):
|
|||||||
if ip_address:
|
if ip_address:
|
||||||
next_ip = ip_address
|
next_ip = ip_address
|
||||||
address = db_api.ip_address_find(
|
address = db_api.ip_address_find(
|
||||||
elevated,
|
elevated, network_id=net_id, ip_address=next_ip,
|
||||||
network_id=net_id,
|
tenant_id=elevated.tenant_id, scope=db_api.ONE)
|
||||||
ip_address=next_ip,
|
|
||||||
tenant_id=elevated.tenant_id,
|
|
||||||
scope=db_api.ONE)
|
|
||||||
if address:
|
if address:
|
||||||
raise exceptions.IpAddressGenerationFailure(net_id=net_id)
|
raise exceptions.IpAddressGenerationFailure(net_id=net_id)
|
||||||
else:
|
else:
|
||||||
@@ -143,11 +140,8 @@ class QuarkIpam(object):
|
|||||||
if ip_policy_rules and next_ip in ip_policy_rules:
|
if ip_policy_rules and next_ip in ip_policy_rules:
|
||||||
continue
|
continue
|
||||||
address = db_api.ip_address_find(
|
address = db_api.ip_address_find(
|
||||||
elevated,
|
elevated, network_id=net_id, ip_address=next_ip,
|
||||||
network_id=net_id,
|
tenant_id=elevated.tenant_id, scope=db_api.ONE)
|
||||||
ip_address=next_ip,
|
|
||||||
tenant_id=elevated.tenant_id,
|
|
||||||
scope=db_api.ONE)
|
|
||||||
|
|
||||||
address = db_api.ip_address_create(
|
address = db_api.ip_address_create(
|
||||||
elevated, address=next_ip, subnet_id=subnet["id"],
|
elevated, address=next_ip, subnet_id=subnet["id"],
|
||||||
|
|||||||
110
quark/plugin.py
110
quark/plugin.py
@@ -44,6 +44,7 @@ from quark.db import api as db_api
|
|||||||
from quark.db import models
|
from quark.db import models
|
||||||
from quark import exceptions as quark_exceptions
|
from quark import exceptions as quark_exceptions
|
||||||
from quark import network_strategy
|
from quark import network_strategy
|
||||||
|
from quark.plugin_modules import mac_address_ranges
|
||||||
from quark import plugin_views as v
|
from quark import plugin_views as v
|
||||||
|
|
||||||
LOG = logging.getLogger("neutron.quark")
|
LOG = logging.getLogger("neutron.quark")
|
||||||
@@ -75,11 +76,19 @@ quark_quota_opts = [
|
|||||||
default=20,
|
default=20,
|
||||||
help=_('Maximum security group rules in a group')),
|
help=_('Maximum security group rules in a group')),
|
||||||
]
|
]
|
||||||
|
quark_resources = [
|
||||||
|
quota.BaseResource('ports_per_network',
|
||||||
|
'quota_ports_per_network'),
|
||||||
|
quota.BaseResource('security_rules_per_group',
|
||||||
|
'quota_security_rules_per_group'),
|
||||||
|
]
|
||||||
|
|
||||||
STRATEGY = network_strategy.STRATEGY
|
STRATEGY = network_strategy.STRATEGY
|
||||||
CONF.register_opts(quark_opts, "QUARK")
|
CONF.register_opts(quark_opts, "QUARK")
|
||||||
CONF.register_opts(quark_quota_opts, "QUOTAS")
|
CONF.register_opts(quark_quota_opts, "QUOTAS")
|
||||||
|
|
||||||
|
quota.QUOTAS.register_resources(quark_resources)
|
||||||
|
|
||||||
|
|
||||||
def _pop_param(attrs, param, default=None):
|
def _pop_param(attrs, param, default=None):
|
||||||
val = attrs.pop(param, default)
|
val = attrs.pop(param, default)
|
||||||
@@ -137,14 +146,6 @@ class Plugin(neutron_plugin_base_v2.NeutronPluginBaseV2,
|
|||||||
self.ipam_reuse_after = CONF.QUARK.ipam_reuse_after
|
self.ipam_reuse_after = CONF.QUARK.ipam_reuse_after
|
||||||
neutron_db_api.register_models(base=models.BASEV2)
|
neutron_db_api.register_models(base=models.BASEV2)
|
||||||
|
|
||||||
quark_resources = [
|
|
||||||
quota.BaseResource('ports_per_network',
|
|
||||||
'quota_ports_per_network'),
|
|
||||||
quota.BaseResource('security_rules_per_group',
|
|
||||||
'quota_security_rules_per_group'),
|
|
||||||
]
|
|
||||||
quota.QUOTAS.register_resources(quark_resources)
|
|
||||||
|
|
||||||
def _make_security_group_list(self, context, group_ids):
|
def _make_security_group_list(self, context, group_ids):
|
||||||
if not group_ids or group_ids is attributes.ATTR_NOT_SPECIFIED:
|
if not group_ids or group_ids is attributes.ATTR_NOT_SPECIFIED:
|
||||||
return ([], [])
|
return ([], [])
|
||||||
@@ -888,87 +889,6 @@ class Plugin(neutron_plugin_base_v2.NeutronPluginBaseV2,
|
|||||||
the_address["deallocated"] = 1
|
the_address["deallocated"] = 1
|
||||||
return v._make_port_dict(port)
|
return v._make_port_dict(port)
|
||||||
|
|
||||||
def get_mac_address_range(self, context, id, fields=None):
|
|
||||||
"""Retrieve a mac_address_range.
|
|
||||||
|
|
||||||
: param context: neutron 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 neutron/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 v._make_mac_range_dict(mac_address_range)
|
|
||||||
|
|
||||||
def get_mac_address_ranges(self, context):
|
|
||||||
LOG.info("get_mac_address_ranges for tenant %s" % context.tenant_id)
|
|
||||||
ranges = db_api.mac_address_range_find(context)
|
|
||||||
return [v._make_mac_range_dict(m) for m in ranges]
|
|
||||||
|
|
||||||
def create_mac_address_range(self, context, mac_range):
|
|
||||||
LOG.info("create_mac_address_range for tenant %s" % context.tenant_id)
|
|
||||||
cidr = mac_range["mac_address_range"]["cidr"]
|
|
||||||
cidr, first_address, last_address = self._to_mac_range(cidr)
|
|
||||||
new_range = db_api.mac_address_range_create(
|
|
||||||
context, cidr=cidr, first_address=first_address,
|
|
||||||
last_address=last_address, next_auto_assign_mac=first_address)
|
|
||||||
return v._make_mac_range_dict(new_range)
|
|
||||||
|
|
||||||
def _to_mac_range(self, val):
|
|
||||||
cidr_parts = val.split("/")
|
|
||||||
prefix = cidr_parts[0]
|
|
||||||
|
|
||||||
#FIXME(anyone): replace is slow, but this doesn't really
|
|
||||||
# get called ever. Fix maybe?
|
|
||||||
prefix = prefix.replace(':', '')
|
|
||||||
prefix = prefix.replace('-', '')
|
|
||||||
prefix_length = len(prefix)
|
|
||||||
if prefix_length < 6 or prefix_length > 10:
|
|
||||||
raise quark_exceptions.InvalidMacAddressRange(cidr=val)
|
|
||||||
|
|
||||||
diff = 12 - len(prefix)
|
|
||||||
if len(cidr_parts) > 1:
|
|
||||||
mask = int(cidr_parts[1])
|
|
||||||
else:
|
|
||||||
mask = 48 - diff * 4
|
|
||||||
mask_size = 1 << (48 - mask)
|
|
||||||
prefix = "%s%s" % (prefix, "0" * diff)
|
|
||||||
try:
|
|
||||||
cidr = "%s/%s" % (str(netaddr.EUI(prefix)).replace("-", ":"), mask)
|
|
||||||
except netaddr.AddrFormatError:
|
|
||||||
raise quark_exceptions.InvalidMacAddressRange(cidr=val)
|
|
||||||
prefix_int = int(prefix, base=16)
|
|
||||||
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: neutron 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, scope=db_api.ONE)
|
route = db_api.route_find(context, id=id, scope=db_api.ONE)
|
||||||
@@ -1309,3 +1229,15 @@ class Plugin(neutron_plugin_base_v2.NeutronPluginBaseV2,
|
|||||||
if not ipp:
|
if not ipp:
|
||||||
raise quark_exceptions.IPPolicyNotFound(id=id)
|
raise quark_exceptions.IPPolicyNotFound(id=id)
|
||||||
db_api.ip_policy_delete(context, ipp)
|
db_api.ip_policy_delete(context, ipp)
|
||||||
|
|
||||||
|
def get_mac_address_range(self, context, id, fields=None):
|
||||||
|
return mac_address_ranges.get_mac_address_range(context, id, fields)
|
||||||
|
|
||||||
|
def get_mac_address_ranges(self, context):
|
||||||
|
return mac_address_ranges.get_mac_address_ranges(context)
|
||||||
|
|
||||||
|
def create_mac_address_range(self, context, mac_range):
|
||||||
|
return mac_address_ranges.create_mac_address_range(context, mac_range)
|
||||||
|
|
||||||
|
def delete_mac_address_range(self, context, id):
|
||||||
|
mac_address_ranges.delete_mac_address_range(context, id)
|
||||||
|
|||||||
0
quark/plugin_modules/__init__.py
Normal file
0
quark/plugin_modules/__init__.py
Normal file
110
quark/plugin_modules/mac_address_ranges.py
Normal file
110
quark/plugin_modules/mac_address_ranges.py
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
# Copyright 2013 Openstack Foundation
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import netaddr
|
||||||
|
from neutron.openstack.common import log as logging
|
||||||
|
|
||||||
|
from quark.db import api as db_api
|
||||||
|
from quark import exceptions as quark_exceptions
|
||||||
|
from quark import plugin_views as v
|
||||||
|
|
||||||
|
LOG = logging.getLogger("neutron.quark")
|
||||||
|
|
||||||
|
|
||||||
|
def _to_mac_range(val):
|
||||||
|
cidr_parts = val.split("/")
|
||||||
|
prefix = cidr_parts[0]
|
||||||
|
|
||||||
|
#FIXME(anyone): replace is slow, but this doesn't really
|
||||||
|
# get called ever. Fix maybe?
|
||||||
|
prefix = prefix.replace(':', '')
|
||||||
|
prefix = prefix.replace('-', '')
|
||||||
|
prefix_length = len(prefix)
|
||||||
|
if prefix_length < 6 or prefix_length > 10:
|
||||||
|
raise quark_exceptions.InvalidMacAddressRange(cidr=val)
|
||||||
|
|
||||||
|
diff = 12 - len(prefix)
|
||||||
|
if len(cidr_parts) > 1:
|
||||||
|
mask = int(cidr_parts[1])
|
||||||
|
else:
|
||||||
|
mask = 48 - diff * 4
|
||||||
|
mask_size = 1 << (48 - mask)
|
||||||
|
prefix = "%s%s" % (prefix, "0" * diff)
|
||||||
|
try:
|
||||||
|
cidr = "%s/%s" % (str(netaddr.EUI(prefix)).replace("-", ":"), mask)
|
||||||
|
except netaddr.AddrFormatError:
|
||||||
|
raise quark_exceptions.InvalidMacAddressRange(cidr=val)
|
||||||
|
prefix_int = int(prefix, base=16)
|
||||||
|
return cidr, prefix_int, prefix_int + mask_size
|
||||||
|
|
||||||
|
|
||||||
|
def get_mac_address_range(context, id, fields=None):
|
||||||
|
"""Retrieve a mac_address_range.
|
||||||
|
|
||||||
|
: param context: neutron 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 neutron/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 v._make_mac_range_dict(mac_address_range)
|
||||||
|
|
||||||
|
|
||||||
|
def get_mac_address_ranges(context):
|
||||||
|
LOG.info("get_mac_address_ranges for tenant %s" % context.tenant_id)
|
||||||
|
ranges = db_api.mac_address_range_find(context)
|
||||||
|
return [v._make_mac_range_dict(m) for m in ranges]
|
||||||
|
|
||||||
|
|
||||||
|
def create_mac_address_range(context, mac_range):
|
||||||
|
LOG.info("create_mac_address_range for tenant %s" % context.tenant_id)
|
||||||
|
cidr = mac_range["mac_address_range"]["cidr"]
|
||||||
|
cidr, first_address, last_address = _to_mac_range(cidr)
|
||||||
|
new_range = db_api.mac_address_range_create(
|
||||||
|
context, cidr=cidr, first_address=first_address,
|
||||||
|
last_address=last_address, next_auto_assign_mac=first_address)
|
||||||
|
return v._make_mac_range_dict(new_range)
|
||||||
|
|
||||||
|
|
||||||
|
def _delete_mac_address_range(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(context, id):
|
||||||
|
"""Delete a mac_address_range.
|
||||||
|
|
||||||
|
: param context: neutron 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)
|
||||||
|
_delete_mac_address_range(context, mar)
|
||||||
0
quark/tests/plugin_modules/__init__.py
Normal file
0
quark/tests/plugin_modules/__init__.py
Normal file
146
quark/tests/plugin_modules/test_mac_address_ranges.py
Normal file
146
quark/tests/plugin_modules/test_mac_address_ranges.py
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
# Copyright 2013 Openstack Foundation
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import contextlib
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import netaddr
|
||||||
|
|
||||||
|
from quark import exceptions as quark_exceptions
|
||||||
|
from quark.plugin_modules import mac_address_ranges
|
||||||
|
from quark.tests import test_quark_plugin
|
||||||
|
|
||||||
|
|
||||||
|
class TestQuarkGetMacAddressRanges(test_quark_plugin.TestQuarkPlugin):
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def _stubs(self, mac_range):
|
||||||
|
db_mod = "quark.db.api"
|
||||||
|
with mock.patch("%s.mac_address_range_find" % db_mod) as mar_find:
|
||||||
|
mar_find.return_value = mac_range
|
||||||
|
yield
|
||||||
|
|
||||||
|
def test_find_mac_ranges(self):
|
||||||
|
mar = dict(id=1, cidr="AA:BB:CC/24")
|
||||||
|
with self._stubs([mar]):
|
||||||
|
res = self.plugin.get_mac_address_ranges(self.context)
|
||||||
|
self.assertEqual(res[0]["id"], mar["id"])
|
||||||
|
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(test_quark_plugin.TestQuarkPlugin):
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def _stubs(self, mac_range):
|
||||||
|
db_mod = "quark.db.api"
|
||||||
|
with mock.patch("%s.mac_address_range_create" % db_mod) as mar_create:
|
||||||
|
mar_create.return_value = mac_range
|
||||||
|
yield
|
||||||
|
|
||||||
|
def test_create_range(self):
|
||||||
|
mar = dict(mac_address_range=dict(id=1, cidr="AA:BB:CC/24"))
|
||||||
|
with self._stubs(mar["mac_address_range"]):
|
||||||
|
res = self.plugin.create_mac_address_range(self.context, mar)
|
||||||
|
self.assertEqual(res["id"], mar["mac_address_range"]["id"])
|
||||||
|
self.assertEqual(res["cidr"], mar["mac_address_range"]["cidr"])
|
||||||
|
|
||||||
|
def test_to_mac_range_cidr_format(self):
|
||||||
|
cidr, first, last = mac_address_ranges._to_mac_range("AA:BB:CC/24")
|
||||||
|
first_mac = str(netaddr.EUI(first, dialect=netaddr.mac_unix))
|
||||||
|
last_mac = str(netaddr.EUI(last, dialect=netaddr.mac_unix))
|
||||||
|
self.assertEqual(cidr, "AA:BB:CC:00:00:00/24")
|
||||||
|
self.assertEqual(first_mac, "aa:bb:cc:0:0:0")
|
||||||
|
self.assertEqual(last_mac, "aa:bb:cd:0:0:0")
|
||||||
|
|
||||||
|
def test_to_mac_range_just_prefix(self):
|
||||||
|
cidr, first, last = mac_address_ranges._to_mac_range("AA:BB:CC")
|
||||||
|
first_mac = str(netaddr.EUI(first, dialect=netaddr.mac_unix))
|
||||||
|
last_mac = str(netaddr.EUI(last, dialect=netaddr.mac_unix))
|
||||||
|
self.assertEqual(cidr, "AA:BB:CC:00:00:00/24")
|
||||||
|
self.assertEqual(first_mac, "aa:bb:cc:0:0:0")
|
||||||
|
self.assertEqual(last_mac, "aa:bb:cd:0:0:0")
|
||||||
|
|
||||||
|
def test_to_mac_range_unix_format(self):
|
||||||
|
cidr, first, last = mac_address_ranges._to_mac_range("AA-BB-CC")
|
||||||
|
first_mac = str(netaddr.EUI(first, dialect=netaddr.mac_unix))
|
||||||
|
last_mac = str(netaddr.EUI(last, dialect=netaddr.mac_unix))
|
||||||
|
self.assertEqual(cidr, "AA:BB:CC:00:00:00/24")
|
||||||
|
self.assertEqual(first_mac, "aa:bb:cc:0:0:0")
|
||||||
|
self.assertEqual(last_mac, "aa:bb:cd:0:0:0")
|
||||||
|
|
||||||
|
def test_to_mac_range_unix_cidr_format(self):
|
||||||
|
cidr, first, last = mac_address_ranges._to_mac_range("AA-BB-CC/24")
|
||||||
|
first_mac = str(netaddr.EUI(first, dialect=netaddr.mac_unix))
|
||||||
|
last_mac = str(netaddr.EUI(last, dialect=netaddr.mac_unix))
|
||||||
|
self.assertEqual(cidr, "AA:BB:CC:00:00:00/24")
|
||||||
|
self.assertEqual(first_mac, "aa:bb:cc:0:0:0")
|
||||||
|
self.assertEqual(last_mac, "aa:bb:cd:0:0:0")
|
||||||
|
|
||||||
|
def test_to_mac_prefix_too_short_fails(self):
|
||||||
|
with self.assertRaises(quark_exceptions.InvalidMacAddressRange):
|
||||||
|
cidr, first, last = mac_address_ranges._to_mac_range("AA-BB")
|
||||||
|
|
||||||
|
def test_to_mac_prefix_too_long_fails(self):
|
||||||
|
with self.assertRaises(quark_exceptions.InvalidMacAddressRange):
|
||||||
|
cidr, first, last = mac_address_ranges._to_mac_range(
|
||||||
|
"AA-BB-CC-DD-EE-F0")
|
||||||
|
|
||||||
|
def test_to_mac_prefix_is_garbage_fails(self):
|
||||||
|
with self.assertRaises(quark_exceptions.InvalidMacAddressRange):
|
||||||
|
cidr, first, last = mac_address_ranges._to_mac_range("F0-0-BAR")
|
||||||
|
|
||||||
|
|
||||||
|
class TestQuarkDeleteMacAddressRanges(test_quark_plugin.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)
|
||||||
@@ -22,6 +22,7 @@ from oslo.config import cfg
|
|||||||
|
|
||||||
from quark.db import models
|
from quark.db import models
|
||||||
import quark.ipam
|
import quark.ipam
|
||||||
|
import quark.plugin
|
||||||
|
|
||||||
from quark.tests import test_base
|
from quark.tests import test_base
|
||||||
|
|
||||||
@@ -35,6 +36,10 @@ class QuarkIpamBaseTest(test_base.TestBase):
|
|||||||
models.BASEV2.metadata.create_all(neutron_session._ENGINE)
|
models.BASEV2.metadata.create_all(neutron_session._ENGINE)
|
||||||
self.ipam = quark.ipam.QuarkIpam()
|
self.ipam = quark.ipam.QuarkIpam()
|
||||||
|
|
||||||
|
# FIXME(mdietz): refactor around issue #130 and remove this
|
||||||
|
# Ensures that the perhaps_generate_uuid event handler is initialized
|
||||||
|
self.plugin = quark.plugin.Plugin()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
neutron_db_api.clear_db()
|
neutron_db_api.clear_db()
|
||||||
|
|
||||||
@@ -348,7 +353,7 @@ class QuarkIPAddressAllocateDeallocated(QuarkIpamBaseTest):
|
|||||||
False, subnet, address, addresses_found
|
False, subnet, address, addresses_found
|
||||||
) as (choose_subnet):
|
) as (choose_subnet):
|
||||||
ipaddress = self.ipam.allocate_ip_address(self.context, 0, 0, 0)
|
ipaddress = self.ipam.allocate_ip_address(self.context, 0, 0, 0)
|
||||||
self.assertIsNone(ipaddress['id'])
|
self.assertIsNotNone(ipaddress['id'])
|
||||||
self.assertTrue(choose_subnet.called)
|
self.assertTrue(choose_subnet.called)
|
||||||
|
|
||||||
def test_allocate_finds_gap_in_address_space(self):
|
def test_allocate_finds_gap_in_address_space(self):
|
||||||
@@ -368,7 +373,7 @@ class QuarkIPAddressAllocateDeallocated(QuarkIpamBaseTest):
|
|||||||
) as (choose_subnet):
|
) as (choose_subnet):
|
||||||
ipaddress = self.ipam.allocate_ip_address(self.context, 0, 0, 0)
|
ipaddress = self.ipam.allocate_ip_address(self.context, 0, 0, 0)
|
||||||
self.assertEqual(ipaddress["address"], 2)
|
self.assertEqual(ipaddress["address"], 2)
|
||||||
self.assertIsNone(ipaddress['id'])
|
self.assertIsNotNone(ipaddress['id'])
|
||||||
self.assertTrue(choose_subnet.called)
|
self.assertTrue(choose_subnet.called)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1568,128 +1568,6 @@ class TestQuarkDisassociatePort(TestQuarkPlugin):
|
|||||||
self.plugin.disassociate_port(self.context, 1, 1)
|
self.plugin.disassociate_port(self.context, 1, 1)
|
||||||
|
|
||||||
|
|
||||||
class TestQuarkGetMacAddressRanges(TestQuarkPlugin):
|
|
||||||
@contextlib.contextmanager
|
|
||||||
def _stubs(self, mac_range):
|
|
||||||
db_mod = "quark.db.api"
|
|
||||||
with mock.patch("%s.mac_address_range_find" % db_mod) as mar_find:
|
|
||||||
mar_find.return_value = mac_range
|
|
||||||
yield
|
|
||||||
|
|
||||||
def test_find_mac_ranges(self):
|
|
||||||
mar = dict(id=1, cidr="AA:BB:CC/24")
|
|
||||||
with self._stubs([mar]):
|
|
||||||
res = self.plugin.get_mac_address_ranges(self.context)
|
|
||||||
self.assertEqual(res[0]["id"], mar["id"])
|
|
||||||
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):
|
|
||||||
@contextlib.contextmanager
|
|
||||||
def _stubs(self, mac_range):
|
|
||||||
db_mod = "quark.db.api"
|
|
||||||
with mock.patch("%s.mac_address_range_create" % db_mod) as mar_create:
|
|
||||||
mar_create.return_value = mac_range
|
|
||||||
yield
|
|
||||||
|
|
||||||
def test_create_range(self):
|
|
||||||
mar = dict(mac_address_range=dict(id=1, cidr="AA:BB:CC/24"))
|
|
||||||
with self._stubs(mar["mac_address_range"]):
|
|
||||||
res = self.plugin.create_mac_address_range(self.context, mar)
|
|
||||||
self.assertEqual(res["id"], mar["mac_address_range"]["id"])
|
|
||||||
self.assertEqual(res["cidr"], mar["mac_address_range"]["cidr"])
|
|
||||||
|
|
||||||
def test_to_mac_range_cidr_format(self):
|
|
||||||
cidr, first, last = self.plugin._to_mac_range("AA:BB:CC/24")
|
|
||||||
first_mac = str(netaddr.EUI(first, dialect=netaddr.mac_unix))
|
|
||||||
last_mac = str(netaddr.EUI(last, dialect=netaddr.mac_unix))
|
|
||||||
self.assertEqual(cidr, "AA:BB:CC:00:00:00/24")
|
|
||||||
self.assertEqual(first_mac, "aa:bb:cc:0:0:0")
|
|
||||||
self.assertEqual(last_mac, "aa:bb:cd:0:0:0")
|
|
||||||
|
|
||||||
def test_to_mac_range_just_prefix(self):
|
|
||||||
cidr, first, last = self.plugin._to_mac_range("AA:BB:CC")
|
|
||||||
first_mac = str(netaddr.EUI(first, dialect=netaddr.mac_unix))
|
|
||||||
last_mac = str(netaddr.EUI(last, dialect=netaddr.mac_unix))
|
|
||||||
self.assertEqual(cidr, "AA:BB:CC:00:00:00/24")
|
|
||||||
self.assertEqual(first_mac, "aa:bb:cc:0:0:0")
|
|
||||||
self.assertEqual(last_mac, "aa:bb:cd:0:0:0")
|
|
||||||
|
|
||||||
def test_to_mac_range_unix_format(self):
|
|
||||||
cidr, first, last = self.plugin._to_mac_range("AA-BB-CC")
|
|
||||||
first_mac = str(netaddr.EUI(first, dialect=netaddr.mac_unix))
|
|
||||||
last_mac = str(netaddr.EUI(last, dialect=netaddr.mac_unix))
|
|
||||||
self.assertEqual(cidr, "AA:BB:CC:00:00:00/24")
|
|
||||||
self.assertEqual(first_mac, "aa:bb:cc:0:0:0")
|
|
||||||
self.assertEqual(last_mac, "aa:bb:cd:0:0:0")
|
|
||||||
|
|
||||||
def test_to_mac_range_unix_cidr_format(self):
|
|
||||||
cidr, first, last = self.plugin._to_mac_range("AA-BB-CC/24")
|
|
||||||
first_mac = str(netaddr.EUI(first, dialect=netaddr.mac_unix))
|
|
||||||
last_mac = str(netaddr.EUI(last, dialect=netaddr.mac_unix))
|
|
||||||
self.assertEqual(cidr, "AA:BB:CC:00:00:00/24")
|
|
||||||
self.assertEqual(first_mac, "aa:bb:cc:0:0:0")
|
|
||||||
self.assertEqual(last_mac, "aa:bb:cd:0:0:0")
|
|
||||||
|
|
||||||
def test_to_mac_prefix_too_short_fails(self):
|
|
||||||
with self.assertRaises(quark_exceptions.InvalidMacAddressRange):
|
|
||||||
cidr, first, last = self.plugin._to_mac_range("AA-BB")
|
|
||||||
|
|
||||||
def test_to_mac_prefix_too_long_fails(self):
|
|
||||||
with self.assertRaises(quark_exceptions.InvalidMacAddressRange):
|
|
||||||
cidr, first, last = self.plugin._to_mac_range("AA-BB-CC-DD-EE-F0")
|
|
||||||
|
|
||||||
def test_to_mac_prefix_is_garbage_fails(self):
|
|
||||||
with self.assertRaises(quark_exceptions.InvalidMacAddressRange):
|
|
||||||
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):
|
||||||
@@ -1891,7 +1769,6 @@ class TestQuarkCreateSecurityGroup(TestQuarkPlugin):
|
|||||||
result = self.plugin.create_security_group(
|
result = self.plugin.create_security_group(
|
||||||
self.context, {'security_group': group})
|
self.context, {'security_group': group})
|
||||||
self.assertTrue(group_create.called)
|
self.assertTrue(group_create.called)
|
||||||
print "expected: %s but got: %s" % (expected, result)
|
|
||||||
for key in expected.keys():
|
for key in expected.keys():
|
||||||
self.assertEqual(result[key], expected[key])
|
self.assertEqual(result[key], expected[key])
|
||||||
|
|
||||||
@@ -2004,7 +1881,6 @@ class TestQuarkCreateSecurityGroupRule(TestQuarkPlugin):
|
|||||||
result = self.plugin.create_security_group_rule(
|
result = self.plugin.create_security_group_rule(
|
||||||
self.context, {'security_group_rule': rule})
|
self.context, {'security_group_rule': rule})
|
||||||
self.assertTrue(rule_create.called)
|
self.assertTrue(rule_create.called)
|
||||||
print "expected: %s but got: %s" % (expected, result)
|
|
||||||
for key in expected.keys():
|
for key in expected.keys():
|
||||||
self.assertEqual(expected[key], result[key])
|
self.assertEqual(expected[key], result[key])
|
||||||
|
|
||||||
@@ -2072,7 +1948,6 @@ class TestQuarkDeleteSecurityGroupRule(TestQuarkPlugin):
|
|||||||
if rule:
|
if rule:
|
||||||
dbrule = models.SecurityGroupRule()
|
dbrule = models.SecurityGroupRule()
|
||||||
dbrule.update(dict(rule, group=dbgroup))
|
dbrule.update(dict(rule, group=dbgroup))
|
||||||
print rule
|
|
||||||
|
|
||||||
with contextlib.nested(
|
with contextlib.nested(
|
||||||
mock.patch("quark.db.api.security_group_find"),
|
mock.patch("quark.db.api.security_group_find"),
|
||||||
|
|||||||
Reference in New Issue
Block a user