Josh's networking refactor, modified to work with projects

This commit is contained in:
Vishvananda Ishaya
2010-05-31 18:56:20 -07:00
parent c36ea2ce5d
commit d897aac1f3
3 changed files with 58 additions and 68 deletions

View File

@@ -28,6 +28,7 @@ import json
import logging import logging
import os import os
import sqlite3 import sqlite3
import time
from nova import vendor from nova import vendor
import redis import redis
@@ -77,10 +78,11 @@ class RedisModel(object):
def set_default_state(self): def set_default_state(self):
self.state = {'state' : 'pending'} self.state = {'state' : 'pending'}
self.state[self.object_type+"_id"] = self.object_id self.state[self.object_type+"_id"] = self.object_id
self.state["create_time"] = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
@property @property
def __redis_key(self): def __redis_key(self):
""" Magic string for instance keys """ """ Magic string for keys """
return '%s:%s' % (self.object_type, self.object_id) return '%s:%s' % (self.object_type, self.object_id)
def __repr__(self): def __repr__(self):

View File

@@ -60,7 +60,7 @@ class CloudController(object):
""" """
def __init__(self): def __init__(self):
self.instdir = model.InstanceDirectory() self.instdir = model.InstanceDirectory()
self.network = network.NetworkController() self.network = network.PublicNetworkController()
self.setup() self.setup()
@property @property
@@ -254,21 +254,10 @@ class CloudController(object):
res.addCallback(_format_result) res.addCallback(_format_result)
return res 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): def _get_address(self, context, public_ip):
# right now all addresses are allocated locally
# FIXME(vish) this should move into network.py # FIXME(vish) this should move into network.py
for network_address in self.network.describe_addresses(): for address in self.network.hosts:
if network_address[u'address'] == public_ip: if address['address'] == public_ip:
address = self._convert_address(network_address)
if context.user.is_admin() or address['project_id'] == context.project.id: if context.user.is_admin() or address['project_id'] == context.project.id:
return address return address
raise exception.NotFound("Address at ip %s not found" % public_ip) raise exception.NotFound("Address at ip %s not found" % public_ip)
@@ -398,14 +387,12 @@ class CloudController(object):
def format_addresses(self, context): def format_addresses(self, context):
addresses = [] addresses = []
# TODO(vish): move authorization checking into network.py # 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) #logging.debug(address_record)
address = self._convert_address(network_address)
address_rv = { address_rv = {
'public_ip': address['public_ip'], 'public_ip': address['address'],
'instance_id' : address.get('instance_id', 'free') 'instance_id' : address.get('instance_id', 'free')
} }
# FIXME: add another field for user id
if context.user.is_admin(): if context.user.is_admin():
address_rv['instance_id'] = "%s (%s, %s)" % ( address_rv['instance_id'] = "%s (%s, %s)" % (
address['instance_id'], address['instance_id'],
@@ -417,17 +404,17 @@ class CloudController(object):
return {'addressesSet': addresses} return {'addressesSet': addresses}
def allocate_address(self, context, **kwargs): def allocate_address(self, context, **kwargs):
(address,network_name) = self.network.allocate_address( address = self.network.allocate_ip(
context.user.id, context.project_id, type=network.PublicNetwork) context.user.id, context.project.id, 'public')
return defer.succeed({'addressSet': [{'publicIp' : address}]}) return defer.succeed({'addressSet': [{'publicIp' : address}]})
def release_address(self, context, public_ip, **kwargs): 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."]}) return defer.succeed({'releaseResponse': ["Address released."]})
def associate_address(self, context, instance_id, **kwargs): def associate_address(self, context, instance_id, **kwargs):
instance = self._get_instance(context, instance_id) instance = self._get_instance(context, instance_id)
rv = self.network.associate_address( self.network.associate_address(
kwargs['public_ip'], kwargs['public_ip'],
instance['private_dns_name'], instance['private_dns_name'],
instance_id) instance_id)
@@ -435,7 +422,7 @@ class CloudController(object):
def disassociate_address(self, context, public_ip, **kwargs): def disassociate_address(self, context, public_ip, **kwargs):
address = self._get_address(public_ip) 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 # TODO - Strip the IP from the instance
return defer.succeed({'disassociateResponse': ["Address disassociated."]}) return defer.succeed({'disassociateResponse': ["Address disassociated."]})
@@ -466,14 +453,10 @@ class CloudController(object):
inst['project_id'] = context.project.id inst['project_id'] = context.project.id
inst['mac_address'] = utils.generate_mac() inst['mac_address'] = utils.generate_mac()
inst['ami_launch_index'] = num inst['ami_launch_index'] = num
address, _netname = self.network.allocate_address( address = network.allocate_ip(
user_id=inst['user_id'], inst['user_id'], inst['project_id'], mac=inst['mac_address'])
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
inst['private_dns_name'] = str(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 # TODO: allocate expresses on the router node
inst.save() inst.save()
rpc.cast(FLAGS.compute_topic, rpc.cast(FLAGS.compute_topic,
@@ -502,7 +485,7 @@ class CloudController(object):
if instance.get('private_dns_name', None): if instance.get('private_dns_name', None):
logging.debug("Deallocating address %s" % instance.get('private_dns_name', None)) logging.debug("Deallocating address %s" % instance.get('private_dns_name', None))
try: try:
self.network.deallocate_address(instance.get('private_dns_name', None)) self.network.deallocate_ip(instance.get('private_dns_name', None))
except Exception, _err: except Exception, _err:
pass pass
if instance.get('node_name', 'unassigned') != 'unassigned': #It's also internal default if instance.get('node_name', 'unassigned') != 'unassigned': #It's also internal default

View File

@@ -23,11 +23,17 @@ from nova import flags
from nova import test from nova import test
from nova.compute import network from nova.compute import network
from nova.auth import users from nova.auth import users
from nova import utils
class NetworkTestCase(test.TrialTestCase): class NetworkTestCase(test.TrialTestCase):
def setUp(self): def setUp(self):
super(NetworkTestCase, self).setUp() 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) logging.getLogger().setLevel(logging.DEBUG)
self.manager = users.UserManager.instance() self.manager = users.UserManager.instance()
try: try:
@@ -37,7 +43,7 @@ class NetworkTestCase(test.TrialTestCase):
name = 'project%s' % i name = 'project%s' % i
if not self.manager.get_project(name): if not self.manager.get_project(name):
self.manager.create_project(name, 'netuser', name) self.manager.create_project(name, 'netuser', name)
self.network = network.NetworkController(netsize=16) self.network = network.PublicNetworkController()
def tearDown(self): def tearDown(self):
super(NetworkTestCase, self).tearDown() super(NetworkTestCase, self).tearDown()
@@ -46,70 +52,69 @@ class NetworkTestCase(test.TrialTestCase):
self.manager.delete_project(name) self.manager.delete_project(name)
self.manager.delete_user('netuser') self.manager.delete_user('netuser')
def test_network_serialization(self): def test_public_network_allocation(self):
net1 = network.Network(vlan=100, network="192.168.100.0/24", conn=None) pubnet = IPy.IP(flags.FLAGS.public_range)
address = net1.allocate_ip("netuser", "project0", "01:24:55:36:f2:a0") address = self.network.allocate_ip("netuser", "project0", "public")
net_json = str(net1) self.assertTrue(IPy.IP(address) in pubnet)
net2 = network.Network.from_json(net_json) self.assertTrue(IPy.IP(address) in self.network.network)
self.assertEqual(net_json, str(net2))
self.assertTrue(IPy.IP(address) in net2.network)
def test_allocate_deallocate_address(self): def test_allocate_deallocate_ip(self):
(address, net_name) = self.network.allocate_address("netuser", address = network.allocate_ip(
"project0", "01:24:55:36:f2:a0") "netuser", "project0", utils.generate_mac())
logging.debug("Was allocated %s" % (address)) logging.debug("Was allocated %s" % (address))
self.assertEqual(True, address in self._get_project_addresses("project0")) 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")) self.assertEqual(False, address in self._get_project_addresses("project0"))
def test_range_allocation(self): def test_range_allocation(self):
(address, net_name) = self.network.allocate_address("netuser", address = network.allocate_ip(
"project0", "01:24:55:36:f2:a0") "netuser", "project0", utils.generate_mac())
(secondaddress, net_name) = self.network.allocate_address("netuser", secondaddress = network.allocate_ip(
"project1", "01:24:55:36:f2:a0") "netuser", "project1", utils.generate_mac())
self.assertEqual(True, address in self._get_project_addresses("project0")) self.assertEqual(True,
address in self._get_project_addresses("project0"))
self.assertEqual(True, self.assertEqual(True,
secondaddress in self._get_project_addresses("project1")) secondaddress in self._get_project_addresses("project1"))
self.assertEqual(False, address 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")) self.assertEqual(False, address in self._get_project_addresses("project0"))
rv = self.network.deallocate_address(secondaddress) rv = network.deallocate_ip(secondaddress)
self.assertEqual(False, self.assertEqual(False,
secondaddress in self._get_project_addresses("project1")) secondaddress in self._get_project_addresses("project1"))
def test_subnet_edge(self): 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): for project in range(1,5):
project_id = "project%s" % (project) project_id = "project%s" % (project)
(address, net_name) = self.network.allocate_address("netuser", address = network.allocate_ip(
project_id, "01:24:55:36:f2:a0") "netuser", project_id, utils.generate_mac())
(address2, net_name) = self.network.allocate_address("netuser", address2 = network.allocate_ip(
project_id, "01:24:55:36:f2:a0") "netuser", project_id, utils.generate_mac())
(address3, net_name) = self.network.allocate_address("netuser", address3 = network.allocate_ip(
project_id, "01:24:55:36:f2:a0") "netuser", project_id, utils.generate_mac())
self.assertEqual(False, self.assertEqual(False,
address in self._get_project_addresses("project0")) address in self._get_project_addresses("project0"))
self.assertEqual(False, self.assertEqual(False,
address2 in self._get_project_addresses("project0")) address2 in self._get_project_addresses("project0"))
self.assertEqual(False, self.assertEqual(False,
address3 in self._get_project_addresses("project0")) address3 in self._get_project_addresses("project0"))
rv = self.network.deallocate_address(address) rv = network.deallocate_ip(address)
rv = self.network.deallocate_address(address2) rv = network.deallocate_ip(address2)
rv = self.network.deallocate_address(address3) rv = network.deallocate_ip(address3)
rv = self.network.deallocate_address(secondaddress) rv = network.deallocate_ip(secondaddress)
def test_too_many_projects(self): def test_too_many_projects(self):
for i in range(0, 30): for i in range(0, 30):
name = 'toomany-project%s' % i name = 'toomany-project%s' % i
self.manager.create_project(name, 'netuser', name) self.manager.create_project(name, 'netuser', name)
(address, net_name) = self.network.allocate_address("netuser", address = network.allocate_ip(
name, "01:24:55:36:f2:a0") "netuser", name, utils.generate_mac())
rv = network.deallocate_ip(address)
self.manager.delete_project(name) self.manager.delete_project(name)
def _get_project_addresses(self, project_id): def _get_project_addresses(self, project_id):
rv = self.network.describe_addresses()
project_addresses = [] project_addresses = []
for item in rv: for addr in network.get_project_network(project_id).list_addresses():
if item['project_id'] == project_id: project_addresses.append(addr)
project_addresses.append(item['address'])
return project_addresses return project_addresses