Create Networks based on release information on cluster create

This commit is contained in:
Mike Scherbakov 2012-09-07 16:10:57 +04:00 committed by default
parent c195bb5d68
commit b368559018
4 changed files with 114 additions and 58 deletions

View File

@ -1,12 +1,12 @@
# -*- coding: utf-8 -*-
import json
import web
import ipaddr
from models import Release, Cluster, Node, Role, Network
import netaddr
from models import Release, Cluster, Node, Role, Network, Vlan
from settings import settings
from helpers.vlan import VlanManager
def check_client_content_type(handler):
@ -179,34 +179,36 @@ class ClusterCollectionHandler(JSONHandler):
web.ctx.orm.add(cluster)
web.ctx.orm.commit()
network_objects = web.ctx.orm.query(Network)
for network in release.networks_metadata:
for nw_pool in settings.NETWORK_POOLS[network['access']]:
nw_ip = ipaddr.IPv4Network(nw_pool)
new_network = None
for net in nw_ip.iter_subnets(new_prefix=24):
nw_exist = network_objects.filter(
Network.network == str(net)
).first()
if not nw_exist:
new_network = net
break
if new_network:
break
used_nets = [n.cidr for n in web.ctx.orm.query(Network).all()]
used_vlans = [v.id for v in web.ctx.orm.query(Vlan).all()]
nw = Network(
for network in release.networks_metadata:
new_vlan = sorted(list(set(settings.VLANS) - set(used_vlans)))[0]
vlan_db = Vlan(id=new_vlan)
web.ctx.orm.add(vlan_db)
pool = settings.NETWORK_POOLS[network['access']]
nets_free_set = netaddr.IPSet(pool) -\
netaddr.IPSet(settings.NET_EXCLUDE) -\
netaddr.IPSet(used_nets)
free_cidrs = sorted(list(nets_free_set._cidrs))
new_net = list(free_cidrs[0].subnet(24, count=1))[0]
nw_db = Network(
release=release.id,
name=network['name'],
access=network['access'],
network=str(new_network),
gateway=str(new_network[1]),
range_l=str(new_network[3]),
range_h=str(new_network[-1]),
vlan_id=VlanManager.generate_id(network['name'])
cidr=str(new_net),
gateway=str(new_net[1]),
vlan=vlan_db.id
)
web.ctx.orm.add(nw)
web.ctx.orm.add(nw_db)
web.ctx.orm.commit()
used_vlans.append(new_vlan)
used_nets.append(str(new_net))
raise web.webapi.created(json.dumps(
ClusterHandler.render(cluster),
indent=4

View File

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
import web
import ipaddr
from sqlalchemy import Column, UniqueConstraint, Table
from sqlalchemy import Integer, String, Unicode, Boolean, ForeignKey, Enum
from sqlalchemy import create_engine
@ -196,26 +195,22 @@ class IPAddr(Base):
ip_addr = Column(String(25))
class Vlan(Base, BasicValidator):
__tablename__ = 'vlan'
id = Column(Integer, primary_key=True)
network = relationship("Network")
class Network(Base, BasicValidator):
__tablename__ = 'networks'
id = Column(Integer, primary_key=True)
release = Column(Integer, ForeignKey('releases.id'), nullable=False)
name = Column(Unicode(20), nullable=False)
name = Column(Unicode(100), nullable=False)
access = Column(String(20), nullable=False)
vlan_id = Column(Integer)
network = Column(String(25), nullable=False)
range_l = Column(String(25))
range_h = Column(String(25))
vlan = Column(Integer, ForeignKey('vlan.id'))
cidr = Column(String(25), nullable=False)
gateway = Column(String(25))
nodes = relationship(
"Node",
secondary=IPAddr.__table__,
backref="networks")
@property
def netmask(self):
return str(ipaddr.IPv4Network(self.network).netmask)
@property
def broadcast(self):
return str(ipaddr.IPv4Network(self.network).broadcast)

View File

@ -1,18 +0,0 @@
# -*- coding: utf-8 -*-
class VlanManager(object):
"""
A stub for some real logic in the future
"""
vlan_ids = {
'storage': 200,
'public': 300,
'floating': 400,
'fixed': 500,
'admin': 100
}
@classmethod
def generate_id(cls, name):
return cls.vlan_ids[name]

View File

@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
import json
from paste.fixture import TestApp
from api.models import Release, Network
from base import BaseHandlers
from base import reverse
@ -38,5 +40,80 @@ class TestHandlers(BaseHandlers):
)
self.assertEquals(201, resp.status)
#def test_if_cluster_creates_correct_networks(self):
#pass
def test_if_cluster_creates_correct_networks(self):
release = Release()
release.version = "1.1.1"
release.name = u"release_name_" + str(release.version)
release.description = u"release_desc" + str(release.version)
release.networks_metadata = [
{"name": "floating", "access": "public"},
{"name": "fixed", "access": "private10"},
{"name": "storage", "access": "private192"},
{"name": "management", "access": "private172"},
{"name": "other_172", "access": "private172"},
]
self.db.add(release)
self.db.commit()
resp = self.app.post(
reverse('ClusterCollectionHandler'),
json.dumps({
'name': 'cluster-name',
'release': release.id,
}),
headers=self.default_headers
)
self.assertEquals(201, resp.status)
nets = self.db.query(Network).all()
obtained = []
for net in nets:
obtained.append({
'release': net.release,
'name': net.name,
'access': net.access,
'vlan': net.vlan,
'cidr': net.cidr,
'gateway': net.gateway
})
expected = [
{
'release': release.id,
'name': u'floating',
'access': 'public',
'vlan': 100,
'cidr': '240.0.0.0/24',
'gateway': '240.0.0.1'
},
{
'release': release.id,
'name': u'fixed',
'access': 'private10',
'vlan': 101,
'cidr': '10.0.0.0/24',
'gateway': '10.0.0.1'
},
{
'release': release.id,
'name': u'storage',
'access': 'private192',
'vlan': 102,
'cidr': '192.168.0.0/24',
'gateway': '192.168.0.1'
},
{
'release': release.id,
'name': u'management',
'access': 'private172',
'vlan': 103,
'cidr': '172.16.0.0/24',
'gateway': '172.16.0.1'
},
{
'release': release.id,
'name': u'other_172',
'access': 'private172',
'vlan': 104,
'cidr': '172.16.1.0/24',
'gateway': '172.16.1.1'
},
]
self.assertEquals(expected, obtained)