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
1=== modified file 'nova/api/openstack/views/addresses.py'
2--- nova/api/openstack/views/addresses.py 2011-07-14 18:23:23 +0000
3+++ nova/api/openstack/views/addresses.py 2011-07-19 13:40:32 +0000
4@@ -15,9 +15,12 @@
5 # License for the specific language governing permissions and limitations
6 # under the License.
7
8+from nova import flags
9 from nova import utils
10 from nova.api.openstack import common
11
12+FLAGS = flags.FLAGS
13+
14
15 class ViewBuilder(object):
16 """Models a server addresses response as a python dictionary."""
17@@ -50,22 +53,37 @@
18 if network_label not in networks:
19 networks[network_label] = []
20
21- networks[network_label].extend(self._extract_ipv4(interface))
22+ ip_addresses = list(self._extract_ipv4_addresses(interface))
23+
24+ if FLAGS.use_ipv6:
25+ ipv6_address = self._extract_ipv6_address(interface)
26+ if ipv6_address is not None:
27+ ip_addresses.append(ipv6_address)
28+
29+ networks[network_label].extend(ip_addresses)
30
31 return networks
32
33 def build_network(self, interfaces, network_label):
34 for interface in interfaces:
35 if interface['network']['label'] == network_label:
36- ips = self._extract_ipv4(interface)
37- return {network_label: list(ips)}
38+ ips = list(self._extract_ipv4_addresses(interface))
39+ ipv6 = self._extract_ipv6_address(interface)
40+ if ipv6 is not None:
41+ ips.append(ipv6)
42+ return {network_label: ips}
43 return None
44
45- def _extract_ipv4(self, interface):
46+ def _extract_ipv4_addresses(self, interface):
47 for fixed_ip in interface['fixed_ips']:
48 yield self._build_ip_entity(fixed_ip['address'], 4)
49 for floating_ip in fixed_ip.get('floating_ips', []):
50 yield self._build_ip_entity(floating_ip['address'], 4)
51
52+ def _extract_ipv6_address(self, interface):
53+ fixed_ipv6 = interface.get('fixed_ipv6')
54+ if fixed_ipv6 is not None:
55+ return self._build_ip_entity(fixed_ipv6, 6)
56+
57 def _build_ip_entity(self, address, version):
58 return {'addr': address, 'version': version}
59
60=== modified file 'nova/db/sqlalchemy/models.py'
61--- nova/db/sqlalchemy/models.py 2011-07-08 03:07:58 +0000
62+++ nova/db/sqlalchemy/models.py 2011-07-19 13:40:32 +0000
63@@ -31,6 +31,7 @@
64 from nova import auth
65 from nova import exception
66 from nova import flags
67+from nova import ipv6
68 from nova import utils
69
70
71@@ -577,6 +578,18 @@
72 instance_id = Column(Integer, ForeignKey('instances.id'), nullable=False)
73 instance = relationship(Instance, backref=backref('virtual_interfaces'))
74
75+ @property
76+ def fixed_ipv6(self):
77+ cidr_v6 = self.network.cidr_v6
78+ if cidr_v6 is None:
79+ ipv6_address = None
80+ else:
81+ project_id = self.instance.project_id
82+ mac = self.address
83+ ipv6_address = ipv6.to_global(cidr_v6, mac, project_id)
84+
85+ return ipv6_address
86+
87
88 # TODO(vish): can these both come from the same baseclass?
89 class FixedIp(BASE, NovaBase):
90
91=== modified file 'nova/tests/api/openstack/test_servers.py'
92--- nova/tests/api/openstack/test_servers.py 2011-07-16 00:46:09 +0000
93+++ nova/tests/api/openstack/test_servers.py 2011-07-19 13:40:32 +0000
94@@ -433,20 +433,65 @@
95 self.assertEquals(ip.getAttribute('addr'), private)
96
97 def test_get_server_by_id_with_addresses_v1_1(self):
98- interfaces = [
99- {
100- 'network': {'label': 'network_1'},
101- 'fixed_ips': [
102- {'address': '192.168.0.3'},
103- {'address': '192.168.0.4'},
104- ],
105- },
106- {
107- 'network': {'label': 'network_2'},
108- 'fixed_ips': [
109- {'address': '172.19.0.1'},
110- {'address': '172.19.0.2'},
111- ],
112+ FLAGS.use_ipv6 = True
113+ interfaces = [
114+ {
115+ 'network': {'label': 'network_1'},
116+ 'fixed_ips': [
117+ {'address': '192.168.0.3'},
118+ {'address': '192.168.0.4'},
119+ ],
120+ },
121+ {
122+ 'network': {'label': 'network_2'},
123+ 'fixed_ips': [
124+ {'address': '172.19.0.1'},
125+ {'address': '172.19.0.2'},
126+ ],
127+ 'fixed_ipv6': '2001:4860::12',
128+ },
129+ ]
130+ new_return_server = return_server_with_interfaces(interfaces)
131+ self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
132+
133+ req = webob.Request.blank('/v1.1/servers/1')
134+ res = req.get_response(fakes.wsgi_app())
135+
136+ res_dict = json.loads(res.body)
137+ self.assertEqual(res_dict['server']['id'], 1)
138+ self.assertEqual(res_dict['server']['name'], 'server1')
139+ addresses = res_dict['server']['addresses']
140+ expected = {
141+ 'network_1': [
142+ {'addr': '192.168.0.3', 'version': 4},
143+ {'addr': '192.168.0.4', 'version': 4},
144+ ],
145+ 'network_2': [
146+ {'addr': '172.19.0.1', 'version': 4},
147+ {'addr': '172.19.0.2', 'version': 4},
148+ {'addr': '2001:4860::12', 'version': 6},
149+ ],
150+ }
151+
152+ self.assertEqual(addresses, expected)
153+
154+ def test_get_server_by_id_with_addresses_v1_1_ipv6_disabled(self):
155+ FLAGS.use_ipv6 = False
156+ interfaces = [
157+ {
158+ 'network': {'label': 'network_1'},
159+ 'fixed_ips': [
160+ {'address': '192.168.0.3'},
161+ {'address': '192.168.0.4'},
162+ ],
163+ },
164+ {
165+ 'network': {'label': 'network_2'},
166+ 'fixed_ips': [
167+ {'address': '172.19.0.1'},
168+ {'address': '172.19.0.2'},
169+ ],
170+ 'fixed_ipv6': '2001:4860::12',
171 },
172 ]
173 new_return_server = return_server_with_interfaces(interfaces)
174@@ -473,6 +518,7 @@
175 self.assertEqual(addresses, expected)
176
177 def test_get_server_addresses_v1_1(self):
178+ FLAGS.use_ipv6 = True
179 interfaces = [
180 {
181 'network': {'label': 'network_1'},
182@@ -492,6 +538,7 @@
183 },
184 {'address': '172.19.0.2'},
185 ],
186+ 'fixed_ipv6': '2001:4860::12',
187 },
188 ]
189
190@@ -514,6 +561,7 @@
191 {'version': 4, 'addr': '172.19.0.1'},
192 {'version': 4, 'addr': '1.2.3.4'},
193 {'version': 4, 'addr': '172.19.0.2'},
194+ {'version': 6, 'addr': '2001:4860::12'},
195 ],
196 },
197 }
198@@ -521,6 +569,7 @@
199 self.assertEqual(res_dict, expected)
200
201 def test_get_server_addresses_single_network_v1_1(self):
202+ FLAGS.use_ipv6 = True
203 interfaces = [
204 {
205 'network': {'label': 'network_1'},
206@@ -540,6 +589,7 @@
207 },
208 {'address': '172.19.0.2'},
209 ],
210+ 'fixed_ipv6': '2001:4860::12',
211 },
212 ]
213 _return_vifs = return_virtual_interface_by_instance(interfaces)
214@@ -556,6 +606,7 @@
215 {'version': 4, 'addr': '172.19.0.1'},
216 {'version': 4, 'addr': '1.2.3.4'},
217 {'version': 4, 'addr': '172.19.0.2'},
218+ {'version': 6, 'addr': '2001:4860::12'},
219 ],
220 }
221 self.assertEqual(res_dict, expected)