blob: 7e329d8829dd08c2e6e61b1703984d602373698e [file] [log] [blame]
Pavel Svimberskyb3c21f52017-09-26 15:06:31 +02001#!/usr/bin/python
2# Copyright 2017 Mirantis, Inc.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16# todo:
17# CRUD VirtualService
18# CRUD Pool
19# CRUD
20
21import requests
22import os
23import re
24import json
25
26__opts__ = {}
27
28def _auth(**kwargs):
29 '''
30 Set up Contrail API credentials.
31 '''
32 cluster_ip = __pillar__['avinetworks']['api']['ip']
33 username = __pillar__['avinetworks']['api']['user']
34 password = __pillar__['avinetworks']['api']['password']
35 login = requests.post('https://' + cluster_ip + '/login',
36 verify=False,
37 data={'username': username, 'password': password})
38 return login
39
40
41def _get_input_type(_input):
42 test = re.compile(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$")
43 result = test.match(_input)
44 if result:
45 return "V4"
46 return "DNS"
47
48
49def logout(login):
50 cluster_ip = __pillar__['avinetworks']['api']['ip']
51 requests.post('https://' + cluster_ip + '/logout',
52 verify=False,
53 headers={'X-CSRFToken': login.cookies['csrftoken'],
54 'Referer': 'https://' + cluster_ip},
55 cookies=login.cookies)
56
57
58def send_request_get(_command):
59 cluster_ip = __pillar__['avinetworks']['api']['ip']
60 login = _auth()
61 url = "https://" + os.path.join(cluster_ip, "api", _command)
62 try:
63 resp = requests.get(url,
64 verify=False,
65 cookies=dict(sessionid=login.cookies['sessionid']))
66 except requests.exceptions.RequestException as ex:
67 print ex
68 return None
69 logout(login)
70 return resp
71
72
73def send_request_post(_command, data):
74 cluster_ip = __pillar__['avinetworks']['api']['ip']
75 login = _auth()
76 url = "https://" + os.path.join(cluster_ip, "api", _command)
77 try:
78 resp = requests.post(url,
79 verify=False,
80 headers={'X-CSRFToken': login.cookies['csrftoken'],
81 'Referer': 'https://' + cluster_ip,
82 'Content-Type': 'application/json'},
83 cookies=login.cookies,
84 data=json.dumps(data))
85 except requests.exceptions.RequestException as ex:
86 print ex
87 return None
88 logout(login)
89 return resp
90
91
92def send_request_put(_command, data):
93 cluster_ip = __pillar__['avinetworks']['api']['ip']
94 login = _auth()
95 url = "https://" + os.path.join(cluster_ip, "api", _command)
96 try:
97 resp = requests.put(url,
98 verify=False,
99 headers={'X-CSRFToken': login.cookies['csrftoken'],
100 'Referer': 'https://' + cluster_ip,
101 'Content-Type': 'application/json'},
102 cookies=login.cookies,
103 data=json.dumps(data))
104 except requests.exceptions.RequestException as ex:
105 print ex
106 return None
107 logout(login)
108 return resp
109
110
111def send_request_delete(_command, uuid, **kwargs):
112 cluster_ip = __pillar__['avinetworks']['api']['ip']
113 login = _auth()
114 url = "https://" + os.path.join(cluster_ip, "api", _command, uuid)
115 try:
116 resp = requests.delete(url,
117 verify=False,
118 headers={'X-CSRFToken': login.cookies['csrftoken'],
119 'Referer': 'https://' + cluster_ip,
120 'Content-Type': 'application/json'},
121 cookies=login.cookies)
122 except requests.exceptions.RequestException as ex:
123 print ex
124 return None
125 logout(login)
126 return resp
127
128
129def pool_list(**kwargs):
130 command = "pool"
131 ret = send_request_get(command)
132 return ret.json()
133
134
135def pool_get(name, **kwargs):
136 pools = pool_list()
137 for pool in pools['results']:
138 if name == pool['name'] or name == pool['uuid']:
139 return pool
140 return {'result': False,
141 'Error': "Error in the retrieving pool."}
142
143
144def pool_create(name, lb_algorithm='LB_ALGORITHM_ROUND_ROBIN', server_port=80, servers=None, **kwargs):
145 command = 'pool'
146 ret = {'name': name,
147 'changes': {},
148 'result': True,
149 'comment': ''}
150
151 if not servers:
152 ret['result'] = False
153 ret['comment'] = "Error: Server not defined"
154 return ret
155
156 check = pool_get(name)
157 if 'Error' not in check:
158 ret['comment'] = "Pool " + name + " already exists"
159 return ret
160
161 if __opts__['test']:
162 ret['result'] = None
163 ret['comment'] = "Pool " + name + " will be created"
164 return ret
165
166 data = {}
167 data["lb_algorithm"] = lb_algorithm
168 data["default_server_port"] = server_port
169 data["name"] = name
170 server_data = []
171 for server in servers:
172 servers_type = _get_input_type(server)
173 srv = {'ip': {'type': servers_type,
174 'addr': server}}
175 server_data.append(srv)
176 data['servers'] = server_data
177 result = send_request_post(command, data)
178 if result:
179 ret['comment'] = "Pool " + name + " has been created"
180 ret['changes'] = {'Pool': {'old': '', 'new': name}}
181 else:
182 ret['result'] = False
183 ret['comment'] = {"Error": "Pool was not created", "reason": result}
184 return ret
185
186
187def pool_delete(name, **kwargs):
188 command = 'pool'
189 ret = {'name': name,
190 'changes': {},
191 'result': True,
192 'comment': ''}
193
194 check = pool_get(name)
195 if not check:
196 ret['comment'] = "Pool " + name + " is already deleted"
197 return ret
198
199 if __opts__['test']:
200 ret['result'] = None
201 ret['comment'] = "Pool " + name + " will be deleted"
202 return ret
203
204 result = send_request_delete(command, check['uuid'])
205 if result:
206 ret['comment'] = "Pool " + name + " has been deleted"
207 ret['changes'] = {'Pool': {'old': name, 'new': ''}}
208 else:
209 ret['result'] = False
210 ret['comment'] = "Error: Pool was not created"
211 return ret
212
213
214def virtual_service_list():
215 command = "virtualservice"
216 ret = send_request_get(command)
217 return ret.json()
218
219
220def virtual_service_get(name):
221 vservices = virtual_service_list()
222 for vs in vservices['results']:
223 if name == vs['name'] or name == vs['uuid']:
224 return vs
225 return None
226
227
228def virtual_service_create():
229 command = "virtualservice"
230 vip = [{'auto_allocate_floating_ip': True,
231 'auto_allocate_ip': True,
232 'ipam_network_subnet': {
233 'subnet': {
234 "mask": 24,
235 "ip_addr": {
236 "type": "V4",
237 "addr": "192.168.32.0"
238 }
239 }
240 }
241 }]
242 service = [{"port": 8080}]
243 data = {'name': "test",
244 'services': service,
245 'vip': vip
246 }
247 ret = send_request_post(command, data)
248 return ret.json()
249
250
251def cloud_list():
252 command = "cloud"
253 ret = send_request_get(command)
254 return ret.json()
255
256
257def cloud_get(name, **kwargs):
258 clouds = cloud_list()
259 for cloud in clouds['results']:
260 if name == cloud['name'] or name == cloud['uuid']:
261 return cloud
262 return {'result': False,
263 'Error': "Error in the retrieving cloud."}
264
265
266def cloud_create(name, mtu=1500, dhcp_enabled=False, openstack=None, **kwargs):
267 command = 'cloud'
268 ret = {'name': name,
269 'changes': {},
270 'result': True,
271 'comment': ''}
272
273 check = cloud_get(name)
274 if 'Error' not in check:
275 ret['comment'] = "Cloud " + name + " already exists"
276 return ret
277
278 if __opts__['test']:
279 ret['result'] = None
280 ret['comment'] = "Cloud " + name + " will be created"
281 return ret
282
283 data = {}
284 data["name"] = name
285 data["vtype"] = "CLOUD_OPENSTACK"
286 data["license_type"] = "LIC_CORES"
287 data["mtu"] = mtu
288 data["dhcp_enabled"] = dhcp_enabled
289
290 if openstack:
291 openstack_conf = {}
292 openstack_conf['username'] = openstack['username']
293 openstack_conf['password'] = openstack['password']
294 openstack_conf['admin_tenant'] = openstack['admin_tenant']
295 openstack_conf['auth_url'] = openstack['auth_url']
296 openstack_conf['mgmt_network_name'] = openstack['mgmt_network_name']
297 openstack_conf['privilege'] = 'WRITE_ACCESS'
298 openstack_conf['region'] = openstack['region']
299 openstack_conf['hypervisor'] = 'KVM'
300 openstack_conf['free_floatingips'] = openstack['free_floatingips']
301 openstack_conf['img_format'] = 'OS_IMG_FMT_QCOW2'
302 openstack_conf['use_internal_endpoints'] = openstack['use_internal_endpoints']
303 openstack_conf['insecure'] = openstack['insecure']
304 openstack_conf['contrail_endpoint'] = openstack['contrail_endpoint']
305 role_mapping = {'os_role': '*', 'avi_role': openstack['avi_role']}
306 openstack_conf['role_mapping'] = role_mapping
307 data["openstack_configuration"] = openstack_conf
308 result = send_request_post(command, data)
309 if result:
310 ret['comment'] = "Cloud " + name + " has been created"
311 ret['changes'] = {'Cloud': {'old': '', 'new': name}}
312 else:
313 ret['result'] = False
314 ret['comment'] = {"Error": "Cloud was not created", "reason": result}
315 return ret
316
317
318def cloud_delete(name, **kwargs):
319 command = 'cloud'
320 ret = {'name': name,
321 'changes': {},
322 'result': True,
323 'comment': ''}
324
325 check = cloud_get(name)
326 if not check:
327 ret['comment'] = "Cloud " + name + " is already deleted"
328 return ret
329
330 if __opts__['test']:
331 ret['result'] = None
332 ret['comment'] = "Cloud " + name + " will be deleted"
333 return ret
334
335 result = send_request_delete(command, check['uuid'])
336 if result:
337 ret['comment'] = "Cloud " + name + " has been deleted"
338 ret['changes'] = {'Cloud': {'old': name, 'new': ''}}
339 else:
340 ret['result'] = False
341 ret['comment'] = "Error: Cloud was not created"
342 return ret
343
344
345def cluster_get():
346 command = "cluster"
347 ret = send_request_get(command)
348 return ret.json()
349
350
351def cluster_update(name, nodes, virtual_ip=None, **kwargs):
352 command = 'cluster'
353 ret = {'name': name,
354 'changes': {},
355 'result': True,
356 'comment': ''}
357
358 if __opts__['test']:
359 ret['result'] = None
360 ret['comment'] = "Cluster " + name + " will be updated"
361 return ret
362
363 data = {}
364 data["name"] = name
365
366 vip = {'addr': virtual_ip,
367 'type': _get_input_type(virtual_ip)}
368 data['virtual_ip'] = vip
369 nodes_data = []
370 for node in nodes:
371 node_type = _get_input_type(node['addr'])
372 n = {'ip': {'type': node_type,
373 'addr': node['addr']},
374 'name': node['name']}
375 nodes_data.append(n)
376 data['nodes'] = nodes_data
377
378 result = send_request_put(command, data)
379 if result:
380 ret['comment'] = "Cluster " + name + " has been updated"
381 ret['changes'] = {'Pool': {'old': 'unknown', 'new': name}}
382 else:
383 ret['result'] = False
384 ret['comment'] = {"Error": "Cluster was not updates", "reason": result.json()['error']}
385 return ret
Pavel Svimberskycb1a3922017-11-07 12:08:33 +0100386
387
388def user_list():
389 command = "user"
390 ret = send_request_get(command)
391 return ret.json()
392
393
394def user_get(name, **kwargs):
395 users = user_list()
396 for user in users['results']:
397 if name == user['username'] or name == user['uuid']:
398 return user
399 return {'result': False,
400 'Error': "Error in the retrieving user " + name + "."}
401
402
403def _compare_attr(origin, new):
404 if not new:
405 return origin
406 return new
407
408
409def user_create(name, uuid=None, username=None, password=None, email=None, full_name=None, is_superuser=None, local=None, **kwargs):
410 command = 'user'
411 ret = {'name': name,
412 'changes': {},
413 'result': True,
414 'comment': ''}
415
416 user = user_get(name)
417 if 'Error' not in user:
418 data = {}
419 data['username'] = _compare_attr(user['username'], username)
420 data['password'] = _compare_attr(user['password'], password)
421 data['email'] = _compare_attr(user['email'], email)
422 data['full_name'] = _compare_attr(user['full_name'], full_name)
423 data['is_superuser'] = _compare_attr(user['is_superuser'], is_superuser)
424 data['local'] = _compare_attr(user['local'], local)
425 # data['default_tenant_uuid'] = _compare_attr(user['default_tenant_uuid'], default_tenant_uuid)
426
427 if __opts__['test']:
428 ret['changes'] = None
429 ret['comment'] = "User " + name + " will be updated"
430 return ret
431
432 command += "/"+user["uuid"]
433 result = send_request_put(command, data)
434 ret['result'] = result
435 ret['comment'] = "User " + name + " has been updated"
436 return ret
437
438 data = {}
439 data['username'] = username
440 data['password'] = password
441 data['email'] = email
442 data['full_name'] = full_name
443 data['is_superuser'] = is_superuser
444 data['local'] = local
445
446 if __opts__['test']:
447 ret['changes'] = None
448 ret['comment'] = "User " + name + " will be created"
449 return ret
450
451 result = send_request_post(command, data)
452 ret['result'] = result
453 ret['comment'] = "User " + name + " has been created"
454 return ret
455
456
457def useraccount_get():
458 command = "useraccount"
459 ret = send_request_get(command)
460 return ret.json()
461
462
463def useraccount_update(old_password, password, full_name=None, email=None, **kwargs):
464 command = 'useraccount'
465 ret = {'name': "user_account",
466 'changes': {},
467 'result': True,
468 'comment': ''}
469 data = {}
470 data['old_password'] = old_password
471 data['password'] = password
472 account = useraccount_get()
473 if email:
474 data['email'] = email
475 elif (len(account["email"]) > 0):
476 data['email'] = str(account["email"])
477 else:
478 data['email'] = ""
479
480 if full_name:
481 data['full_name'] = full_name
482 elif (len(account["full_name"]) > 0):
483 data['full_name'] = str(account["full_name"])
484 else:
485 data['full_name'] = ""
486
487 if __opts__['test']:
488 ret['result'] = None
489 ret['comment'] = "User Account will be updated"
490 return ret
491
492 send_request_put(command, data)
493 ret['result'] = True
494 ret['changes'] = data
495 ret['comment'] = "User Account has been updated"
496 return ret