Skip to content

Commit b2783dc

Browse files
author
Dean Troyer
committed
Low-level Compute v2 API: network
api.compute.APIv2 network functions. novaclient 8.0 is now released without support for the previously deprecated nova-net functions, so include a new low-level REST implementation of the removed APIs. Change-Id: If230f128e91cda44461fe93c976cac2aecec2252
1 parent 6f473be commit b2783dc

7 files changed

Lines changed: 430 additions & 188 deletions

File tree

openstackclient/api/compute_v2.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,100 @@ def floating_ip_list(
175175

176176
return self.list(url)["floating_ips"]
177177

178+
# Networks
179+
180+
def network_create(
181+
self,
182+
name=None,
183+
subnet=None,
184+
share_subnet=None,
185+
):
186+
"""Create a new network
187+
188+
https://developer.openstack.org/api-ref/compute/#create-project-network
189+
190+
:param string name:
191+
Network label
192+
:param integer subnet:
193+
Subnet for IPv4 fixed addresses in CIDR notation
194+
:param integer share_subnet:
195+
Shared subnet between projects, True or False
196+
:returns: A dict of the network attributes
197+
"""
198+
199+
url = "/os-tenant-networks"
200+
201+
params = {
202+
'label': name,
203+
'cidr': subnet,
204+
'share_address': share_subnet,
205+
}
206+
207+
return self.create(
208+
url,
209+
json={'network': params},
210+
)['network']
211+
212+
def network_delete(
213+
self,
214+
network=None,
215+
):
216+
"""Delete a network
217+
218+
https://developer.openstack.org/api-ref/compute/#delete-project-network
219+
220+
:param string network:
221+
Network name or ID
222+
"""
223+
224+
url = "/os-tenant-networks"
225+
226+
network = self.find(
227+
url,
228+
attr='label',
229+
value=network,
230+
)['id']
231+
if network is not None:
232+
return self.delete('/%s/%s' % (url, network))
233+
234+
return None
235+
236+
def network_find(
237+
self,
238+
network=None,
239+
):
240+
"""Return a network given name or ID
241+
242+
https://developer.openstack.org/api-ref/compute/#show-project-network-details
243+
244+
:param string network:
245+
Network name or ID
246+
:returns: A dict of the network attributes
247+
"""
248+
249+
url = "/os-tenant-networks"
250+
251+
return self.find(
252+
url,
253+
attr='label',
254+
value=network,
255+
)
256+
257+
def network_list(
258+
self,
259+
):
260+
"""Get networks
261+
262+
https://developer.openstack.org/api-ref/compute/#list-project-networks
263+
264+
:returns:
265+
list of networks
266+
"""
267+
268+
url = "/os-tenant-networks"
269+
270+
return self.list(url)["networks"]
271+
178272
# Security Groups
179273

180274
def security_group_create(

openstackclient/compute/v2/server.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,11 +215,13 @@ def take_action(self, parsed_args):
215215
server = utils.find_resource(
216216
compute_client.servers, parsed_args.server)
217217

218-
network = utils.find_resource(
219-
compute_client.networks, parsed_args.network)
218+
network = compute_client.api.network_find(parsed_args.network)
220219

221-
server.interface_attach(port_id=None, net_id=network.id,
222-
fixed_ip=parsed_args.fixed_ip_address)
220+
server.interface_attach(
221+
port_id=None,
222+
net_id=network['id'],
223+
fixed_ip=parsed_args.fixed_ip_address,
224+
)
223225

224226

225227
class AddFloatingIP(command.Command):

openstackclient/network/v2/network.py

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -171,13 +171,13 @@ def _add_additional_network_options(parser):
171171
def _get_attrs_compute(client_manager, parsed_args):
172172
attrs = {}
173173
if parsed_args.name is not None:
174-
attrs['label'] = str(parsed_args.name)
174+
attrs['name'] = str(parsed_args.name)
175175
if parsed_args.share:
176-
attrs['share_address'] = True
176+
attrs['share_subnet'] = True
177177
if parsed_args.no_share:
178-
attrs['share_address'] = False
178+
attrs['share_subnet'] = False
179179
if parsed_args.subnet is not None:
180-
attrs['cidr'] = parsed_args.subnet
180+
attrs['subnet'] = parsed_args.subnet
181181
return attrs
182182

183183

@@ -302,9 +302,9 @@ def take_action_network(self, client, parsed_args):
302302

303303
def take_action_compute(self, client, parsed_args):
304304
attrs = _get_attrs_compute(self.app.client_manager, parsed_args)
305-
obj = client.networks.create(**attrs)
306-
display_columns, columns = _get_columns(obj._info)
307-
data = utils.get_dict_properties(obj._info, columns)
305+
obj = client.api.network_create(**attrs)
306+
display_columns, columns = _get_columns(obj)
307+
data = utils.get_dict_properties(obj, columns)
308308
return (display_columns, data)
309309

310310

@@ -330,8 +330,7 @@ def take_action_network(self, client, parsed_args):
330330
client.delete_network(obj)
331331

332332
def take_action_compute(self, client, parsed_args):
333-
network = utils.find_resource(client.networks, self.r)
334-
client.networks.delete(network.id)
333+
client.api.network_delete(self.r)
335334

336335

337336
# TODO(sindhu): Use the SDK resource mapped attribute names once the
@@ -552,10 +551,10 @@ def take_action_compute(self, client, parsed_args):
552551
'Subnet',
553552
)
554553

555-
data = client.networks.list()
554+
data = client.api.network_list()
556555

557556
return (column_headers,
558-
(utils.get_item_properties(
557+
(utils.get_dict_properties(
559558
s, columns,
560559
formatters=_formatters,
561560
) for s in data))
@@ -683,10 +682,7 @@ def take_action_network(self, client, parsed_args):
683682
return (display_columns, data)
684683

685684
def take_action_compute(self, client, parsed_args):
686-
obj = utils.find_resource(
687-
client.networks,
688-
parsed_args.network,
689-
)
690-
display_columns, columns = _get_columns(obj._info)
691-
data = utils.get_dict_properties(obj._info, columns)
685+
obj = client.api.network_find(parsed_args.network)
686+
display_columns, columns = _get_columns(obj)
687+
data = utils.get_dict_properties(obj, columns)
692688
return (display_columns, data)

openstackclient/tests/unit/api/test_compute_v2.py

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,157 @@ def test_floating_ip_list(self):
145145
self.assertEqual(self.LIST_FLOATING_IP_RESP, ret)
146146

147147

148+
class TestNetwork(TestComputeAPIv2):
149+
150+
FAKE_NETWORK_RESP = {
151+
'id': '1',
152+
'label': 'label1',
153+
'cidr': '1.2.3.0/24',
154+
}
155+
156+
FAKE_NETWORK_RESP_2 = {
157+
'id': '2',
158+
'label': 'label2',
159+
'cidr': '4.5.6.0/24',
160+
}
161+
162+
LIST_NETWORK_RESP = [
163+
FAKE_NETWORK_RESP,
164+
FAKE_NETWORK_RESP_2,
165+
]
166+
167+
def test_network_create_default(self):
168+
self.requests_mock.register_uri(
169+
'POST',
170+
FAKE_URL + '/os-tenant-networks',
171+
json={'network': self.FAKE_NETWORK_RESP},
172+
status_code=200,
173+
)
174+
ret = self.api.network_create('label1')
175+
self.assertEqual(self.FAKE_NETWORK_RESP, ret)
176+
177+
def test_network_create_options(self):
178+
self.requests_mock.register_uri(
179+
'POST',
180+
FAKE_URL + '/os-tenant-networks',
181+
json={'network': self.FAKE_NETWORK_RESP},
182+
status_code=200,
183+
)
184+
ret = self.api.network_create(
185+
name='label1',
186+
subnet='1.2.3.0/24',
187+
)
188+
self.assertEqual(self.FAKE_NETWORK_RESP, ret)
189+
190+
def test_network_delete_id(self):
191+
self.requests_mock.register_uri(
192+
'GET',
193+
FAKE_URL + '/os-tenant-networks/1',
194+
json={'network': self.FAKE_NETWORK_RESP},
195+
status_code=200,
196+
)
197+
self.requests_mock.register_uri(
198+
'DELETE',
199+
FAKE_URL + '/os-tenant-networks/1',
200+
status_code=202,
201+
)
202+
ret = self.api.network_delete('1')
203+
self.assertEqual(202, ret.status_code)
204+
self.assertEqual("", ret.text)
205+
206+
def test_network_delete_name(self):
207+
self.requests_mock.register_uri(
208+
'GET',
209+
FAKE_URL + '/os-tenant-networks/label1',
210+
status_code=404,
211+
)
212+
self.requests_mock.register_uri(
213+
'GET',
214+
FAKE_URL + '/os-tenant-networks',
215+
json={'networks': self.LIST_NETWORK_RESP},
216+
status_code=200,
217+
)
218+
self.requests_mock.register_uri(
219+
'DELETE',
220+
FAKE_URL + '/os-tenant-networks/1',
221+
status_code=202,
222+
)
223+
ret = self.api.network_delete('label1')
224+
self.assertEqual(202, ret.status_code)
225+
self.assertEqual("", ret.text)
226+
227+
def test_network_delete_not_found(self):
228+
self.requests_mock.register_uri(
229+
'GET',
230+
FAKE_URL + '/os-tenant-networks/label3',
231+
status_code=404,
232+
)
233+
self.requests_mock.register_uri(
234+
'GET',
235+
FAKE_URL + '/os-tenant-networks',
236+
json={'networks': self.LIST_NETWORK_RESP},
237+
status_code=200,
238+
)
239+
self.assertRaises(
240+
osc_lib_exceptions.NotFound,
241+
self.api.network_delete,
242+
'label3',
243+
)
244+
245+
def test_network_find_id(self):
246+
self.requests_mock.register_uri(
247+
'GET',
248+
FAKE_URL + '/os-tenant-networks/1',
249+
json={'network': self.FAKE_NETWORK_RESP},
250+
status_code=200,
251+
)
252+
ret = self.api.network_find('1')
253+
self.assertEqual(self.FAKE_NETWORK_RESP, ret)
254+
255+
def test_network_find_name(self):
256+
self.requests_mock.register_uri(
257+
'GET',
258+
FAKE_URL + '/os-tenant-networks/label2',
259+
status_code=404,
260+
)
261+
self.requests_mock.register_uri(
262+
'GET',
263+
FAKE_URL + '/os-tenant-networks',
264+
json={'networks': self.LIST_NETWORK_RESP},
265+
status_code=200,
266+
)
267+
ret = self.api.network_find('label2')
268+
self.assertEqual(self.FAKE_NETWORK_RESP_2, ret)
269+
270+
def test_network_find_not_found(self):
271+
self.requests_mock.register_uri(
272+
'GET',
273+
FAKE_URL + '/os-tenant-networks/label3',
274+
status_code=404,
275+
)
276+
self.requests_mock.register_uri(
277+
'GET',
278+
FAKE_URL + '/os-tenant-networks',
279+
json={'networks': self.LIST_NETWORK_RESP},
280+
status_code=200,
281+
)
282+
self.assertRaises(
283+
osc_lib_exceptions.NotFound,
284+
self.api.network_find,
285+
'label3',
286+
)
287+
288+
def test_network_list_no_options(self):
289+
self.requests_mock.register_uri(
290+
'GET',
291+
FAKE_URL + '/os-tenant-networks',
292+
json={'networks': self.LIST_NETWORK_RESP},
293+
status_code=200,
294+
)
295+
ret = self.api.network_list()
296+
self.assertEqual(self.LIST_NETWORK_RESP, ret)
297+
298+
148299
class TestSecurityGroup(TestComputeAPIv2):
149300

150301
FAKE_SECURITY_GROUP_RESP = {

openstackclient/tests/unit/compute/v2/fakes.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,6 @@ def __init__(self, **kwargs):
190190
self.floating_ip_pools = mock.Mock()
191191
self.floating_ip_pools.resource_class = fakes.FakeResource(None, {})
192192

193-
self.networks = mock.Mock()
194-
self.networks.resource_class = fakes.FakeResource(None, {})
195-
196193
self.keypairs = mock.Mock()
197194
self.keypairs.resource_class = fakes.FakeResource(None, {})
198195

@@ -1155,10 +1152,7 @@ def create_one_network(attrs=None):
11551152
# Overwrite default attributes.
11561153
network_attrs.update(attrs)
11571154

1158-
network = fakes.FakeResource(info=copy.deepcopy(network_attrs),
1159-
loaded=True)
1160-
1161-
return network
1155+
return network_attrs
11621156

11631157
@staticmethod
11641158
def create_networks(attrs=None, count=2):

0 commit comments

Comments
 (0)