Merge branch 'master' of github.com:jkoelker/quark
This commit is contained in:
commit
f16f1f91a0
21
quark/db/custom_types.py
Normal file
21
quark/db/custom_types.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy import types
|
||||||
|
from sqlalchemy.dialects import sqlite
|
||||||
|
|
||||||
|
|
||||||
|
class INET(types.TypeDecorator):
|
||||||
|
impl = types.LargeBinary
|
||||||
|
|
||||||
|
def load_dialect_impl(self, dialect):
|
||||||
|
if dialect.name == 'sqlite':
|
||||||
|
return dialect.type_descriptor(sqlite.CHAR)
|
||||||
|
return dialect.type_descriptor(self.impl)
|
||||||
|
|
||||||
|
|
||||||
|
class MACAddress(types.TypeDecorator):
|
||||||
|
impl = types.BigInteger
|
||||||
|
|
||||||
|
def load_dialect_impl(self, dialect):
|
||||||
|
if dialect.name == 'sqlite':
|
||||||
|
return dialect.type_descriptor(sqlite.CHAR)
|
||||||
|
return dialect.type_descriptor(self.impl)
|
@ -26,6 +26,8 @@ from quantum.db.models_v2 import HasTenant, HasId
|
|||||||
from quantum.openstack.common import timeutils
|
from quantum.openstack.common import timeutils
|
||||||
from quantum.openstack.common import log as logging
|
from quantum.openstack.common import log as logging
|
||||||
|
|
||||||
|
from quark.db import custom_types
|
||||||
|
|
||||||
LOG = logging.getLogger("quantum.quark.db.models")
|
LOG = logging.getLogger("quantum.quark.db.models")
|
||||||
|
|
||||||
|
|
||||||
@ -109,7 +111,7 @@ class IPAddress(BASEV2, HasId, HasTenant):
|
|||||||
|
|
||||||
address_readable = sa.Column(sa.String(128), nullable=False)
|
address_readable = sa.Column(sa.String(128), nullable=False)
|
||||||
|
|
||||||
address = sa.Column(sa.LargeBinary(16), nullable=False)
|
address = sa.Column(custom_types.INET(), nullable=False)
|
||||||
|
|
||||||
subnet_id = sa.Column(sa.String(36),
|
subnet_id = sa.Column(sa.String(36),
|
||||||
sa.ForeignKey("quark_subnets.id",
|
sa.ForeignKey("quark_subnets.id",
|
||||||
@ -191,11 +193,15 @@ class Subnet(BASEV2, HasId, HasTenant, IsHazTags):
|
|||||||
def cidr(cls):
|
def cidr(cls):
|
||||||
return Subnet._cidr
|
return Subnet._cidr
|
||||||
|
|
||||||
first_ip = sa.Column(sa.LargeBinary())
|
first_ip = sa.Column(custom_types.INET())
|
||||||
last_ip = sa.Column(sa.LargeBinary())
|
last_ip = sa.Column(custom_types.INET())
|
||||||
ip_version = sa.Column(sa.Integer())
|
ip_version = sa.Column(sa.Integer())
|
||||||
|
|
||||||
allocated_ips = orm.relationship(IPAddress, backref="subnet")
|
allocated_ips = orm.relationship(IPAddress,
|
||||||
|
primaryjoin=
|
||||||
|
'and_(Subnet.id==IPAddress.subnet_id, '
|
||||||
|
'IPAddress._deallocated!=1)',
|
||||||
|
backref="subnet")
|
||||||
routes = orm.relationship(Route, backref='subnet', cascade='delete')
|
routes = orm.relationship(Route, backref='subnet', cascade='delete')
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ class QuarkIpam(object):
|
|||||||
return deallocated_mac
|
return deallocated_mac
|
||||||
|
|
||||||
ranges = session.query(models.MacAddressRange,
|
ranges = session.query(models.MacAddressRange,
|
||||||
sql_func.count(models.MacAddress).
|
sql_func.count(models.MacAddress.address).
|
||||||
label("count")).\
|
label("count")).\
|
||||||
outerjoin(models.MacAddress).\
|
outerjoin(models.MacAddress).\
|
||||||
group_by(models.MacAddressRange).\
|
group_by(models.MacAddressRange).\
|
||||||
@ -127,6 +127,7 @@ class QuarkIpam(object):
|
|||||||
address["version"] = subnet["ip_version"]
|
address["version"] = subnet["ip_version"]
|
||||||
address["network_id"] = net_id
|
address["network_id"] = net_id
|
||||||
address["tenant_id"] = subnet["tenant_id"]
|
address["tenant_id"] = subnet["tenant_id"]
|
||||||
|
address["_deallocated"] = 0
|
||||||
|
|
||||||
if address:
|
if address:
|
||||||
address["port_id"] = port_id
|
address["port_id"] = port_id
|
||||||
|
@ -49,7 +49,8 @@ quark_opts = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
CONF.register_opts(quark_opts, "QUARK")
|
CONF.register_opts(quark_opts, "QUARK")
|
||||||
CONF.set_override('api_extensions_path', ":".join(extensions.__path__))
|
if 'api_extensions_path' in CONF:
|
||||||
|
CONF.set_override('api_extensions_path', ":".join(extensions.__path__))
|
||||||
|
|
||||||
|
|
||||||
class Plugin(quantum_plugin_base_v2.QuantumPluginBaseV2):
|
class Plugin(quantum_plugin_base_v2.QuantumPluginBaseV2):
|
||||||
@ -343,7 +344,7 @@ class Plugin(quantum_plugin_base_v2.QuantumPluginBaseV2):
|
|||||||
subnets = []
|
subnets = []
|
||||||
if network["network"].get("subnets"):
|
if network["network"].get("subnets"):
|
||||||
subnets = network["network"].pop("subnets")
|
subnets = network["network"].pop("subnets")
|
||||||
new_net = models.Network(id=net_uuid)
|
new_net = models.Network(id=net_uuid, tenant_id=context.tenant_id)
|
||||||
new_net.update(network["network"])
|
new_net.update(network["network"])
|
||||||
|
|
||||||
for sub in subnets:
|
for sub in subnets:
|
||||||
@ -520,6 +521,7 @@ class Plugin(quantum_plugin_base_v2.QuantumPluginBaseV2):
|
|||||||
new_port["backend_key"] = backend_port["uuid"]
|
new_port["backend_key"] = backend_port["uuid"]
|
||||||
new_port["addresses"] = addresses
|
new_port["addresses"] = addresses
|
||||||
new_port["mac_address"] = mac["address"]
|
new_port["mac_address"] = mac["address"]
|
||||||
|
new_port["tenant_id"] = context.tenant_id
|
||||||
|
|
||||||
session.add(new_port)
|
session.add(new_port)
|
||||||
session.add(mac)
|
session.add(mac)
|
||||||
@ -665,8 +667,9 @@ class Plugin(quantum_plugin_base_v2.QuantumPluginBaseV2):
|
|||||||
raise exceptions.NetworkNotFound(net_id=id)
|
raise exceptions.NetworkNotFound(net_id=id)
|
||||||
|
|
||||||
backend_key = port["backend_key"]
|
backend_key = port["backend_key"]
|
||||||
|
mac_address = netaddr.EUI(port["mac_address"]).value
|
||||||
self.ipam_driver.deallocate_mac_address(session,
|
self.ipam_driver.deallocate_mac_address(session,
|
||||||
port["mac_address"])
|
mac_address,)
|
||||||
self.ipam_driver.deallocate_ip_address(
|
self.ipam_driver.deallocate_ip_address(
|
||||||
session, id, ipam_reuse_after=self.ipam_reuse_after)
|
session, id, ipam_reuse_after=self.ipam_reuse_after)
|
||||||
session.delete(port)
|
session.delete(port)
|
||||||
|
6
quark/tests/test_base.py
Normal file
6
quark/tests/test_base.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import unittest2
|
||||||
|
|
||||||
|
|
||||||
|
class TestBase(unittest2.TestCase):
|
||||||
|
'''Class to decide which unit test class to inherit from uniformly.'''
|
||||||
|
pass
|
51
quark/tests/test_db_models.py
Normal file
51
quark/tests/test_db_models.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
from collections import namedtuple
|
||||||
|
from sqlalchemy import create_engine
|
||||||
|
|
||||||
|
from quantum.db import api as db_api
|
||||||
|
|
||||||
|
from quark.db import models
|
||||||
|
import quark.plugin
|
||||||
|
|
||||||
|
import test_base
|
||||||
|
|
||||||
|
|
||||||
|
class TestSubnets(test_base.TestBase):
|
||||||
|
def setUp(self):
|
||||||
|
db_api._ENGINE = create_engine('sqlite://')
|
||||||
|
db_api.register_models()
|
||||||
|
self.session = db_api.get_session()
|
||||||
|
self.plugin = quark.plugin.Plugin()
|
||||||
|
|
||||||
|
def test_allocated_ips_only(self):
|
||||||
|
MockContext = namedtuple('MockContext', ['tenant_id', 'session'])
|
||||||
|
context = MockContext('0', self.session)
|
||||||
|
|
||||||
|
# 1. Create network
|
||||||
|
network = {'network': {'name': 'test'}}
|
||||||
|
response = self.plugin.create_network(context, network)
|
||||||
|
network_id = response['id']
|
||||||
|
|
||||||
|
# 2. Create subnet
|
||||||
|
subnet = {'subnet': {'cidr': '192.168.10.1/24',
|
||||||
|
'network_id': network_id}}
|
||||||
|
self.plugin.create_subnet(context, subnet)
|
||||||
|
|
||||||
|
# 3. Create M.A.R.
|
||||||
|
mac_range = {'mac_address_range': {'cidr': '01:23:45/24'}}
|
||||||
|
self.plugin.create_mac_address_range(context, mac_range)
|
||||||
|
|
||||||
|
# 4. Create port
|
||||||
|
port = {'port': {'network_id': network_id,
|
||||||
|
'device_id': ''}}
|
||||||
|
response = self.plugin.create_port(context, port)
|
||||||
|
|
||||||
|
q = self.session.query(models.Subnet).outerjoin(models.IPAddress)
|
||||||
|
self.assertEqual(len(q.first().allocated_ips),
|
||||||
|
1)
|
||||||
|
|
||||||
|
# 5. Delete port.
|
||||||
|
self.plugin.delete_port(context, response['id'])
|
||||||
|
|
||||||
|
q = self.session.query(models.Subnet).outerjoin(models.IPAddress)
|
||||||
|
self.assertEqual(len(q.first().allocated_ips),
|
||||||
|
0)
|
Loading…
Reference in New Issue
Block a user