Merge lp:~ntt-pf-lab/nova/flatmanager-ipv6 into lp:~hudson-openstack/nova/trunk

Proposed by Tushar Patil
Status: Merged
Approved by: Rick Clark
Approved revision: 760
Merged at revision: 850
Proposed branch: lp:~ntt-pf-lab/nova/flatmanager-ipv6
Merge into: lp:~hudson-openstack/nova/trunk
Diff against target: 1445 lines (+836/-411)
13 files modified
nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py (+154/-0)
nova/db/sqlalchemy/models.py (+2/-5)
nova/network/linux_net.py (+1/-1)
nova/network/manager.py (+8/-2)
nova/tests/network/__init__.py (+67/-0)
nova/tests/network/base.py (+154/-0)
nova/tests/test_flat_network.py (+161/-0)
nova/tests/test_network.py (+0/-371)
nova/tests/test_vlan_network.py (+242/-0)
nova/virt/interfaces.template (+11/-5)
nova/virt/libvirt.xml.template (+2/-2)
nova/virt/libvirt_conn.py (+30/-22)
nova/virt/xenapi/vmops.py (+4/-3)
To merge this branch: bzr merge lp:~ntt-pf-lab/nova/flatmanager-ipv6
Reviewer Review Type Date Requested Status
Rick Clark (community) Approve
Josh Kearney (community) Approve
Soren Hansen Pending
Review via email: mp+53064@code.launchpad.net

Commit message

Enable flat manager support for ipv6.

Description of the change

Enable flat manager support for ipv6.
Also made changes to xs-ipv6 blueprint portion of code which is impacted because of the addition of the flat manager support for ipv6.

To post a comment you must log in.
Revision history for this message
Tushar Patil (tpatil) wrote :

After submitting my branch for merging, I see there are 2 conflicts.
Before I submitted my branch for merge proposal, I have merged my branch with trunk (lp:nova) and I saw following output of merge.
$root@ubuntu-development-server:/home/tpatil/openstack/ntt/nova# bzr merge
Merging from remembered parent location bzr+ssh://bazaar.launchpad.net/~ntt-pf-lab/nova/flatmanager-ipv6/
Nothing to do.

Conflicts:
1) conflict in nova/tests/test_network.py
I have deleted this file in my branch and added 2 files
test_flat_network.py
test_vlan_network.py
2) nova/virt/libvirt_conn.py

Did I made any mistake?

Revision history for this message
Tushar Patil (tpatil) wrote :

I checked the ./bzr/branch/branch.conf and noticed that the parent location has changed from bzr+ssh://bazaar.launchpad.net/%2Bbranch/nova/ to bzr+ssh://bazaar.launchpad.net/~ntt-pf-lab/nova/flatmanager-ipv6/.

I will fix this soon and resubmit it once again.

Revision history for this message
Josh Kearney (jk0) wrote :

It looks like you have a few merge conflicts starting at line #1065. Also I'm not sure that a DB migration version can be replaced like that -- you will want to make a new version (011) and stick the modifications in there.

review: Needs Fixing
Revision history for this message
Josh Kearney (jk0) wrote :

I set this back to Work In Progress while you make the changes.

Revision history for this message
Koji Iida (iida-koji) wrote :

We found some problems under use_ipv6=false.
Fix will come soon.

Revision history for this message
Josh Kearney (jk0) wrote :

Good to go for another review/test?

Revision history for this message
Koji Iida (iida-koji) wrote :

Hi,

We fixed detected problems.

Please review the code.

Koji Iida

Revision history for this message
Josh Kearney (jk0) wrote :

Migrations work as expected. All tests pass.

One suggestion about the copyright headers of the new files -- you may want to have them in your name (NTT) unless you were instructed to use OpenStack LLC?

lp:~ntt-pf-lab/nova/flatmanager-ipv6 updated
759. By Tushar Patil

Changed Copyright to NTT for newly added files for flatmanager ipv6

Revision history for this message
Tushar Patil (tpatil) wrote :

Josh : Thank you very much for pointing this out, We missed it completely. I have modified the copyright headers to NTT whereever it was applicable. Reqeust you to please mark the status as Approve if you don't have any more review comments. Thanks.

Revision history for this message
Josh Kearney (jk0) wrote :

Thanks for the updates. I believe this is good to go.

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

Tests fail. I verified that trunk tests fine in my environment.

I haven't had time to dig into it.

2011-03-22 22:35:32,283 DEBUG migrate.versioning.repository [-] Config: {'db_settings': {'__name__': 'db_settings', 'required_dbs': '[]', 'version_table': 'migrate_version', 'repository_id': 'nova'}} from (pid=7568) __init__ /home/rclark/dev/flatmanager-ipv6/.nova-venv/lib/python2.6/site-packages/migrate/versioning/repository.py:83
2011-03-22 22:35:32,287 INFO migrate.versioning.api [-] 0 -> 1...
2011-03-22 22:35:33,902 INFO migrate.versioning.api [-] done
2011-03-22 22:35:33,902 INFO migrate.versioning.api [-] 1 -> 2...
2011-03-22 22:35:34,935 INFO migrate.versioning.api [-] done
2011-03-22 22:35:34,935 INFO migrate.versioning.api [-] 2 -> 3...
2011-03-22 22:35:35,070 INFO migrate.versioning.api [-] done
2011-03-22 22:35:35,070 INFO migrate.versioning.api [-] 3 -> 4...
2011-03-22 22:35:35,202 INFO migrate.versioning.api [-] done
2011-03-22 22:35:35,202 INFO migrate.versioning.api [-] 4 -> 5...
2011-03-22 22:35:35,437 INFO migrate.versioning.api [-] done
2011-03-22 22:35:35,438 INFO migrate.versioning.api [-] 5 -> 6...
2011-03-22 22:35:35,652 INFO migrate.versioning.api [-] done
2011-03-22 22:35:35,652 INFO migrate.versioning.api [-] 6 -> 7...
2011-03-22 22:35:35,920 INFO migrate.versioning.api [-] done
2011-03-22 22:35:35,921 INFO migrate.versioning.api [-] 7 -> 8...
2011-03-22 22:35:36,437 INFO migrate.versioning.api [-] done
2011-03-22 22:35:36,437 INFO migrate.versioning.api [-] 8 -> 9...
2011-03-22 22:35:36,620 INFO migrate.versioning.api [-] done
2011-03-22 22:35:36,621 INFO migrate.versioning.api [-] 9 -> 10...
2011-03-22 22:35:36,762 INFO migrate.versioning.api [-] done
2011-03-22 22:35:36,762 INFO migrate.versioning.api [-] 10 -> 11...
2011-03-22 22:35:36,977 INFO migrate.versioning.api [-] done
2011-03-22 22:35:36,977 INFO migrate.versioning.api [-] 11 -> 12...
2011-03-22 22:35:37,404 DEBUG migrate.versioning.util [-] Disposing SQLAlchemy engine Engine(sqlite:////home/rclark/dev/flatmanager-ipv6/nova/..//tests.sqlite) from (pid=7568) with_engine /home/rclark/dev/flatmanager-ipv6/.nova-venv/lib/python2.6/site-packages/migrate/versioning/util/__init__.py:162
--------------------- >> end captured logging << ---------------------

----------------------------------------------------------------------
Ran 0 tests in 5.453s

FAILED (errors=1)

review: Needs Fixing
lp:~ntt-pf-lab/nova/flatmanager-ipv6 updated
760. By Koji Iida

Fix to avoid db migration failure in virtualenv

Revision history for this message
Koji Iida (iida-koji) wrote :

Hi, Rick,

Thank you for your finding a bug. I fixed that problem.

Please review again.

Koji Iida

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

tests pass. lgtm

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py'
2--- nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py 1970-01-01 00:00:00 +0000
3+++ nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py 2011-03-23 04:18:31 +0000
4@@ -0,0 +1,154 @@
5+# Copyright (c) 2011 NTT.
6+# All Rights Reserved.
7+#
8+# Licensed under the Apache License, Version 2.0 (the "License"); you may
9+# not use this file except in compliance with the License. You may obtain
10+# a copy of the License at
11+#
12+# http://www.apache.org/licenses/LICENSE-2.0
13+#
14+# Unless required by applicable law or agreed to in writing, software
15+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17+# License for the specific language governing permissions and limitations
18+# under the License.
19+
20+from sqlalchemy import *
21+from migrate import *
22+
23+from nova import log as logging
24+
25+
26+meta = MetaData()
27+
28+
29+# Table stub-definitions
30+# Just for the ForeignKey and column creation to succeed, these are not the
31+# actual definitions of instances or services.
32+#
33+instances = Table('instances', meta,
34+ Column('id', Integer(), primary_key=True, nullable=False),
35+ )
36+
37+#
38+# Tables to alter
39+#
40+networks = Table('networks', meta,
41+ Column('created_at', DateTime(timezone=False)),
42+ Column('updated_at', DateTime(timezone=False)),
43+ Column('deleted_at', DateTime(timezone=False)),
44+ Column('deleted', Boolean(create_constraint=True, name=None)),
45+ Column('id', Integer(), primary_key=True, nullable=False),
46+ Column('injected', Boolean(create_constraint=True, name=None)),
47+ Column('cidr',
48+ String(length=255, convert_unicode=False, assert_unicode=None,
49+ unicode_error=None, _warn_on_bytestring=False)),
50+ Column('netmask',
51+ String(length=255, convert_unicode=False, assert_unicode=None,
52+ unicode_error=None, _warn_on_bytestring=False)),
53+ Column('bridge',
54+ String(length=255, convert_unicode=False, assert_unicode=None,
55+ unicode_error=None, _warn_on_bytestring=False)),
56+ Column('gateway',
57+ String(length=255, convert_unicode=False, assert_unicode=None,
58+ unicode_error=None, _warn_on_bytestring=False)),
59+ Column('broadcast',
60+ String(length=255, convert_unicode=False, assert_unicode=None,
61+ unicode_error=None, _warn_on_bytestring=False)),
62+ Column('dns',
63+ String(length=255, convert_unicode=False, assert_unicode=None,
64+ unicode_error=None, _warn_on_bytestring=False)),
65+ Column('vlan', Integer()),
66+ Column('vpn_public_address',
67+ String(length=255, convert_unicode=False, assert_unicode=None,
68+ unicode_error=None, _warn_on_bytestring=False)),
69+ Column('vpn_public_port', Integer()),
70+ Column('vpn_private_address',
71+ String(length=255, convert_unicode=False, assert_unicode=None,
72+ unicode_error=None, _warn_on_bytestring=False)),
73+ Column('dhcp_start',
74+ String(length=255, convert_unicode=False, assert_unicode=None,
75+ unicode_error=None, _warn_on_bytestring=False)),
76+ Column('project_id',
77+ String(length=255, convert_unicode=False, assert_unicode=None,
78+ unicode_error=None, _warn_on_bytestring=False)),
79+ Column('host',
80+ String(length=255, convert_unicode=False, assert_unicode=None,
81+ unicode_error=None, _warn_on_bytestring=False)),
82+ Column('cidr_v6',
83+ String(length=255, convert_unicode=False, assert_unicode=None,
84+ unicode_error=None, _warn_on_bytestring=False)),
85+ Column('ra_server', String(length=255,
86+ convert_unicode=False,
87+ assert_unicode=None,
88+ unicode_error=None,
89+ _warn_on_bytestring=False)),
90+ Column(
91+ 'label',
92+ String(length=255, convert_unicode=False, assert_unicode=None,
93+ unicode_error=None, _warn_on_bytestring=False)))
94+
95+fixed_ips = Table('fixed_ips', meta,
96+ Column('created_at', DateTime(timezone=False)),
97+ Column('updated_at', DateTime(timezone=False)),
98+ Column('deleted_at', DateTime(timezone=False)),
99+ Column('deleted', Boolean(create_constraint=True, name=None)),
100+ Column('id', Integer(), primary_key=True, nullable=False),
101+ Column('address',
102+ String(length=255, convert_unicode=False, assert_unicode=None,
103+ unicode_error=None, _warn_on_bytestring=False)),
104+ Column('network_id',
105+ Integer(),
106+ ForeignKey('networks.id'),
107+ nullable=True),
108+ Column('instance_id',
109+ Integer(),
110+ ForeignKey('instances.id'),
111+ nullable=True),
112+ Column('allocated', Boolean(create_constraint=True, name=None)),
113+ Column('leased', Boolean(create_constraint=True, name=None)),
114+ Column('reserved', Boolean(create_constraint=True, name=None)),
115+ Column("addressV6", String(length=255,
116+ convert_unicode=False,
117+ assert_unicode=None,
118+ unicode_error=None,
119+ _warn_on_bytestring=False)),
120+ Column("netmaskV6", String(length=3,
121+ convert_unicode=False,
122+ assert_unicode=None,
123+ unicode_error=None,
124+ _warn_on_bytestring=False)),
125+ Column("gatewayV6", String(length=255,
126+ convert_unicode=False,
127+ assert_unicode=None,
128+ unicode_error=None,
129+ _warn_on_bytestring=False)),
130+ )
131+#
132+# New Tables
133+#
134+# None
135+
136+#
137+# Columns to add to existing tables
138+#
139+networks_netmask_v6 = Column(
140+ 'netmask_v6',
141+ String(length=255, convert_unicode=False, assert_unicode=None,
142+ unicode_error=None, _warn_on_bytestring=False))
143+
144+
145+def upgrade(migrate_engine):
146+ # Upgrade operations go here. Don't create your own engine;
147+ # bind migrate_engine to your metadata
148+ meta.bind = migrate_engine
149+
150+ # Alter column name
151+ networks.c.ra_server.alter(name='gateway_v6')
152+ # Add new column to existing table
153+ networks.create_column(networks_netmask_v6)
154+
155+ # drop existing columns from table
156+ fixed_ips.c.addressV6.drop()
157+ fixed_ips.c.netmaskV6.drop()
158+ fixed_ips.c.gatewayV6.drop()
159
160=== modified file 'nova/db/sqlalchemy/models.py'
161--- nova/db/sqlalchemy/models.py 2011-03-15 21:56:00 +0000
162+++ nova/db/sqlalchemy/models.py 2011-03-23 04:18:31 +0000
163@@ -454,8 +454,8 @@
164 cidr = Column(String(255), unique=True)
165 cidr_v6 = Column(String(255), unique=True)
166
167- ra_server = Column(String(255))
168-
169+ gateway_v6 = Column(String(255))
170+ netmask_v6 = Column(String(255))
171 netmask = Column(String(255))
172 bridge = Column(String(255))
173 gateway = Column(String(255))
174@@ -508,9 +508,6 @@
175 allocated = Column(Boolean, default=False)
176 leased = Column(Boolean, default=False)
177 reserved = Column(Boolean, default=False)
178- addressV6 = Column(String(255))
179- netmaskV6 = Column(String(3))
180- gatewayV6 = Column(String(255))
181
182
183 class User(BASE, NovaBase):
184
185=== modified file 'nova/network/linux_net.py'
186--- nova/network/linux_net.py 2011-03-21 08:49:32 +0000
187+++ nova/network/linux_net.py 2011-03-23 04:18:31 +0000
188@@ -634,7 +634,7 @@
189 command = _ra_cmd(network_ref)
190 _execute(*command)
191 db.network_update(context, network_id,
192- {"ra_server":
193+ {"gateway_v6":
194 utils.get_my_linklocal(network_ref['bridge'])})
195
196
197
198=== modified file 'nova/network/manager.py'
199--- nova/network/manager.py 2011-03-21 17:51:27 +0000
200+++ nova/network/manager.py 2011-03-23 04:18:31 +0000
201@@ -167,7 +167,7 @@
202 # with a network, or a cluster of computes with a network
203 # and use that network here with a method like
204 # network_get_by_compute_host
205- network_ref = self.db.network_get_by_bridge(context,
206+ network_ref = self.db.network_get_by_bridge(context.elevated(),
207 FLAGS.flat_network_bridge)
208 address = self.db.fixed_ip_associate_pool(context.elevated(),
209 network_ref['id'],
210@@ -292,9 +292,11 @@
211 fixed_net = IPy.IP(cidr)
212 fixed_net_v6 = IPy.IP(cidr_v6)
213 significant_bits_v6 = 64
214+ network_size_v6 = 1 << 64
215 count = 1
216 for index in range(num_networks):
217 start = index * network_size
218+ start_v6 = index * network_size_v6
219 significant_bits = 32 - int(math.log(network_size, 2))
220 cidr = "%s/%s" % (fixed_net[start], significant_bits)
221 project_net = IPy.IP(cidr)
222@@ -313,8 +315,12 @@
223 count += 1
224
225 if(FLAGS.use_ipv6):
226- cidr_v6 = "%s/%s" % (fixed_net_v6[0], significant_bits_v6)
227+ cidr_v6 = "%s/%s" % (fixed_net_v6[start_v6],
228+ significant_bits_v6)
229 net['cidr_v6'] = cidr_v6
230+ project_net_v6 = IPy.IP(cidr_v6)
231+ net['gateway_v6'] = str(project_net_v6[1])
232+ net['netmask_v6'] = str(project_net_v6.prefixlen())
233
234 network_ref = self.db.network_create_safe(context, net)
235
236
237=== added directory 'nova/tests/network'
238=== added file 'nova/tests/network/__init__.py'
239--- nova/tests/network/__init__.py 1970-01-01 00:00:00 +0000
240+++ nova/tests/network/__init__.py 2011-03-23 04:18:31 +0000
241@@ -0,0 +1,67 @@
242+# vim: tabstop=4 shiftwidth=4 softtabstop=4
243+
244+# Copyright 2010 United States Government as represented by the
245+# Administrator of the National Aeronautics and Space Administration.
246+# All Rights Reserved.
247+#
248+# Licensed under the Apache License, Version 2.0 (the "License"); you may
249+# not use this file except in compliance with the License. You may obtain
250+# a copy of the License at
251+#
252+# http://www.apache.org/licenses/LICENSE-2.0
253+#
254+# Unless required by applicable law or agreed to in writing, software
255+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
256+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
257+# License for the specific language governing permissions and limitations
258+# under the License.
259+"""
260+Utility methods
261+"""
262+import os
263+
264+from nova import context
265+from nova import db
266+from nova import flags
267+from nova import log as logging
268+from nova import utils
269+
270+FLAGS = flags.FLAGS
271+LOG = logging.getLogger('nova.tests.network')
272+
273+
274+def binpath(script):
275+ """Returns the absolute path to a script in bin"""
276+ return os.path.abspath(os.path.join(__file__, "../../../../bin", script))
277+
278+
279+def lease_ip(private_ip):
280+ """Run add command on dhcpbridge"""
281+ network_ref = db.fixed_ip_get_network(context.get_admin_context(),
282+ private_ip)
283+ instance_ref = db.fixed_ip_get_instance(context.get_admin_context(),
284+ private_ip)
285+ cmd = (binpath('nova-dhcpbridge'), 'add',
286+ instance_ref['mac_address'],
287+ private_ip, 'fake')
288+ env = {'DNSMASQ_INTERFACE': network_ref['bridge'],
289+ 'TESTING': '1',
290+ 'FLAGFILE': FLAGS.dhcpbridge_flagfile}
291+ (out, err) = utils.execute(*cmd, addl_env=env)
292+ LOG.debug("ISSUE_IP: %s, %s ", out, err)
293+
294+
295+def release_ip(private_ip):
296+ """Run del command on dhcpbridge"""
297+ network_ref = db.fixed_ip_get_network(context.get_admin_context(),
298+ private_ip)
299+ instance_ref = db.fixed_ip_get_instance(context.get_admin_context(),
300+ private_ip)
301+ cmd = (binpath('nova-dhcpbridge'), 'del',
302+ instance_ref['mac_address'],
303+ private_ip, 'fake')
304+ env = {'DNSMASQ_INTERFACE': network_ref['bridge'],
305+ 'TESTING': '1',
306+ 'FLAGFILE': FLAGS.dhcpbridge_flagfile}
307+ (out, err) = utils.execute(*cmd, addl_env=env)
308+ LOG.debug("RELEASE_IP: %s, %s ", out, err)
309
310=== added file 'nova/tests/network/base.py'
311--- nova/tests/network/base.py 1970-01-01 00:00:00 +0000
312+++ nova/tests/network/base.py 2011-03-23 04:18:31 +0000
313@@ -0,0 +1,154 @@
314+# vim: tabstop=4 shiftwidth=4 softtabstop=4
315+
316+# Copyright 2010 United States Government as represented by the
317+# Administrator of the National Aeronautics and Space Administration.
318+# All Rights Reserved.
319+#
320+# Licensed under the Apache License, Version 2.0 (the "License"); you may
321+# not use this file except in compliance with the License. You may obtain
322+# a copy of the License at
323+#
324+# http://www.apache.org/licenses/LICENSE-2.0
325+#
326+# Unless required by applicable law or agreed to in writing, software
327+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
328+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
329+# License for the specific language governing permissions and limitations
330+# under the License.
331+"""
332+Base class of Unit Tests for all network models
333+"""
334+import IPy
335+import os
336+
337+from nova import context
338+from nova import db
339+from nova import exception
340+from nova import flags
341+from nova import log as logging
342+from nova import test
343+from nova import utils
344+from nova.auth import manager
345+
346+FLAGS = flags.FLAGS
347+LOG = logging.getLogger('nova.tests.network')
348+
349+
350+class NetworkTestCase(test.TestCase):
351+ """Test cases for network code"""
352+ def setUp(self):
353+ super(NetworkTestCase, self).setUp()
354+ # NOTE(vish): if you change these flags, make sure to change the
355+ # flags in the corresponding section in nova-dhcpbridge
356+ self.flags(connection_type='fake',
357+ fake_call=True,
358+ fake_network=True)
359+ self.manager = manager.AuthManager()
360+ self.user = self.manager.create_user('netuser', 'netuser', 'netuser')
361+ self.projects = []
362+ self.network = utils.import_object(FLAGS.network_manager)
363+ self.context = context.RequestContext(project=None, user=self.user)
364+ for i in range(FLAGS.num_networks):
365+ name = 'project%s' % i
366+ project = self.manager.create_project(name, 'netuser', name)
367+ self.projects.append(project)
368+ # create the necessary network data for the project
369+ user_context = context.RequestContext(project=self.projects[i],
370+ user=self.user)
371+ host = self.network.get_network_host(user_context.elevated())
372+ instance_ref = self._create_instance(0)
373+ self.instance_id = instance_ref['id']
374+ instance_ref = self._create_instance(1)
375+ self.instance2_id = instance_ref['id']
376+
377+ def tearDown(self):
378+ # TODO(termie): this should really be instantiating clean datastores
379+ # in between runs, one failure kills all the tests
380+ db.instance_destroy(context.get_admin_context(), self.instance_id)
381+ db.instance_destroy(context.get_admin_context(), self.instance2_id)
382+ for project in self.projects:
383+ self.manager.delete_project(project)
384+ self.manager.delete_user(self.user)
385+ super(NetworkTestCase, self).tearDown()
386+
387+ def _create_instance(self, project_num, mac=None):
388+ if not mac:
389+ mac = utils.generate_mac()
390+ project = self.projects[project_num]
391+ self.context._project = project
392+ self.context.project_id = project.id
393+ return db.instance_create(self.context,
394+ {'project_id': project.id,
395+ 'mac_address': mac})
396+
397+ def _create_address(self, project_num, instance_id=None):
398+ """Create an address in given project num"""
399+ if instance_id is None:
400+ instance_id = self.instance_id
401+ self.context._project = self.projects[project_num]
402+ self.context.project_id = self.projects[project_num].id
403+ return self.network.allocate_fixed_ip(self.context, instance_id)
404+
405+ def _deallocate_address(self, project_num, address):
406+ self.context._project = self.projects[project_num]
407+ self.context.project_id = self.projects[project_num].id
408+ self.network.deallocate_fixed_ip(self.context, address)
409+
410+ def _is_allocated_in_project(self, address, project_id):
411+ """Returns true if address is in specified project"""
412+ project_net = db.network_get_by_bridge(context.get_admin_context(),
413+ FLAGS.flat_network_bridge)
414+ network = db.fixed_ip_get_network(context.get_admin_context(),
415+ address)
416+ instance = db.fixed_ip_get_instance(context.get_admin_context(),
417+ address)
418+ # instance exists until release
419+ return instance is not None and network['id'] == project_net['id']
420+
421+ def test_private_ipv6(self):
422+ """Make sure ipv6 is OK"""
423+ if FLAGS.use_ipv6:
424+ instance_ref = self._create_instance(0)
425+ address = self._create_address(0, instance_ref['id'])
426+ network_ref = db.project_get_network(
427+ context.get_admin_context(),
428+ self.context.project_id)
429+ address_v6 = db.instance_get_fixed_address_v6(
430+ context.get_admin_context(),
431+ instance_ref['id'])
432+ self.assertEqual(instance_ref['mac_address'],
433+ utils.to_mac(address_v6))
434+ instance_ref2 = db.fixed_ip_get_instance_v6(
435+ context.get_admin_context(),
436+ address_v6)
437+ self.assertEqual(instance_ref['id'], instance_ref2['id'])
438+ self.assertEqual(address_v6,
439+ utils.to_global_ipv6(
440+ network_ref['cidr_v6'],
441+ instance_ref['mac_address']))
442+ self._deallocate_address(0, address)
443+ db.instance_destroy(context.get_admin_context(),
444+ instance_ref['id'])
445+
446+ def test_available_ips(self):
447+ """Make sure the number of available ips for the network is correct
448+
449+ The number of available IP addresses depends on the test
450+ environment's setup.
451+
452+ Network size is set in test fixture's setUp method.
453+
454+ There are ips reserved at the bottom and top of the range.
455+ services (network, gateway, CloudPipe, broadcast)
456+ """
457+ network = db.project_get_network(context.get_admin_context(),
458+ self.projects[0].id)
459+ net_size = flags.FLAGS.network_size
460+ admin_context = context.get_admin_context()
461+ total_ips = (db.network_count_available_ips(admin_context,
462+ network['id']) +
463+ db.network_count_reserved_ips(admin_context,
464+ network['id']) +
465+ db.network_count_allocated_ips(admin_context,
466+ network['id']))
467+ self.assertEqual(total_ips, net_size)
468
469=== added file 'nova/tests/test_flat_network.py'
470--- nova/tests/test_flat_network.py 1970-01-01 00:00:00 +0000
471+++ nova/tests/test_flat_network.py 2011-03-23 04:18:31 +0000
472@@ -0,0 +1,161 @@
473+# vim: tabstop=4 shiftwidth=4 softtabstop=4
474+
475+# Copyright 2010 United States Government as represented by the
476+# Administrator of the National Aeronautics and Space Administration.
477+# All Rights Reserved.
478+#
479+# Licensed under the Apache License, Version 2.0 (the "License"); you may
480+# not use this file except in compliance with the License. You may obtain
481+# a copy of the License at
482+#
483+# http://www.apache.org/licenses/LICENSE-2.0
484+#
485+# Unless required by applicable law or agreed to in writing, software
486+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
487+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
488+# License for the specific language governing permissions and limitations
489+# under the License.
490+"""
491+Unit Tests for flat network code
492+"""
493+import IPy
494+import os
495+import unittest
496+
497+from nova import context
498+from nova import db
499+from nova import exception
500+from nova import flags
501+from nova import log as logging
502+from nova import test
503+from nova import utils
504+from nova.auth import manager
505+from nova.tests.network import base
506+
507+
508+FLAGS = flags.FLAGS
509+LOG = logging.getLogger('nova.tests.network')
510+
511+
512+class FlatNetworkTestCase(base.NetworkTestCase):
513+ """Test cases for network code"""
514+ def test_public_network_association(self):
515+ """Makes sure that we can allocate a public ip"""
516+ # TODO(vish): better way of adding floating ips
517+
518+ self.context._project = self.projects[0]
519+ self.context.project_id = self.projects[0].id
520+ pubnet = IPy.IP(flags.FLAGS.floating_range)
521+ address = str(pubnet[0])
522+ try:
523+ db.floating_ip_get_by_address(context.get_admin_context(), address)
524+ except exception.NotFound:
525+ db.floating_ip_create(context.get_admin_context(),
526+ {'address': address,
527+ 'host': FLAGS.host})
528+
529+ self.assertRaises(NotImplementedError,
530+ self.network.allocate_floating_ip,
531+ self.context, self.projects[0].id)
532+
533+ fix_addr = self._create_address(0)
534+ float_addr = address
535+ self.assertRaises(NotImplementedError,
536+ self.network.associate_floating_ip,
537+ self.context, float_addr, fix_addr)
538+
539+ address = db.instance_get_floating_address(context.get_admin_context(),
540+ self.instance_id)
541+ self.assertEqual(address, None)
542+
543+ self.assertRaises(NotImplementedError,
544+ self.network.disassociate_floating_ip,
545+ self.context, float_addr)
546+
547+ address = db.instance_get_floating_address(context.get_admin_context(),
548+ self.instance_id)
549+ self.assertEqual(address, None)
550+
551+ self.assertRaises(NotImplementedError,
552+ self.network.deallocate_floating_ip,
553+ self.context, float_addr)
554+
555+ self.network.deallocate_fixed_ip(self.context, fix_addr)
556+ db.floating_ip_destroy(context.get_admin_context(), float_addr)
557+
558+ def test_allocate_deallocate_fixed_ip(self):
559+ """Makes sure that we can allocate and deallocate a fixed ip"""
560+ address = self._create_address(0)
561+ self.assertTrue(self._is_allocated_in_project(address,
562+ self.projects[0].id))
563+ self._deallocate_address(0, address)
564+
565+ # check if the fixed ip address is really deallocated
566+ self.assertFalse(self._is_allocated_in_project(address,
567+ self.projects[0].id))
568+
569+ def test_side_effects(self):
570+ """Ensures allocating and releasing has no side effects"""
571+ address = self._create_address(0)
572+ address2 = self._create_address(1, self.instance2_id)
573+
574+ self.assertTrue(self._is_allocated_in_project(address,
575+ self.projects[0].id))
576+ self.assertTrue(self._is_allocated_in_project(address2,
577+ self.projects[1].id))
578+
579+ self._deallocate_address(0, address)
580+ self.assertFalse(self._is_allocated_in_project(address,
581+ self.projects[0].id))
582+
583+ # First address release shouldn't affect the second
584+ self.assertTrue(self._is_allocated_in_project(address2,
585+ self.projects[0].id))
586+
587+ self._deallocate_address(1, address2)
588+ self.assertFalse(self._is_allocated_in_project(address2,
589+ self.projects[1].id))
590+
591+ def test_ips_are_reused(self):
592+ """Makes sure that ip addresses that are deallocated get reused"""
593+ address = self._create_address(0)
594+ self.network.deallocate_fixed_ip(self.context, address)
595+
596+ address2 = self._create_address(0)
597+ self.assertEqual(address, address2)
598+
599+ self.network.deallocate_fixed_ip(self.context, address2)
600+
601+ def test_too_many_addresses(self):
602+ """Test for a NoMoreAddresses exception when all fixed ips are used.
603+ """
604+ admin_context = context.get_admin_context()
605+ network = db.project_get_network(admin_context, self.projects[0].id)
606+ num_available_ips = db.network_count_available_ips(admin_context,
607+ network['id'])
608+ addresses = []
609+ instance_ids = []
610+ for i in range(num_available_ips):
611+ instance_ref = self._create_instance(0)
612+ instance_ids.append(instance_ref['id'])
613+ address = self._create_address(0, instance_ref['id'])
614+ addresses.append(address)
615+
616+ ip_count = db.network_count_available_ips(context.get_admin_context(),
617+ network['id'])
618+ self.assertEqual(ip_count, 0)
619+ self.assertRaises(db.NoMoreAddresses,
620+ self.network.allocate_fixed_ip,
621+ self.context,
622+ 'foo')
623+
624+ for i in range(num_available_ips):
625+ self.network.deallocate_fixed_ip(self.context, addresses[i])
626+ db.instance_destroy(context.get_admin_context(), instance_ids[i])
627+ ip_count = db.network_count_available_ips(context.get_admin_context(),
628+ network['id'])
629+ self.assertEqual(ip_count, num_available_ips)
630+
631+ def run(self, result=None):
632+ if(FLAGS.network_manager == 'nova.network.manager.FlatManager'):
633+ super(FlatNetworkTestCase, self).run(result)
634
635=== modified file 'nova/tests/test_network.py'
636--- nova/tests/test_network.py 2011-03-14 13:21:44 +0000
637+++ nova/tests/test_network.py 2011-03-23 04:18:31 +0000
638@@ -20,21 +20,10 @@
639 """
640 import IPy
641 import os
642-import time
643
644-from nova import context
645-from nova import db
646-from nova import exception
647-from nova import flags
648-from nova import log as logging
649 from nova import test
650-from nova import utils
651-from nova.auth import manager
652 from nova.network import linux_net
653
654-FLAGS = flags.FLAGS
655-LOG = logging.getLogger('nova.tests.network')
656-
657
658 class IptablesManagerTestCase(test.TestCase):
659 sample_filter = ['#Generated by iptables-save on Fri Feb 18 15:17:05 2011',
660@@ -175,363 +164,3 @@
661 self.assertTrue('-A %s -j run_tests.py-%s' \
662 % (chain, chain) in new_lines,
663 "Built-in chain %s not wrapped" % (chain,))
664-
665-
666-class NetworkTestCase(test.TestCase):
667- """Test cases for network code"""
668- def setUp(self):
669- super(NetworkTestCase, self).setUp()
670- # NOTE(vish): if you change these flags, make sure to change the
671- # flags in the corresponding section in nova-dhcpbridge
672- self.flags(connection_type='fake',
673- fake_call=True,
674- fake_network=True)
675- self.manager = manager.AuthManager()
676- self.user = self.manager.create_user('netuser', 'netuser', 'netuser')
677- self.projects = []
678- self.network = utils.import_object(FLAGS.network_manager)
679- self.context = context.RequestContext(project=None, user=self.user)
680- for i in range(FLAGS.num_networks):
681- name = 'project%s' % i
682- project = self.manager.create_project(name, 'netuser', name)
683- self.projects.append(project)
684- # create the necessary network data for the project
685- user_context = context.RequestContext(project=self.projects[i],
686- user=self.user)
687- host = self.network.get_network_host(user_context.elevated())
688- instance_ref = self._create_instance(0)
689- self.instance_id = instance_ref['id']
690- instance_ref = self._create_instance(1)
691- self.instance2_id = instance_ref['id']
692-
693- def tearDown(self):
694- # TODO(termie): this should really be instantiating clean datastores
695- # in between runs, one failure kills all the tests
696- db.instance_destroy(context.get_admin_context(), self.instance_id)
697- db.instance_destroy(context.get_admin_context(), self.instance2_id)
698- for project in self.projects:
699- self.manager.delete_project(project)
700- self.manager.delete_user(self.user)
701- super(NetworkTestCase, self).tearDown()
702-
703- def _create_instance(self, project_num, mac=None):
704- if not mac:
705- mac = utils.generate_mac()
706- project = self.projects[project_num]
707- self.context._project = project
708- self.context.project_id = project.id
709- return db.instance_create(self.context,
710- {'project_id': project.id,
711- 'mac_address': mac})
712-
713- def _create_address(self, project_num, instance_id=None):
714- """Create an address in given project num"""
715- if instance_id is None:
716- instance_id = self.instance_id
717- self.context._project = self.projects[project_num]
718- self.context.project_id = self.projects[project_num].id
719- return self.network.allocate_fixed_ip(self.context, instance_id)
720-
721- def _deallocate_address(self, project_num, address):
722- self.context._project = self.projects[project_num]
723- self.context.project_id = self.projects[project_num].id
724- self.network.deallocate_fixed_ip(self.context, address)
725-
726- def test_private_ipv6(self):
727- """Make sure ipv6 is OK"""
728- if FLAGS.use_ipv6:
729- instance_ref = self._create_instance(0)
730- address = self._create_address(0, instance_ref['id'])
731- network_ref = db.project_get_network(
732- context.get_admin_context(),
733- self.context.project_id)
734- address_v6 = db.instance_get_fixed_address_v6(
735- context.get_admin_context(),
736- instance_ref['id'])
737- self.assertEqual(instance_ref['mac_address'],
738- utils.to_mac(address_v6))
739- instance_ref2 = db.fixed_ip_get_instance_v6(
740- context.get_admin_context(),
741- address_v6)
742- self.assertEqual(instance_ref['id'], instance_ref2['id'])
743- self.assertEqual(address_v6,
744- utils.to_global_ipv6(
745- network_ref['cidr_v6'],
746- instance_ref['mac_address']))
747- self._deallocate_address(0, address)
748- db.instance_destroy(context.get_admin_context(),
749- instance_ref['id'])
750-
751- def test_public_network_association(self):
752- """Makes sure that we can allocaate a public ip"""
753- # TODO(vish): better way of adding floating ips
754- self.context._project = self.projects[0]
755- self.context.project_id = self.projects[0].id
756- pubnet = IPy.IP(flags.FLAGS.floating_range)
757- address = str(pubnet[0])
758- try:
759- db.floating_ip_get_by_address(context.get_admin_context(), address)
760- except exception.NotFound:
761- db.floating_ip_create(context.get_admin_context(),
762- {'address': address,
763- 'host': FLAGS.host})
764- float_addr = self.network.allocate_floating_ip(self.context,
765- self.projects[0].id)
766- fix_addr = self._create_address(0)
767- lease_ip(fix_addr)
768- self.assertEqual(float_addr, str(pubnet[0]))
769- self.network.associate_floating_ip(self.context, float_addr, fix_addr)
770- address = db.instance_get_floating_address(context.get_admin_context(),
771- self.instance_id)
772- self.assertEqual(address, float_addr)
773- self.network.disassociate_floating_ip(self.context, float_addr)
774- address = db.instance_get_floating_address(context.get_admin_context(),
775- self.instance_id)
776- self.assertEqual(address, None)
777- self.network.deallocate_floating_ip(self.context, float_addr)
778- self.network.deallocate_fixed_ip(self.context, fix_addr)
779- release_ip(fix_addr)
780- db.floating_ip_destroy(context.get_admin_context(), float_addr)
781-
782- def test_allocate_deallocate_fixed_ip(self):
783- """Makes sure that we can allocate and deallocate a fixed ip"""
784- address = self._create_address(0)
785- self.assertTrue(is_allocated_in_project(address, self.projects[0].id))
786- lease_ip(address)
787- self._deallocate_address(0, address)
788-
789- # Doesn't go away until it's dhcp released
790- self.assertTrue(is_allocated_in_project(address, self.projects[0].id))
791-
792- release_ip(address)
793- self.assertFalse(is_allocated_in_project(address, self.projects[0].id))
794-
795- def test_side_effects(self):
796- """Ensures allocating and releasing has no side effects"""
797- address = self._create_address(0)
798- address2 = self._create_address(1, self.instance2_id)
799-
800- self.assertTrue(is_allocated_in_project(address, self.projects[0].id))
801- self.assertTrue(is_allocated_in_project(address2, self.projects[1].id))
802- self.assertFalse(is_allocated_in_project(address, self.projects[1].id))
803-
804- # Addresses are allocated before they're issued
805- lease_ip(address)
806- lease_ip(address2)
807-
808- self._deallocate_address(0, address)
809- release_ip(address)
810- self.assertFalse(is_allocated_in_project(address, self.projects[0].id))
811-
812- # First address release shouldn't affect the second
813- self.assertTrue(is_allocated_in_project(address2, self.projects[1].id))
814-
815- self._deallocate_address(1, address2)
816- release_ip(address2)
817- self.assertFalse(is_allocated_in_project(address2,
818- self.projects[1].id))
819-
820- def test_subnet_edge(self):
821- """Makes sure that private ips don't overlap"""
822- first = self._create_address(0)
823- lease_ip(first)
824- instance_ids = []
825- for i in range(1, FLAGS.num_networks):
826- instance_ref = self._create_instance(i, mac=utils.generate_mac())
827- instance_ids.append(instance_ref['id'])
828- address = self._create_address(i, instance_ref['id'])
829- instance_ref = self._create_instance(i, mac=utils.generate_mac())
830- instance_ids.append(instance_ref['id'])
831- address2 = self._create_address(i, instance_ref['id'])
832- instance_ref = self._create_instance(i, mac=utils.generate_mac())
833- instance_ids.append(instance_ref['id'])
834- address3 = self._create_address(i, instance_ref['id'])
835- lease_ip(address)
836- lease_ip(address2)
837- lease_ip(address3)
838- self.context._project = self.projects[i]
839- self.context.project_id = self.projects[i].id
840- self.assertFalse(is_allocated_in_project(address,
841- self.projects[0].id))
842- self.assertFalse(is_allocated_in_project(address2,
843- self.projects[0].id))
844- self.assertFalse(is_allocated_in_project(address3,
845- self.projects[0].id))
846- self.network.deallocate_fixed_ip(self.context, address)
847- self.network.deallocate_fixed_ip(self.context, address2)
848- self.network.deallocate_fixed_ip(self.context, address3)
849- release_ip(address)
850- release_ip(address2)
851- release_ip(address3)
852- for instance_id in instance_ids:
853- db.instance_destroy(context.get_admin_context(), instance_id)
854- self.context._project = self.projects[0]
855- self.context.project_id = self.projects[0].id
856- self.network.deallocate_fixed_ip(self.context, first)
857- self._deallocate_address(0, first)
858- release_ip(first)
859-
860- def test_vpn_ip_and_port_looks_valid(self):
861- """Ensure the vpn ip and port are reasonable"""
862- self.assert_(self.projects[0].vpn_ip)
863- self.assert_(self.projects[0].vpn_port >= FLAGS.vpn_start)
864- self.assert_(self.projects[0].vpn_port <= FLAGS.vpn_start +
865- FLAGS.num_networks)
866-
867- def test_too_many_networks(self):
868- """Ensure error is raised if we run out of networks"""
869- projects = []
870- networks_left = (FLAGS.num_networks -
871- db.network_count(context.get_admin_context()))
872- for i in range(networks_left):
873- project = self.manager.create_project('many%s' % i, self.user)
874- projects.append(project)
875- db.project_get_network(context.get_admin_context(), project.id)
876- project = self.manager.create_project('last', self.user)
877- projects.append(project)
878- self.assertRaises(db.NoMoreNetworks,
879- db.project_get_network,
880- context.get_admin_context(),
881- project.id)
882- for project in projects:
883- self.manager.delete_project(project)
884-
885- def test_ips_are_reused(self):
886- """Makes sure that ip addresses that are deallocated get reused"""
887- address = self._create_address(0)
888- lease_ip(address)
889- self.network.deallocate_fixed_ip(self.context, address)
890- release_ip(address)
891-
892- address2 = self._create_address(0)
893- self.assertEqual(address, address2)
894- lease_ip(address)
895- self.network.deallocate_fixed_ip(self.context, address2)
896- release_ip(address)
897-
898- def test_available_ips(self):
899- """Make sure the number of available ips for the network is correct
900-
901- The number of available IP addresses depends on the test
902- environment's setup.
903-
904- Network size is set in test fixture's setUp method.
905-
906- There are ips reserved at the bottom and top of the range.
907- services (network, gateway, CloudPipe, broadcast)
908- """
909- network = db.project_get_network(context.get_admin_context(),
910- self.projects[0].id)
911- net_size = flags.FLAGS.network_size
912- admin_context = context.get_admin_context()
913- total_ips = (db.network_count_available_ips(admin_context,
914- network['id']) +
915- db.network_count_reserved_ips(admin_context,
916- network['id']) +
917- db.network_count_allocated_ips(admin_context,
918- network['id']))
919- self.assertEqual(total_ips, net_size)
920-
921- def test_too_many_addresses(self):
922- """Test for a NoMoreAddresses exception when all fixed ips are used.
923- """
924- admin_context = context.get_admin_context()
925- network = db.project_get_network(admin_context, self.projects[0].id)
926- num_available_ips = db.network_count_available_ips(admin_context,
927- network['id'])
928- addresses = []
929- instance_ids = []
930- for i in range(num_available_ips):
931- instance_ref = self._create_instance(0)
932- instance_ids.append(instance_ref['id'])
933- address = self._create_address(0, instance_ref['id'])
934- addresses.append(address)
935- lease_ip(address)
936-
937- ip_count = db.network_count_available_ips(context.get_admin_context(),
938- network['id'])
939- self.assertEqual(ip_count, 0)
940- self.assertRaises(db.NoMoreAddresses,
941- self.network.allocate_fixed_ip,
942- self.context,
943- 'foo')
944-
945- for i in range(num_available_ips):
946- self.network.deallocate_fixed_ip(self.context, addresses[i])
947- release_ip(addresses[i])
948- db.instance_destroy(context.get_admin_context(), instance_ids[i])
949- ip_count = db.network_count_available_ips(context.get_admin_context(),
950- network['id'])
951- self.assertEqual(ip_count, num_available_ips)
952-
953- def test_dhcp_lease_output(self):
954- admin_ctxt = context.get_admin_context()
955- address = self._create_address(0, self.instance_id)
956- lease_ip(address)
957- network_ref = db.network_get_by_instance(admin_ctxt, self.instance_id)
958- leases = linux_net.get_dhcp_leases(context.get_admin_context(),
959- network_ref['id'])
960- for line in leases.split('\n'):
961- seconds, mac, ip, hostname, client_id = line.split(' ')
962- self.assertTrue(int(seconds) > time.time(), 'Lease expires in '
963- 'the past')
964- octets = mac.split(':')
965- self.assertEqual(len(octets), 6, "Wrong number of octets "
966- "in %s" % (max,))
967- for octet in octets:
968- self.assertEqual(len(octet), 2, "Oddly sized octet: %s"
969- % (octet,))
970- # This will throw an exception if the octet is invalid
971- int(octet, 16)
972-
973- # And this will raise an exception in case of an invalid IP
974- IPy.IP(ip)
975-
976- release_ip(address)
977-
978-
979-def is_allocated_in_project(address, project_id):
980- """Returns true if address is in specified project"""
981- project_net = db.project_get_network(context.get_admin_context(),
982- project_id)
983- network = db.fixed_ip_get_network(context.get_admin_context(), address)
984- instance = db.fixed_ip_get_instance(context.get_admin_context(), address)
985- # instance exists until release
986- return instance is not None and network['id'] == project_net['id']
987-
988-
989-def binpath(script):
990- """Returns the absolute path to a script in bin"""
991- return os.path.abspath(os.path.join(__file__, "../../../bin", script))
992-
993-
994-def lease_ip(private_ip):
995- """Run add command on dhcpbridge"""
996- network_ref = db.fixed_ip_get_network(context.get_admin_context(),
997- private_ip)
998- instance_ref = db.fixed_ip_get_instance(context.get_admin_context(),
999- private_ip)
1000- cmd = (binpath('nova-dhcpbridge'), 'add',
1001- instance_ref['mac_address'],
1002- private_ip, 'fake')
1003- env = {'DNSMASQ_INTERFACE': network_ref['bridge'],
1004- 'TESTING': '1',
1005- 'FLAGFILE': FLAGS.dhcpbridge_flagfile}
1006- (out, err) = utils.execute(*cmd, addl_env=env)
1007- LOG.debug("ISSUE_IP: %s, %s ", out, err)
1008-
1009-
1010-def release_ip(private_ip):
1011- """Run del command on dhcpbridge"""
1012- network_ref = db.fixed_ip_get_network(context.get_admin_context(),
1013- private_ip)
1014- instance_ref = db.fixed_ip_get_instance(context.get_admin_context(),
1015- private_ip)
1016- cmd = (binpath('nova-dhcpbridge'), 'del',
1017- instance_ref['mac_address'],
1018- private_ip, 'fake')
1019- env = {'DNSMASQ_INTERFACE': network_ref['bridge'],
1020- 'TESTING': '1',
1021- 'FLAGFILE': FLAGS.dhcpbridge_flagfile}
1022- (out, err) = utils.execute(*cmd, addl_env=env)
1023- LOG.debug("RELEASE_IP: %s, %s ", out, err)
1024
1025=== added file 'nova/tests/test_vlan_network.py'
1026--- nova/tests/test_vlan_network.py 1970-01-01 00:00:00 +0000
1027+++ nova/tests/test_vlan_network.py 2011-03-23 04:18:31 +0000
1028@@ -0,0 +1,242 @@
1029+# vim: tabstop=4 shiftwidth=4 softtabstop=4
1030+
1031+# Copyright 2010 United States Government as represented by the
1032+# Administrator of the National Aeronautics and Space Administration.
1033+# All Rights Reserved.
1034+#
1035+# Licensed under the Apache License, Version 2.0 (the "License"); you may
1036+# not use this file except in compliance with the License. You may obtain
1037+# a copy of the License at
1038+#
1039+# http://www.apache.org/licenses/LICENSE-2.0
1040+#
1041+# Unless required by applicable law or agreed to in writing, software
1042+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
1043+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1044+# License for the specific language governing permissions and limitations
1045+# under the License.
1046+"""
1047+Unit Tests for vlan network code
1048+"""
1049+import IPy
1050+import os
1051+
1052+from nova import context
1053+from nova import db
1054+from nova import exception
1055+from nova import flags
1056+from nova import log as logging
1057+from nova import test
1058+from nova import utils
1059+from nova.auth import manager
1060+from nova.tests.network import base
1061+from nova.tests.network import binpath,\
1062+ lease_ip, release_ip
1063+
1064+FLAGS = flags.FLAGS
1065+LOG = logging.getLogger('nova.tests.network')
1066+
1067+
1068+class VlanNetworkTestCase(base.NetworkTestCase):
1069+ """Test cases for network code"""
1070+ def test_public_network_association(self):
1071+ """Makes sure that we can allocaate a public ip"""
1072+ # TODO(vish): better way of adding floating ips
1073+ self.context._project = self.projects[0]
1074+ self.context.project_id = self.projects[0].id
1075+ pubnet = IPy.IP(flags.FLAGS.floating_range)
1076+ address = str(pubnet[0])
1077+ try:
1078+ db.floating_ip_get_by_address(context.get_admin_context(), address)
1079+ except exception.NotFound:
1080+ db.floating_ip_create(context.get_admin_context(),
1081+ {'address': address,
1082+ 'host': FLAGS.host})
1083+ float_addr = self.network.allocate_floating_ip(self.context,
1084+ self.projects[0].id)
1085+ fix_addr = self._create_address(0)
1086+ lease_ip(fix_addr)
1087+ self.assertEqual(float_addr, str(pubnet[0]))
1088+ self.network.associate_floating_ip(self.context, float_addr, fix_addr)
1089+ address = db.instance_get_floating_address(context.get_admin_context(),
1090+ self.instance_id)
1091+ self.assertEqual(address, float_addr)
1092+ self.network.disassociate_floating_ip(self.context, float_addr)
1093+ address = db.instance_get_floating_address(context.get_admin_context(),
1094+ self.instance_id)
1095+ self.assertEqual(address, None)
1096+ self.network.deallocate_floating_ip(self.context, float_addr)
1097+ self.network.deallocate_fixed_ip(self.context, fix_addr)
1098+ release_ip(fix_addr)
1099+ db.floating_ip_destroy(context.get_admin_context(), float_addr)
1100+
1101+ def test_allocate_deallocate_fixed_ip(self):
1102+ """Makes sure that we can allocate and deallocate a fixed ip"""
1103+ address = self._create_address(0)
1104+ self.assertTrue(self._is_allocated_in_project(address,
1105+ self.projects[0].id))
1106+ lease_ip(address)
1107+ self._deallocate_address(0, address)
1108+
1109+ # Doesn't go away until it's dhcp released
1110+ self.assertTrue(self._is_allocated_in_project(address,
1111+ self.projects[0].id))
1112+
1113+ release_ip(address)
1114+ self.assertFalse(self._is_allocated_in_project(address,
1115+ self.projects[0].id))
1116+
1117+ def test_side_effects(self):
1118+ """Ensures allocating and releasing has no side effects"""
1119+ address = self._create_address(0)
1120+ address2 = self._create_address(1, self.instance2_id)
1121+
1122+ self.assertTrue(self._is_allocated_in_project(address,
1123+ self.projects[0].id))
1124+ self.assertTrue(self._is_allocated_in_project(address2,
1125+ self.projects[1].id))
1126+ self.assertFalse(self._is_allocated_in_project(address,
1127+ self.projects[1].id))
1128+
1129+ # Addresses are allocated before they're issued
1130+ lease_ip(address)
1131+ lease_ip(address2)
1132+
1133+ self._deallocate_address(0, address)
1134+ release_ip(address)
1135+ self.assertFalse(self._is_allocated_in_project(address,
1136+ self.projects[0].id))
1137+
1138+ # First address release shouldn't affect the second
1139+ self.assertTrue(self._is_allocated_in_project(address2,
1140+ self.projects[1].id))
1141+
1142+ self._deallocate_address(1, address2)
1143+ release_ip(address2)
1144+ self.assertFalse(self._is_allocated_in_project(address2,
1145+ self.projects[1].id))
1146+
1147+ def test_subnet_edge(self):
1148+ """Makes sure that private ips don't overlap"""
1149+ first = self._create_address(0)
1150+ lease_ip(first)
1151+ instance_ids = []
1152+ for i in range(1, FLAGS.num_networks):
1153+ instance_ref = self._create_instance(i, mac=utils.generate_mac())
1154+ instance_ids.append(instance_ref['id'])
1155+ address = self._create_address(i, instance_ref['id'])
1156+ instance_ref = self._create_instance(i, mac=utils.generate_mac())
1157+ instance_ids.append(instance_ref['id'])
1158+ address2 = self._create_address(i, instance_ref['id'])
1159+ instance_ref = self._create_instance(i, mac=utils.generate_mac())
1160+ instance_ids.append(instance_ref['id'])
1161+ address3 = self._create_address(i, instance_ref['id'])
1162+ lease_ip(address)
1163+ lease_ip(address2)
1164+ lease_ip(address3)
1165+ self.context._project = self.projects[i]
1166+ self.context.project_id = self.projects[i].id
1167+ self.assertFalse(self._is_allocated_in_project(address,
1168+ self.projects[0].id))
1169+ self.assertFalse(self._is_allocated_in_project(address2,
1170+ self.projects[0].id))
1171+ self.assertFalse(self._is_allocated_in_project(address3,
1172+ self.projects[0].id))
1173+ self.network.deallocate_fixed_ip(self.context, address)
1174+ self.network.deallocate_fixed_ip(self.context, address2)
1175+ self.network.deallocate_fixed_ip(self.context, address3)
1176+ release_ip(address)
1177+ release_ip(address2)
1178+ release_ip(address3)
1179+ for instance_id in instance_ids:
1180+ db.instance_destroy(context.get_admin_context(), instance_id)
1181+ self.context._project = self.projects[0]
1182+ self.context.project_id = self.projects[0].id
1183+ self.network.deallocate_fixed_ip(self.context, first)
1184+ self._deallocate_address(0, first)
1185+ release_ip(first)
1186+
1187+ def test_vpn_ip_and_port_looks_valid(self):
1188+ """Ensure the vpn ip and port are reasonable"""
1189+ self.assert_(self.projects[0].vpn_ip)
1190+ self.assert_(self.projects[0].vpn_port >= FLAGS.vpn_start)
1191+ self.assert_(self.projects[0].vpn_port <= FLAGS.vpn_start +
1192+ FLAGS.num_networks)
1193+
1194+ def test_too_many_networks(self):
1195+ """Ensure error is raised if we run out of networks"""
1196+ projects = []
1197+ networks_left = (FLAGS.num_networks -
1198+ db.network_count(context.get_admin_context()))
1199+ for i in range(networks_left):
1200+ project = self.manager.create_project('many%s' % i, self.user)
1201+ projects.append(project)
1202+ db.project_get_network(context.get_admin_context(), project.id)
1203+ project = self.manager.create_project('last', self.user)
1204+ projects.append(project)
1205+ self.assertRaises(db.NoMoreNetworks,
1206+ db.project_get_network,
1207+ context.get_admin_context(),
1208+ project.id)
1209+ for project in projects:
1210+ self.manager.delete_project(project)
1211+
1212+ def test_ips_are_reused(self):
1213+ """Makes sure that ip addresses that are deallocated get reused"""
1214+ address = self._create_address(0)
1215+ lease_ip(address)
1216+ self.network.deallocate_fixed_ip(self.context, address)
1217+ release_ip(address)
1218+
1219+ address2 = self._create_address(0)
1220+ self.assertEqual(address, address2)
1221+ lease_ip(address)
1222+ self.network.deallocate_fixed_ip(self.context, address2)
1223+ release_ip(address)
1224+
1225+ def test_too_many_addresses(self):
1226+ """Test for a NoMoreAddresses exception when all fixed ips are used.
1227+ """
1228+ admin_context = context.get_admin_context()
1229+ network = db.project_get_network(admin_context, self.projects[0].id)
1230+ num_available_ips = db.network_count_available_ips(admin_context,
1231+ network['id'])
1232+ addresses = []
1233+ instance_ids = []
1234+ for i in range(num_available_ips):
1235+ instance_ref = self._create_instance(0)
1236+ instance_ids.append(instance_ref['id'])
1237+ address = self._create_address(0, instance_ref['id'])
1238+ addresses.append(address)
1239+ lease_ip(address)
1240+
1241+ ip_count = db.network_count_available_ips(context.get_admin_context(),
1242+ network['id'])
1243+ self.assertEqual(ip_count, 0)
1244+ self.assertRaises(db.NoMoreAddresses,
1245+ self.network.allocate_fixed_ip,
1246+ self.context,
1247+ 'foo')
1248+
1249+ for i in range(num_available_ips):
1250+ self.network.deallocate_fixed_ip(self.context, addresses[i])
1251+ release_ip(addresses[i])
1252+ db.instance_destroy(context.get_admin_context(), instance_ids[i])
1253+ ip_count = db.network_count_available_ips(context.get_admin_context(),
1254+ network['id'])
1255+ self.assertEqual(ip_count, num_available_ips)
1256+
1257+ def _is_allocated_in_project(self, address, project_id):
1258+ """Returns true if address is in specified project"""
1259+ project_net = db.project_get_network(context.get_admin_context(),
1260+ project_id)
1261+ network = db.fixed_ip_get_network(context.get_admin_context(),
1262+ address)
1263+ instance = db.fixed_ip_get_instance(context.get_admin_context(),
1264+ address)
1265+ # instance exists until release
1266+ return instance is not None and network['id'] == project_net['id']
1267+
1268+ def run(self, result=None):
1269+ if(FLAGS.network_manager == 'nova.network.manager.VlanManager'):
1270+ super(VlanNetworkTestCase, self).run(result)
1271
1272=== modified file 'nova/virt/interfaces.template'
1273--- nova/virt/interfaces.template 2010-09-14 13:23:58 +0000
1274+++ nova/virt/interfaces.template 2011-03-23 04:18:31 +0000
1275@@ -8,10 +8,16 @@
1276 # The primary network interface
1277 auto eth0
1278 iface eth0 inet static
1279- address %(address)s
1280- netmask %(netmask)s
1281- broadcast %(broadcast)s
1282- gateway %(gateway)s
1283- dns-nameservers %(dns)s
1284+ address ${address}
1285+ netmask ${netmask}
1286+ broadcast ${broadcast}
1287+ gateway ${gateway}
1288+ dns-nameservers ${dns}
1289
1290+#if $use_ipv6
1291+iface eth0 inet6 static
1292+ address ${address_v6}
1293+ netmask ${netmask_v6}
1294+ gateway ${gateway_v6}
1295+#end if
1296
1297
1298=== modified file 'nova/virt/libvirt.xml.template'
1299--- nova/virt/libvirt.xml.template 2011-01-21 11:04:02 +0000
1300+++ nova/virt/libvirt.xml.template 2011-03-23 04:18:31 +0000
1301@@ -79,8 +79,8 @@
1302 #if $getVar('extra_params', False)
1303 ${extra_params}
1304 #end if
1305-#if $getVar('ra_server', False)
1306- <parameter name="RASERVER" value="${ra_server}" />
1307+#if $getVar('gateway_v6', False)
1308+ <parameter name="RASERVER" value="${gateway_v6}" />
1309 #end if
1310 </filterref>
1311 </interface>
1312
1313=== modified file 'nova/virt/libvirt_conn.py'
1314--- nova/virt/libvirt_conn.py 2011-03-22 21:41:41 +0000
1315+++ nova/virt/libvirt_conn.py 2011-03-23 04:18:31 +0000
1316@@ -160,6 +160,7 @@
1317 self.libvirt_uri = self.get_uri()
1318
1319 self.libvirt_xml = open(FLAGS.libvirt_xml_template).read()
1320+ self.interfaces_xml = open(FLAGS.injected_network_template).read()
1321 self.cpuinfo_xml = open(FLAGS.cpuinfo_xml_template).read()
1322 self._wrapped_conn = None
1323 self.read_only = read_only
1324@@ -663,16 +664,23 @@
1325 if network_ref['injected']:
1326 admin_context = context.get_admin_context()
1327 address = db.instance_get_fixed_address(admin_context, inst['id'])
1328- ra_server = network_ref['ra_server']
1329- if not ra_server:
1330- ra_server = "fd00::"
1331- with open(FLAGS.injected_network_template) as f:
1332- net = f.read() % {'address': address,
1333- 'netmask': network_ref['netmask'],
1334- 'gateway': network_ref['gateway'],
1335- 'broadcast': network_ref['broadcast'],
1336- 'dns': network_ref['dns'],
1337- 'ra_server': ra_server}
1338+ address_v6 = None
1339+ if FLAGS.use_ipv6:
1340+ address_v6 = db.instance_get_fixed_address_v6(admin_context,
1341+ inst['id'])
1342+
1343+ interfaces_info = {'address': address,
1344+ 'netmask': network_ref['netmask'],
1345+ 'gateway': network_ref['gateway'],
1346+ 'broadcast': network_ref['broadcast'],
1347+ 'dns': network_ref['dns'],
1348+ 'address_v6': address_v6,
1349+ 'gateway_v6': network_ref['gateway_v6'],
1350+ 'netmask_v6': network_ref['netmask_v6'],
1351+ 'use_ipv6': FLAGS.use_ipv6}
1352+
1353+ net = str(Template(self.interfaces_xml,
1354+ searchList=[interfaces_info]))
1355 if key or net:
1356 inst_name = inst['name']
1357 img_id = inst.image_id
1358@@ -707,7 +715,7 @@
1359 instance['id'])
1360 # Assume that the gateway also acts as the dhcp server.
1361 dhcp_server = network['gateway']
1362- ra_server = network['ra_server']
1363+ gateway_v6 = network['gateway_v6']
1364
1365 if FLAGS.allow_project_net_traffic:
1366 if FLAGS.use_ipv6:
1367@@ -752,8 +760,8 @@
1368 'local': instance_type['local_gb'],
1369 'driver_type': driver_type}
1370
1371- if ra_server:
1372- xml_info['ra_server'] = ra_server + "/128"
1373+ if gateway_v6:
1374+ xml_info['gateway_v6'] = gateway_v6 + "/128"
1375 if not rescue:
1376 if instance['kernel_id']:
1377 xml_info['kernel'] = xml_info['basepath'] + "/kernel"
1378@@ -1310,10 +1318,10 @@
1379 """
1380 raise NotImplementedError()
1381
1382- def _ra_server_for_instance(self, instance):
1383+ def _gateway_v6_for_instance(self, instance):
1384 network = db.network_get_by_instance(context.get_admin_context(),
1385 instance['id'])
1386- return network['ra_server']
1387+ return network['gateway_v6']
1388
1389
1390 class NWFilterFirewall(FirewallDriver):
1391@@ -1529,8 +1537,8 @@
1392 'nova-base-ipv6',
1393 'nova-allow-dhcp-server']
1394 if FLAGS.use_ipv6:
1395- ra_server = self._ra_server_for_instance(instance)
1396- if ra_server:
1397+ gateway_v6 = self._gateway_v6_for_instance(instance)
1398+ if gateway_v6:
1399 instance_secgroup_filter_children += ['nova-allow-ra-server']
1400
1401 ctxt = context.get_admin_context()
1402@@ -1698,9 +1706,9 @@
1403 # they're not worth the clutter.
1404 if FLAGS.use_ipv6:
1405 # Allow RA responses
1406- ra_server = self._ra_server_for_instance(instance)
1407- if ra_server:
1408- ipv6_rules += ['-s %s/128 -p icmpv6 -j ACCEPT' % (ra_server,)]
1409+ gateway_v6 = self._gateway_v6_for_instance(instance)
1410+ if gateway_v6:
1411+ ipv6_rules += ['-s %s/128 -p icmpv6 -j ACCEPT' % (gateway_v6,)]
1412
1413 #Allow project network traffic
1414 if FLAGS.allow_project_net_traffic:
1415@@ -1801,10 +1809,10 @@
1416 instance['id'])
1417 return network['gateway']
1418
1419- def _ra_server_for_instance(self, instance):
1420+ def _gateway_v6_for_instance(self, instance):
1421 network = db.network_get_by_instance(context.get_admin_context(),
1422 instance['id'])
1423- return network['ra_server']
1424+ return network['gateway_v6']
1425
1426 def _project_cidr_for_instance(self, instance):
1427 network = db.network_get_by_instance(context.get_admin_context(),
1428
1429=== modified file 'nova/virt/xenapi/vmops.py'
1430--- nova/virt/xenapi/vmops.py 2011-03-21 18:19:20 +0000
1431+++ nova/virt/xenapi/vmops.py 2011-03-23 04:18:31 +0000
1432@@ -711,9 +711,10 @@
1433
1434 def ip6_dict(ip6):
1435 return {
1436- "ip": ip6.addressV6,
1437- "netmask": ip6.netmaskV6,
1438- "gateway": ip6.gatewayV6,
1439+ "ip": utils.to_global_ipv6(network['cidr_v6'],
1440+ instance['mac_address']),
1441+ "netmask": network['netmask_v6'],
1442+ "gateway": network['gateway_v6'],
1443 "enabled": "1"}
1444
1445 info = {