blob: 87bc154b7e0a7e0f9976a637869e19ab90c6d75b [file] [log] [blame]
Jiri Broulikf1b3aa42017-01-26 17:08:44 +01001# -*- coding: utf-8 -*-
2
3import logging
Oleh Hryhorov4ce5d2c2018-11-08 18:41:20 +02004import time
Jiri Broulikf1b3aa42017-01-26 17:08:44 +01005from functools import wraps
Oleh Hryhorov4ce5d2c2018-11-08 18:41:20 +02006from salt.exceptions import CommandExecutionError
Jiri Broulikf1b3aa42017-01-26 17:08:44 +01007LOG = logging.getLogger(__name__)
Jiri Broulik5368cc52017-02-08 18:53:59 +01008
Jiri Broulikf1b3aa42017-01-26 17:08:44 +01009# Import third party libs
10HAS_NEUTRON = False
11try:
12 from neutronclient.v2_0 import client
13 HAS_NEUTRON = True
14except ImportError:
15 pass
16
17__opts__ = {}
18
19
20def __virtual__():
21 '''
22 Only load this module if neutron
23 is installed on this minion.
24 '''
25 if HAS_NEUTRON:
26 return 'neutronng'
27 return False
28
29
30def _autheticate(func_name):
31 '''
32 Authenticate requests with the salt keystone module and format return data
33 '''
34 @wraps(func_name)
35 def decorator_method(*args, **kwargs):
36 '''
37 Authenticate request and format return data
38 '''
Your Name96fdc0a2017-05-05 12:56:28 +000039 connection_args = {'profile': kwargs.pop('profile', None)}
Jiri Broulikf1b3aa42017-01-26 17:08:44 +010040 nkwargs = {}
41 for kwarg in kwargs:
42 if 'connection_' in kwarg:
43 connection_args.update({kwarg: kwargs[kwarg]})
44 elif '__' not in kwarg:
45 nkwargs.update({kwarg: kwargs[kwarg]})
Oleg Iurchenko87f56322017-10-20 00:40:50 +030046 kstone = __salt__['keystoneng.auth'](**connection_args)
47 endpoint_type = kwargs.get('connection_endpoint_type', 'internal')
48 neutron_interface = client.Client(session=kstone.session, endpoint_type=endpoint_type)
Jiri Broulikf1b3aa42017-01-26 17:08:44 +010049 return_data = func_name(neutron_interface, *args, **nkwargs)
Your Name96fdc0a2017-05-05 12:56:28 +000050 # TODO(vsaienko) drop this formatting when all commands are updated
51 # to return dictionary
Jiri Broulikf1b3aa42017-01-26 17:08:44 +010052 if isinstance(return_data, list):
53 # format list as a dict for rendering
54 return {data.get('name', None) or data['id']: data
55 for data in return_data}
56 return return_data
57 return decorator_method
58
59
60@_autheticate
61def list_floatingips(neutron_interface, **kwargs):
62 '''
63 list all floatingips
64 CLI Example:
65 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +000066 salt '*' neutronng.list_floatingips
Jiri Broulikf1b3aa42017-01-26 17:08:44 +010067 '''
68 return neutron_interface.list_floatingips(**kwargs)['floatingips']
69
70
71@_autheticate
72def list_security_groups(neutron_interface, **kwargs):
73 '''
74 list all security_groups
75 CLI Example:
76 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +000077 salt '*' neutronng.list_security_groups
Jiri Broulikf1b3aa42017-01-26 17:08:44 +010078 '''
79 return neutron_interface.list_security_groups(**kwargs)['security_groups']
80
81
82@_autheticate
83def list_subnets(neutron_interface, **kwargs):
84 '''
85 list all subnets
86 CLI Example:
87 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +000088 salt '*' neutronng.list_subnets
Jiri Broulikf1b3aa42017-01-26 17:08:44 +010089 '''
Your Name96fdc0a2017-05-05 12:56:28 +000090 return neutron_interface.list_subnets(**kwargs)
Jiri Broulikf1b3aa42017-01-26 17:08:44 +010091
92
93@_autheticate
94def list_networks(neutron_interface, **kwargs):
95 '''
96 list all networks
97 CLI Example:
98 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +000099 salt '*' neutronng.list_networks
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100100 '''
Your Name96fdc0a2017-05-05 12:56:28 +0000101 return neutron_interface.list_networks(**kwargs)
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100102
103
104@_autheticate
105def list_ports(neutron_interface, **kwargs):
106 '''
107 list all ports
108 CLI Example:
109 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000110 salt '*' neutronng.list_ports
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100111 '''
112 return neutron_interface.list_ports(**kwargs)['ports']
113
114
115@_autheticate
116def list_routers(neutron_interface, **kwargs):
117 '''
118 list all routers
119 CLI Example:
120 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000121 salt '*' neutronng.list_routers
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100122 '''
123 return neutron_interface.list_routers(**kwargs)['routers']
124
125@_autheticate
126def update_floatingip(neutron_interface, fip, port_id=None):
127 '''
128 update floating IP. Should be used to associate and disassociate
129 floating IP with instance
130 CLI Example:
131 .. code-block:: bash
132 to associate with an instance's port
Your Name96fdc0a2017-05-05 12:56:28 +0000133 salt '*' neutronng.update_floatingip openstack-floatingip-id port-id
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100134 to disassociate from an instance's port
Your Name96fdc0a2017-05-05 12:56:28 +0000135 salt '*' neutronng.update_floatingip openstack-floatingip-id
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100136 '''
137 neutron_interface.update_floatingip(fip, {"floatingip":
138 {"port_id": port_id}})
139
140
141@_autheticate
142def update_subnet(neutron_interface, subnet_id, **subnet_params):
143 '''
144 update given subnet
145 CLI Example:
146 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000147 salt '*' neutronng.update_subnet openstack-subnet-id name='new_name'
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100148 '''
Your Name96fdc0a2017-05-05 12:56:28 +0000149 return neutron_interface.update_subnet(subnet_id, {'subnet': subnet_params})
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100150
151
152@_autheticate
153def update_network(neutron_interface, network_id, **net_params):
154 '''
155 Update give network
156 CLI Example:
157 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000158 salt '*' neutronng.update_network openstack-net-id admin_state_up=false
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100159 '''
160 network_params = {}
161 for param in net_params:
162 if 'provider_' in param or 'router_' in param:
163 network_params[param.replace('_', ':', 1)] = net_params[param]
164 else:
165 network_params[param] = net_params[param]
166 LOG.info('ATTRIBUTES ' + str(network_params))
Your Name96fdc0a2017-05-05 12:56:28 +0000167 return neutron_interface.update_network(network_id, {'network': network_params})
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100168
169
170@_autheticate
171def update_router(neutron_interface, router_id, **router_params):
172 '''
173 update given router
174 CLI Example:
175 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000176 salt '*' neutronng.update_router openstack-router-id name='new_name'
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100177 external_gateway='openstack-network-id' administrative_state=true
178 '''
179 neutron_interface.update_router(router_id, {'router': router_params})
180
181
182@_autheticate
183def router_gateway_set(neutron_interface, router_id, external_gateway):
184 '''
185 Set external gateway for a router
186 CLI Example:
187 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000188 salt '*' neutronng.update_router openstack-router-id openstack-network-id
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100189 '''
190 neutron_interface.update_router(
191 router_id, {'router': {'external_gateway_info':
192 {'network_id': external_gateway}}})
193
194
195@_autheticate
196def router_gateway_clear(neutron_interface, router_id):
197 '''
198 Clear external gateway for a router
199 CLI Example:
200 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000201 salt '*' neutronng.update_router openstack-router-id
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100202 '''
203 neutron_interface.update_router(
204 router_id, {'router': {'external_gateway_info': None}})
205
206
207@_autheticate
208def create_router(neutron_interface, **router_params):
209 '''
210 Create OpenStack Neutron router
211 CLI Example:
212 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000213 salt '*' neutronng.create_router name=R1
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100214 '''
215 response = neutron_interface.create_router({'router': router_params})
216 if 'router' in response and 'id' in response['router']:
217 return response['router']['id']
218
219
220@_autheticate
221def router_add_interface(neutron_interface, router_id, subnet_id):
222 '''
223 Attach router to a subnet
224 CLI Example:
225 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000226 salt '*' neutronng.router_add_interface openstack-router-id subnet-id
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100227 '''
228 neutron_interface.add_interface_router(router_id, {'subnet_id': subnet_id})
229
230
231@_autheticate
232def router_rem_interface(neutron_interface, router_id, subnet_id):
233 '''
234 Dettach router from a subnet
235 CLI Example:
236 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000237 salt '*' neutronng.router_rem_interface openstack-router-id subnet-id
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100238 '''
239 neutron_interface.remove_interface_router(
240 router_id, {'subnet_id': subnet_id})
241
242
243@_autheticate
244def create_security_group(neutron_interface, **sg_params):
245 '''
246 Create a new security group
247 CLI Example:
248 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000249 salt '*' neutronng.create_security_group name='new_rule'
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100250 description='test rule'
251 '''
252 response = neutron_interface.create_security_group(
253 {'security_group': sg_params})
254 if 'security_group' in response and 'id' in response['security_group']:
255 return response['security_group']['id']
256
257
258@_autheticate
259def create_security_group_rule(neutron_interface, **rule_params):
260 '''
261 Create a rule entry for a security group
262 CLI Example:
263 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000264 salt '*' neutronng.create_security_group_rule
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100265 '''
266 neutron_interface.create_security_group_rule(
267 {'security_group_rule': rule_params})
268
269
270@_autheticate
271def create_floatingip(neutron_interface, **floatingip_params):
272 '''
273 Create a new floating IP
274 CLI Example:
275 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000276 salt '*' neutronng.create_floatingip floating_network_id=ext-net-id
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100277 '''
278 response = neutron_interface.create_floatingip(
279 {'floatingip': floatingip_params})
280 if 'floatingip' in response and 'id' in response['floatingip']:
Jiri Broulikde2e2902017-02-13 15:03:47 +0100281 return response
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100282
283
284@_autheticate
285def create_subnet(neutron_interface, **subnet_params):
286 '''
287 Create a new subnet in OpenStack
288 CLI Example:
289 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000290 salt '*' neutronng.create_subnet name='subnet name'
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100291 network_id='openstack-network-id' cidr='192.168.10.0/24' \\
Your Name96fdc0a2017-05-05 12:56:28 +0000292 gateway_ip='192.168.10.1' ip_version='4' enable_dhcp=false
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100293 '''
Your Name96fdc0a2017-05-05 12:56:28 +0000294 return neutron_interface.create_subnet({'subnet': subnet_params})
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100295
296
297@_autheticate
298def create_network(neutron_interface, **net_params):
299 '''
300 Create a new network segment in OpenStack
301 CLI Example:
302 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000303 salt '*' neutronng.create_network name=External
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100304 provider_network_type=flat provider_physical_network=ext
305 '''
306 network_params = {}
307 for param in net_params:
308 if 'provider_' in param or 'router_' in param:
309 network_params[param.replace('_', ':', 1)] = net_params[param]
310 else:
311 network_params[param] = net_params[param]
Your Name96fdc0a2017-05-05 12:56:28 +0000312 return neutron_interface.create_network({'network': network_params})
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100313
314
315@_autheticate
316def create_port(neutron_interface, **port_params):
317 '''
318 Create a new port in OpenStack
319 CLI Example:
320 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000321 salt '*' neutronng.create_port network_id='openstack-network-id'
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100322 '''
Elena Ezhova20456692017-07-10 14:30:27 +0400323 return neutron_interface.create_port({'port': port_params})
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100324
325
326@_autheticate
327def update_port(neutron_interface, port_id, **port_params):
328 '''
329 Create a new port in OpenStack
330 CLI Example:
331 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000332 salt '*' neutronng.update_port name='new_port_name'
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100333 '''
334 neutron_interface.update_port(port_id, {'port': port_params})
335
336
337@_autheticate
338def delete_floatingip(neutron_interface, floating_ip_id):
339 '''
340 delete a floating IP
341 CLI Example:
342 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000343 salt '*' neutronng.delete_floatingip openstack-floating-ip-id
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100344 '''
345 neutron_interface.delete_floatingip(floating_ip_id)
346
347
348@_autheticate
349def delete_security_group(neutron_interface, sg_id):
350 '''
351 delete a security group
352 CLI Example:
353 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000354 salt '*' neutronng.delete_security_group openstack-security-group-id
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100355 '''
356 neutron_interface.delete_security_group(sg_id)
357
358
359@_autheticate
360def delete_security_group_rule(neutron_interface, rule):
361 '''
362 delete a security group rule. pass all rule params that match the rule
363 to be deleted
364 CLI Example:
365 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000366 salt '*' neutronng.delete_security_group_rule direction='ingress'
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100367 ethertype='ipv4' security_group_id='openstack-security-group-id'
368 port_range_min=100 port_range_max=4096 protocol='tcp'
369 remote_group_id='default'
370 '''
371 sg_rules = neutron_interface.list_security_group_rules(
372 security_group_id=rule['security_group_id'])
373 for sg_rule in sg_rules['security_group_rules']:
374 sgr_id = sg_rule.pop('id')
375 if sg_rule == rule:
376 neutron_interface.delete_security_group_rule(sgr_id)
377
378
379@_autheticate
380def delete_subnet(neutron_interface, subnet_id):
381 '''
382 delete given subnet
383 CLI Example:
384 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000385 salt '*' neutronng.delete_subnet openstack-subnet-id
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100386 '''
387 neutron_interface.delete_subnet(subnet_id)
388
389
390@_autheticate
391def delete_network(neutron_interface, network_id):
392 '''
393 delete given network
394 CLI Example:
395 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000396 salt '*' neutronng.delete_network openstack-network-id
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100397 '''
398 neutron_interface.delete_network(network_id)
399
400
401@_autheticate
402def delete_router(neutron_interface, router_id):
403 '''
404 delete given router
405 CLI Example:
406 .. code-block:: bash
Your Name96fdc0a2017-05-05 12:56:28 +0000407 salt '*' neutronng.delete_router openstack-router-id
Jiri Broulikf1b3aa42017-01-26 17:08:44 +0100408 '''
Your Name96fdc0a2017-05-05 12:56:28 +0000409 neutron_interface.delete_router(router_id)
410
Artem27d70bb2018-05-14 10:37:18 +0300411
412@_autheticate
413def list_extensions(neutron_interface, **kwargs):
414 '''
415 list all extensions
416 CLI Example:
417 .. code-block:: bash
418 salt '*' neutronng.list_extensions
419 '''
420 return neutron_interface.list_extensions(**kwargs)
Oleh Hryhorov4ce5d2c2018-11-08 18:41:20 +0200421
422
423def wait_for_api_ready(profile, retries=1, retry_timeout=10):
424
425 response = {'status': 'up'}
426 for i in range(1, retries+1):
427 try:
428 list_routers(profile=profile)
429 except Exception as e:
430 msg = ("Error: %s "
431 "Sleeping for %ss. "
432 "Attempts %s of %s ")
433 LOG.error(msg % (e, retry_timeout, i, retries))
434 time.sleep(retry_timeout)
435 if i == retries:
436 raise CommandExecutionError(e)
437 continue
438 return response
439