Merge lp:~rackspace-titan/nova/osapi-ipv6-lp798457 into lp:~hudson-openstack/nova/trunk

Proposed by Brian Waldon
Status: Merged
Approved by: Brian Lamar
Approved revision: 1286
Merged at revision: 1294
Proposed branch: lp:~rackspace-titan/nova/osapi-ipv6-lp798457
Merge into: lp:~hudson-openstack/nova/trunk
Diff against target: 221 lines (+100/-18)
3 files modified
nova/api/openstack/views/addresses.py (+22/-4)
nova/db/sqlalchemy/models.py (+13/-0)
nova/tests/api/openstack/test_servers.py (+65/-14)
To merge this branch: bzr merge lp:~rackspace-titan/nova/osapi-ipv6-lp798457
Reviewer Review Type Date Requested Status
Brian Lamar (community) Approve
Trey Morris (community) Approve
Vish Ishaya (community) Approve
Jason Kölker (community) Approve
Review via email: mp+68304@code.launchpad.net

Description of the change

- Add 'fixed_ipv6' property to VirtualInterface model
- Expose ipv6 addresses in each network in OSAPI v1.1

To post a comment you must log in.
1286. By Brian Waldon

respecting use_ipv6 flag if set to False

Revision history for this message
Jason Kölker (jason-koelker) wrote :

Is bueno.

I'm not a fan of the different treatment of IPv4 vs IPv6, but that's just nova in general right now ;).

review: Approve
Revision history for this message
Vish Ishaya (vishvananda) wrote :

nice. LGTM

review: Approve
Revision history for this message
Trey Morris (tr3buchet) wrote :

other than the fact that we're writing this in such a way that it would be difficult to pluralize ipv6_address in the future (a symptom shared with all of nova) this is great.

review: Approve
Revision history for this message
Brian Lamar (blamar) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'nova/api/openstack/views/addresses.py'
--- nova/api/openstack/views/addresses.py 2011-07-14 18:23:23 +0000
+++ nova/api/openstack/views/addresses.py 2011-07-19 13:40:32 +0000
@@ -15,9 +15,12 @@
15# License for the specific language governing permissions and limitations15# License for the specific language governing permissions and limitations
16# under the License.16# under the License.
1717
18from nova import flags
18from nova import utils19from nova import utils
19from nova.api.openstack import common20from nova.api.openstack import common
2021
22FLAGS = flags.FLAGS
23
2124
22class ViewBuilder(object):25class ViewBuilder(object):
23 """Models a server addresses response as a python dictionary."""26 """Models a server addresses response as a python dictionary."""
@@ -50,22 +53,37 @@
50 if network_label not in networks:53 if network_label not in networks:
51 networks[network_label] = []54 networks[network_label] = []
5255
53 networks[network_label].extend(self._extract_ipv4(interface))56 ip_addresses = list(self._extract_ipv4_addresses(interface))
57
58 if FLAGS.use_ipv6:
59 ipv6_address = self._extract_ipv6_address(interface)
60 if ipv6_address is not None:
61 ip_addresses.append(ipv6_address)
62
63 networks[network_label].extend(ip_addresses)
5464
55 return networks65 return networks
5666
57 def build_network(self, interfaces, network_label):67 def build_network(self, interfaces, network_label):
58 for interface in interfaces:68 for interface in interfaces:
59 if interface['network']['label'] == network_label:69 if interface['network']['label'] == network_label:
60 ips = self._extract_ipv4(interface)70 ips = list(self._extract_ipv4_addresses(interface))
61 return {network_label: list(ips)}71 ipv6 = self._extract_ipv6_address(interface)
72 if ipv6 is not None:
73 ips.append(ipv6)
74 return {network_label: ips}
62 return None75 return None
6376
64 def _extract_ipv4(self, interface):77 def _extract_ipv4_addresses(self, interface):
65 for fixed_ip in interface['fixed_ips']:78 for fixed_ip in interface['fixed_ips']:
66 yield self._build_ip_entity(fixed_ip['address'], 4)79 yield self._build_ip_entity(fixed_ip['address'], 4)
67 for floating_ip in fixed_ip.get('floating_ips', []):80 for floating_ip in fixed_ip.get('floating_ips', []):
68 yield self._build_ip_entity(floating_ip['address'], 4)81 yield self._build_ip_entity(floating_ip['address'], 4)
6982
83 def _extract_ipv6_address(self, interface):
84 fixed_ipv6 = interface.get('fixed_ipv6')
85 if fixed_ipv6 is not None:
86 return self._build_ip_entity(fixed_ipv6, 6)
87
70 def _build_ip_entity(self, address, version):88 def _build_ip_entity(self, address, version):
71 return {'addr': address, 'version': version}89 return {'addr': address, 'version': version}
7290
=== modified file 'nova/db/sqlalchemy/models.py'
--- nova/db/sqlalchemy/models.py 2011-07-08 03:07:58 +0000
+++ nova/db/sqlalchemy/models.py 2011-07-19 13:40:32 +0000
@@ -31,6 +31,7 @@
31from nova import auth31from nova import auth
32from nova import exception32from nova import exception
33from nova import flags33from nova import flags
34from nova import ipv6
34from nova import utils35from nova import utils
3536
3637
@@ -577,6 +578,18 @@
577 instance_id = Column(Integer, ForeignKey('instances.id'), nullable=False)578 instance_id = Column(Integer, ForeignKey('instances.id'), nullable=False)
578 instance = relationship(Instance, backref=backref('virtual_interfaces'))579 instance = relationship(Instance, backref=backref('virtual_interfaces'))
579580
581 @property
582 def fixed_ipv6(self):
583 cidr_v6 = self.network.cidr_v6
584 if cidr_v6 is None:
585 ipv6_address = None
586 else:
587 project_id = self.instance.project_id
588 mac = self.address
589 ipv6_address = ipv6.to_global(cidr_v6, mac, project_id)
590
591 return ipv6_address
592
580593
581# TODO(vish): can these both come from the same baseclass?594# TODO(vish): can these both come from the same baseclass?
582class FixedIp(BASE, NovaBase):595class FixedIp(BASE, NovaBase):
583596
=== modified file 'nova/tests/api/openstack/test_servers.py'
--- nova/tests/api/openstack/test_servers.py 2011-07-16 00:46:09 +0000
+++ nova/tests/api/openstack/test_servers.py 2011-07-19 13:40:32 +0000
@@ -433,20 +433,65 @@
433 self.assertEquals(ip.getAttribute('addr'), private)433 self.assertEquals(ip.getAttribute('addr'), private)
434434
435 def test_get_server_by_id_with_addresses_v1_1(self):435 def test_get_server_by_id_with_addresses_v1_1(self):
436 interfaces = [436 FLAGS.use_ipv6 = True
437 {437 interfaces = [
438 'network': {'label': 'network_1'},438 {
439 'fixed_ips': [439 'network': {'label': 'network_1'},
440 {'address': '192.168.0.3'},440 'fixed_ips': [
441 {'address': '192.168.0.4'},441 {'address': '192.168.0.3'},
442 ],442 {'address': '192.168.0.4'},
443 },443 ],
444 {444 },
445 'network': {'label': 'network_2'},445 {
446 'fixed_ips': [446 'network': {'label': 'network_2'},
447 {'address': '172.19.0.1'},447 'fixed_ips': [
448 {'address': '172.19.0.2'},448 {'address': '172.19.0.1'},
449 ],449 {'address': '172.19.0.2'},
450 ],
451 'fixed_ipv6': '2001:4860::12',
452 },
453 ]
454 new_return_server = return_server_with_interfaces(interfaces)
455 self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
456
457 req = webob.Request.blank('/v1.1/servers/1')
458 res = req.get_response(fakes.wsgi_app())
459
460 res_dict = json.loads(res.body)
461 self.assertEqual(res_dict['server']['id'], 1)
462 self.assertEqual(res_dict['server']['name'], 'server1')
463 addresses = res_dict['server']['addresses']
464 expected = {
465 'network_1': [
466 {'addr': '192.168.0.3', 'version': 4},
467 {'addr': '192.168.0.4', 'version': 4},
468 ],
469 'network_2': [
470 {'addr': '172.19.0.1', 'version': 4},
471 {'addr': '172.19.0.2', 'version': 4},
472 {'addr': '2001:4860::12', 'version': 6},
473 ],
474 }
475
476 self.assertEqual(addresses, expected)
477
478 def test_get_server_by_id_with_addresses_v1_1_ipv6_disabled(self):
479 FLAGS.use_ipv6 = False
480 interfaces = [
481 {
482 'network': {'label': 'network_1'},
483 'fixed_ips': [
484 {'address': '192.168.0.3'},
485 {'address': '192.168.0.4'},
486 ],
487 },
488 {
489 'network': {'label': 'network_2'},
490 'fixed_ips': [
491 {'address': '172.19.0.1'},
492 {'address': '172.19.0.2'},
493 ],
494 'fixed_ipv6': '2001:4860::12',
450 },495 },
451 ]496 ]
452 new_return_server = return_server_with_interfaces(interfaces)497 new_return_server = return_server_with_interfaces(interfaces)
@@ -473,6 +518,7 @@
473 self.assertEqual(addresses, expected)518 self.assertEqual(addresses, expected)
474519
475 def test_get_server_addresses_v1_1(self):520 def test_get_server_addresses_v1_1(self):
521 FLAGS.use_ipv6 = True
476 interfaces = [522 interfaces = [
477 {523 {
478 'network': {'label': 'network_1'},524 'network': {'label': 'network_1'},
@@ -492,6 +538,7 @@
492 },538 },
493 {'address': '172.19.0.2'},539 {'address': '172.19.0.2'},
494 ],540 ],
541 'fixed_ipv6': '2001:4860::12',
495 },542 },
496 ]543 ]
497544
@@ -514,6 +561,7 @@
514 {'version': 4, 'addr': '172.19.0.1'},561 {'version': 4, 'addr': '172.19.0.1'},
515 {'version': 4, 'addr': '1.2.3.4'},562 {'version': 4, 'addr': '1.2.3.4'},
516 {'version': 4, 'addr': '172.19.0.2'},563 {'version': 4, 'addr': '172.19.0.2'},
564 {'version': 6, 'addr': '2001:4860::12'},
517 ],565 ],
518 },566 },
519 }567 }
@@ -521,6 +569,7 @@
521 self.assertEqual(res_dict, expected)569 self.assertEqual(res_dict, expected)
522570
523 def test_get_server_addresses_single_network_v1_1(self):571 def test_get_server_addresses_single_network_v1_1(self):
572 FLAGS.use_ipv6 = True
524 interfaces = [573 interfaces = [
525 {574 {
526 'network': {'label': 'network_1'},575 'network': {'label': 'network_1'},
@@ -540,6 +589,7 @@
540 },589 },
541 {'address': '172.19.0.2'},590 {'address': '172.19.0.2'},
542 ],591 ],
592 'fixed_ipv6': '2001:4860::12',
543 },593 },
544 ]594 ]
545 _return_vifs = return_virtual_interface_by_instance(interfaces)595 _return_vifs = return_virtual_interface_by_instance(interfaces)
@@ -556,6 +606,7 @@
556 {'version': 4, 'addr': '172.19.0.1'},606 {'version': 4, 'addr': '172.19.0.1'},
557 {'version': 4, 'addr': '1.2.3.4'},607 {'version': 4, 'addr': '1.2.3.4'},
558 {'version': 4, 'addr': '172.19.0.2'},608 {'version': 4, 'addr': '172.19.0.2'},
609 {'version': 6, 'addr': '2001:4860::12'},
559 ],610 ],
560 }611 }
561 self.assertEqual(res_dict, expected)612 self.assertEqual(res_dict, expected)