Merge lp:~vishvananda/nova/remove-network-index into lp:~hudson-openstack/nova/trunk

Proposed by Vish Ishaya
Status: Merged
Approved by: Rick Clark
Approved revision: 304
Merged at revision: 346
Proposed branch: lp:~vishvananda/nova/remove-network-index
Merge into: lp:~hudson-openstack/nova/trunk
Prerequisite: lp:~vishvananda/nova/network-lease-fix
Diff against target: 1162 lines (+297/-254)
17 files modified
bin/nova-manage (+28/-3)
nova/api/ec2/cloud.py (+6/-5)
nova/api/openstack/servers.py (+16/-19)
nova/auth/manager.py (+0/-15)
nova/compute/manager.py (+1/-1)
nova/db/api.py (+25/-20)
nova/db/sqlalchemy/api.py (+58/-65)
nova/db/sqlalchemy/models.py (+10/-23)
nova/network/linux_net.py (+3/-3)
nova/network/manager.py (+94/-77)
nova/test.py (+16/-2)
nova/tests/cloud_unittest.py (+2/-2)
nova/tests/compute_unittest.py (+2/-1)
nova/tests/network_unittest.py (+21/-11)
nova/tests/scheduler_unittest.py (+1/-0)
nova/tests/virt_unittest.py (+11/-5)
nova/virt/libvirt_conn.py (+3/-2)
To merge this branch: bzr merge lp:~vishvananda/nova/remove-network-index
Reviewer Review Type Date Requested Status
Rick Clark (community) Approve
Jay Pipes (community) Needs Fixing
Review via email: mp+36921@code.launchpad.net

Description of the change

This patch removes the ugly network_index that is used by VlanManager and turns network itself into a pool. It adds support for creating the networks through an api command:
    nova-manage network create # creates all of the networks defined by flags
or
    nova-manage network create 5 # create the first five networks

This moves the network out of project.create, associating a network to a project lazily in project_get_network. This allows for a bit greater control over networks. There are a couple outstanding issues:
   1) Where do networks get disassociated? Right now I'm not disassociating at all. We're sharing ldap users across different deploys, whereas sql db is unique per deploy. Perhaps the solution is to have a flag like disassociate_on_project_destroy and make it optional?
   2) How do we handle creation of networks for tests? It is really slow to create a pool of networks and fixed_ips for each test case. Right now I'm taking advantage of the fact that the db isn't cleaned between tests, and creating them if they don't exist in BaseTestCase.SetUp() and disassociating in TearDown(). Ideally this should be replaced with fixtures of some sort.

Comments on these two issues are welcome.

To post a comment you must log in.
Revision history for this message
Jay Pipes (jaypipes) wrote :

"1) Where do networks get disassociated? Right now I'm not disassociating at all. We're sharing ldap users across different deploys, whereas sql db is unique per deploy. Perhaps the solution is to have a flag like disassociate_on_project_destroy and make it optional?"

I think that is an excellent option. ++ on a flag to determine when disassociation occurs.

"2) How do we handle creation of networks for tests? It is really slow to create a pool of networks and fixed_ips for each test case. Right now I'm taking advantage of the fact that the db isn't cleaned between tests, and creating them if they don't exist in BaseTestCase.SetUp() and disassociating in TearDown(). Ideally this should be replaced with fixtures of some sort."

Well, there's a ton to talk about with the current testing systems at the next summit :) I say "systems" because the new rackspace stuff is using nosetests, and the rest is using the nova.test.BaseTestCase or unittest.TestCase.

I'd love to do a discuss the future of how we test OS projects at the summit...including stuff like how we establish fixtures and configuration-dependent environments.

-jay

Revision history for this message
Jay Pipes (jaypipes) wrote :

lgtm.

review: Approve
297. By Vish Ishaya

merged trunk

298. By Vish Ishaya

Fixed flat network manager with network index gone.

Both managers use ips created through nova manage.

Use of project_get_network is minimized to make way for managers that
would prefer to use cluste or host based ips instead of project based ips.

299. By Vish Ishaya

fix typo in setup_compute_network

Revision history for this message
Jay Pipes (jaypipes) wrote :

ping. vishy, looks like you need to merge with trunk and resolve conflicts from devin's auth work...

review: Needs Fixing
300. By Vish Ishaya

merged trunk and fixed tests

301. By Vish Ishaya

merged trunk

302. By Vish Ishaya

fix tests

303. By Vish Ishaya

super teardown

304. By Vish Ishaya

cleanup leftover addresses

Revision history for this message
Rick Clark (dendrobates) wrote :

lgtm

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bin/nova-manage'
--- bin/nova-manage 2010-10-12 14:23:24 +0000
+++ bin/nova-manage 2010-10-13 07:50:58 +0000
@@ -73,6 +73,7 @@
73from nova import quota73from nova import quota
74from nova import utils74from nova import utils
75from nova.auth import manager75from nova.auth import manager
76from nova.network import manager as network_manager
76from nova.cloudpipe import pipelib77from nova.cloudpipe import pipelib
7778
7879
@@ -377,6 +378,29 @@
377 floating_ip['address'],378 floating_ip['address'],
378 instance)379 instance)
379380
381class NetworkCommands(object):
382 """Class for managing networks."""
383
384 def create(self, fixed_range=None, num_networks=None,
385 network_size=None, vlan_start=None, vpn_start=None):
386 """Creates fixed ips for host by range
387 arguments: [fixed_range=FLAG], [num_networks=FLAG],
388 [network_size=FLAG], [vlan_start=FLAG],
389 [vpn_start=FLAG]"""
390 if not fixed_range:
391 fixed_range = FLAGS.fixed_range
392 if not num_networks:
393 num_networks = FLAGS.num_networks
394 if not network_size:
395 network_size = FLAGS.network_size
396 if not vlan_start:
397 vlan_start = FLAGS.vlan_start
398 if not vpn_start:
399 vpn_start = FLAGS.vpn_start
400 net_manager = utils.import_object(FLAGS.network_manager)
401 net_manager.create_networks(None, fixed_range, int(num_networks),
402 int(network_size), int(vlan_start),
403 int(vpn_start))
380404
381CATEGORIES = [405CATEGORIES = [
382 ('user', UserCommands),406 ('user', UserCommands),
@@ -384,7 +408,8 @@
384 ('role', RoleCommands),408 ('role', RoleCommands),
385 ('shell', ShellCommands),409 ('shell', ShellCommands),
386 ('vpn', VpnCommands),410 ('vpn', VpnCommands),
387 ('floating', FloatingIpCommands)411 ('floating', FloatingIpCommands),
412 ('network', NetworkCommands)
388]413]
389414
390415
@@ -454,9 +479,9 @@
454 fn(*argv)479 fn(*argv)
455 sys.exit(0)480 sys.exit(0)
456 except TypeError:481 except TypeError:
457 print "Wrong number of arguments supplied"482 print "Possible wrong number of arguments supplied"
458 print "%s %s: %s" % (category, action, fn.__doc__)483 print "%s %s: %s" % (category, action, fn.__doc__)
459 sys.exit(2)484 raise
460485
461if __name__ == '__main__':486if __name__ == '__main__':
462 main()487 main()
463488
=== modified file 'nova/api/ec2/cloud.py'
--- nova/api/ec2/cloud.py 2010-10-12 07:24:33 +0000
+++ nova/api/ec2/cloud.py 2010-10-13 07:50:58 +0000
@@ -734,13 +734,13 @@
734734
735 def _get_network_topic(self, context):735 def _get_network_topic(self, context):
736 """Retrieves the network host for a project"""736 """Retrieves the network host for a project"""
737 network_ref = db.project_get_network(context, context.project.id)737 network_ref = self.network_manager.get_network(context)
738 host = network_ref['host']738 host = network_ref['host']
739 if not host:739 if not host:
740 host = rpc.call(FLAGS.network_topic,740 host = rpc.call(FLAGS.network_topic,
741 {"method": "set_network_host",741 {"method": "set_network_host",
742 "args": {"context": None,742 "args": {"context": None,
743 "project_id": context.project.id}})743 "network_id": network_ref['id']}})
744 return db.queue_get_for(context, FLAGS.network_topic, host)744 return db.queue_get_for(context, FLAGS.network_topic, host)
745745
746 def _ensure_default_security_group(self, context):746 def _ensure_default_security_group(self, context):
@@ -851,12 +851,13 @@
851 ec2_id = internal_id_to_ec2_id(internal_id)851 ec2_id = internal_id_to_ec2_id(internal_id)
852 inst['hostname'] = ec2_id852 inst['hostname'] = ec2_id
853 db.instance_update(context, inst_id, inst)853 db.instance_update(context, inst_id, inst)
854 # TODO(vish): This probably should be done in the scheduler
855 # or in compute as a call. The network should be
856 # allocated after the host is assigned and setup
857 # can happen at the same time.
854 address = self.network_manager.allocate_fixed_ip(context,858 address = self.network_manager.allocate_fixed_ip(context,
855 inst_id,859 inst_id,
856 vpn)860 vpn)
857
858 # TODO(vish): This probably should be done in the scheduler
859 # network is setup when host is assigned
860 network_topic = self._get_network_topic(context)861 network_topic = self._get_network_topic(context)
861 rpc.call(network_topic,862 rpc.call(network_topic,
862 {"method": "setup_fixed_ip",863 {"method": "setup_fixed_ip",
863864
=== modified file 'nova/api/openstack/servers.py'
--- nova/api/openstack/servers.py 2010-10-08 21:08:48 +0000
+++ nova/api/openstack/servers.py 2010-10-13 07:50:58 +0000
@@ -48,9 +48,9 @@
48 return dict(servers=entities)48 return dict(servers=entities)
4949
50def _entity_detail(inst):50def _entity_detail(inst):
51 """ Maps everything to valid attributes for return"""51 """ Maps everything to Rackspace-like attributes for return"""
52 power_mapping = { 52 power_mapping = {
53 power_state.NOSTATE: 'build', 53 power_state.NOSTATE: 'build',
54 power_state.RUNNING: 'active',54 power_state.RUNNING: 'active',
55 power_state.BLOCKED: 'active',55 power_state.BLOCKED: 'active',
56 power_state.PAUSED: 'suspended',56 power_state.PAUSED: 'suspended',
@@ -60,7 +60,7 @@
60 }60 }
61 inst_dict = {}61 inst_dict = {}
6262
63 mapped_keys = dict(status='state', imageId='image_id', 63 mapped_keys = dict(status='state', imageId='image_id',
64 flavorId='instance_type', name='server_name', id='id')64 flavorId='instance_type', name='server_name', id='id')
6565
66 for k, v in mapped_keys.iteritems():66 for k, v in mapped_keys.iteritems():
@@ -83,7 +83,7 @@
83 _serialization_metadata = {83 _serialization_metadata = {
84 'application/xml': {84 'application/xml': {
85 "attributes": {85 "attributes": {
86 "server": [ "id", "imageId", "name", "flavorId", "hostId", 86 "server": [ "id", "imageId", "name", "flavorId", "hostId",
87 "status", "progress", "progress" ]87 "status", "progress", "progress" ]
88 }88 }
89 }89 }
@@ -155,7 +155,7 @@
155 user_id = req.environ['nova.context']['user']['id']155 user_id = req.environ['nova.context']['user']['id']
156156
157 inst_dict = self._deserialize(req.body, req)157 inst_dict = self._deserialize(req.body, req)
158 158
159 if not inst_dict:159 if not inst_dict:
160 return faults.Fault(exc.HTTPUnprocessableEntity())160 return faults.Fault(exc.HTTPUnprocessableEntity())
161161
@@ -163,12 +163,12 @@
163 if not instance or instance.user_id != user_id:163 if not instance or instance.user_id != user_id:
164 return faults.Fault(exc.HTTPNotFound())164 return faults.Fault(exc.HTTPNotFound())
165165
166 self.db_driver.instance_update(None, int(id), 166 self.db_driver.instance_update(None, int(id),
167 _filter_params(inst_dict['server']))167 _filter_params(inst_dict['server']))
168 return faults.Fault(exc.HTTPNoContent())168 return faults.Fault(exc.HTTPNoContent())
169169
170 def action(self, req, id):170 def action(self, req, id):
171 """ multi-purpose method used to reboot, rebuild, and 171 """ multi-purpose method used to reboot, rebuild, and
172 resize a server """172 resize a server """
173 user_id = req.environ['nova.context']['user']['id']173 user_id = req.environ['nova.context']['user']['id']
174 input_dict = self._deserialize(req.body, req)174 input_dict = self._deserialize(req.body, req)
@@ -195,12 +195,11 @@
195 if v['flavorid'] == flavor_id][0]195 if v['flavorid'] == flavor_id][0]
196196
197 image_id = env['server']['imageId']197 image_id = env['server']['imageId']
198
199 img_service = utils.import_object(FLAGS.image_service)198 img_service = utils.import_object(FLAGS.image_service)
200199
201 image = img_service.show(image_id)200 image = img_service.show(image_id)
202201
203 if not image: 202 if not image:
204 raise Exception, "Image not found"203 raise Exception, "Image not found"
205204
206 inst['server_name'] = env['server']['name']205 inst['server_name'] = env['server']['name']
@@ -236,15 +235,14 @@
236235
237 ref = self.db_driver.instance_create(None, inst)236 ref = self.db_driver.instance_create(None, inst)
238 inst['id'] = ref.internal_id237 inst['id'] = ref.internal_id
239
240 # TODO(dietz): this isn't explicitly necessary, but the networking238 # TODO(dietz): this isn't explicitly necessary, but the networking
241 # calls depend on an object with a project_id property, and therefore239 # calls depend on an object with a project_id property, and therefore
242 # should be cleaned up later240 # should be cleaned up later
243 api_context = context.APIRequestContext(user_id)241 api_context = context.APIRequestContext(user_id)
244 242
245 inst['mac_address'] = utils.generate_mac()243 inst['mac_address'] = utils.generate_mac()
246 244
247 #TODO(dietz) is this necessary? 245 #TODO(dietz) is this necessary?
248 inst['launch_index'] = 0246 inst['launch_index'] = 0
249247
250 inst['hostname'] = str(ref.internal_id)248 inst['hostname'] = str(ref.internal_id)
@@ -256,21 +254,20 @@
256254
257 # TODO(vish): This probably should be done in the scheduler255 # TODO(vish): This probably should be done in the scheduler
258 # network is setup when host is assigned256 # network is setup when host is assigned
259 network_topic = self._get_network_topic(user_id)257 network_topic = self._get_network_topic(None)
260 rpc.call(network_topic,258 rpc.call(network_topic,
261 {"method": "setup_fixed_ip",259 {"method": "setup_fixed_ip",
262 "args": {"context": None,260 "args": {"context": None,
263 "address": address}})261 "address": address}})
264 return inst262 return inst
265263
266 def _get_network_topic(self, user_id):264 def _get_network_topic(self, context):
267 """Retrieves the network host for a project"""265 """Retrieves the network host for a project"""
268 network_ref = self.db_driver.project_get_network(None, 266 network_ref = self.network_manager.get_network(context)
269 user_id)
270 host = network_ref['host']267 host = network_ref['host']
271 if not host:268 if not host:
272 host = rpc.call(FLAGS.network_topic,269 host = rpc.call(FLAGS.network_topic,
273 {"method": "set_network_host",270 {"method": "set_network_host",
274 "args": {"context": None,271 "args": {"context": None,
275 "project_id": user_id}})272 "network_id": network_ref['id']}})
276 return self.db_driver.queue_get_for(None, FLAGS.network_topic, host)273 return self.db_driver.queue_get_for(None, FLAGS.network_topic, host)
277274
=== modified file 'nova/auth/manager.py'
--- nova/auth/manager.py 2010-10-12 20:04:46 +0000
+++ nova/auth/manager.py 2010-10-13 07:50:58 +0000
@@ -484,13 +484,6 @@
484 member_users)484 member_users)
485 if project_dict:485 if project_dict:
486 project = Project(**project_dict)486 project = Project(**project_dict)
487 try:
488 self.network_manager.allocate_network(context,
489 project.id)
490 except:
491 drv.delete_project(project.id)
492 raise
493
494 return project487 return project
495488
496 def modify_project(self, project, manager_user=None, description=None):489 def modify_project(self, project, manager_user=None, description=None):
@@ -559,14 +552,6 @@
559552
560 def delete_project(self, project, context=None):553 def delete_project(self, project, context=None):
561 """Deletes a project"""554 """Deletes a project"""
562 try:
563 network_ref = db.project_get_network(context,
564 Project.safe_id(project))
565 db.network_destroy(context, network_ref['id'])
566 except:
567 logging.exception('Could not destroy network for %s',
568 project)
569
570 with self.driver() as drv:555 with self.driver() as drv:
571 drv.delete_project(Project.safe_id(project))556 drv.delete_project(Project.safe_id(project))
572557
573558
=== modified file 'nova/compute/manager.py'
--- nova/compute/manager.py 2010-10-12 20:18:29 +0000
+++ nova/compute/manager.py 2010-10-13 07:50:58 +0000
@@ -76,7 +76,7 @@
76 raise exception.Error("Instance has already been created")76 raise exception.Error("Instance has already been created")
77 logging.debug("instance %s: starting...", instance_id)77 logging.debug("instance %s: starting...", instance_id)
78 project_id = instance_ref['project_id']78 project_id = instance_ref['project_id']
79 self.network_manager.setup_compute_network(context, project_id)79 self.network_manager.setup_compute_network(context, instance_id)
80 self.db.instance_update(context,80 self.db.instance_update(context,
81 instance_id,81 instance_id,
82 {'host': self.host})82 {'host': self.host})
8383
=== modified file 'nova/db/api.py'
--- nova/db/api.py 2010-10-12 20:04:46 +0000
+++ nova/db/api.py 2010-10-13 07:50:58 +0000
@@ -340,6 +340,11 @@
340####################340####################
341341
342342
343def network_associate(context, project_id):
344 """Associate a free network to a project."""
345 return IMPL.network_associate(context, project_id)
346
347
343def network_count(context):348def network_count(context):
344 """Return the number of networks."""349 """Return the number of networks."""
345 return IMPL.network_count(context)350 return IMPL.network_count(context)
@@ -360,9 +365,12 @@
360 return IMPL.network_count_reserved_ips(context, network_id)365 return IMPL.network_count_reserved_ips(context, network_id)
361366
362367
363def network_create(context, values):368def network_create_safe(context, values):
364 """Create a network from the values dictionary."""369 """Create a network from the values dict
365 return IMPL.network_create(context, values)370
371 The network is only returned if the create succeeds. If the create violates
372 constraints because the network already exists, no exception is raised."""
373 return IMPL.network_create_safe(context, values)
366374
367375
368def network_create_fixed_ips(context, network_id, num_vpn_clients):376def network_create_fixed_ips(context, network_id, num_vpn_clients):
@@ -370,9 +378,14 @@
370 return IMPL.network_create_fixed_ips(context, network_id, num_vpn_clients)378 return IMPL.network_create_fixed_ips(context, network_id, num_vpn_clients)
371379
372380
373def network_destroy(context, network_id):381def network_disassociate(context, network_id):
374 """Destroy the network or raise if it does not exist."""382 """Disassociate the network from project or raise if it does not exist."""
375 return IMPL.network_destroy(context, network_id)383 return IMPL.network_disassociate(context, network_id)
384
385
386def network_disassociate_all(context):
387 """Disassociate all networks from projects."""
388 return IMPL.network_disassociate_all(context)
376389
377390
378def network_get(context, network_id):391def network_get(context, network_id):
@@ -387,10 +400,15 @@
387400
388401
389def network_get_by_bridge(context, bridge):402def network_get_by_bridge(context, bridge):
390 """Get an network or raise if it does not exist."""403 """Get a network by bridge or raise if it does not exist."""
391 return IMPL.network_get_by_bridge(context, bridge)404 return IMPL.network_get_by_bridge(context, bridge)
392405
393406
407def network_get_by_instance(context, instance_id):
408 """Get a network by instance id or raise if it does not exist."""
409 return IMPL.network_get_by_instance(context, instance_id)
410
411
394def network_get_index(context, network_id):412def network_get_index(context, network_id):
395 """Get non-conflicting index for network"""413 """Get non-conflicting index for network"""
396 return IMPL.network_get_index(context, network_id)414 return IMPL.network_get_index(context, network_id)
@@ -401,19 +419,6 @@
401 return IMPL.network_get_vpn_ip(context, network_id)419 return IMPL.network_get_vpn_ip(context, network_id)
402420
403421
404def network_index_count(context):
405 """Return count of network indexes"""
406 return IMPL.network_index_count(context)
407
408
409def network_index_create_safe(context, values):
410 """Create a network index from the values dict
411
412 The index is not returned. If the create violates the unique
413 constraints because the index already exists, no exception is raised."""
414 return IMPL.network_index_create_safe(context, values)
415
416
417def network_set_cidr(context, network_id, cidr):422def network_set_cidr(context, network_id, cidr):
418 """Set the Classless Inner Domain Routing for the network"""423 """Set the Classless Inner Domain Routing for the network"""
419 return IMPL.network_set_cidr(context, network_id, cidr)424 return IMPL.network_set_cidr(context, network_id, cidr)
420425
=== modified file 'nova/db/sqlalchemy/api.py'
--- nova/db/sqlalchemy/api.py 2010-10-12 05:21:25 +0000
+++ nova/db/sqlalchemy/api.py 2010-10-13 07:50:58 +0000
@@ -805,6 +805,24 @@
805805
806806
807@require_admin_context807@require_admin_context
808def network_associate(context, project_id):
809 session = get_session()
810 with session.begin():
811 network_ref = session.query(models.Network
812 ).filter_by(deleted=False
813 ).filter_by(project_id=None
814 ).with_lockmode('update'
815 ).first()
816 # NOTE(vish): if with_lockmode isn't supported, as in sqlite,
817 # then this has concurrency issues
818 if not network_ref:
819 raise db.NoMoreNetworks()
820 network_ref['project_id'] = project_id
821 session.add(network_ref)
822 return network_ref
823
824
825@require_admin_context
808def network_count(context):826def network_count(context):
809 session = get_session()827 session = get_session()
810 return session.query(models.Network828 return session.query(models.Network
@@ -844,31 +862,26 @@
844862
845863
846@require_admin_context864@require_admin_context
847def network_create(context, values):865def network_create_safe(context, values):
848 network_ref = models.Network()866 network_ref = models.Network()
849 for (key, value) in values.iteritems():867 for (key, value) in values.iteritems():
850 network_ref[key] = value868 network_ref[key] = value
851 network_ref.save()869 try:
852 return network_ref870 network_ref.save()
853871 return network_ref
854872 except IntegrityError:
855@require_admin_context873 return None
856def network_destroy(context, network_id):874
875
876@require_admin_context
877def network_disassociate(context, network_id):
878 network_update(context, network_id, {'project_id': None})
879
880
881@require_admin_context
882def network_disassociate_all(context):
857 session = get_session()883 session = get_session()
858 with session.begin():884 session.execute('update networks set project_id=NULL')
859 # TODO(vish): do we have to use sql here?
860 session.execute('update networks set deleted=1 where id=:id',
861 {'id': network_id})
862 session.execute('update fixed_ips set deleted=1 where network_id=:id',
863 {'id': network_id})
864 session.execute('update floating_ips set deleted=1 '
865 'where fixed_ip_id in '
866 '(select id from fixed_ips '
867 'where network_id=:id)',
868 {'id': network_id})
869 session.execute('update network_indexes set network_id=NULL '
870 'where network_id=:id',
871 {'id': network_id})
872885
873886
874@require_context887@require_context
@@ -918,48 +931,21 @@
918931
919 if not result:932 if not result:
920 raise exception.NotFound('No network for bridge %s' % bridge)933 raise exception.NotFound('No network for bridge %s' % bridge)
921
922 return result934 return result
923935
924936
925@require_admin_context937@require_admin_context
926def network_get_index(context, network_id):938def network_get_by_instance(_context, instance_id):
927 session = get_session()939 session = get_session()
928 with session.begin():940 rv = session.query(models.Network
929 network_index = session.query(models.NetworkIndex941 ).filter_by(deleted=False
930 ).filter_by(network_id=None942 ).join(models.Network.fixed_ips
931 ).filter_by(deleted=False943 ).filter_by(instance_id=instance_id
932 ).with_lockmode('update'944 ).filter_by(deleted=False
933 ).first()945 ).first()
934946 if not rv:
935 if not network_index:947 raise exception.NotFound('No network for instance %s' % instance_id)
936 raise db.NoMoreNetworks()948 return rv
937
938 network_index['network'] = network_get(context,
939 network_id,
940 session=session)
941 session.add(network_index)
942
943 return network_index['index']
944
945
946@require_admin_context
947def network_index_count(context):
948 session = get_session()
949 return session.query(models.NetworkIndex
950 ).filter_by(deleted=can_read_deleted(context)
951 ).count()
952
953
954@require_admin_context
955def network_index_create_safe(context, values):
956 network_index_ref = models.NetworkIndex()
957 for (key, value) in values.iteritems():
958 network_index_ref[key] = value
959 try:
960 network_index_ref.save()
961 except IntegrityError:
962 pass
963949
964950
965@require_admin_context951@require_admin_context
@@ -999,15 +985,22 @@
999@require_context985@require_context
1000def project_get_network(context, project_id):986def project_get_network(context, project_id):
1001 session = get_session()987 session = get_session()
1002 result= session.query(models.Network988 rv = session.query(models.Network
1003 ).filter_by(project_id=project_id989 ).filter_by(project_id=project_id
1004 ).filter_by(deleted=False990 ).filter_by(deleted=False
1005 ).first()991 ).first()
1006992 if not rv:
1007 if not result:993 try:
1008 raise exception.NotFound('No network for project: %s' % project_id)994 return network_associate(context, project_id)
1009995 except IntegrityError:
1010 return result996 # NOTE(vish): We hit this if there is a race and two
997 # processes are attempting to allocate the
998 # network at the same time
999 rv = session.query(models.Network
1000 ).filter_by(project_id=project_id
1001 ).filter_by(deleted=False
1002 ).first()
1003 return rv
10111004
10121005
1013###################1006###################
10141007
=== modified file 'nova/db/sqlalchemy/models.py'
--- nova/db/sqlalchemy/models.py 2010-10-12 22:43:37 +0000
+++ nova/db/sqlalchemy/models.py 2010-10-13 07:50:58 +0000
@@ -25,7 +25,7 @@
2525
26# TODO(vish): clean up these imports26# TODO(vish): clean up these imports
27from sqlalchemy.orm import relationship, backref, exc, object_mapper27from sqlalchemy.orm import relationship, backref, exc, object_mapper
28from sqlalchemy import Column, Integer, String28from sqlalchemy import Column, Integer, String, schema
29from sqlalchemy import ForeignKey, DateTime, Boolean, Text29from sqlalchemy import ForeignKey, DateTime, Boolean, Text
30from sqlalchemy.exc import IntegrityError30from sqlalchemy.exc import IntegrityError
31from sqlalchemy.ext.declarative import declarative_base31from sqlalchemy.ext.declarative import declarative_base
@@ -363,10 +363,13 @@
363class Network(BASE, NovaBase):363class Network(BASE, NovaBase):
364 """Represents a network"""364 """Represents a network"""
365 __tablename__ = 'networks'365 __tablename__ = 'networks'
366 __table_args__ = (schema.UniqueConstraint("vpn_public_address",
367 "vpn_public_port"),
368 {'mysql_engine': 'InnoDB'})
366 id = Column(Integer, primary_key=True)369 id = Column(Integer, primary_key=True)
367370
368 injected = Column(Boolean, default=False)371 injected = Column(Boolean, default=False)
369 cidr = Column(String(255))372 cidr = Column(String(255), unique=True)
370 netmask = Column(String(255))373 netmask = Column(String(255))
371 bridge = Column(String(255))374 bridge = Column(String(255))
372 gateway = Column(String(255))375 gateway = Column(String(255))
@@ -379,28 +382,13 @@
379 vpn_private_address = Column(String(255))382 vpn_private_address = Column(String(255))
380 dhcp_start = Column(String(255))383 dhcp_start = Column(String(255))
381384
382 project_id = Column(String(255))385 # NOTE(vish): The unique constraint below helps avoid a race condition
386 # when associating a network, but it also means that we
387 # can't associate two networks with one project.
388 project_id = Column(String(255), unique=True)
383 host = Column(String(255)) # , ForeignKey('hosts.id'))389 host = Column(String(255)) # , ForeignKey('hosts.id'))
384390
385391
386class NetworkIndex(BASE, NovaBase):
387 """Represents a unique offset for a network
388
389 Currently vlan number, vpn port, and fixed ip ranges are keyed off of
390 this index. These may ultimately need to be converted to separate
391 pools.
392 """
393 __tablename__ = 'network_indexes'
394 id = Column(Integer, primary_key=True)
395 index = Column(Integer, unique=True)
396 network_id = Column(Integer, ForeignKey('networks.id'), nullable=True)
397 network = relationship(Network,
398 backref=backref('network_index', uselist=False),
399 foreign_keys=network_id,
400 primaryjoin='and_(NetworkIndex.network_id==Network.id,'
401 'NetworkIndex.deleted==False)')
402
403
404class AuthToken(BASE, NovaBase):392class AuthToken(BASE, NovaBase):
405 """Represents an authorization token for all API transactions. Fields393 """Represents an authorization token for all API transactions. Fields
406 are a string representing the actual token and a user id for mapping394 are a string representing the actual token and a user id for mapping
@@ -413,7 +401,6 @@
413 cdn_management_url = Column(String(255))401 cdn_management_url = Column(String(255))
414402
415403
416
417# TODO(vish): can these both come from the same baseclass?404# TODO(vish): can these both come from the same baseclass?
418class FixedIp(BASE, NovaBase):405class FixedIp(BASE, NovaBase):
419 """Represents a fixed ip for an instance"""406 """Represents a fixed ip for an instance"""
@@ -517,7 +504,7 @@
517 """Register Models and create metadata"""504 """Register Models and create metadata"""
518 from sqlalchemy import create_engine505 from sqlalchemy import create_engine
519 models = (Service, Instance, Volume, ExportDevice, FixedIp,506 models = (Service, Instance, Volume, ExportDevice, FixedIp,
520 FloatingIp, Network, NetworkIndex, SecurityGroup,507 FloatingIp, Network, SecurityGroup,
521 SecurityGroupIngressRule, SecurityGroupInstanceAssociation,508 SecurityGroupIngressRule, SecurityGroupInstanceAssociation,
522 AuthToken, User, Project) # , Image, Host509 AuthToken, User, Project) # , Image, Host
523 engine = create_engine(FLAGS.sql_connection, echo=False)510 engine = create_engine(FLAGS.sql_connection, echo=False)
524511
=== modified file 'nova/network/linux_net.py'
--- nova/network/linux_net.py 2010-10-02 10:39:47 +0000
+++ nova/network/linux_net.py 2010-10-13 07:50:58 +0000
@@ -65,12 +65,12 @@
65 # SNAT rule for outbound traffic.65 # SNAT rule for outbound traffic.
66 _confirm_rule("POSTROUTING", "-t nat -s %s "66 _confirm_rule("POSTROUTING", "-t nat -s %s "
67 "-j SNAT --to-source %s"67 "-j SNAT --to-source %s"
68 % (FLAGS.private_range, FLAGS.routing_source_ip))68 % (FLAGS.fixed_range, FLAGS.routing_source_ip))
6969
70 _confirm_rule("POSTROUTING", "-t nat -s %s -j MASQUERADE" %70 _confirm_rule("POSTROUTING", "-t nat -s %s -j MASQUERADE" %
71 FLAGS.private_range)71 FLAGS.fixed_range)
72 _confirm_rule("POSTROUTING", "-t nat -s %(range)s -d %(range)s -j ACCEPT" %72 _confirm_rule("POSTROUTING", "-t nat -s %(range)s -d %(range)s -j ACCEPT" %
73 {'range': FLAGS.private_range})73 {'range': FLAGS.fixed_range})
7474
75def bind_floating_ip(floating_ip):75def bind_floating_ip(floating_ip):
76 """Bind ip to public interface"""76 """Bind ip to public interface"""
7777
=== modified file 'nova/network/manager.py'
--- nova/network/manager.py 2010-10-04 10:53:55 +0000
+++ nova/network/manager.py 2010-10-13 07:50:58 +0000
@@ -37,17 +37,6 @@
37FLAGS = flags.FLAGS37FLAGS = flags.FLAGS
38flags.DEFINE_string('flat_network_bridge', 'br100',38flags.DEFINE_string('flat_network_bridge', 'br100',
39 'Bridge for simple network instances')39 'Bridge for simple network instances')
40flags.DEFINE_list('flat_network_ips',
41 ['192.168.0.2', '192.168.0.3', '192.168.0.4'],
42 'Available ips for simple network')
43flags.DEFINE_string('flat_network_network', '192.168.0.0',
44 'Network for simple network')
45flags.DEFINE_string('flat_network_netmask', '255.255.255.0',
46 'Netmask for simple network')
47flags.DEFINE_string('flat_network_gateway', '192.168.0.1',
48 'Broadcast for simple network')
49flags.DEFINE_string('flat_network_broadcast', '192.168.0.255',
50 'Broadcast for simple network')
51flags.DEFINE_string('flat_network_dns', '8.8.4.4',40flags.DEFINE_string('flat_network_dns', '8.8.4.4',
52 'Dns for simple network')41 'Dns for simple network')
53flags.DEFINE_integer('vlan_start', 100, 'First VLAN for private networks')42flags.DEFINE_integer('vlan_start', 100, 'First VLAN for private networks')
@@ -57,8 +46,8 @@
57flags.DEFINE_integer('vpn_start', 1000, 'First Vpn port for private networks')46flags.DEFINE_integer('vpn_start', 1000, 'First Vpn port for private networks')
58flags.DEFINE_integer('network_size', 256,47flags.DEFINE_integer('network_size', 256,
59 'Number of addresses in each private subnet')48 'Number of addresses in each private subnet')
60flags.DEFINE_string('public_range', '4.4.4.0/24', 'Public IP address block')49flags.DEFINE_string('floating_range', '4.4.4.0/24', 'Floating IP address block')
61flags.DEFINE_string('private_range', '10.0.0.0/8', 'Private IP address block')50flags.DEFINE_string('fixed_range', '10.0.0.0/8', 'Fixed IP address block')
62flags.DEFINE_integer('cnt_vpn_clients', 5,51flags.DEFINE_integer('cnt_vpn_clients', 5,
63 'Number of addresses reserved for vpn clients')52 'Number of addresses reserved for vpn clients')
64flags.DEFINE_string('network_driver', 'nova.network.linux_net',53flags.DEFINE_string('network_driver', 'nova.network.linux_net',
@@ -91,13 +80,9 @@
91 for network in self.db.host_get_networks(None, self.host):80 for network in self.db.host_get_networks(None, self.host):
92 self._on_set_network_host(None, network['id'])81 self._on_set_network_host(None, network['id'])
9382
94 def set_network_host(self, context, project_id):83 def set_network_host(self, context, network_id):
95 """Safely sets the host of the projects network"""84 """Safely sets the host of the network"""
96 logging.debug("setting network host")85 logging.debug("setting network host")
97 network_ref = self.db.project_get_network(context, project_id)
98 # TODO(vish): can we minimize db access by just getting the
99 # id here instead of the ref?
100 network_id = network_ref['id']
101 host = self.db.network_set_host(None,86 host = self.db.network_set_host(None,
102 network_id,87 network_id,
103 self.host)88 self.host)
@@ -117,10 +102,10 @@
117 raise NotImplementedError()102 raise NotImplementedError()
118103
119 def _on_set_network_host(self, context, network_id):104 def _on_set_network_host(self, context, network_id):
120 """Called when this host becomes the host for a project"""105 """Called when this host becomes the host for a network"""
121 raise NotImplementedError()106 raise NotImplementedError()
122107
123 def setup_compute_network(self, context, project_id):108 def setup_compute_network(self, context, instance_id):
124 """Sets up matching network for compute hosts"""109 """Sets up matching network for compute hosts"""
125 raise NotImplementedError()110 raise NotImplementedError()
126111
@@ -150,6 +135,16 @@
150 """Returns an floating ip to the pool"""135 """Returns an floating ip to the pool"""
151 self.db.floating_ip_deallocate(context, floating_address)136 self.db.floating_ip_deallocate(context, floating_address)
152137
138 def get_network(self, context):
139 """Get the network for the current context"""
140 raise NotImplementedError()
141
142 def create_networks(self, context, num_networks, network_size,
143 *args, **kwargs):
144 """Create networks based on parameters"""
145 raise NotImplementedError()
146
147
153 @property148 @property
154 def _bottom_reserved_ips(self): # pylint: disable-msg=R0201149 def _bottom_reserved_ips(self): # pylint: disable-msg=R0201
155 """Number of reserved ips at the bottom of the range"""150 """Number of reserved ips at the bottom of the range"""
@@ -163,7 +158,7 @@
163 def _create_fixed_ips(self, context, network_id):158 def _create_fixed_ips(self, context, network_id):
164 """Create all fixed ips for network"""159 """Create all fixed ips for network"""
165 network_ref = self.db.network_get(context, network_id)160 network_ref = self.db.network_get(context, network_id)
166 # NOTE(vish): should these be properties of the network as opposed161 # NOTE(vish): Should these be properties of the network as opposed
167 # to properties of the manager class?162 # to properties of the manager class?
168 bottom_reserved = self._bottom_reserved_ips163 bottom_reserved = self._bottom_reserved_ips
169 top_reserved = self._top_reserved_ips164 top_reserved = self._top_reserved_ips
@@ -185,8 +180,13 @@
185180
186 def allocate_fixed_ip(self, context, instance_id, *args, **kwargs):181 def allocate_fixed_ip(self, context, instance_id, *args, **kwargs):
187 """Gets a fixed ip from the pool"""182 """Gets a fixed ip from the pool"""
188 network_ref = self.db.project_get_network(context, context.project.id)183 # TODO(vish): when this is called by compute, we can associate compute
189 address = self.db.fixed_ip_associate_pool(context,184 # with a network, or a cluster of computes with a network
185 # and use that network here with a method like
186 # network_get_by_compute_host
187 network_ref = self.db.network_get_by_bridge(None,
188 FLAGS.flat_network_bridge)
189 address = self.db.fixed_ip_associate_pool(None,
190 network_ref['id'],190 network_ref['id'],
191 instance_id)191 instance_id)
192 self.db.fixed_ip_update(context, address, {'allocated': True})192 self.db.fixed_ip_update(context, address, {'allocated': True})
@@ -195,9 +195,9 @@
195 def deallocate_fixed_ip(self, context, address, *args, **kwargs):195 def deallocate_fixed_ip(self, context, address, *args, **kwargs):
196 """Returns a fixed ip to the pool"""196 """Returns a fixed ip to the pool"""
197 self.db.fixed_ip_update(context, address, {'allocated': False})197 self.db.fixed_ip_update(context, address, {'allocated': False})
198 self.db.fixed_ip_disassociate(context, address)198 self.db.fixed_ip_disassociate(None, address)
199199
200 def setup_compute_network(self, context, project_id):200 def setup_compute_network(self, context, instance_id):
201 """Network is created manually"""201 """Network is created manually"""
202 pass202 pass
203203
@@ -205,24 +205,42 @@
205 """Currently no setup"""205 """Currently no setup"""
206 pass206 pass
207207
208 def create_networks(self, context, cidr, num_networks, network_size,
209 *args, **kwargs):
210 """Create networks based on parameters"""
211 fixed_net = IPy.IP(cidr)
212 for index in range(num_networks):
213 start = index * network_size
214 significant_bits = 32 - int(math.log(network_size, 2))
215 cidr = "%s/%s" % (fixed_net[start], significant_bits)
216 project_net = IPy.IP(cidr)
217 net = {}
218 net['cidr'] = cidr
219 net['netmask'] = str(project_net.netmask())
220 net['gateway'] = str(project_net[1])
221 net['broadcast'] = str(project_net.broadcast())
222 net['dhcp_start'] = str(project_net[2])
223 network_ref = self.db.network_create_safe(context, net)
224 if network_ref:
225 self._create_fixed_ips(context, network_ref['id'])
226
227 def get_network(self, context):
228 """Get the network for the current context"""
229 # NOTE(vish): To support mutilple network hosts, This could randomly
230 # select from multiple networks instead of just
231 # returning the one. It could also potentially be done
232 # in the scheduler.
233 return self.db.network_get_by_bridge(context,
234 FLAGS.flat_network_bridge)
235
208 def _on_set_network_host(self, context, network_id):236 def _on_set_network_host(self, context, network_id):
209 """Called when this host becomes the host for a project"""237 """Called when this host becomes the host for a network"""
210 # NOTE(vish): should there be two types of network objects
211 # in the datastore?
212 net = {}238 net = {}
213 net['injected'] = True239 net['injected'] = True
214 net['netmask'] = FLAGS.flat_network_netmask
215 net['bridge'] = FLAGS.flat_network_bridge240 net['bridge'] = FLAGS.flat_network_bridge
216 net['gateway'] = FLAGS.flat_network_gateway
217 net['broadcast'] = FLAGS.flat_network_broadcast
218 net['dns'] = FLAGS.flat_network_dns241 net['dns'] = FLAGS.flat_network_dns
219 self.db.network_update(context, network_id, net)242 self.db.network_update(context, network_id, net)
220 # NOTE(vish): Rignt now we are putting all of the fixed ips in243
221 # one large pool, but ultimately it may be better to
222 # have each network manager have its own network that
223 # it is responsible for and its own pool of ips.
224 for address in FLAGS.flat_network_ips:
225 self.db.fixed_ip_create(context, {'address': address})
226244
227245
228class VlanManager(NetworkManager):246class VlanManager(NetworkManager):
@@ -250,10 +268,13 @@
250268
251 def allocate_fixed_ip(self, context, instance_id, *args, **kwargs):269 def allocate_fixed_ip(self, context, instance_id, *args, **kwargs):
252 """Gets a fixed ip from the pool"""270 """Gets a fixed ip from the pool"""
271 # TODO(vish): This should probably be getting project_id from
272 # the instance, but it is another trip to the db.
273 # Perhaps this method should take an instance_ref.
253 network_ref = self.db.project_get_network(context, context.project.id)274 network_ref = self.db.project_get_network(context, context.project.id)
254 if kwargs.get('vpn', None):275 if kwargs.get('vpn', None):
255 address = network_ref['vpn_private_address']276 address = network_ref['vpn_private_address']
256 self.db.fixed_ip_associate(context, address, instance_id)277 self.db.fixed_ip_associate(None, address, instance_id)
257 else:278 else:
258 address = self.db.fixed_ip_associate_pool(None,279 address = self.db.fixed_ip_associate_pool(None,
259 network_ref['id'],280 network_ref['id'],
@@ -319,38 +340,9 @@
319 network_ref = self.db.fixed_ip_get_network(context, address)340 network_ref = self.db.fixed_ip_get_network(context, address)
320 self.driver.update_dhcp(context, network_ref['id'])341 self.driver.update_dhcp(context, network_ref['id'])
321342
322 def allocate_network(self, context, project_id):343 def setup_compute_network(self, context, instance_id):
323 """Set up the network"""
324 self._ensure_indexes(context)
325 network_ref = db.network_create(context, {'project_id': project_id})
326 network_id = network_ref['id']
327 private_net = IPy.IP(FLAGS.private_range)
328 index = db.network_get_index(context, network_id)
329 vlan = FLAGS.vlan_start + index
330 start = index * FLAGS.network_size
331 significant_bits = 32 - int(math.log(FLAGS.network_size, 2))
332 cidr = "%s/%s" % (private_net[start], significant_bits)
333 project_net = IPy.IP(cidr)
334
335 net = {}
336 net['cidr'] = cidr
337 # NOTE(vish): we could turn these into properties
338 net['netmask'] = str(project_net.netmask())
339 net['gateway'] = str(project_net[1])
340 net['broadcast'] = str(project_net.broadcast())
341 net['vpn_private_address'] = str(project_net[2])
342 net['dhcp_start'] = str(project_net[3])
343 net['vlan'] = vlan
344 net['bridge'] = 'br%s' % vlan
345 net['vpn_public_address'] = FLAGS.vpn_ip
346 net['vpn_public_port'] = FLAGS.vpn_start + index
347 db.network_update(context, network_id, net)
348 self._create_fixed_ips(context, network_id)
349 return network_id
350
351 def setup_compute_network(self, context, project_id):
352 """Sets up matching network for compute hosts"""344 """Sets up matching network for compute hosts"""
353 network_ref = self.db.project_get_network(context, project_id)345 network_ref = db.network_get_by_instance(context, instance_id)
354 self.driver.ensure_vlan_bridge(network_ref['vlan'],346 self.driver.ensure_vlan_bridge(network_ref['vlan'],
355 network_ref['bridge'])347 network_ref['bridge'])
356348
@@ -359,17 +351,42 @@
359 # TODO(vish): Implement this351 # TODO(vish): Implement this
360 pass352 pass
361353
362 def _ensure_indexes(self, context):354 def create_networks(self, context, cidr, num_networks, network_size,
363 """Ensure the indexes for the network exist355 vlan_start, vpn_start):
356 """Create networks based on parameters"""
357 fixed_net = IPy.IP(cidr)
358 for index in range(num_networks):
359 vlan = vlan_start + index
360 start = index * network_size
361 significant_bits = 32 - int(math.log(network_size, 2))
362 cidr = "%s/%s" % (fixed_net[start], significant_bits)
363 project_net = IPy.IP(cidr)
364 net = {}
365 net['cidr'] = cidr
366 net['netmask'] = str(project_net.netmask())
367 net['gateway'] = str(project_net[1])
368 net['broadcast'] = str(project_net.broadcast())
369 net['vpn_private_address'] = str(project_net[2])
370 net['dhcp_start'] = str(project_net[3])
371 net['vlan'] = vlan
372 net['bridge'] = 'br%s' % vlan
373 # NOTE(vish): This makes ports unique accross the cloud, a more
374 # robust solution would be to make them unique per ip
375 net['vpn_public_port'] = vpn_start + index
376 network_ref = self.db.network_create_safe(context, net)
377 if network_ref:
378 self._create_fixed_ips(context, network_ref['id'])
364379
365 This could use a manage command instead of keying off of a flag"""380 def get_network(self, context):
366 if not self.db.network_index_count(context):381 """Get the network for the current context"""
367 for index in range(FLAGS.num_networks):382 return self.db.project_get_network(None, context.project.id)
368 self.db.network_index_create_safe(context, {'index': index})
369383
370 def _on_set_network_host(self, context, network_id):384 def _on_set_network_host(self, context, network_id):
371 """Called when this host becomes the host for a project"""385 """Called when this host becomes the host for a network"""
372 network_ref = self.db.network_get(context, network_id)386 network_ref = self.db.network_get(context, network_id)
387 net = {}
388 net['vpn_public_address'] = FLAGS.vpn_ip
389 db.network_update(context, network_id, net)
373 self.driver.ensure_vlan_bridge(network_ref['vlan'],390 self.driver.ensure_vlan_bridge(network_ref['vlan'],
374 network_ref['bridge'],391 network_ref['bridge'],
375 network_ref)392 network_ref)
376393
=== modified file 'nova/test.py'
--- nova/test.py 2010-09-29 11:39:09 +0000
+++ nova/test.py 2010-10-13 07:50:58 +0000
@@ -24,6 +24,7 @@
2424
25import sys25import sys
26import time26import time
27import datetime
2728
28import mox29import mox
29import stubout30import stubout
@@ -35,6 +36,7 @@
35from nova import fakerabbit36from nova import fakerabbit
36from nova import flags37from nova import flags
37from nova import rpc38from nova import rpc
39from nova.network import manager as network_manager
3840
3941
40FLAGS = flags.FLAGS42FLAGS = flags.FLAGS
@@ -58,6 +60,16 @@
58 def setUp(self): # pylint: disable-msg=C010360 def setUp(self): # pylint: disable-msg=C0103
59 """Run before each test method to initialize test environment"""61 """Run before each test method to initialize test environment"""
60 super(TrialTestCase, self).setUp()62 super(TrialTestCase, self).setUp()
63 # NOTE(vish): We need a better method for creating fixtures for tests
64 # now that we have some required db setup for the system
65 # to work properly.
66 self.start = datetime.datetime.utcnow()
67 if db.network_count(None) != 5:
68 network_manager.VlanManager().create_networks(None,
69 FLAGS.fixed_range,
70 5, 16,
71 FLAGS.vlan_start,
72 FLAGS.vpn_start)
6173
62 # emulate some of the mox stuff, we can't use the metaclass74 # emulate some of the mox stuff, we can't use the metaclass
63 # because it screws with our generators75 # because it screws with our generators
@@ -74,7 +86,9 @@
74 self.stubs.UnsetAll()86 self.stubs.UnsetAll()
75 self.stubs.SmartUnsetAll()87 self.stubs.SmartUnsetAll()
76 self.mox.VerifyAll()88 self.mox.VerifyAll()
77 89 # NOTE(vish): Clean up any ips associated during the test.
90 db.fixed_ip_disassociate_all_by_timeout(None, FLAGS.host, self.start)
91 db.network_disassociate_all(None)
78 rpc.Consumer.attach_to_twisted = self.originalAttach92 rpc.Consumer.attach_to_twisted = self.originalAttach
79 for x in self.injected:93 for x in self.injected:
80 try:94 try:
@@ -140,7 +154,7 @@
140class BaseTestCase(TrialTestCase):154class BaseTestCase(TrialTestCase):
141 # TODO(jaypipes): Can this be moved into the TrialTestCase class?155 # TODO(jaypipes): Can this be moved into the TrialTestCase class?
142 """Base test case class for all unit tests.156 """Base test case class for all unit tests.
143 157
144 DEPRECATED: This is being removed once Tornado is gone, use TrialTestCase.158 DEPRECATED: This is being removed once Tornado is gone, use TrialTestCase.
145 """159 """
146 def setUp(self): # pylint: disable-msg=C0103160 def setUp(self): # pylint: disable-msg=C0103
147161
=== modified file 'nova/tests/cloud_unittest.py'
--- nova/tests/cloud_unittest.py 2010-10-11 11:39:33 +0000
+++ nova/tests/cloud_unittest.py 2010-10-13 07:50:58 +0000
@@ -64,12 +64,12 @@
64 self.cloud = cloud.CloudController()64 self.cloud = cloud.CloudController()
6565
66 # set up a service66 # set up a service
67 self.compute = utils.import_class(FLAGS.compute_manager)()67 self.compute = utils.import_object(FLAGS.compute_manager)
68 self.compute_consumer = rpc.AdapterConsumer(connection=self.conn,68 self.compute_consumer = rpc.AdapterConsumer(connection=self.conn,
69 topic=FLAGS.compute_topic,69 topic=FLAGS.compute_topic,
70 proxy=self.compute)70 proxy=self.compute)
71 self.compute_consumer.attach_to_eventlet()71 self.compute_consumer.attach_to_eventlet()
72 self.network = utils.import_class(FLAGS.network_manager)()72 self.network = utils.import_object(FLAGS.network_manager)
73 self.network_consumer = rpc.AdapterConsumer(connection=self.conn,73 self.network_consumer = rpc.AdapterConsumer(connection=self.conn,
74 topic=FLAGS.network_topic,74 topic=FLAGS.network_topic,
75 proxy=self.network)75 proxy=self.network)
7676
=== modified file 'nova/tests/compute_unittest.py'
--- nova/tests/compute_unittest.py 2010-09-30 09:47:05 +0000
+++ nova/tests/compute_unittest.py 2010-10-13 07:50:58 +0000
@@ -40,7 +40,8 @@
40 def setUp(self): # pylint: disable-msg=C010340 def setUp(self): # pylint: disable-msg=C0103
41 logging.getLogger().setLevel(logging.DEBUG)41 logging.getLogger().setLevel(logging.DEBUG)
42 super(ComputeTestCase, self).setUp()42 super(ComputeTestCase, self).setUp()
43 self.flags(connection_type='fake')43 self.flags(connection_type='fake',
44 network_manager='nova.network.manager.FlatManager')
44 self.compute = utils.import_object(FLAGS.compute_manager)45 self.compute = utils.import_object(FLAGS.compute_manager)
45 self.manager = manager.AuthManager()46 self.manager = manager.AuthManager()
46 self.user = self.manager.create_user('fake', 'fake', 'fake')47 self.user = self.manager.create_user('fake', 'fake', 'fake')
4748
=== modified file 'nova/tests/network_unittest.py'
--- nova/tests/network_unittest.py 2010-10-03 18:22:35 +0000
+++ nova/tests/network_unittest.py 2010-10-13 07:50:58 +0000
@@ -52,13 +52,14 @@
52 self.context = context.APIRequestContext(project=None, user=self.user)52 self.context = context.APIRequestContext(project=None, user=self.user)
53 for i in range(5):53 for i in range(5):
54 name = 'project%s' % i54 name = 'project%s' % i
55 self.projects.append(self.manager.create_project(name,55 project = self.manager.create_project(name, 'netuser', name)
56 'netuser',56 self.projects.append(project)
57 name))
58 # create the necessary network data for the project57 # create the necessary network data for the project
59 user_context = context.get_admin_context(user=self.user)58 user_context = context.APIRequestContext(project=self.projects[i],
6059 user=self.user)
61 self.network.set_network_host(user_context, self.projects[i].id)60 network_ref = self.network.get_network(user_context)
61 self.network.set_network_host(context.get_admin_context(),
62 network_ref['id'])
62 instance_ref = self._create_instance(0)63 instance_ref = self._create_instance(0)
63 self.instance_id = instance_ref['id']64 self.instance_id = instance_ref['id']
64 instance_ref = self._create_instance(1)65 instance_ref = self._create_instance(1)
@@ -99,7 +100,7 @@
99 """Makes sure that we can allocaate a public ip"""100 """Makes sure that we can allocaate a public ip"""
100 # TODO(vish): better way of adding floating ips101 # TODO(vish): better way of adding floating ips
101 self.context.project = self.projects[0]102 self.context.project = self.projects[0]
102 pubnet = IPy.IP(flags.FLAGS.public_range)103 pubnet = IPy.IP(flags.FLAGS.floating_range)
103 address = str(pubnet[0])104 address = str(pubnet[0])
104 try:105 try:
105 db.floating_ip_get_by_address(None, address)106 db.floating_ip_get_by_address(None, address)
@@ -109,6 +110,7 @@
109 float_addr = self.network.allocate_floating_ip(self.context,110 float_addr = self.network.allocate_floating_ip(self.context,
110 self.projects[0].id)111 self.projects[0].id)
111 fix_addr = self._create_address(0)112 fix_addr = self._create_address(0)
113 lease_ip(fix_addr)
112 self.assertEqual(float_addr, str(pubnet[0]))114 self.assertEqual(float_addr, str(pubnet[0]))
113 self.network.associate_floating_ip(self.context, float_addr, fix_addr)115 self.network.associate_floating_ip(self.context, float_addr, fix_addr)
114 address = db.instance_get_floating_address(None, self.instance_id)116 address = db.instance_get_floating_address(None, self.instance_id)
@@ -118,6 +120,7 @@
118 self.assertEqual(address, None)120 self.assertEqual(address, None)
119 self.network.deallocate_floating_ip(self.context, float_addr)121 self.network.deallocate_floating_ip(self.context, float_addr)
120 self.network.deallocate_fixed_ip(self.context, fix_addr)122 self.network.deallocate_fixed_ip(self.context, fix_addr)
123 release_ip(fix_addr)
121124
122 def test_allocate_deallocate_fixed_ip(self):125 def test_allocate_deallocate_fixed_ip(self):
123 """Makes sure that we can allocate and deallocate a fixed ip"""126 """Makes sure that we can allocate and deallocate a fixed ip"""
@@ -190,8 +193,10 @@
190 release_ip(address3)193 release_ip(address3)
191 for instance_id in instance_ids:194 for instance_id in instance_ids:
192 db.instance_destroy(None, instance_id)195 db.instance_destroy(None, instance_id)
196 self.context.project = self.projects[0]
197 self.network.deallocate_fixed_ip(self.context, first)
198 self._deallocate_address(0, first)
193 release_ip(first)199 release_ip(first)
194 self._deallocate_address(0, first)
195200
196 def test_vpn_ip_and_port_looks_valid(self):201 def test_vpn_ip_and_port_looks_valid(self):
197 """Ensure the vpn ip and port are reasonable"""202 """Ensure the vpn ip and port are reasonable"""
@@ -207,10 +212,13 @@
207 for i in range(networks_left):212 for i in range(networks_left):
208 project = self.manager.create_project('many%s' % i, self.user)213 project = self.manager.create_project('many%s' % i, self.user)
209 projects.append(project)214 projects.append(project)
215 db.project_get_network(None, project.id)
216 project = self.manager.create_project('last', self.user)
217 projects.append(project)
210 self.assertRaises(db.NoMoreNetworks,218 self.assertRaises(db.NoMoreNetworks,
211 self.manager.create_project,219 db.project_get_network,
212 'boom',220 None,
213 self.user)221 project.id)
214 for project in projects:222 for project in projects:
215 self.manager.delete_project(project)223 self.manager.delete_project(project)
216224
@@ -223,7 +231,9 @@
223231
224 address2 = self._create_address(0)232 address2 = self._create_address(0)
225 self.assertEqual(address, address2)233 self.assertEqual(address, address2)
234 lease_ip(address)
226 self.network.deallocate_fixed_ip(self.context, address2)235 self.network.deallocate_fixed_ip(self.context, address2)
236 release_ip(address)
227237
228 def test_available_ips(self):238 def test_available_ips(self):
229 """Make sure the number of available ips for the network is correct239 """Make sure the number of available ips for the network is correct
230240
=== modified file 'nova/tests/scheduler_unittest.py'
--- nova/tests/scheduler_unittest.py 2010-10-04 09:53:27 +0000
+++ nova/tests/scheduler_unittest.py 2010-10-13 07:50:58 +0000
@@ -75,6 +75,7 @@
75 self.flags(connection_type='fake',75 self.flags(connection_type='fake',
76 max_cores=4,76 max_cores=4,
77 max_gigabytes=4,77 max_gigabytes=4,
78 network_manager='nova.network.manager.FlatManager',
78 volume_driver='nova.volume.driver.FakeAOEDriver',79 volume_driver='nova.volume.driver.FakeAOEDriver',
79 scheduler_driver='nova.scheduler.simple.SimpleScheduler')80 scheduler_driver='nova.scheduler.simple.SimpleScheduler')
80 self.scheduler = manager.SchedulerManager()81 self.scheduler = manager.SchedulerManager()
8182
=== modified file 'nova/tests/virt_unittest.py'
--- nova/tests/virt_unittest.py 2010-10-12 20:18:29 +0000
+++ nova/tests/virt_unittest.py 2010-10-13 07:50:58 +0000
@@ -20,21 +20,22 @@
20from nova import db20from nova import db
21from nova import flags21from nova import flags
22from nova import test22from nova import test
23from nova import utils
23from nova.api import context24from nova.api import context
24from nova.api.ec2 import cloud25from nova.api.ec2 import cloud
25from nova.auth import manager26from nova.auth import manager
26
27# Needed to get FLAGS.instances_path defined:
28from nova.compute import manager as compute_manager
29from nova.virt import libvirt_conn27from nova.virt import libvirt_conn
3028
31FLAGS = flags.FLAGS29FLAGS = flags.FLAGS
30flags.DECLARE('instances_path', 'nova.compute.manager')
3231
33class LibvirtConnTestCase(test.TrialTestCase):32class LibvirtConnTestCase(test.TrialTestCase):
34 def setUp(self):33 def setUp(self):
34 super(LibvirtConnTestCase, self).setUp()
35 self.manager = manager.AuthManager()35 self.manager = manager.AuthManager()
36 self.user = self.manager.create_user('fake', 'fake', 'fake', admin=True)36 self.user = self.manager.create_user('fake', 'fake', 'fake', admin=True)
37 self.project = self.manager.create_project('fake', 'fake', 'fake')37 self.project = self.manager.create_project('fake', 'fake', 'fake')
38 self.network = utils.import_object(FLAGS.network_manager)
38 FLAGS.instances_path = ''39 FLAGS.instances_path = ''
3940
40 def test_get_uri_and_template(self):41 def test_get_uri_and_template(self):
@@ -51,11 +52,15 @@
51 'instance_type' : 'm1.small'}52 'instance_type' : 'm1.small'}
5253
53 instance_ref = db.instance_create(None, instance)54 instance_ref = db.instance_create(None, instance)
54 network_ref = db.project_get_network(None, self.project.id)55 user_context = context.APIRequestContext(project=self.project,
56 user=self.user)
57 network_ref = self.network.get_network(user_context)
58 self.network.set_network_host(context.get_admin_context(),
59 network_ref['id'])
5560
56 fixed_ip = { 'address' : ip,61 fixed_ip = { 'address' : ip,
57 'network_id' : network_ref['id'] }62 'network_id' : network_ref['id'] }
58 63
59 fixed_ip_ref = db.fixed_ip_create(None, fixed_ip)64 fixed_ip_ref = db.fixed_ip_create(None, fixed_ip)
60 db.fixed_ip_update(None, ip, { 'allocated' : True,65 db.fixed_ip_update(None, ip, { 'allocated' : True,
61 'instance_id' : instance_ref['id'] })66 'instance_id' : instance_ref['id'] })
@@ -113,6 +118,7 @@
113118
114119
115 def tearDown(self):120 def tearDown(self):
121 super(LibvirtConnTestCase, self).tearDown()
116 self.manager.delete_project(self.project)122 self.manager.delete_project(self.project)
117 self.manager.delete_user(self.user)123 self.manager.delete_user(self.user)
118124
119125
=== modified file 'nova/virt/libvirt_conn.py'
--- nova/virt/libvirt_conn.py 2010-10-04 19:58:22 +0000
+++ nova/virt/libvirt_conn.py 2010-10-13 07:50:58 +0000
@@ -287,7 +287,7 @@
287287
288 key = str(inst['key_data'])288 key = str(inst['key_data'])
289 net = None289 net = None
290 network_ref = db.project_get_network(None, project.id)290 network_ref = db.network_get_by_instance(None, inst['id'])
291 if network_ref['injected']:291 if network_ref['injected']:
292 address = db.instance_get_fixed_address(None, inst['id'])292 address = db.instance_get_fixed_address(None, inst['id'])
293 with open(FLAGS.injected_network_template) as f:293 with open(FLAGS.injected_network_template) as f:
@@ -320,7 +320,8 @@
320 def to_xml(self, instance):320 def to_xml(self, instance):
321 # TODO(termie): cache?321 # TODO(termie): cache?
322 logging.debug('instance %s: starting toXML method', instance['name'])322 logging.debug('instance %s: starting toXML method', instance['name'])
323 network = db.project_get_network(None, instance['project_id'])323 network = db.project_get_network(None,
324 instance['project_id'])
324 # FIXME(vish): stick this in db325 # FIXME(vish): stick this in db
325 instance_type = instance_types.INSTANCE_TYPES[instance['instance_type']]326 instance_type = instance_types.INSTANCE_TYPES[instance['instance_type']]
326 ip_address = db.instance_get_fixed_address({}, instance['id'])327 ip_address = db.instance_get_fixed_address({}, instance['id'])