interface has a list of allowed ips

This commit is contained in:
Rajaram Mallya 2011-11-10 15:41:15 +05:30
parent 0c3abeafd7
commit e7e568d7b6
7 changed files with 94 additions and 16 deletions

View File

@ -38,8 +38,8 @@ default_cidr = 10.0.0.0/24
#ipv6_generator=melange.ipv6.tenant_based_generator.TenantBasedIpV6Generator
#DNS info for a data_center
dns1 = "ns1.example.com"
dns2 = "ns2.example.com"
dns1 = 8.8.8.8
dns2 = 8.8.4.4
#Number of days before deallocated IPs are deleted
keep_deallocated_ips_for_days = 2

View File

@ -19,6 +19,7 @@ import sqlalchemy.exc
from sqlalchemy import and_
from sqlalchemy import or_
from sqlalchemy.orm import aliased
from sqlalchemy.orm import joinedload
from melange import ipam
from melange.common import exception
@ -71,7 +72,7 @@ def delete_all(query_func, model, **conditions):
query_func(model, **conditions).delete()
def update(model, values):
def update(model, **values):
for k, v in values.iteritems():
model[k] = v
@ -106,7 +107,7 @@ def save_nat_relationships(nat_relationships):
for relationship in nat_relationships:
ip_nat = mappers.IpNat()
relationship['id'] = utils.generate_uuid()
update(ip_nat, relationship)
update(ip_nat, **relationship)
save(ip_nat)
@ -203,6 +204,21 @@ def pop_allocatable_address(**conditions):
return ip.address
def save_allowed_ip(interface_id, ip_address_id):
allowed_ip = mappers.AllowedIp()
update(allowed_ip,
id=utils.generate_uuid(),
interface_id=interface_id,
ip_address_id=ip_address_id)
save(allowed_ip)
def find_allowed_ips(**conditions):
query = _query_by(mappers.AllowedIp, **conditions).\
options(joinedload('ip_address'))
return [allowed_ip.ip_address for allowed_ip in query]
def configure_db(options):
session.configure_db(options)

View File

@ -33,6 +33,7 @@ def map(engine, models):
mac_address_ranges_table = Table('mac_address_ranges', meta, autoload=True)
mac_addresses_table = Table('mac_addresses', meta, autoload=True)
interfaces_table = Table('interfaces', meta, autoload=True)
allowed_ips_table = Table('allowed_ips', meta, autoload=True)
orm.mapper(models["IpBlock"], Table('ip_blocks', meta, autoload=True))
orm.mapper(models["IpAddress"], ip_addresses_table)
@ -60,6 +61,13 @@ def map(engine, models):
}
)
orm.mapper(AllowedIp, allowed_ips_table,
properties={
'interface': orm.relation(models["Interface"]),
'ip_address': orm.relation(models["IpAddress"])
}
)
class IpNat(object):
"""Many to Many table for natting inside globals and locals.
@ -75,3 +83,19 @@ class IpNat(object):
def __getitem__(self, key):
return getattr(self, key)
class AllowedIp(object):
"""Many to Many table for natting inside globals and locals.
This resides in sqlalchemy mappers as its not a true model
and non-relational dbs may not expose many-to-many relationships as
another table
"""
def __setitem__(self, key, value):
setattr(self, key, value)
def __getitem__(self, key):
return getattr(self, key)

View File

@ -142,16 +142,24 @@ interfaces = Table('interfaces', meta,
Column('updated_at', DateTime()),
UniqueConstraint('virtual_interface_id'))
allowed_ips = Table('allowed_ips', meta,
Column('id', String(36), primary_key=True, nullable=False),
Column('ip_address_id', String(36), ForeignKey('ip_addresses.id'),
nullable=False),
Column('interface_id', String(36), ForeignKey('interfaces.id'),
nullable=False),
UniqueConstraint('ip_address_id', 'interface_id'))
def upgrade(migrate_engine):
meta.bind = migrate_engine
create_tables([policies, ip_ranges, ip_octets, ip_blocks, ip_routes,
mac_address_ranges, mac_addresses, interfaces, ip_addresses,
ip_nats, allocatable_ips])
ip_nats, allocatable_ips, allowed_ips])
def downgrade(migrate_engine):
meta.bind = migrate_engine
drop_tables([allocatable_ips, ip_nats, ip_addresses, interfaces,
mac_addresses, mac_address_ranges, ip_routes, ip_blocks,
ip_ranges, ip_octets, policies])
drop_tables([allowed_ips, allocatable_ips, ip_nats, ip_addresses,
interfaces, mac_addresses, mac_address_ranges, ip_routes,
ip_blocks, ip_ranges, ip_octets, policies])

View File

@ -338,10 +338,11 @@ class IpBlock(ModelBase):
mac_address=interface.mac_address_eui_format,
**kwargs)
try:
return IpAddress.create(address=address,
ip_block_id=self.id,
interface_id=interface.id)
ip = IpAddress.create(address=address,
ip_block_id=self.id,
interface_id=interface.id)
interface.allow_ip(ip)
return ip
except exception.DBConstraintError as error:
LOG.debug("IP allocation retry count :{0}".format(retries + 1))
LOG.exception(error)
@ -796,6 +797,12 @@ class Interface(ModelBase):
data['id'] = self.virtual_interface_id
return data
def allow_ip(self, ip):
db_api.save_allowed_ip(self.id, ip.id)
def ips_allowed(self):
return db_api.find_allowed_ips(interface_id=self.id)
@utils.cached_property
def mac_address(self):
return MacAddress.get_by(interface_id=self.id)

View File

@ -26,8 +26,8 @@ class IpBlockFactory(factory.Factory):
FACTORY_FOR = models.IpBlock
cidr = factory.Sequence(lambda n: "192.168.{0}.0/24".format(int(n) % 255))
type = "private"
dns1 = "ns1.example.com"
dns2 = "ns2.example.com"
dns1 = "8.8.8.8"
dns2 = "8.8.4.4"
tenant_id = "tenant_id"
@ -40,8 +40,8 @@ class PrivateIpBlockFactory(IpBlockFactory):
class IpV6IpBlockFactory(IpBlockFactory):
cidr = factory.Sequence(lambda n: "fe::{0}00/120".format(hex(int(n) % 16)))
type = "public"
cidr = factory.Sequence(lambda n: "fe::{0}/120".format(hex(int(n))[2:]))
type = "private"
class IpAddressFactory(factory.Factory):

View File

@ -2124,6 +2124,29 @@ class TestInterface(tests.BaseTest):
self.assertModelsEqual(interface.ip_addresses, [ip1, ip2])
class TestAllowedIps(tests.BaseTest):
def test_allow_an_ip_on_an_interface(self):
interface = factory_models.InterfaceFactory()
ip1 = factory_models.IpAddressFactory(interface_id=interface.id)
ip2 = factory_models.IpAddressFactory(interface_id=interface.id)
noise_ip = factory_models.IpAddressFactory(interface_id=interface.id)
interface.allow_ip(ip1)
interface.allow_ip(ip2)
actual_allowed_ips = interface.ips_allowed()
self.assertModelsEqual(actual_allowed_ips, [ip1, ip2])
def test_allocating_ips_allows_the_ip_on_the_interface(self):
interface = factory_models.InterfaceFactory()
block = factory_models.IpBlockFactory()
ip = block.allocate_ip(interface=interface)
self.assertEqual(interface.ips_allowed(), [ip])
def _allocate_ip(block, interface=None, **kwargs):
if interface is None:
interface = factory_models.InterfaceFactory()