summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/nova-manage33
-rw-r--r--nova/auth/novarc.template8
-rw-r--r--nova/auth/users.py16
-rw-r--r--nova/compute/linux_net.py69
-rw-r--r--nova/compute/network.py644
-rw-r--r--nova/compute/node.py38
-rw-r--r--nova/datastore.py4
-rw-r--r--nova/endpoint/cloud.py45
-rw-r--r--nova/tests/network_unittest.py77
9 files changed, 405 insertions, 529 deletions
diff --git a/bin/nova-manage b/bin/nova-manage
index d2108626b..765eb1f53 100755
--- a/bin/nova-manage
+++ b/bin/nova-manage
@@ -71,15 +71,35 @@ class UserCommands(object):
for user in self.manager.get_users():
print user.name
- def zip(self, name, filename='nova.zip'):
+class ProjectCommands(object):
+ def __init__(self):
+ self.manager = users.UserManager.instance()
+
+ def create(self, name, project_manager, description=None):
+ """creates a new project
+ arguments: name project_manager [description]"""
+ user = self.manager.create_project(name, project_manager, description)
+
+ def delete(self, name):
+ """deletes an existing project
+ arguments: name"""
+ self.manager.delete_project(name)
+
+ def list(self):
+ """lists all projects
+ arguments: <none>"""
+ for project in self.manager.get_projects():
+ print project.name
+
+ def zip(self, project_id, user_id, filename='nova.zip'):
"""exports credentials for user to a zip file
- arguments: name [filename='nova.zip]"""
- user = self.manager.get_user(name)
- if user:
+ arguments: project_id user_id [filename='nova.zip]"""
+ project = self.manager.get_project(project_id)
+ if project:
with open(filename, 'w') as f:
- f.write(user.get_credentials())
+ f.write(project.get_credentials(user_id))
else:
- print "User %s doesn't exist" % name
+ print "Project %s doesn't exist" % project
def usage(script_name):
@@ -88,6 +108,7 @@ def usage(script_name):
categories = [
('user', UserCommands),
+ ('project', ProjectCommands),
]
diff --git a/nova/auth/novarc.template b/nova/auth/novarc.template
index a993d1882..ee1bc75f2 100644
--- a/nova/auth/novarc.template
+++ b/nova/auth/novarc.template
@@ -1,11 +1,11 @@
# Copyright [2010] [Anso Labs, LLC]
-#
+#
# 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.
@@ -13,7 +13,7 @@
# limitations under the License.
NOVA_KEY_DIR=$(pushd $(dirname $BASH_SOURCE)>/dev/null; pwd; popd>/dev/null)
-export EC2_ACCESS_KEY="%(access)s"
+export EC2_ACCESS_KEY="%(access)s:%(project)s"
export EC2_SECRET_KEY="%(secret)s"
export EC2_URL="%(ec2)s"
export S3_URL="%(s3)s"
diff --git a/nova/auth/users.py b/nova/auth/users.py
index b09bcfcf2..c60922feb 100644
--- a/nova/auth/users.py
+++ b/nova/auth/users.py
@@ -93,9 +93,12 @@ class User(AuthBase):
def is_project_manager(self, project):
return UserManager.instance().is_project_manager(self, project)
- def generate_rc(self):
+ def generate_rc(self, project=None):
+ if project is None:
+ project = self.id
rc = open(FLAGS.credentials_template).read()
rc = rc % { 'access': self.access,
+ 'project': project,
'secret': self.secret,
'ec2': FLAGS.ec2_url,
's3': 'http://%s:%s' % (FLAGS.s3_host, FLAGS.s3_port),
@@ -168,7 +171,9 @@ class Project(Group):
return User.safe_id(user) == self.project_manager_id
def get_credentials(self, user):
- rc = user.generate_rc()
+ if not isinstance(user, User):
+ user = UserManager.instance().get_user(user)
+ rc = user.generate_rc(self.id)
private_key, signed_cert = self.generate_x509_cert(user)
tmpdir = tempfile.mkdtemp()
@@ -238,7 +243,7 @@ class UserManager(object):
raise exception.NotAuthorized('Signature does not match')
return (user, project)
- def create_project(self, name, manager_user, description, member_users=None):
+ def create_project(self, name, manager_user, description=None, member_users=None):
if member_users:
member_users = [User.safe_id(u) for u in member_users]
with LDAPWrapper() as conn:
@@ -462,12 +467,15 @@ class LDAPWrapper(object):
self.conn.add_s(self.__uid_to_dn(name), attr)
return self.__to_user(dict(attr))
- def create_project(self, name, manager_uid, description, member_uids = None):
+ def create_project(self, name, manager_uid, description=None, member_uids=None):
if self.project_exists(name):
raise exception.Duplicate("Project can't be created because project %s already exists" % name)
if not self.user_exists(manager_uid):
raise exception.NotFound("Project can't be created because manager %s doesn't exist" % manager_uid)
manager_dn = self.__uid_to_dn(manager_uid)
+ # description is a required attribute
+ if description is None:
+ description = name
members = []
if member_uids != None:
for member_uid in member_uids:
diff --git a/nova/compute/linux_net.py b/nova/compute/linux_net.py
index 319ccbdd6..b9f775aa3 100644
--- a/nova/compute/linux_net.py
+++ b/nova/compute/linux_net.py
@@ -1,25 +1,11 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
-# Copyright [2010] [Anso Labs, LLC]
-#
-# 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 logging
-import os
import signal
+import os
+import nova.utils
import subprocess
-from nova import utils
-
# todo(ja): does the definition of network_path belong here?
from nova import flags
@@ -30,13 +16,13 @@ def execute(cmd):
logging.debug("FAKE NET: %s" % cmd)
return "fake", 0
else:
- utils.execute(cmd)
+ return nova.utils.execute(cmd)
def runthis(desc, cmd):
if FLAGS.fake_network:
- execute(cmd)
+ return execute(cmd)
else:
- utils.runthis(desc,cmd)
+ return nova.utils.runthis(desc,cmd)
def Popen(cmd):
if FLAGS.fake_network:
@@ -61,44 +47,46 @@ def bind_public_ip(ip, interface):
def vlan_create(net):
""" create a vlan on on a bridge device unless vlan already exists """
- if not device_exists("vlan%s" % net.vlan):
+ if not device_exists("vlan%s" % net['vlan']):
+ logging.debug("Starting VLAN inteface for %s network", (net['vlan']))
execute("sudo vconfig set_name_type VLAN_PLUS_VID_NO_PAD")
- execute("sudo vconfig add %s %s" % (net.bridge_dev, net.vlan))
- execute("sudo ifconfig vlan%s up" % (net.vlan))
+ execute("sudo vconfig add %s %s" % (FLAGS.bridge_dev, net['vlan']))
+ execute("sudo ifconfig vlan%s up" % (net['vlan']))
def bridge_create(net):
""" create a bridge on a vlan unless it already exists """
- if not device_exists(net.bridge_name):
- execute("sudo brctl addbr %s" % (net.bridge_name))
+ if not device_exists(net['bridge_name']):
+ logging.debug("Starting Bridge inteface for %s network", (net['vlan']))
+ execute("sudo brctl addbr %s" % (net['bridge_name']))
# execute("sudo brctl setfd %s 0" % (net.bridge_name))
# execute("sudo brctl setageing %s 10" % (net.bridge_name))
- execute("sudo brctl stp %s off" % (net.bridge_name))
- execute("sudo brctl addif %s vlan%s" % (net.bridge_name, net.vlan))
+ execute("sudo brctl stp %s off" % (net['bridge_name']))
+ execute("sudo brctl addif %s vlan%s" % (net['bridge_name'], net['vlan']))
if net.bridge_gets_ip:
execute("sudo ifconfig %s %s broadcast %s netmask %s up" % \
- (net.bridge_name, net.gateway, net.broadcast, net.netmask))
- confirm_rule("FORWARD --in-interface %s -j ACCEPT" % (net.bridge_name))
+ (net['bridge_name'], net.gateway, net.broadcast, net.netmask))
+ confirm_rule("FORWARD --in-interface %s -j ACCEPT" % (net['bridge_name']))
else:
- execute("sudo ifconfig %s up" % net.bridge_name)
+ execute("sudo ifconfig %s up" % net['bridge_name'])
def dnsmasq_cmd(net):
cmd = ['sudo dnsmasq',
' --strict-order',
' --bind-interfaces',
' --conf-file=',
- ' --pid-file=%s' % dhcp_file(net.vlan, 'pid'),
+ ' --pid-file=%s' % dhcp_file(net['vlan'], 'pid'),
' --listen-address=%s' % net.dhcp_listen_address,
' --except-interface=lo',
- ' --dhcp-range=%s,%s,120s' % (net.dhcp_range_start, net.dhcp_range_end),
+ ' --dhcp-range=%s,static,120s' % (net.dhcp_range_start),
' --dhcp-lease-max=61',
- ' --dhcp-hostsfile=%s' % dhcp_file(net.vlan, 'conf'),
- ' --dhcp-leasefile=%s' % dhcp_file(net.vlan, 'leases')]
+ ' --dhcp-hostsfile=%s' % dhcp_file(net['vlan'], 'conf'),
+ ' --dhcp-leasefile=%s' % dhcp_file(net['vlan'], 'leases')]
return ''.join(cmd)
-def hostDHCP(network, host):
- idx = host['address'].split(".")[-1] # Logically, the idx of instances they've launched in this net
+def hostDHCP(network, host, mac):
+ idx = host.split(".")[-1] # Logically, the idx of instances they've launched in this net
return "%s,%s-%s-%s.novalocal,%s" % \
- (host['mac'], host['user_id'], network.vlan, idx, host['address'])
+ (mac, network['user_id'], network['vlan'], idx, host)
# todo(ja): if the system has restarted or pid numbers have wrapped
# then you cannot be certain that the pid refers to the
@@ -111,9 +99,9 @@ def start_dnsmasq(network):
if a dnsmasq instance is already running then send a HUP
signal causing it to reload, otherwise spawn a new instance
"""
- with open(dhcp_file(network.vlan, 'conf'), 'w') as f:
+ with open(dhcp_file(network['vlan'], 'conf'), 'w') as f:
for host_name in network.hosts:
- f.write("%s\n" % hostDHCP(network, network.hosts[host_name]))
+ f.write("%s\n" % hostDHCP(network, host_name, network.hosts[host_name]))
pid = dnsmasq_pid_for(network)
@@ -123,12 +111,11 @@ def start_dnsmasq(network):
# correct dnsmasq process
try:
os.kill(pid, signal.SIGHUP)
- return
except Exception, e:
logging.debug("Hupping dnsmasq threw %s", e)
# otherwise delete the existing leases file and start dnsmasq
- lease_file = dhcp_file(network.vlan, 'leases')
+ lease_file = dhcp_file(network['vlan'], 'leases')
if os.path.exists(lease_file):
os.unlink(lease_file)
@@ -156,7 +143,7 @@ def dnsmasq_pid_for(network):
if machine has rebooted pid might be incorrect (caller should check)
"""
- pid_file = dhcp_file(network.vlan, 'pid')
+ pid_file = dhcp_file(network['vlan'], 'pid')
if os.path.exists(pid_file):
with open(pid_file, 'r') as f:
diff --git a/nova/compute/network.py b/nova/compute/network.py
index 9a9bb9527..4d5f4bf5f 100644
--- a/nova/compute/network.py
+++ b/nova/compute/network.py
@@ -17,15 +17,16 @@
Classes for network control, including VLANs, DHCP, and IP allocation.
"""
-import json
import logging
import os
+import time
# TODO(termie): clean up these imports
from nova import vendor
import IPy
from nova import datastore
+import nova.exception
from nova.compute import exception
from nova import flags
from nova import utils
@@ -34,145 +35,129 @@ from nova.auth import users
import linux_net
FLAGS = flags.FLAGS
-flags.DEFINE_string('net_libvirt_xml_template',
- utils.abspath('compute/net.libvirt.xml.template'),
- 'Template file for libvirt networks')
flags.DEFINE_string('networks_path', utils.abspath('../networks'),
'Location to keep network config files')
flags.DEFINE_integer('public_vlan', 1, 'VLAN for public IP addresses')
-flags.DEFINE_string('public_interface', 'vlan1', 'Interface for public IP addresses')
+flags.DEFINE_string('public_interface', 'vlan1',
+ 'Interface for public IP addresses')
flags.DEFINE_string('bridge_dev', 'eth1',
'network device for bridges')
flags.DEFINE_integer('vlan_start', 100, 'First VLAN for private networks')
flags.DEFINE_integer('vlan_end', 4093, 'Last VLAN for private networks')
-flags.DEFINE_integer('network_size', 256, 'Number of addresses in each private subnet')
+flags.DEFINE_integer('network_size', 256,
+ 'Number of addresses in each private subnet')
flags.DEFINE_string('public_range', '4.4.4.0/24', 'Public IP address block')
flags.DEFINE_string('private_range', '10.0.0.0/8', 'Private IP address block')
-
-# HACK(vish): to delay _get_keeper() loading
-def _get_keeper():
- if _get_keeper.keeper == None:
- _get_keeper.keeper = datastore.Keeper(prefix="net")
- return _get_keeper.keeper
-_get_keeper.keeper = None
-
logging.getLogger().setLevel(logging.DEBUG)
-# CLEANUP:
-# TODO(ja): use singleton for usermanager instead of self.manager in vlanpool et al
-# TODO(ja): does vlanpool "keeper" need to know the min/max - shouldn't FLAGS always win?
-class Network(object):
- def __init__(self, *args, **kwargs):
- self.bridge_gets_ip = False
- try:
- os.makedirs(FLAGS.networks_path)
- except Exception, err:
- pass
- self.load(**kwargs)
-
- def to_dict(self):
- return {'vlan': self.vlan,
- 'network': self.network_str,
- 'hosts': self.hosts}
-
- def load(self, **kwargs):
- self.network_str = kwargs.get('network', "192.168.100.0/24")
- self.hosts = kwargs.get('hosts', {})
- self.vlan = kwargs.get('vlan', 100)
- self.name = "nova-%s" % (self.vlan)
- self.network = IPy.IP(self.network_str)
- self.gateway = self.network[1]
- self.netmask = self.network.netmask()
- self.broadcast = self.network.broadcast()
- self.bridge_name = "br%s" % (self.vlan)
-
- def __str__(self):
- return json.dumps(self.to_dict())
-
- def __unicode__(self):
- return json.dumps(self.to_dict())
+class BaseNetwork(datastore.RedisModel):
+ bridge_gets_ip = False
+ object_type = 'network'
@classmethod
- def from_dict(cls, args):
- for arg in args.keys():
- value = args[arg]
- del args[arg]
- args[str(arg)] = value
- self = cls(**args)
- return self
+ def get_all_hosts(cls):
+ for vlan in get_assigned_vlans().values():
+ network_str = get_subnet_from_vlan(vlan)
+ for addr in datastore.Redis.instance().hgetall(
+ "network:%s:hosts" % (network_str)):
+ yield addr
@classmethod
- def from_json(cls, json_string):
- parsed = json.loads(json_string)
- return cls.from_dict(parsed)
+ def create(cls, user_id, project_id, security_group, vlan, network_str):
+ network_id = "%s:%s" % (project_id, security_group)
+ net = cls(network_id, network_str)
+ net['user_id'] = user_id
+ net['project_id'] = project_id
+ net["vlan"] = vlan
+ net["bridge_name"] = "br%s" % vlan
+ net.save()
+ return net
+
+ def __init__(self, network_id, network_str=None):
+ super(BaseNetwork, self).__init__(object_id=network_id)
+ self['network_id'] = network_id
+ self['network_str'] = network_str
+ self.save()
- def range(self):
- for idx in range(3, len(self.network)-2):
- yield self.network[idx]
+ @property
+ def network(self):
+ return IPy.IP(self['network_str'])
+ @property
+ def netmask(self):
+ return self.network.netmask()
+ @property
+ def broadcast(self):
+ return self.network.broadcast()
+ @property
+ def bridge_name(self):
+ return "br%s" % (self["vlan"])
- def allocate_ip(self, user_id, project_id, mac):
- for ip in self.range():
- address = str(ip)
- if not address in self.hosts.keys():
- logging.debug("Allocating IP %s to %s" % (address, project_id))
- self.hosts[address] = {
- "address" : address, "user_id": user_id, "project_id" : project_id, 'mac' : mac
- }
- self.express(address=address)
- return address
- raise exception.NoMoreAddresses()
+ @property
+ def user(self):
+ return users.UserManager.instance().get_user(self['user_id'])
- def deallocate_ip(self, ip_str):
- if not ip_str in self.hosts.keys():
- raise exception.AddressNotAllocated()
- del self.hosts[ip_str]
- # TODO(joshua) SCRUB from the leases file somehow
- self.deexpress(address=ip_str)
+ @property
+ def project(self):
+ return users.UserManager.instance().get_project(self['project_id'])
- def list_addresses(self):
- for address in self.hosts.values():
- yield address
+ @property
+ def _hosts_key(self):
+ return "network:%s:hosts" % (self['network_str'])
- def express(self, address=None):
- pass
+ @property
+ def hosts(self):
+ return datastore.Redis.instance().hgetall(self._hosts_key)
- def deexpress(self, address=None):
- pass
+ def _add_host(self, _user_id, _project_id, host, target):
+ datastore.Redis.instance().hset(self._hosts_key, host, target)
+ def _rem_host(self, host):
+ datastore.Redis.instance().hdel(self._hosts_key, host)
-class Vlan(Network):
- """
- VLAN configuration, that when expressed creates the vlan
+ @property
+ def assigned(self):
+ return datastore.Redis.instance().hkeys(self._hosts_key)
- properties:
+ @property
+ def available(self):
+ for idx in range(3, len(self.network) - 1):
+ address = str(self.network[idx])
+ if not address in self.hosts.keys():
+ yield str(address)
- vlan - integer (example: 42)
- bridge_dev - string (example: eth0)
- """
+ def allocate_ip(self, user_id, project_id, mac):
+ for address in self.available:
+ logging.debug("Allocating IP %s to %s" % (address, project_id))
+ self._add_host(user_id, project_id, address, mac)
+ self.express(address=address)
+ return address
+ raise exception.NoMoreAddresses()
- def __init__(self, *args, **kwargs):
- super(Vlan, self).__init__(*args, **kwargs)
- self.bridge_dev = FLAGS.bridge_dev
+ def deallocate_ip(self, ip_str):
+ if not ip_str in self.assigned:
+ raise exception.AddressNotAllocated()
+ self._rem_host(ip_str)
+ self.deexpress(address=ip_str)
- def express(self, address=None):
- super(Vlan, self).express(address=address)
- try:
- logging.debug("Starting VLAN inteface for %s network" % (self.vlan))
- linux_net.vlan_create(self)
- except:
- pass
+ def list_addresses(self):
+ for address in self.hosts:
+ yield address
+ def express(self, address=None): pass
+ def deexpress(self, address=None): pass
-class VirtNetwork(Vlan):
+
+class BridgedNetwork(BaseNetwork):
"""
- Virtual Network that can export libvirt configuration or express itself to
- create a bridge (with or without an IP address/netmask/gateway)
+ Virtual Network that can express itself to create a vlan and
+ a bridge (with or without an IP address/netmask/gateway)
properties:
bridge_name - string (example value: br42)
vlan - integer (example value: 42)
+ bridge_dev - string (example: eth0)
bridge_gets_ip - boolean used during bridge creation
if bridge_gets_ip then network address for bridge uses the properties:
@@ -181,333 +166,242 @@ class VirtNetwork(Vlan):
netmask
"""
- def __init__(self, *args, **kwargs):
- super(VirtNetwork, self).__init__(*args, **kwargs)
-
- def virtXML(self):
- """ generate XML for libvirt network """
+ @classmethod
+ def get_network_for_project(cls, user_id, project_id, security_group):
+ vlan = get_vlan_for_project(project_id)
+ network_str = get_subnet_from_vlan(vlan)
+ logging.debug("creating network on vlan %s with network string %s" % (vlan, network_str))
+ return cls.create(user_id, project_id, security_group, vlan, network_str)
- libvirt_xml = open(FLAGS.net_libvirt_xml_template).read()
- xml_info = {'name' : self.name,
- 'bridge_name' : self.bridge_name,
- 'device' : "vlan%s" % (self.vlan),
- 'gateway' : self.gateway,
- 'netmask' : self.netmask,
- }
- libvirt_xml = libvirt_xml % xml_info
- return libvirt_xml
+ def __init__(self, *args, **kwargs):
+ super(BridgedNetwork, self).__init__(*args, **kwargs)
+ self['bridge_dev'] = FLAGS.bridge_dev
+ self.save()
def express(self, address=None):
- """ creates a bridge device on top of the Vlan """
- super(VirtNetwork, self).express(address=address)
- try:
- logging.debug("Starting Bridge inteface for %s network" % (self.vlan))
- linux_net.bridge_create(self)
- except:
- pass
+ super(BridgedNetwork, self).express(address=address)
+ linux_net.vlan_create(self)
+ linux_net.bridge_create(self)
-class DHCPNetwork(VirtNetwork):
+class DHCPNetwork(BridgedNetwork):
"""
properties:
dhcp_listen_address: the ip of the gateway / dhcp host
dhcp_range_start: the first ip to give out
dhcp_range_end: the last ip to give out
"""
+ bridge_gets_ip = True
+
def __init__(self, *args, **kwargs):
super(DHCPNetwork, self).__init__(*args, **kwargs)
logging.debug("Initing DHCPNetwork object...")
- self.bridge_gets_ip = True
self.dhcp_listen_address = self.network[1]
self.dhcp_range_start = self.network[3]
- self.dhcp_range_end = self.network[-2]
+ self.dhcp_range_end = self.network[-1]
+ try:
+ os.makedirs(FLAGS.networks_path)
+ except Exception, err:
+ pass
def express(self, address=None):
super(DHCPNetwork, self).express(address=address)
- if len(self.hosts.values()) > 0:
- logging.debug("Starting dnsmasq server for network with vlan %s" % self.vlan)
+ if len(self.assigned) > 0:
+ logging.debug("Starting dnsmasq server for network with vlan %s",
+ self['vlan'])
linux_net.start_dnsmasq(self)
else:
- logging.debug("Not launching dnsmasq cause I don't think we have any hosts.")
+ logging.debug("Not launching dnsmasq: no hosts.")
def deexpress(self, address=None):
# if this is the last address, stop dns
super(DHCPNetwork, self).deexpress(address=address)
- if len(self.hosts.values()) == 0:
+ if len(self.assigned) == 0:
linux_net.stop_dnsmasq(self)
else:
linux_net.start_dnsmasq(self)
-class PrivateNetwork(DHCPNetwork):
- def __init__(self, **kwargs):
- super(PrivateNetwork, self).__init__(**kwargs)
- # self.express()
+class PublicAddress(datastore.RedisModel):
+ object_type="address"
- def to_dict(self):
- return {'vlan': self.vlan,
- 'network': self.network_str,
- 'hosts': self.hosts}
+ def __init__(self, address):
+ super(PublicAddress, self).__init__(address)
-class PublicNetwork(Network):
- def __init__(self, network="192.168.216.0/24", **kwargs):
- super(PublicNetwork, self).__init__(network=network, **kwargs)
+ @classmethod
+ def create(cls, user_id, project_id, address):
+ addr = cls(address=address)
+ addr['address'] = address
+ addr['user_id'] = user_id
+ addr['project_id'] = project_id
+ addr['instance_id'] = 'available'
+ addr['private_ip'] = 'available'
+ addr["create_time"] = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
+ addr.save()
+ return addr
+
+DEFAULT_PORTS = [("tcp",80), ("tcp",22), ("udp",1194), ("tcp",443)]
+class PublicNetworkController(BaseNetwork):
+ def __init__(self, *args, **kwargs):
+ network_id = "public:default"
+ super(PublicNetworkController, self).__init__(network_id, FLAGS.public_range)
+ self['user_id'] = "public"
+ self['project_id'] = "public"
+ self["create_time"] = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
+ self["vlan"] = FLAGS.public_vlan
+ self.save()
self.express()
- def allocate_ip(self, user_id, project_id, mac):
- for ip in self.range():
- address = str(ip)
+ @property
+ def available(self):
+ for idx in range(2, len(self.network)-1):
+ address = str(self.network[idx])
if not address in self.hosts.keys():
- logging.debug("Allocating IP %s to %s" % (address, project_id))
- self.hosts[address] = {
- "address" : address, "user_id": user_id, "project_id" : project_id, 'mac' : mac
- }
- self.express(address=address)
- return address
- raise exception.NoMoreAddresses()
+ yield address
- def deallocate_ip(self, ip_str):
- if not ip_str in self.hosts:
- raise exception.AddressNotAllocated()
- del self.hosts[ip_str]
- # TODO(joshua) SCRUB from the leases file somehow
- self.deexpress(address=ip_str)
+ @property
+ def host_objs(self):
+ for address in self.assigned:
+ yield PublicAddress(address)
+
+ def get_public_ip_for_instance(self, instance_id):
+ # FIXME: this should be a lookup - iteration won't scale
+ for address_record in self.host_objs:
+ if address_record.get('instance_id', 'available') == instance_id:
+ return address_record['address']
+
+ def get_host(self, host):
+ if host in self.assigned:
+ return PublicAddress(host)
+ return None
+
+ def _add_host(self, user_id, project_id, host, _target):
+ datastore.Redis.instance().hset(self._hosts_key, host, project_id)
+ PublicAddress.create(user_id, project_id, host)
+
+ def _rem_host(self, host):
+ PublicAddress(host).destroy()
+ datastore.Redis.instance().hdel(self._hosts_key, host)
def associate_address(self, public_ip, private_ip, instance_id):
- if not public_ip in self.hosts:
+ if not public_ip in self.assigned:
raise exception.AddressNotAllocated()
- for addr in self.hosts.values():
- if addr.has_key('private_ip') and addr['private_ip'] == private_ip:
+ # TODO(joshua): Keep an index going both ways
+ for addr in self.host_objs:
+ if addr.get('private_ip', None) == private_ip:
raise exception.AddressAlreadyAssociated()
- if self.hosts[public_ip].has_key('private_ip'):
+ addr = self.get_host(public_ip)
+ if addr.get('private_ip', 'available') != 'available':
raise exception.AddressAlreadyAssociated()
- self.hosts[public_ip]['private_ip'] = private_ip
- self.hosts[public_ip]['instance_id'] = instance_id
+ addr['private_ip'] = private_ip
+ addr['instance_id'] = instance_id
+ addr.save()
self.express(address=public_ip)
def disassociate_address(self, public_ip):
- if not public_ip in self.hosts:
+ if not public_ip in self.assigned:
raise exception.AddressNotAllocated()
- if not self.hosts[public_ip].has_key('private_ip'):
+ addr = self.get_host(public_ip)
+ if addr.get('private_ip', 'available') == 'available':
raise exception.AddressNotAssociated()
- self.deexpress(public_ip)
- del self.hosts[public_ip]['private_ip']
- del self.hosts[public_ip]['instance_id']
- # TODO Express the removal
-
- def deexpress(self, address):
- addr = self.hosts[address]
- public_ip = addr['address']
- private_ip = addr['private_ip']
- linux_net.remove_rule("PREROUTING -t nat -d %s -j DNAT --to %s" % (public_ip, private_ip))
- linux_net.remove_rule("POSTROUTING -t nat -s %s -j SNAT --to %s" % (private_ip, public_ip))
- linux_net.remove_rule("FORWARD -d %s -p icmp -j ACCEPT" % (private_ip))
- for (protocol, port) in [("tcp",80), ("tcp",22), ("udp",1194), ("tcp",443)]:
- linux_net.remove_rule("FORWARD -d %s -p %s --dport %s -j ACCEPT" % (private_ip, protocol, port))
+ self.deexpress(address=public_ip)
+ addr['private_ip'] = 'available'
+ addr['instance_id'] = 'available'
+ addr.save()
def express(self, address=None):
- logging.debug("Todo - need to create IPTables natting entries for this net.")
- addresses = self.hosts.values()
+ addresses = self.host_objs
if address:
- addresses = [self.hosts[address]]
+ addresses = [self.get_host(address)]
for addr in addresses:
- if not addr.has_key('private_ip'):
+ if addr.get('private_ip','available') == 'available':
continue
public_ip = addr['address']
private_ip = addr['private_ip']
linux_net.bind_public_ip(public_ip, FLAGS.public_interface)
- linux_net.confirm_rule("PREROUTING -t nat -d %s -j DNAT --to %s" % (public_ip, private_ip))
- linux_net.confirm_rule("POSTROUTING -t nat -s %s -j SNAT --to %s" % (private_ip, public_ip))
+ linux_net.confirm_rule("PREROUTING -t nat -d %s -j DNAT --to %s"
+ % (public_ip, private_ip))
+ linux_net.confirm_rule("POSTROUTING -t nat -s %s -j SNAT --to %s"
+ % (private_ip, public_ip))
# TODO: Get these from the secgroup datastore entries
- linux_net.confirm_rule("FORWARD -d %s -p icmp -j ACCEPT" % (private_ip))
- for (protocol, port) in [("tcp",80), ("tcp",22), ("udp",1194), ("tcp",443)]:
- linux_net.confirm_rule("FORWARD -d %s -p %s --dport %s -j ACCEPT" % (private_ip, protocol, port))
+ linux_net.confirm_rule("FORWARD -d %s -p icmp -j ACCEPT"
+ % (private_ip))
+ for (protocol, port) in DEFAULT_PORTS:
+ linux_net.confirm_rule("FORWARD -d %s -p %s --dport %s -j ACCEPT"
+ % (private_ip, protocol, port))
+ def deexpress(self, address=None):
+ addr = self.get_host(address)
+ private_ip = addr['private_ip']
+ linux_net.remove_rule("PREROUTING -t nat -d %s -j DNAT --to %s"
+ % (address, private_ip))
+ linux_net.remove_rule("POSTROUTING -t nat -s %s -j SNAT --to %s"
+ % (private_ip, address))
+ linux_net.remove_rule("FORWARD -d %s -p icmp -j ACCEPT"
+ % (private_ip))
+ for (protocol, port) in DEFAULT_PORTS:
+ linux_net.remove_rule("FORWARD -d %s -p %s --dport %s -j ACCEPT"
+ % (private_ip, protocol, port))
-class NetworkPool(object):
- # TODO - Allocations need to be system global
-
- def __init__(self):
- self.network = IPy.IP(FLAGS.private_range)
- netsize = FLAGS.network_size
- if not netsize in [4,8,16,32,64,128,256,512,1024]:
- raise exception.NotValidNetworkSize()
- self.netsize = netsize
- self.startvlan = FLAGS.vlan_start
-
- def get_from_vlan(self, vlan):
- start = (vlan-self.startvlan) * self.netsize
- net_str = "%s-%s" % (self.network[start], self.network[start + self.netsize - 1])
- logging.debug("Allocating %s" % net_str)
- return net_str
-
-
-class VlanPool(object):
- def __init__(self, **kwargs):
- self.start = FLAGS.vlan_start
- self.end = FLAGS.vlan_end
- self.vlans = kwargs.get('vlans', {})
- self.vlanpool = {}
- self.manager = users.UserManager.instance()
- for project_id, vlan in self.vlans.iteritems():
- self.vlanpool[vlan] = project_id
-
- def to_dict(self):
- return {'vlans': self.vlans}
-
- def __str__(self):
- return json.dumps(self.to_dict())
-
- def __unicode__(self):
- return json.dumps(self.to_dict())
-
- @classmethod
- def from_dict(cls, args):
- for arg in args.keys():
- value = args[arg]
- del args[arg]
- args[str(arg)] = value
- self = cls(**args)
- return self
-
- @classmethod
- def from_json(cls, json_string):
- parsed = json.loads(json_string)
- return cls.from_dict(parsed)
-
- def assign_vlan(self, project_id, vlan):
- logging.debug("Assigning vlan %s to project %s" % (vlan, project_id))
- self.vlans[project_id] = vlan
- self.vlanpool[vlan] = project_id
- return self.vlans[project_id]
-
- def next(self, project_id):
- for old_project_id, vlan in self.vlans.iteritems():
- if not self.manager.get_project(old_project_id):
- _get_keeper()["%s-default" % old_project_id] = {}
- del _get_keeper()["%s-default" % old_project_id]
- del self.vlans[old_project_id]
- return self.assign_vlan(project_id, vlan)
- vlans = self.vlanpool.keys()
- vlans.append(self.start)
- nextvlan = max(vlans) + 1
- if nextvlan == self.end:
- raise exception.AddressNotAllocated("Out of VLANs")
- return self.assign_vlan(project_id, nextvlan)
-
-
-class NetworkController(object):
- """ The network controller is in charge of network connections """
-
- def __init__(self, **kwargs):
- logging.debug("Starting up the network controller.")
- self.manager = users.UserManager.instance()
- self._pubnet = None
- if not _get_keeper()['vlans']:
- _get_keeper()['vlans'] = {}
- if not _get_keeper()['public']:
- _get_keeper()['public'] = {'vlan': FLAGS.public_vlan, 'network' : FLAGS.public_range}
- self.express()
-
- def reset(self):
- _get_keeper()['public'] = {'vlan': FLAGS.public_vlan, 'network': FLAGS.public_range }
- _get_keeper()['vlans'] = {}
- # TODO : Get rid of old interfaces, bridges, and IPTables rules.
-
- @property
- def public_net(self):
- if not self._pubnet:
- self._pubnet = PublicNetwork.from_dict(_get_keeper()['public'])
- self._pubnet.load(**_get_keeper()['public'])
- return self._pubnet
- @property
- def vlan_pool(self):
- return VlanPool.from_dict(_get_keeper()['vlans'])
+VLANS_KEY = "vlans"
+def _add_vlan(project_id, vlan):
+ datastore.Redis.instance().hset(VLANS_KEY, project_id, vlan)
- def get_network_from_name(self, network_name):
- net_dict = _get_keeper()[network_name]
- if net_dict:
- return PrivateNetwork.from_dict(net_dict)
- return None
+def _rem_vlan(project_id):
+ datastore.Redis.instance().hdel(VLANS_KEY, project_id)
- def get_public_ip_for_instance(self, instance_id):
- # FIXME: this should be a lookup - iteration won't scale
- for address_record in self.describe_addresses(type=PublicNetwork):
- if address_record.get(u'instance_id', 'free') == instance_id:
- return address_record[u'address']
-
- def get_project_network(self, project_id):
- """ get a project's private network, allocating one if needed """
-
- project = self.manager.get_project(project_id)
- if not project:
- raise Exception("Project %s doesn't exist, uhoh." % project_id)
- project_net = self.get_network_from_name("%s-default" % project_id)
- if not project_net:
- pool = self.vlan_pool
- vlan = pool.next(project_id)
- private_pool = NetworkPool()
- network_str = private_pool.get_from_vlan(vlan)
- logging.debug("Constructing network %s and %s for %s" % (network_str, vlan, project_id))
- project_net = PrivateNetwork(
- network=network_str,
- vlan=vlan)
- _get_keeper()["%s-default" % project_id] = project_net.to_dict()
- _get_keeper()['vlans'] = pool.to_dict()
- return project_net
-
- def allocate_address(self, user_id, project_id, mac=None, type=PrivateNetwork):
- ip = None
- net_name = None
- if type == PrivateNetwork:
- net = self.get_project_network(project_id)
- ip = net.allocate_ip(user_id, project_id, mac)
- net_name = net.name
- _get_keeper()["%s-default" % project_id] = net.to_dict()
- else:
- net = self.public_net
- ip = net.allocate_ip(user_id, project_id, mac)
- net_name = net.name
- _get_keeper()['public'] = net.to_dict()
- return (ip, net_name)
-
- def deallocate_address(self, address):
- if address in self.public_net.network:
- net = self.public_net
- rv = net.deallocate_ip(str(address))
- _get_keeper()['public'] = net.to_dict()
- return rv
- for project in self.manager.get_projects():
- if address in self.get_project_network(project.id).network:
- net = self.get_project_network(project.id)
- rv = net.deallocate_ip(str(address))
- _get_keeper()["%s-default" % project.id] = net.to_dict()
- return rv
- raise exception.AddressNotAllocated()
-
- def describe_addresses(self, type=PrivateNetwork):
- if type == PrivateNetwork:
- addresses = []
- for project in self.manager.get_projects():
- addresses.extend(self.get_project_network(project.id).list_addresses())
- return addresses
- return self.public_net.list_addresses()
-
- def associate_address(self, address, private_ip, instance_id):
- net = self.public_net
- rv = net.associate_address(address, private_ip, instance_id)
- _get_keeper()['public'] = net.to_dict()
- return rv
-
- def disassociate_address(self, address):
- net = self.public_net
- rv = net.disassociate_address(address)
- _get_keeper()['public'] = net.to_dict()
- return rv
-
- def express(self,address=None):
- for project in self.manager.get_projects():
- self.get_project_network(project.id).express()
-
- def report_state(self):
- pass
+def get_assigned_vlans():
+ """ Returns a dictionary, with keys of project_id and values of vlan_id """
+ return datastore.Redis.instance().hgetall(VLANS_KEY)
+def get_vlan_for_project(project_id):
+ """
+ Allocate vlan IDs to individual users.
+ """
+ vlan = datastore.Redis.instance().hget(VLANS_KEY, project_id)
+ if vlan:
+ return vlan
+ assigned_vlans = get_assigned_vlans()
+ # TODO(joshua) I can do this in one loop, I think
+ for old_project_id, vlan in assigned_vlans.iteritems():
+ if not users.UserManager.instance().get_project(old_project_id):
+ _rem_vlan(old_project_id)
+ _add_vlan(project_id, vlan)
+ return vlan
+ for vlan in range(FLAGS.vlan_start, FLAGS.vlan_end):
+ if not str(vlan) in assigned_vlans.values():
+ _add_vlan(project_id, vlan)
+ return vlan
+ raise exception.AddressNotAllocated("Out of VLANs")
+
+
+def get_network_by_address(address):
+ for project in users.UserManager.instance().get_projects():
+ net = get_project_network(project.id)
+ if address in net.assigned:
+ return net
+ raise exception.AddressNotAllocated()
+
+def allocate_ip(user_id, project_id, mac):
+ return get_project_network(project_id).allocate_ip(user_id, project_id, mac)
+
+def deallocate_ip(address):
+ return get_network_by_address(address).deallocate_ip(address)
+
+def get_project_network(project_id, security_group='default'):
+ """ get a project's private network, allocating one if needed """
+ project = users.UserManager.instance().get_project(project_id)
+ if not project:
+ raise nova.exception.Error("Project %s doesn't exist, uhoh." % project_id)
+ return DHCPNetwork.get_network_for_project(project.project_manager_id, project.id, security_group)
+
+def get_subnet_from_vlan(vlan):
+ """Assign one subnet to each VLAN, for now."""
+ vlan = int(vlan)
+ network = IPy.IP(FLAGS.private_range)
+ start = (vlan-FLAGS.vlan_start) * FLAGS.network_size
+ return "%s-%s" % (network[start], network[start + FLAGS.network_size - 1])
+
+def restart_nets():
+ """ Ensure the network for each user is enabled"""
+ for project in users.UserManager.instance().get_projects():
+ get_project_network(project.id).express()
diff --git a/nova/compute/node.py b/nova/compute/node.py
index 0f9a15672..7c1636f34 100644
--- a/nova/compute/node.py
+++ b/nova/compute/node.py
@@ -137,11 +137,15 @@ class Node(object, service.Service):
logging.debug("Reporting State")
return
- @exception.wrap_exception
+ # @exception.wrap_exception
def run_instance(self, instance_id, **_kwargs):
""" launch a new instance with specified options """
logging.debug("Starting instance %s..." % (instance_id))
inst = self.instdir.get(instance_id)
+ # TODO: Get the real security group of launch in here
+ security_group = "default"
+ net = network.BridgedNetwork.get_network_for_project(inst['user_id'], inst['project_id'],
+ security_group).express()
inst['node_name'] = FLAGS.node_name
inst.save()
# TODO(vish) check to make sure the availability zone matches
@@ -337,8 +341,6 @@ class Instance(object):
'basepath', os.path.abspath(
os.path.join(FLAGS.instances_path, self.name)))
self._s['memory_kb'] = int(self._s['memory_mb']) * 1024
- # TODO(joshua) - Get this from network directory controller later
- self._s['bridge_name'] = data.get('bridge_name', 'br0')
self._s['image_id'] = data.get('image_id', FLAGS.default_image)
self._s['kernel_id'] = data.get('kernel_id', FLAGS.default_kernel)
self._s['ramdisk_id'] = data.get('ramdisk_id', FLAGS.default_ramdisk)
@@ -360,6 +362,7 @@ class Instance(object):
self._s['addressing_type'] = data.get('addressing_type', None)
self._s['availability_zone'] = data.get('availability_zone', 'fixme')
+ self._s['bridge_name'] = data.get('bridge_name', None)
#TODO: put real dns items here
self._s['private_dns_name'] = data.get('private_dns_name', 'fixme')
self._s['dns_name'] = data.get('dns_name',
@@ -476,7 +479,7 @@ class Instance(object):
logging.debug('rebooted instance %s' % self.name)
defer.returnValue(None)
- @exception.wrap_exception
+ # @exception.wrap_exception
def spawn(self):
self.datamodel['state'] = "spawning"
self.datamodel.save()
@@ -516,30 +519,3 @@ class Instance(object):
else:
console = 'FAKE CONSOLE OUTPUT'
return defer.succeed(console)
-
- def generate_mac(self):
- mac = [0x00, 0x16, 0x3e, random.randint(0x00, 0x7f),
- random.randint(0x00, 0xff), random.randint(0x00, 0xff)
- ]
- return ':'.join(map(lambda x: "%02x" % x, mac))
-
-
-
-class NetworkNode(Node):
- def __init__(self, **kwargs):
- super(NetworkNode, self).__init__(**kwargs)
- self.virtNets = {}
-
- def add_network(self, net_dict):
- net = network.VirtNetwork(**net_dict)
- self.virtNets[net.name] = net
- self.virtNets[net.name].express()
- return defer.succeed({'retval': 'network added'})
-
- @exception.wrap_exception
- def run_instance(self, instance_id, **kwargs):
- inst = self.instdir.get(instance_id)
- net_dict = json.loads(inst.get('network_str', "{}"))
- self.add_network(net_dict)
- return super(NetworkNode, self).run_instance(instance_id, **kwargs)
-
diff --git a/nova/datastore.py b/nova/datastore.py
index 97c00264d..0da89d594 100644
--- a/nova/datastore.py
+++ b/nova/datastore.py
@@ -28,6 +28,7 @@ import json
import logging
import os
import sqlite3
+import time
from nova import vendor
import redis
@@ -77,10 +78,11 @@ class RedisModel(object):
def set_default_state(self):
self.state = {'state' : 'pending'}
self.state[self.object_type+"_id"] = self.object_id
+ self.state["create_time"] = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
@property
def __redis_key(self):
- """ Magic string for instance keys """
+ """ Magic string for keys """
return '%s:%s' % (self.object_type, self.object_id)
def __repr__(self):
diff --git a/nova/endpoint/cloud.py b/nova/endpoint/cloud.py
index 53290e386..768a6b3e0 100644
--- a/nova/endpoint/cloud.py
+++ b/nova/endpoint/cloud.py
@@ -60,7 +60,7 @@ class CloudController(object):
"""
def __init__(self):
self.instdir = model.InstanceDirectory()
- self.network = network.NetworkController()
+ self.network = network.PublicNetworkController()
self.setup()
@property
@@ -254,21 +254,10 @@ class CloudController(object):
res.addCallback(_format_result)
return res
- def _convert_address(self, network_address):
- # FIXME(vish): this should go away when network.py stores info properly
- address = {}
- address['public_ip'] == network_address[u'address']
- address['user_id'] == network_address[u'user_id']
- address['project_id'] == network_address.get(u'project_id', address['user_id'])
- address['instance_id'] == network_address.get(u'instance_id', None)
- return address
-
def _get_address(self, context, public_ip):
- # right now all addresses are allocated locally
# FIXME(vish) this should move into network.py
- for network_address in self.network.describe_addresses():
- if network_address[u'address'] == public_ip:
- address = self._convert_address(network_address)
+ for address in self.network.hosts:
+ if address['address'] == public_ip:
if context.user.is_admin() or address['project_id'] == context.project.id:
return address
raise exception.NotFound("Address at ip %s not found" % public_ip)
@@ -398,14 +387,12 @@ class CloudController(object):
def format_addresses(self, context):
addresses = []
# TODO(vish): move authorization checking into network.py
- for network_address in self.network.describe_addresses(type=network.PublicNetwork):
+ for address in self.network.hosts:
#logging.debug(address_record)
- address = self._convert_address(network_address)
address_rv = {
- 'public_ip': address['public_ip'],
+ 'public_ip': address['address'],
'instance_id' : address.get('instance_id', 'free')
}
- # FIXME: add another field for user id
if context.user.is_admin():
address_rv['instance_id'] = "%s (%s, %s)" % (
address['instance_id'],
@@ -417,17 +404,17 @@ class CloudController(object):
return {'addressesSet': addresses}
def allocate_address(self, context, **kwargs):
- (address,network_name) = self.network.allocate_address(
- context.user.id, context.project_id, type=network.PublicNetwork)
+ address = self.network.allocate_ip(
+ context.user.id, context.project.id, 'public')
return defer.succeed({'addressSet': [{'publicIp' : address}]})
def release_address(self, context, public_ip, **kwargs):
- address = self._get_address(public_ip)
+ self.network.deallocate_ip(public_ip)
return defer.succeed({'releaseResponse': ["Address released."]})
def associate_address(self, context, instance_id, **kwargs):
instance = self._get_instance(context, instance_id)
- rv = self.network.associate_address(
+ self.network.associate_address(
kwargs['public_ip'],
instance['private_dns_name'],
instance_id)
@@ -435,7 +422,7 @@ class CloudController(object):
def disassociate_address(self, context, public_ip, **kwargs):
address = self._get_address(public_ip)
- rv = self.network.disassociate_address(public_ip)
+ self.network.disassociate_address(public_ip)
# TODO - Strip the IP from the instance
return defer.succeed({'disassociateResponse': ["Address disassociated."]})
@@ -466,14 +453,10 @@ class CloudController(object):
inst['project_id'] = context.project.id
inst['mac_address'] = utils.generate_mac()
inst['ami_launch_index'] = num
- address, _netname = self.network.allocate_address(
- user_id=inst['user_id'],
- project_id=inst['project_id'],
- mac=inst['mac_address'])
- network = self.network.get_users_network(str(context.user.id))
- inst['network_str'] = json.dumps(network.to_dict())
- inst['bridge_name'] = network.bridge_name
+ address = network.allocate_ip(
+ inst['user_id'], inst['project_id'], mac=inst['mac_address'])
inst['private_dns_name'] = str(address)
+ inst['bridge_name'] = network.BridgedNetwork.get_network_for_project(inst['user_id'], inst['project_id'])['bridge_name']
# TODO: allocate expresses on the router node
inst.save()
rpc.cast(FLAGS.compute_topic,
@@ -502,7 +485,7 @@ class CloudController(object):
if instance.get('private_dns_name', None):
logging.debug("Deallocating address %s" % instance.get('private_dns_name', None))
try:
- self.network.deallocate_address(instance.get('private_dns_name', None))
+ self.network.deallocate_ip(instance.get('private_dns_name', None))
except Exception, _err:
pass
if instance.get('node_name', 'unassigned') != 'unassigned': #It's also internal default
diff --git a/nova/tests/network_unittest.py b/nova/tests/network_unittest.py
index a78d9075d..a2ad89a32 100644
--- a/nova/tests/network_unittest.py
+++ b/nova/tests/network_unittest.py
@@ -23,11 +23,17 @@ from nova import flags
from nova import test
from nova.compute import network
from nova.auth import users
+from nova import utils
class NetworkTestCase(test.TrialTestCase):
def setUp(self):
super(NetworkTestCase, self).setUp()
+ self.flags(fake_libvirt=True,
+ fake_storage=True,
+ fake_network=True,
+ network_size=32,
+ redis_db=8)
logging.getLogger().setLevel(logging.DEBUG)
self.manager = users.UserManager.instance()
try:
@@ -37,7 +43,7 @@ class NetworkTestCase(test.TrialTestCase):
name = 'project%s' % i
if not self.manager.get_project(name):
self.manager.create_project(name, 'netuser', name)
- self.network = network.NetworkController(netsize=16)
+ self.network = network.PublicNetworkController()
def tearDown(self):
super(NetworkTestCase, self).tearDown()
@@ -46,70 +52,69 @@ class NetworkTestCase(test.TrialTestCase):
self.manager.delete_project(name)
self.manager.delete_user('netuser')
- def test_network_serialization(self):
- net1 = network.Network(vlan=100, network="192.168.100.0/24", conn=None)
- address = net1.allocate_ip("netuser", "project0", "01:24:55:36:f2:a0")
- net_json = str(net1)
- net2 = network.Network.from_json(net_json)
- self.assertEqual(net_json, str(net2))
- self.assertTrue(IPy.IP(address) in net2.network)
+ def test_public_network_allocation(self):
+ pubnet = IPy.IP(flags.FLAGS.public_range)
+ address = self.network.allocate_ip("netuser", "project0", "public")
+ self.assertTrue(IPy.IP(address) in pubnet)
+ self.assertTrue(IPy.IP(address) in self.network.network)
- def test_allocate_deallocate_address(self):
- (address, net_name) = self.network.allocate_address("netuser",
- "project0", "01:24:55:36:f2:a0")
+ def test_allocate_deallocate_ip(self):
+ address = network.allocate_ip(
+ "netuser", "project0", utils.generate_mac())
logging.debug("Was allocated %s" % (address))
self.assertEqual(True, address in self._get_project_addresses("project0"))
- rv = self.network.deallocate_address(address)
+ rv = network.deallocate_ip(address)
self.assertEqual(False, address in self._get_project_addresses("project0"))
def test_range_allocation(self):
- (address, net_name) = self.network.allocate_address("netuser",
- "project0", "01:24:55:36:f2:a0")
- (secondaddress, net_name) = self.network.allocate_address("netuser",
- "project1", "01:24:55:36:f2:a0")
- self.assertEqual(True, address in self._get_project_addresses("project0"))
+ address = network.allocate_ip(
+ "netuser", "project0", utils.generate_mac())
+ secondaddress = network.allocate_ip(
+ "netuser", "project1", utils.generate_mac())
+ self.assertEqual(True,
+ address in self._get_project_addresses("project0"))
self.assertEqual(True,
secondaddress in self._get_project_addresses("project1"))
self.assertEqual(False, address in self._get_project_addresses("project1"))
- rv = self.network.deallocate_address(address)
+ rv = network.deallocate_ip(address)
self.assertEqual(False, address in self._get_project_addresses("project0"))
- rv = self.network.deallocate_address(secondaddress)
+ rv = network.deallocate_ip(secondaddress)
self.assertEqual(False,
secondaddress in self._get_project_addresses("project1"))
def test_subnet_edge(self):
- (secondaddress, net_name) = self.network.allocate_address("netuser", "project0")
+ secondaddress = network.allocate_ip("netuser", "project0",
+ utils.generate_mac())
for project in range(1,5):
project_id = "project%s" % (project)
- (address, net_name) = self.network.allocate_address("netuser",
- project_id, "01:24:55:36:f2:a0")
- (address2, net_name) = self.network.allocate_address("netuser",
- project_id, "01:24:55:36:f2:a0")
- (address3, net_name) = self.network.allocate_address("netuser",
- project_id, "01:24:55:36:f2:a0")
+ address = network.allocate_ip(
+ "netuser", project_id, utils.generate_mac())
+ address2 = network.allocate_ip(
+ "netuser", project_id, utils.generate_mac())
+ address3 = network.allocate_ip(
+ "netuser", project_id, utils.generate_mac())
self.assertEqual(False,
address in self._get_project_addresses("project0"))
self.assertEqual(False,
address2 in self._get_project_addresses("project0"))
self.assertEqual(False,
address3 in self._get_project_addresses("project0"))
- rv = self.network.deallocate_address(address)
- rv = self.network.deallocate_address(address2)
- rv = self.network.deallocate_address(address3)
- rv = self.network.deallocate_address(secondaddress)
+ rv = network.deallocate_ip(address)
+ rv = network.deallocate_ip(address2)
+ rv = network.deallocate_ip(address3)
+ rv = network.deallocate_ip(secondaddress)
def test_too_many_projects(self):
for i in range(0, 30):
name = 'toomany-project%s' % i
self.manager.create_project(name, 'netuser', name)
- (address, net_name) = self.network.allocate_address("netuser",
- name, "01:24:55:36:f2:a0")
+ address = network.allocate_ip(
+ "netuser", name, utils.generate_mac())
+ rv = network.deallocate_ip(address)
self.manager.delete_project(name)
def _get_project_addresses(self, project_id):
- rv = self.network.describe_addresses()
project_addresses = []
- for item in rv:
- if item['project_id'] == project_id:
- project_addresses.append(item['address'])
+ for addr in network.get_project_network(project_id).list_addresses():
+ project_addresses.append(addr)
return project_addresses