From b36855901864653bc2d39e498710a1cdf961b003 Mon Sep 17 00:00:00 2001 From: Mike Scherbakov Date: Fri, 7 Sep 2012 16:10:57 +0400 Subject: [PATCH] Create Networks based on release information on cluster create --- nailgun/api/handlers.py | 50 ++++++------ nailgun/api/models.py | 23 +++--- nailgun/helpers/vlan.py | 18 ----- .../test/test_cluster_collection_handlers.py | 81 ++++++++++++++++++- 4 files changed, 114 insertions(+), 58 deletions(-) delete mode 100644 nailgun/helpers/vlan.py diff --git a/nailgun/api/handlers.py b/nailgun/api/handlers.py index c5f40666e..7c3663ee2 100644 --- a/nailgun/api/handlers.py +++ b/nailgun/api/handlers.py @@ -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 diff --git a/nailgun/api/models.py b/nailgun/api/models.py index f43d4bc85..3fd5a98f2 100644 --- a/nailgun/api/models.py +++ b/nailgun/api/models.py @@ -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) diff --git a/nailgun/helpers/vlan.py b/nailgun/helpers/vlan.py deleted file mode 100644 index 82c4c0d31..000000000 --- a/nailgun/helpers/vlan.py +++ /dev/null @@ -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] diff --git a/nailgun/test/test_cluster_collection_handlers.py b/nailgun/test/test_cluster_collection_handlers.py index 80a9dba0f..230c2528f 100644 --- a/nailgun/test/test_cluster_collection_handlers.py +++ b/nailgun/test/test_cluster_collection_handlers.py @@ -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)