blob: 2434f952a5d92a759775973c37b019d137ded05c [file] [log] [blame]
tierno7edb6752016-03-21 17:37:52 +01001#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# PYTHON_ARGCOMPLETE_OK
4
5##
tierno92021022018-09-12 16:29:23 +02006# Copyright 2015 Telefonica Investigacion y Desarrollo, S.A.U.
tierno7edb6752016-03-21 17:37:52 +01007# This file is part of openmano
8# All Rights Reserved.
9#
10# Licensed under the Apache License, Version 2.0 (the "License"); you may
11# not use this file except in compliance with the License. You may obtain
12# a copy of the License at
13#
14# http://www.apache.org/licenses/LICENSE-2.0
15#
16# Unless required by applicable law or agreed to in writing, software
17# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
18# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
19# License for the specific language governing permissions and limitations
20# under the License.
21#
22# For those usages not covered by the Apache License, Version 2.0 please
23# contact with: nfvlabs@tid.es
24##
25
tierno20df3bb2017-07-07 14:31:00 +020026"""
tierno7edb6752016-03-21 17:37:52 +010027openmano client used to interact with openmano-server (openmanod)
tierno20df3bb2017-07-07 14:31:00 +020028"""
tierno72a08d72017-05-25 13:12:30 +020029__author__ = "Alfonso Tierno, Gerardo Garcia, Pablo Montes"
30__date__ = "$09-oct-2014 09:09:48$"
tiernofc5f80b2018-05-29 16:00:43 +020031__version__ = "0.4.23-r533"
32version_date = "May 2018"
tierno7edb6752016-03-21 17:37:52 +010033
34from argcomplete.completers import FilesCompleter
35import os
36import argparse
37import argcomplete
38import requests
39import json
40import yaml
41import logging
42#from jsonschema import validate as js_v, exceptions as js_e
43
44class ArgumentParserError(Exception): pass
45
46class OpenmanoCLIError(Exception): pass
47
48class ThrowingArgumentParser(argparse.ArgumentParser):
49 def error(self, message):
50 print "Error: %s" %message
51 print
52 self.print_usage()
53 #self.print_help()
54 print
55 print "Type 'openmano -h' for help"
56 raise ArgumentParserError
57
58
59def config(args):
60 print "OPENMANO_HOST: %s" %mano_host
61 print "OPENMANO_PORT: %s" %mano_port
garciadeblas0e9fd832016-07-08 15:20:18 +020062 if args.n:
63 logger.debug("resolving tenant and datacenter names")
64 mano_tenant_id = "None"
65 mano_tenant_name = "None"
66 mano_datacenter_id = "None"
67 mano_datacenter_name = "None"
68 try:
69 mano_tenant_id = _get_item_uuid("tenants", mano_tenant)
70 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, mano_tenant_id)
71 mano_response = requests.get(URLrequest)
72 logger.debug("openmano response: %s", mano_response.text )
73 content = mano_response.json()
74 mano_tenant_name = content["tenant"]["name"]
75 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, mano_tenant_id, mano_datacenter)
76 mano_response = requests.get(URLrequest)
77 logger.debug("openmano response: %s", mano_response.text )
78 content = mano_response.json()
79 if "error" not in content:
80 mano_datacenter_id = content["datacenter"]["uuid"]
81 mano_datacenter_name = content["datacenter"]["name"]
82 except OpenmanoCLIError:
83 pass
84 print "OPENMANO_TENANT: %s" %mano_tenant
85 print " Id: %s" %mano_tenant_id
86 print " Name: %s" %mano_tenant_name
87 print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
88 print " Id: %s" %mano_datacenter_id
89 print " Name: %s" %mano_datacenter_name
90 else:
91 print "OPENMANO_TENANT: %s" %mano_tenant
92 print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
tierno7edb6752016-03-21 17:37:52 +010093
94def _print_verbose(mano_response, verbose_level=0):
95 content = mano_response.json()
96 result = 0 if mano_response.status_code==200 else mano_response.status_code
97 if type(content)!=dict or len(content)!=1:
98 #print "Non expected format output"
99 print str(content)
100 return result
101
102 val=content.values()[0]
103 if type(val)==str:
104 print val
105 return result
106 elif type(val) == list:
107 content_list = val
108 elif type(val)==dict:
109 content_list = [val]
110 else:
111 #print "Non expected dict/list format output"
112 print str(content)
113 return result
114
115 #print content_list
116 if verbose_level==None:
117 verbose_level=0
118 if verbose_level >= 3:
119 print yaml.safe_dump(content, indent=4, default_flow_style=False)
120 return result
121
122 if mano_response.status_code == 200:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100123 uuid = None
tierno7edb6752016-03-21 17:37:52 +0100124 for content in content_list:
125 if "uuid" in content:
126 uuid = content['uuid']
127 elif "id" in content:
128 uuid = content['id']
129 elif "vim_id" in content:
130 uuid = content['vim_id']
tierno250954a2017-01-31 14:25:57 +0100131 name = content.get('name');
132 if not uuid:
133 uuid = ""
134 if not name:
135 name = ""
tiernoa15c4b92017-10-05 12:41:44 +0200136 myoutput = "{:38} {:20}".format(uuid, name)
tierno250954a2017-01-31 14:25:57 +0100137 if content.get("status"):
tiernoa15c4b92017-10-05 12:41:44 +0200138 myoutput += " {:20}".format(content['status'])
tierno7edb6752016-03-21 17:37:52 +0100139 elif "enabled" in content and not content["enabled"]:
140 myoutput += " enabled=False".ljust(20)
141 if verbose_level >=1:
tierno250954a2017-01-31 14:25:57 +0100142 if content.get('created_at'):
tiernoa15c4b92017-10-05 12:41:44 +0200143 myoutput += " {:20}".format(content['created_at'])
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +0200144 if content.get('sdn_attached_ports'):
145 #myoutput += " " + str(content['sdn_attached_ports']).ljust(20)
146 myoutput += "\nsdn_attached_ports:\n" + yaml.safe_dump(content['sdn_attached_ports'], indent=4, default_flow_style=False)
tierno7edb6752016-03-21 17:37:52 +0100147 if verbose_level >=2:
148 new_line='\n'
tierno250954a2017-01-31 14:25:57 +0100149 if content.get('type'):
tiernoa15c4b92017-10-05 12:41:44 +0200150 myoutput += new_line + " Type: {:29}".format(content['type'])
tierno7edb6752016-03-21 17:37:52 +0100151 new_line=''
tierno250954a2017-01-31 14:25:57 +0100152 if content.get('description'):
tiernoa15c4b92017-10-05 12:41:44 +0200153 myoutput += new_line + " Description: {:20}".format(content['description'])
tierno7edb6752016-03-21 17:37:52 +0100154 print myoutput
155 else:
156 print content['error']['description']
157 return result
158
159def parser_json_yaml(file_name):
160 try:
161 f = file(file_name, "r")
162 text = f.read()
163 f.close()
164 except Exception as e:
165 return (False, str(e))
166
167 #Read and parse file
168 if file_name[-5:]=='.yaml' or file_name[-4:]=='.yml' or (file_name[-5:]!='.json' and '\t' not in text):
169 try:
170 config = yaml.load(text)
171 except yaml.YAMLError as exc:
172 error_pos = ""
173 if hasattr(exc, 'problem_mark'):
174 mark = exc.problem_mark
175 error_pos = " at line:%s column:%s" % (mark.line+1, mark.column+1)
176 return (False, "Error loading file '"+file_name+"' yaml format error" + error_pos)
177 else: #json
178 try:
179 config = json.loads(text)
180 except Exception as e:
181 return (False, "Error loading file '"+file_name+"' json format error " + str(e) )
182
183 return True, config
184
185def _load_file_or_yaml(content):
186 '''
187 'content' can be or a yaml/json file or a text containing a yaml/json text format
188 This function autodetect, trying to load and parse the file,
189 if fails trying to parse the 'content' text
190 Returns the dictionary once parsed, or print an error and finish the program
191 '''
192 #Check config file exists
193 if os.path.isfile(content):
194 r,payload = parser_json_yaml(content)
195 if not r:
196 print payload
197 exit(-1)
198 elif "{" in content or ":" in content:
199 try:
200 payload = yaml.load(content)
201 except yaml.YAMLError as exc:
202 error_pos = ""
203 if hasattr(exc, 'problem_mark'):
204 mark = exc.problem_mark
205 error_pos = " at position: (%s:%s)" % (mark.line+1, mark.column+1)
206 print "Error loading yaml/json text"+error_pos
207 exit (-1)
208 else:
209 print "'%s' is neither a valid file nor a yaml/json content" % content
210 exit(-1)
211 return payload
212
213def _get_item_uuid(item, item_name_id, tenant=None):
214 if tenant:
215 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, tenant, item)
216 else:
217 URLrequest = "http://%s:%s/openmano/%s" %(mano_host, mano_port, item)
218 mano_response = requests.get(URLrequest)
219 logger.debug("openmano response: %s", mano_response.text )
220 content = mano_response.json()
221 #print content
222 found = 0
223 for i in content[item]:
224 if i["uuid"] == item_name_id:
225 return item_name_id
226 if i["name"] == item_name_id:
227 uuid = i["uuid"]
228 found += 1
tiernof1ba57e2017-09-07 12:23:19 +0200229 if item_name_id.startswith("osm_id=") and i.get("osm_id") == item_name_id[7:]:
230 uuid = i["uuid"]
231 found += 1
tierno7edb6752016-03-21 17:37:52 +0100232 if found == 0:
233 raise OpenmanoCLIError("No %s found with name/uuid '%s'" %(item[:-1], item_name_id))
234 elif found > 1:
235 raise OpenmanoCLIError("%d %s found with name '%s'. uuid must be used" %(found, item, item_name_id))
236 return uuid
237#
238# def check_valid_uuid(uuid):
239# id_schema = {"type" : "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
240# try:
241# js_v(uuid, id_schema)
242# return True
243# except js_e.ValidationError:
244# return False
245
246def _get_tenant(tenant_name_id = None):
247 if not tenant_name_id:
248 tenant_name_id = mano_tenant
249 if not mano_tenant:
250 raise OpenmanoCLIError("'OPENMANO_TENANT' environment variable is not set")
251 return _get_item_uuid("tenants", tenant_name_id)
252
253def _get_datacenter(datacenter_name_id = None, tenant = "any"):
254 if not datacenter_name_id:
255 datacenter_name_id = mano_datacenter
256 if not datacenter_name_id:
257 raise OpenmanoCLIError("neither 'OPENMANO_DATACENTER' environment variable is set nor --datacenter option is used")
258 return _get_item_uuid("datacenters", datacenter_name_id, tenant)
259
260def vnf_create(args):
261 #print "vnf-create",args
262 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
263 tenant = _get_tenant()
264 myvnf = _load_file_or_yaml(args.file)
tiernof1ba57e2017-09-07 12:23:19 +0200265 api_version = ""
266 if "vnfd:vnfd-catalog" in myvnf or "vnfd-catalog" in myvnf:
267 api_version = "/v3"
268 token = "vnfd"
269 vnfd_catalog = myvnf.get("vnfd:vnfd-catalog")
270 if not vnfd_catalog:
271 vnfd_catalog = myvnf.get("vnfd-catalog")
272 vnfds = vnfd_catalog.get("vnfd:vnfd")
273 if not vnfds:
274 vnfds = vnfd_catalog.get("vnfd")
275 vnfd = vnfds[0]
gcalvino319b8a52018-11-05 15:33:23 +0100276 vdu_list = vnfd.get("vdu")
tiernof1ba57e2017-09-07 12:23:19 +0200277
278 else: # old API
279 api_version = ""
280 token = "vnfs"
281 vnfd = myvnf['vnf']
gcalvino319b8a52018-11-05 15:33:23 +0100282 vdu_list = vnfd.get("VNFC")
tierno7edb6752016-03-21 17:37:52 +0100283
garciadeblas14480452017-01-10 13:08:07 +0100284 if args.name or args.description or args.image_path or args.image_name or args.image_checksum:
tiernof1ba57e2017-09-07 12:23:19 +0200285 # TODO, change this for API v3
286 # print args.name
tierno7edb6752016-03-21 17:37:52 +0100287 try:
288 if args.name:
tiernof1ba57e2017-09-07 12:23:19 +0200289 vnfd['name'] = args.name
tierno7edb6752016-03-21 17:37:52 +0100290 if args.description:
tiernof1ba57e2017-09-07 12:23:19 +0200291 vnfd['description'] = args.description
gcalvino319b8a52018-11-05 15:33:23 +0100292 if vdu_list:
293 if args.image_path:
294 index = 0
295 for image_path_ in args.image_path.split(","):
296 # print "image-path", image_path_
297 if api_version == "/v3":
298 if vdu_list[index].get("image"):
299 vdu_list[index]['image'] = image_path_
300 if "image-checksum" in vdu_list[index]:
301 del vdu_list[index]["image-checksum"]
302 else: # image name in volumes
303 vdu_list[index]["volumes"][0]["image"] = image_path_
304 if "image-checksum" in vdu_list[index]["volumes"][0]:
305 del vdu_list[index]["volumes"][0]["image-checksum"]
306 else:
307 vdu_list[index]['VNFC image'] = image_path_
308 if "image name" in vdu_list[index]:
309 del vdu_list[index]["image name"]
310 if "image checksum" in vdu_list[index]:
311 del vdu_list[index]["image checksum"]
312 index += 1
313 if args.image_name: # image name precedes if both are supplied
314 index = 0
315 for image_name_ in args.image_name.split(","):
316 if api_version == "/v3":
317 if vdu_list[index].get("image"):
318 vdu_list[index]['image'] = image_name_
319 if "image-checksum" in vdu_list[index]:
320 del vdu_list[index]["image-checksum"]
321 if vdu_list[index].get("alternative-images"):
322 for a_image in vdu_list[index]["alternative-images"]:
323 a_image['image'] = image_name_
324 if "image-checksum" in a_image:
325 del a_image["image-checksum"]
326 else: # image name in volumes
327 vdu_list[index]["volumes"][0]["image"] = image_name_
328 if "image-checksum" in vdu_list[index]["volumes"][0]:
329 del vdu_list[index]["volumes"][0]["image-checksum"]
330 else:
331 vdu_list[index]['image name'] = image_name_
332 if "VNFC image" in vdu_list[index]:
333 del vdu_list[index]["VNFC image"]
334 index += 1
335 if args.image_checksum:
336 index = 0
337 for image_checksum_ in args.image_checksum.split(","):
338 if api_version == "/v3":
339 if vdu_list[index].get("image"):
340 vdu_list[index]['image-checksum'] = image_checksum_
341 if vdu_list[index].get("alternative-images"):
342 for a_image in vdu_list[index]["alternative-images"]:
343 a_image['image-checksum'] = image_checksum_
344 else: # image name in volumes
345 vdu_list[index]["volumes"][0]["image-checksum"] = image_checksum_
346 else:
347 vdu_list[index]['image checksum'] = image_checksum_
348 index += 1
tierno7edb6752016-03-21 17:37:52 +0100349 except (KeyError, TypeError), e:
tiernof1ba57e2017-09-07 12:23:19 +0200350 if str(e) == 'vnf': error_pos= "missing field 'vnf'"
351 elif str(e) == 'name': error_pos= "missing field 'vnf':'name'"
352 elif str(e) == 'description': error_pos= "missing field 'vnf':'description'"
353 elif str(e) == 'VNFC': error_pos= "missing field 'vnf':'VNFC'"
354 elif str(e) == str(index): error_pos= "field 'vnf':'VNFC' must be an array"
355 elif str(e) == 'VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
356 elif str(e) == 'image name': error_pos= "missing field 'vnf':'VNFC'['image name']"
357 elif str(e) == 'image checksum': error_pos= "missing field 'vnf':'VNFC'['image checksum']"
tierno7edb6752016-03-21 17:37:52 +0100358 else: error_pos="wrong format"
359 print "Wrong VNF descriptor: " + error_pos
360 return -1
361 payload_req = json.dumps(myvnf)
362
363 #print payload_req
364
tiernof1ba57e2017-09-07 12:23:19 +0200365 URLrequest = "http://{}:{}/openmano{}/{}/{token}".format(mano_host, mano_port, api_version, tenant, token=token)
tierno7edb6752016-03-21 17:37:52 +0100366 logger.debug("openmano request: %s", payload_req)
367 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
368 logger.debug("openmano response: %s", mano_response.text )
369
370 return _print_verbose(mano_response, args.verbose)
371
372def vnf_list(args):
373 #print "vnf-list",args
374 if args.all:
375 tenant = "any"
376 else:
377 tenant = _get_tenant()
378 if args.name:
379 toshow = _get_item_uuid("vnfs", args.name, tenant)
380 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
381 else:
382 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
383 mano_response = requests.get(URLrequest)
384 logger.debug("openmano response: %s", mano_response.text )
385 content = mano_response.json()
tiernof1ba57e2017-09-07 12:23:19 +0200386 # print json.dumps(content, indent=4)
tierno7edb6752016-03-21 17:37:52 +0100387 if args.verbose==None:
388 args.verbose=0
389 result = 0 if mano_response.status_code==200 else mano_response.status_code
390 if mano_response.status_code == 200:
391 if not args.name:
392 if args.verbose >= 3:
393 print yaml.safe_dump(content, indent=4, default_flow_style=False)
394 return result
395 if len(content['vnfs']) == 0:
396 print "No VNFs were found."
tiernof1ba57e2017-09-07 12:23:19 +0200397 return 404 # HTTP_Not_Found
tierno7edb6752016-03-21 17:37:52 +0100398 for vnf in content['vnfs']:
tiernof1ba57e2017-09-07 12:23:19 +0200399 myoutput = "{:38} {:20}".format(vnf['uuid'], vnf['name'])
400 if vnf.get('osm_id') or args.verbose >= 1:
401 myoutput += " osm_id={:20}".format(vnf.get('osm_id'))
402 if args.verbose >= 1:
403 myoutput += " {}".format(vnf['created_at'])
404 print (myoutput)
405 if args.verbose >= 2:
406 print (" Description: {}".format(vnf['description']))
407 # print (" VNF descriptor file: {}".format(vnf['path']))
tierno7edb6752016-03-21 17:37:52 +0100408 else:
409 if args.verbose:
410 print yaml.safe_dump(content, indent=4, default_flow_style=False)
411 return result
412 vnf = content['vnf']
tiernof1ba57e2017-09-07 12:23:19 +0200413 print ("{:38} {:20} osm_id={:20} {:20}".format(vnf['uuid'], vnf['name'], vnf.get('osm_id'),
414 vnf['created_at']))
415 print (" Description: {}".format(vnf['description']))
416 # print " VNF descriptor file: %s" %vnf['path']
417 print (" VMs:")
tierno7edb6752016-03-21 17:37:52 +0100418 for vm in vnf['VNFC']:
tiernof1ba57e2017-09-07 12:23:19 +0200419 print (" {:20} osm_id={:20} {}".format(vm['name'], vm.get('osm_id'), vm['description']))
420 if len(vnf['nets']) > 0:
421 print (" Internal nets:")
tierno7edb6752016-03-21 17:37:52 +0100422 for net in vnf['nets']:
tiernof1ba57e2017-09-07 12:23:19 +0200423 print (" {:20} {}".format(net['name'], net['description']))
424 if len(vnf['external-connections']) > 0:
425 print (" External interfaces:")
tierno7edb6752016-03-21 17:37:52 +0100426 for interface in vnf['external-connections']:
tiernof1ba57e2017-09-07 12:23:19 +0200427 print (" {:20} {:20} {:20} {:14}".format(
428 interface['external_name'], interface['vm_name'],
429 interface['internal_name'],
430 interface.get('vpci') if interface.get('vpci') else ""))
tierno7edb6752016-03-21 17:37:52 +0100431 else:
432 print content['error']['description']
433 if args.verbose:
434 print yaml.safe_dump(content, indent=4, default_flow_style=False)
435 return result
436
437def vnf_delete(args):
438 #print "vnf-delete",args
439 if args.all:
440 tenant = "any"
441 else:
442 tenant = _get_tenant()
443 todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
444 if not args.force:
445 r = raw_input("Delete VNF %s (y/N)? " %(todelete))
446 if not (len(r)>0 and r[0].lower()=="y"):
447 return 0
448 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
449 mano_response = requests.delete(URLrequest)
450 logger.debug("openmano response: %s", mano_response.text )
451 result = 0 if mano_response.status_code==200 else mano_response.status_code
452 content = mano_response.json()
453 #print json.dumps(content, indent=4)
454 if mano_response.status_code == 200:
455 print content['result']
456 else:
457 print content['error']['description']
458 return result
459
460def scenario_create(args):
tiernof1ba57e2017-09-07 12:23:19 +0200461 # print "scenario-create",args
tierno7edb6752016-03-21 17:37:52 +0100462 tenant = _get_tenant()
463 headers_req = {'content-type': 'application/yaml'}
464 myscenario = _load_file_or_yaml(args.file)
tiernof1ba57e2017-09-07 12:23:19 +0200465 if "nsd:nsd-catalog" in myscenario or "nsd-catalog" in myscenario:
466 api_version = "/v3"
467 token = "nsd"
468 nsd_catalog = myscenario.get("nsd:nsd-catalog")
469 if not nsd_catalog:
470 nsd_catalog = myscenario.get("nsd-catalog")
471 nsds = nsd_catalog.get("nsd:nsd")
472 if not nsds:
473 nsds = nsd_catalog.get("nsd")
474 nsd = nsds[0]
475 else: # API<v3
476 api_version = ""
477 token = "scenarios"
478 if "scenario" in myscenario:
479 nsd = myscenario["scenario"]
480 else:
481 nsd = myscenario
482 # TODO modify for API v3
tierno7edb6752016-03-21 17:37:52 +0100483 if args.name:
tiernof1ba57e2017-09-07 12:23:19 +0200484 nsd['name'] = args.name
tierno7edb6752016-03-21 17:37:52 +0100485 if args.description:
tiernof1ba57e2017-09-07 12:23:19 +0200486 nsd['description'] = args.description
487 payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False,
488 encoding='utf-8', allow_unicode=True)
tierno7edb6752016-03-21 17:37:52 +0100489
tiernof1ba57e2017-09-07 12:23:19 +0200490 # print payload_req
491 URLrequest = "http://{host}:{port}/openmano{api}/{tenant}/{token}".format(
492 host=mano_host, port=mano_port, api=api_version, tenant=tenant, token=token)
tierno7edb6752016-03-21 17:37:52 +0100493 logger.debug("openmano request: %s", payload_req)
494 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
495 logger.debug("openmano response: %s", mano_response.text )
496 return _print_verbose(mano_response, args.verbose)
497
498def scenario_list(args):
499 #print "scenario-list",args
500 if args.all:
501 tenant = "any"
502 else:
503 tenant = _get_tenant()
504 if args.name:
505 toshow = _get_item_uuid("scenarios", args.name, tenant)
506 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
507 else:
508 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
509 mano_response = requests.get(URLrequest)
510 logger.debug("openmano response: %s", mano_response.text )
511 content = mano_response.json()
512 #print json.dumps(content, indent=4)
513 if args.verbose==None:
514 args.verbose=0
515
516 result = 0 if mano_response.status_code==200 else mano_response.status_code
517 if mano_response.status_code == 200:
518 if not args.name:
519 if args.verbose >= 3:
520 print yaml.safe_dump(content, indent=4, default_flow_style=False)
521 return result
522 if len(content['scenarios']) == 0:
523 print "No scenarios were found."
524 return 404 #HTTP_Not_Found
525 for scenario in content['scenarios']:
tiernof1ba57e2017-09-07 12:23:19 +0200526 myoutput = "{:38} {:20}".format(scenario['uuid'], scenario['name'])
527 if scenario.get('osm_id') or args.verbose >= 1:
528 myoutput += " osm_id={:20}".format(scenario.get('osm_id'))
529 if args.verbose >= 1:
530 myoutput += " {}".format(scenario['created_at'])
531 print (myoutput)
tierno7edb6752016-03-21 17:37:52 +0100532 if args.verbose >=2:
tiernof1ba57e2017-09-07 12:23:19 +0200533 print (" Description: {}".format(scenario['description']))
tierno7edb6752016-03-21 17:37:52 +0100534 else:
535 if args.verbose:
536 print yaml.safe_dump(content, indent=4, default_flow_style=False)
537 return result
538 scenario = content['scenario']
tiernof1ba57e2017-09-07 12:23:19 +0200539 print ("{:38} {:20} osm_id={:20} {:20}".format(scenario['uuid'], scenario['name'], scenario.get('osm_id'),
540 scenario['created_at']))
541 print (" Description: {}".format(scenario['description']))
542 print (" VNFs:")
tierno7edb6752016-03-21 17:37:52 +0100543 for vnf in scenario['vnfs']:
tiernof1ba57e2017-09-07 12:23:19 +0200544 print (" {:38} {:20} vnf_index={} {}".format(vnf['vnf_id'], vnf['name'], vnf.get("member_vnf_index"),
545 vnf['description']))
546 if len(scenario['nets']) > 0:
547 print (" nets:")
tierno7edb6752016-03-21 17:37:52 +0100548 for net in scenario['nets']:
tiernof1ba57e2017-09-07 12:23:19 +0200549 description = net['description']
550 if not description: # if description does not exist, description is "-". Valid for external and internal nets.
551 description = '-'
552 vim_id = ""
553 if net.get('vim_id'):
554 vim_id = " vim_id=" + net["vim_id"]
555 external = ""
556 if net["external"]:
557 external = " external"
558 print (" {:20} {:38} {:30}{}{}".format(net['name'], net['uuid'], description, vim_id, external))
tierno7edb6752016-03-21 17:37:52 +0100559 else:
tiernof1ba57e2017-09-07 12:23:19 +0200560 print (content['error']['description'])
tierno7edb6752016-03-21 17:37:52 +0100561 if args.verbose:
562 print yaml.safe_dump(content, indent=4, default_flow_style=False)
563 return result
564
565def scenario_delete(args):
566 #print "scenario-delete",args
567 if args.all:
568 tenant = "any"
569 else:
570 tenant = _get_tenant()
571 todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
572 if not args.force:
573 r = raw_input("Delete scenario %s (y/N)? " %(args.name))
574 if not (len(r)>0 and r[0].lower()=="y"):
575 return 0
576 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
577 mano_response = requests.delete(URLrequest)
578 logger.debug("openmano response: %s", mano_response.text )
579 result = 0 if mano_response.status_code==200 else mano_response.status_code
580 content = mano_response.json()
581 #print json.dumps(content, indent=4)
582 if mano_response.status_code == 200:
583 print content['result']
584 else:
585 print content['error']['description']
586 return result
587
588def scenario_deploy(args):
589 print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
590 print
591 args.file = None
592 args.netmap_use = None
593 args.netmap_create = None
tiernobe41e222016-09-02 15:16:13 +0200594 args.keypair = None
595 args.keypair_auto = None
tierno7edb6752016-03-21 17:37:52 +0100596 return instance_create(args)
597
598# #print "scenario-deploy",args
599# headers_req = {'content-type': 'application/json'}
600# action = {}
601# actionCmd="start"
602# if args.nostart:
603# actionCmd="reserve"
604# action[actionCmd] = {}
605# action[actionCmd]["instance_name"] = args.name
606# if args.datacenter != None:
607# action[actionCmd]["datacenter"] = args.datacenter
608# elif mano_datacenter != None:
609# action[actionCmd]["datacenter"] = mano_datacenter
610#
611# if args.description:
612# action[actionCmd]["description"] = args.description
613# payload_req = json.dumps(action, indent=4)
614# #print payload_req
615#
616# URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
617# logger.debug("openmano request: %s", payload_req)
618# mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
619# logger.debug("openmano response: %s", mano_response.text )
620# if args.verbose==None:
621# args.verbose=0
622#
623# result = 0 if mano_response.status_code==200 else mano_response.status_code
624# content = mano_response.json()
625# #print json.dumps(content, indent=4)
626# if args.verbose >= 3:
627# print yaml.safe_dump(content, indent=4, default_flow_style=False)
628# return result
629#
630# if mano_response.status_code == 200:
631# myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
632# if args.verbose >=1:
633# myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
634# if args.verbose >=2:
635# myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
636# print myoutput
637# print ""
638# print "To check the status, run the following command:"
639# print "openmano instance-scenario-list <instance_id>"
640# else:
641# print content['error']['description']
642# return result
643
644def scenario_verify(args):
645 #print "scenario-verify",args
tierno72a08d72017-05-25 13:12:30 +0200646 tenant = _get_tenant()
tierno7edb6752016-03-21 17:37:52 +0100647 headers_req = {'content-type': 'application/json'}
648 action = {}
649 action["verify"] = {}
650 action["verify"]["instance_name"] = "scen-verify-return5"
651 payload_req = json.dumps(action, indent=4)
652 #print payload_req
653
tierno72a08d72017-05-25 13:12:30 +0200654 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, tenant, args.scenario)
tierno7edb6752016-03-21 17:37:52 +0100655 logger.debug("openmano request: %s", payload_req)
656 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
657 logger.debug("openmano response: %s", mano_response.text )
658
659 result = 0 if mano_response.status_code==200 else mano_response.status_code
660 content = mano_response.json()
661 #print json.dumps(content, indent=4)
662 if mano_response.status_code == 200:
663 print content['result']
664 else:
665 print content['error']['description']
666 return result
667
668def instance_create(args):
669 tenant = _get_tenant()
670 headers_req = {'content-type': 'application/yaml'}
671 myInstance={"instance": {}, "schema_version": "0.1"}
672 if args.file:
673 instance_dict = _load_file_or_yaml(args.file)
674 if "instance" not in instance_dict:
675 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
676 else:
677 myInstance = instance_dict
678 if args.name:
679 myInstance["instance"]['name'] = args.name
680 if args.description:
681 myInstance["instance"]['description'] = args.description
682 if args.nostart:
683 myInstance["instance"]['action'] = "reserve"
684 #datacenter
685 datacenter = myInstance["instance"].get("datacenter")
686 if args.datacenter != None:
687 datacenter = args.datacenter
688 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
689 #scenario
690 scenario = myInstance["instance"].get("scenario")
691 if args.scenario != None:
692 scenario = args.scenario
693 if not scenario:
garciadeblased746032017-01-05 11:58:41 +0100694 print "you must provide a scenario in the file descriptor or with --scenario"
tierno7edb6752016-03-21 17:37:52 +0100695 return -1
696 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
697 if args.netmap_use:
698 if "networks" not in myInstance["instance"]:
699 myInstance["instance"]["networks"] = {}
700 for net in args.netmap_use:
701 net_comma_list = net.split(",")
702 for net_comma in net_comma_list:
703 net_tuple = net_comma.split("=")
704 if len(net_tuple) != 2:
705 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
706 return
707 net_scenario = net_tuple[0].strip()
708 net_datacenter = net_tuple[1].strip()
709 if net_scenario not in myInstance["instance"]["networks"]:
710 myInstance["instance"]["networks"][net_scenario] = {}
tiernobe41e222016-09-02 15:16:13 +0200711 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
712 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
713 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
tierno7edb6752016-03-21 17:37:52 +0100714 if args.netmap_create:
715 if "networks" not in myInstance["instance"]:
716 myInstance["instance"]["networks"] = {}
717 for net in args.netmap_create:
718 net_comma_list = net.split(",")
719 for net_comma in net_comma_list:
720 net_tuple = net_comma.split("=")
721 if len(net_tuple) == 1:
722 net_scenario = net_tuple[0].strip()
723 net_datacenter = None
724 elif len(net_tuple) == 2:
725 net_scenario = net_tuple[0].strip()
726 net_datacenter = net_tuple[1].strip()
727 else:
728 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
729 return
730 if net_scenario not in myInstance["instance"]["networks"]:
731 myInstance["instance"]["networks"][net_scenario] = {}
tiernobe41e222016-09-02 15:16:13 +0200732 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
733 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
734 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
tiernoa4e1a6e2016-08-31 14:19:40 +0200735 if args.keypair:
736 if "cloud-config" not in myInstance["instance"]:
737 myInstance["instance"]["cloud-config"] = {}
738 cloud_config = myInstance["instance"]["cloud-config"]
739 for key in args.keypair:
740 index = key.find(":")
741 if index<0:
742 if "key-pairs" not in cloud_config:
743 cloud_config["key-pairs"] = []
744 cloud_config["key-pairs"].append(key)
745 else:
746 user = key[:index]
747 key_ = key[index+1:]
748 key_list = key_.split(",")
749 if "users" not in cloud_config:
750 cloud_config["users"] = []
751 cloud_config["users"].append({"name": user, "key-pairs": key_list })
752 if args.keypair_auto:
753 try:
754 keys=[]
755 home = os.getenv("HOME")
756 user = os.getenv("USER")
757 files = os.listdir(home+'/.ssh')
758 for file in files:
759 if file[-4:] == ".pub":
760 with open(home+'/.ssh/'+file, 'r') as f:
761 keys.append(f.read())
762 if not keys:
763 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
764 return 1
765 except Exception as e:
766 print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
767 return 1
768
769 if "cloud-config" not in myInstance["instance"]:
770 myInstance["instance"]["cloud-config"] = {}
771 cloud_config = myInstance["instance"]["cloud-config"]
772 if "key-pairs" not in cloud_config:
773 cloud_config["key-pairs"] = []
774 if user:
775 if "users" not in cloud_config:
776 cloud_config["users"] = []
777 cloud_config["users"].append({"name": user, "key-pairs": keys })
tierno7edb6752016-03-21 17:37:52 +0100778
779 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
780 logger.debug("openmano request: %s", payload_req)
781 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
782 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
783 logger.debug("openmano response: %s", mano_response.text )
784 if args.verbose==None:
785 args.verbose=0
786
787 result = 0 if mano_response.status_code==200 else mano_response.status_code
788 content = mano_response.json()
789 #print json.dumps(content, indent=4)
790 if args.verbose >= 3:
791 print yaml.safe_dump(content, indent=4, default_flow_style=False)
792 return result
793
794 if mano_response.status_code == 200:
tiernoa15c4b92017-10-05 12:41:44 +0200795 myoutput = "{:38} {:20}".format(content['uuid'], content['name'])
tierno7edb6752016-03-21 17:37:52 +0100796 if args.verbose >=1:
tiernoa15c4b92017-10-05 12:41:44 +0200797 myoutput = "{} {:20}".format(myoutput, content['created_at'])
tierno7edb6752016-03-21 17:37:52 +0100798 if args.verbose >=2:
tiernoa15c4b92017-10-05 12:41:44 +0200799 myoutput = "{} {:30}".format(myoutput, content['description'])
tierno7edb6752016-03-21 17:37:52 +0100800 print myoutput
801 else:
802 print content['error']['description']
803 return result
804
805def instance_scenario_list(args):
806 #print "instance-scenario-list",args
807 if args.all:
808 tenant = "any"
809 else:
810 tenant = _get_tenant()
811 if args.name:
812 toshow = _get_item_uuid("instances", args.name, tenant)
813 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
814 else:
815 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
816 mano_response = requests.get(URLrequest)
817 logger.debug("openmano response: %s", mano_response.text )
818 content = mano_response.json()
819 #print json.dumps(content, indent=4)
820 if args.verbose==None:
821 args.verbose=0
822
823 result = 0 if mano_response.status_code==200 else mano_response.status_code
824 if mano_response.status_code == 200:
825 if not args.name:
826 if args.verbose >= 3:
827 print yaml.safe_dump(content, indent=4, default_flow_style=False)
828 return result
829 if len(content['instances']) == 0:
830 print "No scenario instances were found."
831 return result
832 for instance in content['instances']:
tiernoa15c4b92017-10-05 12:41:44 +0200833 myoutput = "{:38} {:20}".format(instance['uuid'], instance['name'])
tierno7edb6752016-03-21 17:37:52 +0100834 if args.verbose >=1:
tiernoa15c4b92017-10-05 12:41:44 +0200835 myoutput = "{} {:20}".format(myoutput, instance['created_at'])
tierno7edb6752016-03-21 17:37:52 +0100836 print myoutput
837 if args.verbose >=2:
838 print "Description: %s" %instance['description']
839 else:
840 if args.verbose:
841 print yaml.safe_dump(content, indent=4, default_flow_style=False)
842 return result
843 instance = content
tiernoa15c4b92017-10-05 12:41:44 +0200844 print ("{:38} {:20} {:20}".format(instance['uuid'],instance['name'],instance['created_at']))
845 print ("Description: %s" %instance['description'])
846 print ("Template scenario id: {}".format(instance['scenario_id']))
847 print ("Template scenario name: {}".format(instance['scenario_name']))
848 print ("---------------------------------------")
849 print ("VNF instances: {}".format(len(instance['vnfs'])))
tierno7edb6752016-03-21 17:37:52 +0100850 for vnf in instance['vnfs']:
851 #print " %s %s Template vnf name: %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['name'].ljust(20), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
tiernoa15c4b92017-10-05 12:41:44 +0200852 print (" {:38} {:20} Template vnf id: {:38}".format(vnf['uuid'], vnf['vnf_name'], vnf['vnf_id']))
tierno7edb6752016-03-21 17:37:52 +0100853 if len(instance['nets'])>0:
854 print "---------------------------------------"
855 print "Internal nets:"
856 for net in instance['nets']:
tierno5c7c4732016-09-26 13:38:55 +0000857 if net['created']:
tiernoa15c4b92017-10-05 12:41:44 +0200858 print (" {:38} {:12} VIM ID: {}".format(net['uuid'], net['status'], net['vim_net_id']))
tierno7edb6752016-03-21 17:37:52 +0100859 print "---------------------------------------"
860 print "External nets:"
861 for net in instance['nets']:
tierno5c7c4732016-09-26 13:38:55 +0000862 if not net['created']:
tiernoa15c4b92017-10-05 12:41:44 +0200863 print (" {:38} {:12} VIM ID: {}".format(net['uuid'], net['status'], net['vim_net_id']))
864 print ("---------------------------------------")
865 print ("VM instances:")
tierno7edb6752016-03-21 17:37:52 +0100866 for vnf in instance['vnfs']:
867 for vm in vnf['vms']:
tiernoa15c4b92017-10-05 12:41:44 +0200868 print (" {:38} {:20} {:20} {:12} VIM ID: {}".format(vm['uuid'], vnf['vnf_name'], vm['name'],
869 vm['status'], vm['vim_vm_id']))
tierno7edb6752016-03-21 17:37:52 +0100870 else:
871 print content['error']['description']
872 if args.verbose:
873 print yaml.safe_dump(content, indent=4, default_flow_style=False)
874 return result
875
876def instance_scenario_status(args):
877 print "instance-scenario-status"
878 return 0
879
880def instance_scenario_delete(args):
881 if args.all:
882 tenant = "any"
883 else:
884 tenant = _get_tenant()
885 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
886 #print "instance-scenario-delete",args
887 if not args.force:
888 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
889 if not (len(r)>0 and r[0].lower()=="y"):
890 return
891 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
892 mano_response = requests.delete(URLrequest)
893 logger.debug("openmano response: %s", mano_response.text )
894 result = 0 if mano_response.status_code==200 else mano_response.status_code
895 content = mano_response.json()
896 #print json.dumps(content, indent=4)
897 if mano_response.status_code == 200:
898 print content['result']
899 else:
900 print content['error']['description']
901 return result
902
tierno868220c2017-09-26 00:11:05 +0200903def get_action(args):
904 if not args.all:
905 tenant = _get_tenant()
906 else:
907 tenant = "any"
908 if not args.instance:
909 instance_id = "any"
910 else:
911 instance_id =args.instance
912 action_id = ""
913 if args.id:
914 action_id = "/" + args.id
915 URLrequest = "http://{}:{}/openmano/{}/instances/{}/action{}".format(mano_host, mano_port, tenant, instance_id,
916 action_id)
917 mano_response = requests.get(URLrequest)
918 logger.debug("openmano response: %s", mano_response.text )
919 if args.verbose == None:
920 args.verbose = 0
921 if args.id != None:
922 args.verbose += 1
923 return _print_verbose(mano_response, args.verbose)
924
tierno7edb6752016-03-21 17:37:52 +0100925def instance_scenario_action(args):
926 #print "instance-scenario-action", args
927 tenant = _get_tenant()
928 toact = _get_item_uuid("instances", args.name, tenant=tenant)
929 action={}
tiernofc5f80b2018-05-29 16:00:43 +0200930 action[ args.action ] = yaml.safe_load(args.param)
tierno7edb6752016-03-21 17:37:52 +0100931 if args.vnf:
932 action["vnfs"] = args.vnf
933 if args.vm:
934 action["vms"] = args.vm
935
936 headers_req = {'content-type': 'application/json'}
937 payload_req = json.dumps(action, indent=4)
938 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
939 logger.debug("openmano request: %s", payload_req)
940 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
941 logger.debug("openmano response: %s", mano_response.text )
942 result = 0 if mano_response.status_code==200 else mano_response.status_code
943 content = mano_response.json()
tiernofc5f80b2018-05-29 16:00:43 +0200944 # print json.dumps(content, indent=4)
tierno7edb6752016-03-21 17:37:52 +0100945 if mano_response.status_code == 200:
946 if args.verbose:
947 print yaml.safe_dump(content, indent=4, default_flow_style=False)
948 return result
tiernofc5f80b2018-05-29 16:00:43 +0200949 if "instance_action_id" in content:
950 print("instance_action_id={}".format(content["instance_action_id"]))
951 else:
952 for uuid,c in content.iteritems():
953 print ("{:38} {:20} {:20}".format(uuid, c.get('name'), c.get('description')))
tierno7edb6752016-03-21 17:37:52 +0100954 else:
955 print content['error']['description']
956 return result
957
958
959def instance_vnf_list(args):
960 print "instance-vnf-list"
961 return 0
962
963def instance_vnf_status(args):
964 print "instance-vnf-status"
965 return 0
966
967def tenant_create(args):
968 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
969 tenant_dict={"name": args.name}
970 if args.description!=None:
971 tenant_dict["description"] = args.description
972 payload_req = json.dumps( {"tenant": tenant_dict })
973
974 #print payload_req
975
976 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
977 logger.debug("openmano request: %s", payload_req)
978 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
979 logger.debug("openmano response: %s", mano_response.text )
980 return _print_verbose(mano_response, args.verbose)
981
982def tenant_list(args):
983 #print "tenant-list",args
984 if args.name:
tierno392f2852016-05-13 12:28:55 +0200985 toshow = _get_item_uuid("tenants", args.name)
tierno7edb6752016-03-21 17:37:52 +0100986 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
987 else:
988 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
989 mano_response = requests.get(URLrequest)
990 logger.debug("openmano response: %s", mano_response.text )
991 if args.verbose==None:
992 args.verbose=0
993 if args.name!=None:
994 args.verbose += 1
995 return _print_verbose(mano_response, args.verbose)
996
997def tenant_delete(args):
998 #print "tenant-delete",args
999 todelete = _get_item_uuid("tenants", args.name)
1000 if not args.force:
1001 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
1002 if not (len(r)>0 and r[0].lower()=="y"):
1003 return 0
1004 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
1005 mano_response = requests.delete(URLrequest)
1006 logger.debug("openmano response: %s", mano_response.text )
1007 result = 0 if mano_response.status_code==200 else mano_response.status_code
1008 content = mano_response.json()
1009 #print json.dumps(content, indent=4)
1010 if mano_response.status_code == 200:
1011 print content['result']
1012 else:
1013 print content['error']['description']
1014 return result
1015
1016def datacenter_attach(args):
1017 tenant = _get_tenant()
1018 datacenter = _get_datacenter(args.name)
1019 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1020
1021 datacenter_dict={}
1022 if args.vim_tenant_id != None:
1023 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1024 if args.vim_tenant_name != None:
1025 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1026 if args.user != None:
1027 datacenter_dict['vim_username'] = args.user
1028 if args.password != None:
1029 datacenter_dict['vim_password'] = args.password
tierno8008c3a2016-10-13 15:34:28 +00001030 if args.config!=None:
1031 datacenter_dict["config"] = _load_file_or_yaml(args.config)
gcalvinoc62cfa52017-10-05 18:21:25 +02001032
tierno7edb6752016-03-21 17:37:52 +01001033 payload_req = json.dumps( {"datacenter": datacenter_dict })
gcalvinoc62cfa52017-10-05 18:21:25 +02001034
tierno7edb6752016-03-21 17:37:52 +01001035 #print payload_req
1036
1037 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1038 logger.debug("openmano request: %s", payload_req)
1039 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1040 logger.debug("openmano response: %s", mano_response.text )
1041 result = _print_verbose(mano_response, args.verbose)
1042 #provide addional information if error
1043 if mano_response.status_code != 200:
1044 content = mano_response.json()
1045 if "already in use for 'name'" in content['error']['description'] and \
1046 "to database vim_tenants table" in content['error']['description']:
1047 print "Try to specify a different name with --vim-tenant-name"
1048 return result
1049
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001050
1051def datacenter_edit_vim_tenant(args):
1052 tenant = _get_tenant()
1053 datacenter = _get_datacenter(args.name)
1054 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1055
1056 if not (args.vim_tenant_id or args.vim_tenant_name or args.user or args.password or args.config):
1057 raise OpenmanoCLIError("Error. At least one parameter must be updated.")
1058
1059 datacenter_dict = {}
1060 if args.vim_tenant_id != None:
1061 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1062 if args.vim_tenant_name != None:
1063 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1064 if args.user != None:
1065 datacenter_dict['vim_username'] = args.user
1066 if args.password != None:
1067 datacenter_dict['vim_password'] = args.password
1068 if args.config != None:
1069 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1070 payload_req = json.dumps({"datacenter": datacenter_dict})
1071
1072 # print payload_req
1073
1074 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" % (mano_host, mano_port, tenant, datacenter)
1075 logger.debug("openmano request: %s", payload_req)
1076 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1077 logger.debug("openmano response: %s", mano_response.text)
1078 result = _print_verbose(mano_response, args.verbose)
1079
1080 return result
1081
tierno7edb6752016-03-21 17:37:52 +01001082def datacenter_detach(args):
1083 if args.all:
1084 tenant = "any"
1085 else:
1086 tenant = _get_tenant()
1087 datacenter = _get_datacenter(args.name, tenant)
1088 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1089 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1090 mano_response = requests.delete(URLrequest, headers=headers_req)
1091 logger.debug("openmano response: %s", mano_response.text )
1092 content = mano_response.json()
1093 #print json.dumps(content, indent=4)
1094 result = 0 if mano_response.status_code==200 else mano_response.status_code
1095 if mano_response.status_code == 200:
1096 print content['result']
1097 else:
1098 print content['error']['description']
1099 return result
1100
1101def datacenter_create(args):
1102 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1103 datacenter_dict={"name": args.name, "vim_url": args.url}
1104 if args.description!=None:
1105 datacenter_dict["description"] = args.description
1106 if args.type!=None:
1107 datacenter_dict["type"] = args.type
1108 if args.url!=None:
1109 datacenter_dict["vim_url_admin"] = args.url_admin
1110 if args.config!=None:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001111 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1112 if args.sdn_controller!=None:
1113 tenant = _get_tenant()
1114 sdn_controller = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1115 if not 'config' in datacenter_dict:
1116 datacenter_dict['config'] = {}
1117 datacenter_dict['config']['sdn-controller'] = sdn_controller
tierno7edb6752016-03-21 17:37:52 +01001118 payload_req = json.dumps( {"datacenter": datacenter_dict })
1119
1120 #print payload_req
1121
1122 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
1123 logger.debug("openmano request: %s", payload_req)
1124 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1125 logger.debug("openmano response: %s", mano_response.text )
1126 return _print_verbose(mano_response, args.verbose)
1127
1128def datacenter_delete(args):
1129 #print "datacenter-delete",args
1130 todelete = _get_item_uuid("datacenters", args.name, "any")
1131 if not args.force:
1132 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
1133 if not (len(r)>0 and r[0].lower()=="y"):
1134 return 0
1135 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
1136 mano_response = requests.delete(URLrequest)
1137 logger.debug("openmano response: %s", mano_response.text )
1138 result = 0 if mano_response.status_code==200 else mano_response.status_code
1139 content = mano_response.json()
1140 #print json.dumps(content, indent=4)
1141 if mano_response.status_code == 200:
1142 print content['result']
1143 else:
1144 print content['error']['description']
1145 return result
1146
tierno20df3bb2017-07-07 14:31:00 +02001147
tierno7edb6752016-03-21 17:37:52 +01001148def datacenter_list(args):
1149 #print "datacenter-list",args
1150 tenant='any' if args.all else _get_tenant()
1151
1152 if args.name:
1153 toshow = _get_item_uuid("datacenters", args.name, tenant)
1154 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
1155 else:
1156 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
1157 mano_response = requests.get(URLrequest)
1158 logger.debug("openmano response: %s", mano_response.text )
1159 if args.verbose==None:
1160 args.verbose=0
1161 if args.name!=None:
1162 args.verbose += 1
1163 return _print_verbose(mano_response, args.verbose)
1164
tierno20df3bb2017-07-07 14:31:00 +02001165
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001166def datacenter_sdn_port_mapping_set(args):
1167 tenant = _get_tenant()
1168 datacenter = _get_datacenter(args.name, tenant)
1169 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1170
1171 if not args.file:
1172 raise OpenmanoCLIError(
1173 "No yaml/json has been provided specifying the SDN port mapping")
tierno20df3bb2017-07-07 14:31:00 +02001174 sdn_port_mapping = _load_file_or_yaml(args.file)
1175 payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping})
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001176
tierno20df3bb2017-07-07 14:31:00 +02001177 # read
1178 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1179 mano_response = requests.get(URLrequest)
1180 logger.debug("openmano response: %s", mano_response.text)
1181 port_mapping = mano_response.json()
1182 if mano_response.status_code != 200:
1183 str(mano_response.json())
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001184 raise OpenmanoCLIError("openmano client error: {}".format(port_mapping['error']['description']))
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001185 if len(port_mapping["sdn_port_mapping"]["ports_mapping"]) > 0:
1186 if not args.force:
1187 r = raw_input("Datacenter %s already contains a port mapping. Overwrite? (y/N)? " % (datacenter))
1188 if not (len(r) > 0 and r[0].lower() == "y"):
1189 return 0
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001190
tierno20df3bb2017-07-07 14:31:00 +02001191 # clear
1192 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1193 mano_response = requests.delete(URLrequest)
1194 logger.debug("openmano response: %s", mano_response.text)
1195 if mano_response.status_code != 200:
1196 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001197
tierno20df3bb2017-07-07 14:31:00 +02001198 # set
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001199 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1200 logger.debug("openmano request: %s", payload_req)
1201 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1202 logger.debug("openmano response: %s", mano_response.text)
tierno20df3bb2017-07-07 14:31:00 +02001203 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001204
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001205
1206def datacenter_sdn_port_mapping_list(args):
1207 tenant = _get_tenant()
1208 datacenter = _get_datacenter(args.name, tenant)
1209
1210 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1211 mano_response = requests.get(URLrequest)
1212 logger.debug("openmano response: %s", mano_response.text)
1213
tierno20df3bb2017-07-07 14:31:00 +02001214 return _print_verbose(mano_response, 4)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001215
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001216
1217def datacenter_sdn_port_mapping_clear(args):
1218 tenant = _get_tenant()
1219 datacenter = _get_datacenter(args.name, tenant)
1220
1221 if not args.force:
1222 r = raw_input("Clean SDN port mapping for datacenter %s (y/N)? " %(datacenter))
tierno20df3bb2017-07-07 14:31:00 +02001223 if not (len(r) > 0 and r[0].lower() == "y"):
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001224 return 0
1225
1226 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1227 mano_response = requests.delete(URLrequest)
1228 logger.debug("openmano response: %s", mano_response.text)
1229
tierno20df3bb2017-07-07 14:31:00 +02001230 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001231
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001232
1233def sdn_controller_create(args):
1234 tenant = _get_tenant()
1235 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1236
tierno8fe7a492017-07-11 13:50:04 +02001237 error_msg=[]
1238 if not args.ip: error_msg.append("'ip'")
1239 if not args.port: error_msg.append("'port'")
1240 if not args.dpid: error_msg.append("'dpid'")
1241 if not args.type: error_msg.append("'type'")
1242 if error_msg:
1243 raise OpenmanoCLIError("The following arguments are required: " + ",".join(error_msg))
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001244
1245 controller_dict = {}
1246 controller_dict['name'] = args.name
1247 controller_dict['ip'] = args.ip
1248 controller_dict['port'] = int(args.port)
1249 controller_dict['dpid'] = args.dpid
1250 controller_dict['type'] = args.type
1251 if args.description != None:
1252 controller_dict['description'] = args.description
1253 if args.user != None:
1254 controller_dict['user'] = args.user
1255 if args.password != None:
1256 controller_dict['password'] = args.password
1257
1258 payload_req = json.dumps({"sdn_controller": controller_dict})
1259
1260 # print payload_req
1261
1262 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" % (mano_host, mano_port, tenant)
1263 logger.debug("openmano request: %s", payload_req)
1264 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1265 logger.debug("openmano response: %s", mano_response.text)
1266 result = _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001267 return result
1268
tierno20df3bb2017-07-07 14:31:00 +02001269
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001270def sdn_controller_edit(args):
1271 tenant = _get_tenant()
1272 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1273 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1274
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001275 controller_dict = {}
tierno20df3bb2017-07-07 14:31:00 +02001276 if args.new_name:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001277 controller_dict['name'] = args.new_name
tierno20df3bb2017-07-07 14:31:00 +02001278 if args.ip:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001279 controller_dict['ip'] = args.ip
tierno20df3bb2017-07-07 14:31:00 +02001280 if args.port:
Pablo Montes Morenob12711f2017-04-06 11:54:34 +02001281 controller_dict['port'] = int(args.port)
tierno20df3bb2017-07-07 14:31:00 +02001282 if args.dpid:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001283 controller_dict['dpid'] = args.dpid
tierno20df3bb2017-07-07 14:31:00 +02001284 if args.type:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001285 controller_dict['type'] = args.type
tierno20df3bb2017-07-07 14:31:00 +02001286 if args.description:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001287 controller_dict['description'] = args.description
tierno20df3bb2017-07-07 14:31:00 +02001288 if args.user:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001289 controller_dict['user'] = args.user
tierno20df3bb2017-07-07 14:31:00 +02001290 if args.password:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001291 controller_dict['password'] = args.password
1292
tierno20df3bb2017-07-07 14:31:00 +02001293 if not controller_dict:
1294 raise OpenmanoCLIError("At least one parameter must be edited")
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001295
tierno20df3bb2017-07-07 14:31:00 +02001296 if not args.force:
1297 r = raw_input("Update SDN controller {} (y/N)? ".format(args.name))
1298 if not (len(r) > 0 and r[0].lower() == "y"):
1299 return 0
1300
1301 payload_req = json.dumps({"sdn_controller": controller_dict})
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001302 # print payload_req
1303
1304 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1305 logger.debug("openmano request: %s", payload_req)
1306 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1307 logger.debug("openmano response: %s", mano_response.text)
1308 result = _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001309 return result
1310
tierno20df3bb2017-07-07 14:31:00 +02001311
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001312def sdn_controller_list(args):
1313 tenant = _get_tenant()
1314 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1315
1316 if args.name:
1317 toshow = _get_item_uuid("sdn_controllers", args.name, tenant)
1318 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" %(mano_host, mano_port, tenant, toshow)
1319 else:
1320 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" %(mano_host, mano_port, tenant)
1321 #print URLrequest
1322 mano_response = requests.get(URLrequest)
1323 logger.debug("openmano response: %s", mano_response.text )
1324 if args.verbose==None:
1325 args.verbose=0
1326 if args.name!=None:
1327 args.verbose += 1
1328
tierno20df3bb2017-07-07 14:31:00 +02001329 # json.dumps(mano_response.json(), indent=4)
1330 return _print_verbose(mano_response, args.verbose)
1331
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001332
1333def sdn_controller_delete(args):
1334 tenant = _get_tenant()
1335 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1336
1337 if not args.force:
1338 r = raw_input("Delete SDN controller %s (y/N)? " % (args.name))
1339 if not (len(r) > 0 and r[0].lower() == "y"):
1340 return 0
1341
1342 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1343 mano_response = requests.delete(URLrequest)
1344 logger.debug("openmano response: %s", mano_response.text)
tierno20df3bb2017-07-07 14:31:00 +02001345 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001346
tierno7edb6752016-03-21 17:37:52 +01001347def vim_action(args):
1348 #print "datacenter-net-action",args
1349 tenant = _get_tenant()
1350 datacenter = _get_datacenter(args.datacenter, tenant)
1351 if args.verbose==None:
1352 args.verbose=0
1353 if args.action=="list":
1354 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1355 if args.name!=None:
1356 args.verbose += 1
1357 URLrequest += "/" + args.name
1358 mano_response = requests.get(URLrequest)
1359 logger.debug("openmano response: %s", mano_response.text )
1360 return _print_verbose(mano_response, args.verbose)
1361 elif args.action=="delete":
1362 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1363 mano_response = requests.delete(URLrequest)
1364 logger.debug("openmano response: %s", mano_response.text )
1365 result = 0 if mano_response.status_code==200 else mano_response.status_code
1366 content = mano_response.json()
1367 #print json.dumps(content, indent=4)
1368 if mano_response.status_code == 200:
1369 print content['result']
1370 else:
1371 print content['error']['description']
1372 return result
1373 elif args.action=="create":
1374 headers_req = {'content-type': 'application/yaml'}
1375 if args.file:
1376 create_dict = _load_file_or_yaml(args.file)
1377 if args.item not in create_dict:
1378 create_dict = {args.item: create_dict}
1379 else:
1380 create_dict = {args.item:{}}
1381 if args.name:
1382 create_dict[args.item]['name'] = args.name
1383 #if args.description:
1384 # create_dict[args.item]['description'] = args.description
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001385 if args.item=="network":
tierno7edb6752016-03-21 17:37:52 +01001386 if args.bind_net:
1387 create_dict[args.item]['bind_net'] = args.bind_net
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001388 if args.type:
1389 create_dict[args.item]['type'] = args.type
tierno7edb6752016-03-21 17:37:52 +01001390 if args.shared:
1391 create_dict[args.item]['shared'] = args.shared
1392 if "name" not in create_dict[args.item]:
1393 print "You must provide a name in the descriptor file or with the --name option"
1394 return
1395 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1396 logger.debug("openmano request: %s", payload_req)
tierno72a08d72017-05-25 13:12:30 +02001397 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
tierno7edb6752016-03-21 17:37:52 +01001398 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1399 logger.debug("openmano response: %s", mano_response.text )
1400 if args.verbose==None:
1401 args.verbose=0
1402 return _print_verbose(mano_response, args.verbose)
1403
tierno20df3bb2017-07-07 14:31:00 +02001404
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001405def _get_items(item, item_name_id=None, datacenter=None, tenant=None):
1406 URLrequest = "http://%s:%s/openmano" %(mano_host, mano_port)
1407 if tenant:
1408 URLrequest += "/" + tenant
1409 if datacenter:
1410 URLrequest += "/vim/" + datacenter
1411 if item:
1412 URLrequest += "/" + item +"s"
1413 if item_name_id:
1414 URLrequest += "/" + item_name_id
1415 mano_response = requests.get(URLrequest)
1416 logger.debug("openmano response: %s", mano_response.text )
1417
1418 return mano_response
1419
tierno20df3bb2017-07-07 14:31:00 +02001420
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001421def vim_net_sdn_attach(args):
1422 #Verify the network exists in the vim
1423 tenant = _get_tenant()
1424 datacenter = _get_datacenter(args.datacenter, tenant)
1425 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1426 content = yaml.load(result.content)
1427 if 'networks' in content:
1428 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1429 if 'error' in content:
1430 raise OpenmanoCLIError(yaml.safe_dump(content))
1431 network_uuid = content['network']['id']
1432
1433 #Make call to attach the dataplane port to the SND network associated to the vim network
1434 headers_req = {'content-type': 'application/yaml'}
1435 payload_req = {'port': args.port}
1436 if args.vlan:
1437 payload_req['vlan'] = int(args.vlan)
1438 if args.mac:
1439 payload_req['mac'] = args.mac
1440
1441 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/attach" % (mano_host, mano_port, tenant, datacenter, network_uuid)
1442 logger.debug("openmano request: %s", payload_req)
1443 mano_response = requests.post(URLrequest, headers=headers_req, data=json.dumps(payload_req))
1444 logger.debug("openmano response: %s", mano_response.text)
1445 result = _print_verbose(mano_response, args.verbose)
tierno20df3bb2017-07-07 14:31:00 +02001446 return result
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001447
1448
1449def vim_net_sdn_detach(args):
1450 if not args.all and not args.id:
1451 print "--all or --id must be used"
1452 return 1
1453
1454 # Verify the network exists in the vim
1455 tenant = _get_tenant()
1456 datacenter = _get_datacenter(args.datacenter, tenant)
1457 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1458 content = yaml.load(result.content)
1459 if 'networks' in content:
1460 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1461 if 'error' in content:
1462 raise OpenmanoCLIError(yaml.safe_dump(content))
1463 network_uuid = content['network']['id']
1464
1465 if not args.force:
1466 r = raw_input("Confirm action' (y/N)? ")
1467 if len(r) == 0 or r[0].lower() != "y":
1468 return 0
1469
1470 if args.id:
1471 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach/%s" % (
1472 mano_host, mano_port, tenant, datacenter, network_uuid, args.id)
1473 else:
1474 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach" % (
1475 mano_host, mano_port, tenant, datacenter, network_uuid)
1476 mano_response = requests.delete(URLrequest)
1477 logger.debug("openmano response: %s", mano_response.text)
1478 result = _print_verbose(mano_response, args.verbose)
tierno20df3bb2017-07-07 14:31:00 +02001479 return result
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001480
tierno7edb6752016-03-21 17:37:52 +01001481
1482def datacenter_net_action(args):
1483 if args.action == "net-update":
tierno5acf7202016-08-29 14:28:13 +02001484 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
tierno7edb6752016-03-21 17:37:52 +01001485 print
1486 args.action = "netmap-delete"
1487 args.netmap = None
1488 args.all = True
1489 r = datacenter_netmap_action(args)
1490 if r == 0:
1491 args.force = True
tierno5acf7202016-08-29 14:28:13 +02001492 args.action = "netmap-import"
tierno7edb6752016-03-21 17:37:52 +01001493 r = datacenter_netmap_action(args)
1494 return r
1495
1496 if args.action == "net-edit":
1497 args.netmap = args.net
1498 args.name = None
1499 elif args.action == "net-list":
1500 args.netmap = None
1501 elif args.action == "net-delete":
1502 args.netmap = args.net
1503 args.all = False
1504
1505 args.action = "netmap" + args.action[3:]
1506 args.vim_name=None
1507 args.vim_id=None
1508 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1509 print
1510 return datacenter_netmap_action(args)
1511
1512def datacenter_netmap_action(args):
1513 tenant = _get_tenant()
1514 datacenter = _get_datacenter(args.datacenter, tenant)
1515 #print "datacenter_netmap_action",args
1516 payload_req = None
1517 if args.verbose==None:
1518 args.verbose=0
1519 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1520 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1521
1522 if args.action=="netmap-list":
1523 if args.netmap:
1524 URLrequest += "/" + args.netmap
1525 args.verbose += 1
1526 mano_response = requests.get(URLrequest)
1527
1528 elif args.action=="netmap-delete":
1529 if args.netmap and args.all:
1530 print "you can not use a netmap name and the option --all at the same time"
1531 return 1
1532 if args.netmap:
1533 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1534 URLrequest += "/" + args.netmap
1535 elif args.all:
1536 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1537 else:
tiernoae4a8d12016-07-08 12:30:39 +02001538 print "you must specify a netmap name or the option --all"
tierno7edb6752016-03-21 17:37:52 +01001539 return 1
1540 if not args.force:
1541 r = raw_input(force_text)
1542 if len(r)>0 and r[0].lower()=="y":
1543 pass
1544 else:
1545 return 0
1546 mano_response = requests.delete(URLrequest, headers=headers_req)
tierno5acf7202016-08-29 14:28:13 +02001547 elif args.action=="netmap-import":
tierno7edb6752016-03-21 17:37:52 +01001548 if not args.force:
1549 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1550 if len(r)>0 and r[0].lower()=="y":
1551 pass
1552 else:
1553 return 0
1554 URLrequest += "/upload"
1555 mano_response = requests.post(URLrequest, headers=headers_req)
1556 elif args.action=="netmap-edit" or args.action=="netmap-create":
1557 if args.file:
1558 payload = _load_file_or_yaml(args.file)
1559 else:
1560 payload = {}
1561 if "netmap" not in payload:
1562 payload = {"netmap": payload}
1563 if args.name:
1564 payload["netmap"]["name"] = args.name
1565 if args.vim_id:
1566 payload["netmap"]["vim_id"] = args.vim_id
1567 if args.action=="netmap-create" and args.vim_name:
1568 payload["netmap"]["vim_name"] = args.vim_name
1569 payload_req = json.dumps(payload)
1570 logger.debug("openmano request: %s", payload_req)
1571
1572 if args.action=="netmap-edit" and not args.force:
1573 if len(payload["netmap"]) == 0:
1574 print "You must supply some parameter to edit"
1575 return 1
1576 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1577 if len(r)>0 and r[0].lower()=="y":
1578 pass
1579 else:
1580 return 0
1581 URLrequest += "/" + args.netmap
1582 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1583 else: #netmap-create
1584 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1585 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1586 return 1
1587 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1588
1589 logger.debug("openmano response: %s", mano_response.text )
1590 return _print_verbose(mano_response, args.verbose)
1591
tierno20df3bb2017-07-07 14:31:00 +02001592
tierno7edb6752016-03-21 17:37:52 +01001593def element_edit(args):
1594 element = _get_item_uuid(args.element, args.name)
1595 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1596 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1597 payload=_load_file_or_yaml(args.file)
1598 if args.element[:-1] not in payload:
1599 payload = {args.element[:-1]: payload }
1600 payload_req = json.dumps(payload)
1601
1602 #print payload_req
1603 if not args.force or (args.name==None and args.filer==None):
1604 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1605 if len(r)>0 and r[0].lower()=="y":
1606 pass
1607 else:
1608 return 0
1609 logger.debug("openmano request: %s", payload_req)
1610 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1611 logger.debug("openmano response: %s", mano_response.text )
1612 if args.verbose==None:
1613 args.verbose=0
1614 if args.name!=None:
1615 args.verbose += 1
1616 return _print_verbose(mano_response, args.verbose)
1617
1618
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001619def datacenter_edit(args):
1620 tenant = _get_tenant()
1621 element = _get_item_uuid('datacenters', args.name, tenant)
1622 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1623 URLrequest = "http://%s:%s/openmano/datacenters/%s" % (mano_host, mano_port, element)
1624
1625 has_arguments = False
1626 if args.file != None:
1627 has_arguments = True
1628 payload = _load_file_or_yaml(args.file)
1629 else:
1630 payload = {}
1631
1632 if args.sdn_controller != None:
1633 has_arguments = True
1634 if not 'config' in payload:
1635 payload['config'] = {}
1636 if not 'sdn-controller' in payload['config']:
1637 payload['config']['sdn-controller'] = {}
1638 if args.sdn_controller == 'null':
1639 payload['config']['sdn-controller'] = None
1640 else:
1641 payload['config']['sdn-controller'] = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1642
1643 if not has_arguments:
1644 raise OpenmanoCLIError("At least one argument must be provided to modify the datacenter")
1645
1646 if 'datacenter' not in payload:
1647 payload = {'datacenter': payload}
1648 payload_req = json.dumps(payload)
1649
1650 # print payload_req
1651 if not args.force or (args.name == None and args.filer == None):
1652 r = raw_input(" Edit datacenter " + args.name + " (y/N)? ")
1653 if len(r) > 0 and r[0].lower() == "y":
1654 pass
1655 else:
1656 return 0
1657 logger.debug("openmano request: %s", payload_req)
1658 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1659 logger.debug("openmano response: %s", mano_response.text)
1660 if args.verbose == None:
1661 args.verbose = 0
1662 if args.name != None:
1663 args.verbose += 1
1664 return _print_verbose(mano_response, args.verbose)
1665
tierno20df3bb2017-07-07 14:31:00 +02001666
tierno6ddeded2017-05-16 15:40:26 +02001667def version(args):
1668 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1669 URLrequest = "http://%s:%s/openmano/version" % (mano_host, mano_port)
1670
1671 mano_response = requests.get(URLrequest, headers=headers_req)
1672 logger.debug("openmano response: %s", mano_response.text)
1673 print mano_response.text
1674
1675
tierno7edb6752016-03-21 17:37:52 +01001676global mano_host
1677global mano_port
1678global mano_tenant
1679
1680if __name__=="__main__":
1681
1682 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1683 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1684 mano_port = os.getenv('OPENMANO_PORT',"9090")
1685 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1686
1687 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
tierno6ddeded2017-05-16 15:40:26 +02001688 main_parser.add_argument('--version', action='version', help="get version of this client",
1689 version='%(prog)s client version ' + __version__ +
1690 " (Note: use '%(prog)s version' to get server version)")
1691
tierno7edb6752016-03-21 17:37:52 +01001692 subparsers = main_parser.add_subparsers(help='commands')
1693
tierno7edb6752016-03-21 17:37:52 +01001694 parent_parser = argparse.ArgumentParser(add_help=False)
1695 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1696 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1697
garciadeblas0e9fd832016-07-08 15:20:18 +02001698 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1699 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1700 config_parser.set_defaults(func=config)
1701
tierno6ddeded2017-05-16 15:40:26 +02001702 version_parser = subparsers.add_parser('version', parents=[parent_parser], help="get server version")
1703 version_parser.set_defaults(func=version)
1704
tierno7edb6752016-03-21 17:37:52 +01001705 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1706 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1707 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1708 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1709 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
garciadeblas14480452017-01-10 13:08:07 +01001710 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1711 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
tierno7edb6752016-03-21 17:37:52 +01001712 vnf_create_parser.set_defaults(func=vnf_create)
1713
1714 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1715 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1716 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1717 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1718 vnf_list_parser.set_defaults(func=vnf_list)
1719
1720 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1721 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1722 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1723 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1724 vnf_delete_parser.set_defaults(func=vnf_delete)
1725
1726 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1727 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1728 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1729 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1730 scenario_create_parser.set_defaults(func=scenario_create)
1731
1732 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1733 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1734 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1735 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1736 scenario_list_parser.set_defaults(func=scenario_list)
1737
1738 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1739 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1740 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1741 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1742 scenario_delete_parser.set_defaults(func=scenario_delete)
1743
1744 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1745 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1746 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1747 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1748 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1749 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1750 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1751
1752 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1753 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1754 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1755 scenario_deploy_parser.set_defaults(func=scenario_verify)
1756
1757 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1758 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1759 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1760 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1761 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1762 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1763 instance_scenario_create_parser.add_argument("--netmap-use", action="append", type=str, dest="netmap_use", help="indicates a datacenter network to map a scenario network 'scenario-network=datacenter-network'. Can be used several times")
1764 instance_scenario_create_parser.add_argument("--netmap-create", action="append", type=str, dest="netmap_create", help="the scenario network must be created at datacenter 'scenario-network[=datacenter-network-name]' . Can be used several times")
tiernoa4e1a6e2016-08-31 14:19:40 +02001765 instance_scenario_create_parser.add_argument("--keypair", action="append", type=str, dest="keypair", help="public key for ssh access. Format '[user:]key1[,key2...]'. Can be used several times")
1766 instance_scenario_create_parser.add_argument("--keypair-auto", action="store_true", dest="keypair_auto", help="Inject the user ssh-keys found at $HOME/.ssh directory")
tierno7edb6752016-03-21 17:37:52 +01001767 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1768 instance_scenario_create_parser.set_defaults(func=instance_create)
1769
1770 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1771 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1772 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1773 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1774
1775 instance_scenario_delete_parser = subparsers.add_parser('instance-scenario-delete', parents=[parent_parser], help="deletes a scenario instance (and deletes all VM and net instances in VIM)")
1776 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1777 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1778 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1779 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1780
1781 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1782 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1783 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
tiernofc5f80b2018-05-29 16:00:43 +02001784 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console", "add_public_key","vdu-scaling"],\
tierno7edb6752016-03-21 17:37:52 +01001785 help="action to send")
tiernofc5f80b2018-05-29 16:00:43 +02001786 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console: novnc; reboot: type; vdu-scaling: '[{vdu-id: xxx, type: create|delete, count: 1}]'")
tierno7edb6752016-03-21 17:37:52 +01001787 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1788 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1789 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1790
tierno868220c2017-09-26 00:11:05 +02001791 action_parser = subparsers.add_parser('action-list', parents=[parent_parser], help="get action over an instance status")
1792 action_parser.add_argument("id", nargs='?', action="store", help="action id")
1793 action_parser.add_argument("--instance", action="store", help="fitler by this instance_id")
1794 action_parser.add_argument("--all", action="store", help="Not filter by tenant")
1795 action_parser.set_defaults(func=get_action)
1796
tierno7edb6752016-03-21 17:37:52 +01001797 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1798 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1799 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1800
1801 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1802 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1803 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1804 tenant_create_parser.set_defaults(func=tenant_create)
1805
1806 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1807 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1808 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1809 tenant_delete_parser.set_defaults(func=tenant_delete)
1810
1811 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1812 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1813 tenant_list_parser.set_defaults(func=tenant_list)
1814
tierno161c24b2017-05-16 15:45:56 +02001815 element_edit_parser = subparsers.add_parser('tenant-edit', parents=[parent_parser], help="edits one tenant")
1816 element_edit_parser.add_argument("name", help="name or uuid of the tenant")
1817 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1818 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1819 element_edit_parser.set_defaults(func=element_edit, element='tenants')
tierno7edb6752016-03-21 17:37:52 +01001820
1821 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1822 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1823 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1824 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1825 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1826 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1827 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001828 datacenter_create_parser.add_argument("--sdn-controller", action="store", help="Name or uuid of the SDN controller to be used", dest='sdn_controller')
tierno7edb6752016-03-21 17:37:52 +01001829 datacenter_create_parser.set_defaults(func=datacenter_create)
1830
1831 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1832 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1833 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1834 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1835
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001836 datacenter_edit_parser = subparsers.add_parser('datacenter-edit', parents=[parent_parser], help="Edit datacenter")
1837 datacenter_edit_parser.add_argument("name", help="name or uuid of the datacenter")
1838 datacenter_edit_parser.add_argument("--file", help="json/yaml text or file with the changes").completer = FilesCompleter
1839 datacenter_edit_parser.add_argument("--sdn-controller", action="store",
1840 help="Name or uuid of the SDN controller to be used. Specify 'null' to clear entry", dest='sdn_controller')
1841 datacenter_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1842 datacenter_edit_parser.set_defaults(func=datacenter_edit)
1843
tierno7edb6752016-03-21 17:37:52 +01001844 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1845 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1846 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1847 datacenter_list_parser.set_defaults(func=datacenter_list)
1848
1849 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1850 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1851 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1852 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1853 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1854 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
tierno8008c3a2016-10-13 15:34:28 +00001855 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
tierno7edb6752016-03-21 17:37:52 +01001856 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1857
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001858 datacenter_edit_vim_tenant_parser = subparsers.add_parser('datacenter-edit-vim-tenant', parents=[parent_parser],
1859 help="Edit the association of a datacenter to the operating tenant")
1860 datacenter_edit_vim_tenant_parser.add_argument("name", help="name or uuid of the datacenter")
1861 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-id', action='store',
1862 help="specify a datacenter tenant to use. A new one is created by default")
1863 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1864 datacenter_edit_vim_tenant_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1865 datacenter_edit_vim_tenant_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1866 datacenter_edit_vim_tenant_parser.add_argument("--config", action="store",
1867 help="aditional configuration in json/yaml format")
1868 datacenter_edit_vim_tenant_parser.set_defaults(func=datacenter_edit_vim_tenant)
1869
tierno7edb6752016-03-21 17:37:52 +01001870 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1871 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1872 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1873 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1874
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001875 #=======================datacenter_sdn_port_mapping_xxx section=======================
1876 #datacenter_sdn_port_mapping_set
1877 datacenter_sdn_port_mapping_set_parser = subparsers.add_parser('datacenter-sdn-port-mapping-set',
1878 parents=[parent_parser],
1879 help="Load a file with the mapping of physical ports "
1880 "and the ports of the dataplaneswitch controlled "
1881 "by a datacenter")
1882 datacenter_sdn_port_mapping_set_parser.add_argument("name", action="store", help="specifies the datacenter")
1883 datacenter_sdn_port_mapping_set_parser.add_argument("file",
1884 help="json/yaml text or file with the port mapping").completer = FilesCompleter
1885 datacenter_sdn_port_mapping_set_parser.add_argument("-f", "--force", action="store_true",
1886 help="forces overwriting without asking")
1887 datacenter_sdn_port_mapping_set_parser.set_defaults(func=datacenter_sdn_port_mapping_set)
1888
1889 #datacenter_sdn_port_mapping_list
1890 datacenter_sdn_port_mapping_list_parser = subparsers.add_parser('datacenter-sdn-port-mapping-list',
1891 parents=[parent_parser],
1892 help="Show the SDN port mapping in a datacenter")
1893 datacenter_sdn_port_mapping_list_parser.add_argument("name", action="store", help="specifies the datacenter")
1894 datacenter_sdn_port_mapping_list_parser.set_defaults(func=datacenter_sdn_port_mapping_list)
1895
1896 # datacenter_sdn_port_mapping_clear
1897 datacenter_sdn_port_mapping_clear_parser = subparsers.add_parser('datacenter-sdn-port-mapping-clear',
1898 parents=[parent_parser],
1899 help="Clean the the SDN port mapping in a datacenter")
1900 datacenter_sdn_port_mapping_clear_parser.add_argument("name", action="store",
1901 help="specifies the datacenter")
1902 datacenter_sdn_port_mapping_clear_parser.add_argument("-f", "--force", action="store_true",
1903 help="forces clearing without asking")
1904 datacenter_sdn_port_mapping_clear_parser.set_defaults(func=datacenter_sdn_port_mapping_clear)
1905 # =======================
1906
1907 # =======================sdn_controller_xxx section=======================
1908 # sdn_controller_create
1909 sdn_controller_create_parser = subparsers.add_parser('sdn-controller-create', parents=[parent_parser],
1910 help="Creates an SDN controller entity within RO")
1911 sdn_controller_create_parser.add_argument("name", help="name of the SDN controller")
1912 sdn_controller_create_parser.add_argument("--description", action="store", help="description of the SDN controller")
1913 sdn_controller_create_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1914 sdn_controller_create_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1915 sdn_controller_create_parser.add_argument("--dpid", action="store",
1916 help="DPID of the dataplane switch controlled by this SDN controller")
1917 sdn_controller_create_parser.add_argument("--type", action="store",
1918 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1919 sdn_controller_create_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1920 sdn_controller_create_parser.add_argument("--passwd", action="store", dest='password',
1921 help="password credentials for the SDN controller")
1922 sdn_controller_create_parser.set_defaults(func=sdn_controller_create)
1923
1924 # sdn_controller_edit
1925 sdn_controller_edit_parser = subparsers.add_parser('sdn-controller-edit', parents=[parent_parser],
1926 help="Update one or more options of a SDN controller")
1927 sdn_controller_edit_parser.add_argument("name", help="name or uuid of the SDN controller", )
1928 sdn_controller_edit_parser.add_argument("--name", action="store", help="Update the name of the SDN controller",
1929 dest='new_name')
1930 sdn_controller_edit_parser.add_argument("--description", action="store", help="description of the SDN controller")
1931 sdn_controller_edit_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1932 sdn_controller_edit_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1933 sdn_controller_edit_parser.add_argument("--dpid", action="store",
1934 help="DPID of the dataplane switch controlled by this SDN controller")
1935 sdn_controller_edit_parser.add_argument("--type", action="store",
1936 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1937 sdn_controller_edit_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1938 sdn_controller_edit_parser.add_argument("--password", action="store",
1939 help="password credentials for the SDN controller", dest='password')
1940 sdn_controller_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1941 #TODO: include option --file
1942 sdn_controller_edit_parser.set_defaults(func=sdn_controller_edit)
1943
1944 #sdn_controller_list
1945 sdn_controller_list_parser = subparsers.add_parser('sdn-controller-list',
1946 parents=[parent_parser],
1947 help="List the SDN controllers")
1948 sdn_controller_list_parser.add_argument("name", nargs='?', help="name or uuid of the SDN controller")
1949 sdn_controller_list_parser.set_defaults(func=sdn_controller_list)
1950
1951 # sdn_controller_delete
1952 sdn_controller_delete_parser = subparsers.add_parser('sdn-controller-delete',
1953 parents=[parent_parser],
1954 help="Delete the the SDN controller")
1955 sdn_controller_delete_parser.add_argument("name", help="name or uuid of the SDN controller")
1956 sdn_controller_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1957 sdn_controller_delete_parser.set_defaults(func=sdn_controller_delete)
1958 # =======================
tierno7edb6752016-03-21 17:37:52 +01001959
1960 action_dict={'net-update': 'retrieves external networks from datacenter',
1961 'net-edit': 'edits an external network',
1962 'net-delete': 'deletes an external network',
1963 'net-list': 'lists external networks from a datacenter'
1964 }
1965 for item in action_dict:
1966 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1967 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1968 if item=='net-edit' or item=='net-delete':
1969 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1970 if item=='net-edit':
1971 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1972 if item!='net-list':
1973 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1974 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1975
1976
tierno5acf7202016-08-29 14:28:13 +02001977 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
tierno7edb6752016-03-21 17:37:52 +01001978 'netmap-create': 'create a new network senario netmap',
1979 'netmap-edit': 'edit name of a network senario netmap',
1980 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1981 'netmap-list': 'list/show network scenario netmaps'
1982 }
1983 for item in action_dict:
1984 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1985 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1986 #if item=='net-add':
1987 # datacenter_action_parser.add_argument("net", help="name of the network")
1988 if item=='netmap-delete':
1989 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1990 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1991 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1992 if item=='netmap-edit':
1993 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1994 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1995 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1996 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1997 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1998 if item=='netmap-list':
1999 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
2000 if item=='netmap-create':
2001 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
2002 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
2003 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
2004 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
tierno5acf7202016-08-29 14:28:13 +02002005 if item=='netmap-import':
tierno7edb6752016-03-21 17:37:52 +01002006 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
2007 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002008
2009 # =======================vim_net_sdn_xxx section=======================
2010 # vim_net_sdn_attach
2011 vim_net_sdn_attach_parser = subparsers.add_parser('vim-net-sdn-attach',
2012 parents=[parent_parser],
2013 help="Specify the port to access to an external network using SDN")
2014 vim_net_sdn_attach_parser.add_argument("vim_net", action="store",
2015 help="Name/id of the network in the vim that will be used to connect to the external network")
2016 vim_net_sdn_attach_parser.add_argument("port", action="store", help="Specifies the port in the dataplane switch to access to the external network")
2017 vim_net_sdn_attach_parser.add_argument("--vlan", action="store", help="Specifies the vlan (if any) to use in the defined port")
2018 vim_net_sdn_attach_parser.add_argument("--mac", action="store", help="Specifies the MAC (if known) of the physical device that will be reachable by this external port")
2019 vim_net_sdn_attach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2020 vim_net_sdn_attach_parser.set_defaults(func=vim_net_sdn_attach)
2021
2022 # vim_net_sdn_detach
2023 vim_net_sdn_detach_parser = subparsers.add_parser('vim-net-sdn-detach',
2024 parents=[parent_parser],
2025 help="Remove the port information to access to an external network using SDN")
2026
2027 vim_net_sdn_detach_parser.add_argument("vim_net", action="store", help="Name/id of the vim network")
2028 vim_net_sdn_detach_parser.add_argument("--id", action="store",help="Specify the uuid of the external ports from this network to be detached")
2029 vim_net_sdn_detach_parser.add_argument("--all", action="store_true", help="Detach all external ports from this network")
2030 vim_net_sdn_detach_parser.add_argument("-f", "--force", action="store_true", help="forces clearing without asking")
2031 vim_net_sdn_detach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2032 vim_net_sdn_detach_parser.set_defaults(func=vim_net_sdn_detach)
2033 # =======================
2034
tierno4540ea52017-01-18 17:44:32 +01002035 for item in ("network", "tenant", "image"):
tierno7edb6752016-03-21 17:37:52 +01002036 if item=="network":
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002037 command_name = 'vim-net'
tierno7edb6752016-03-21 17:37:52 +01002038 else:
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002039 command_name = 'vim-'+item
2040 vim_item_list_parser = subparsers.add_parser(command_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
tierno7edb6752016-03-21 17:37:52 +01002041 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
2042 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2043 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
2044
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002045 vim_item_del_parser = subparsers.add_parser(command_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
tierno7edb6752016-03-21 17:37:52 +01002046 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
2047 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2048 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
2049
tierno4540ea52017-01-18 17:44:32 +01002050 if item == "network" or item == "tenant":
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002051 vim_item_create_parser = subparsers.add_parser(command_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
tierno4540ea52017-01-18 17:44:32 +01002052 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
2053 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
2054 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2055 if item=="network":
2056 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
2057 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
2058 vim_item_create_parser.add_argument("--bind-net", action="store", help="For openvim datacenter type, net to be bind to, for vlan type, use sufix ':<vlan_tag>'")
2059 else:
2060 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
2061 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
tierno7edb6752016-03-21 17:37:52 +01002062
2063 argcomplete.autocomplete(main_parser)
2064
2065 try:
2066 args = main_parser.parse_args()
2067 #logging info
2068 level = logging.CRITICAL
2069 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
2070 if "debug" in args and args.debug:
2071 level = logging.DEBUG
2072 logging.basicConfig(format=streamformat, level= level)
2073 logger = logging.getLogger('mano')
2074 logger.setLevel(level)
2075 result = args.func(args)
2076 if result == None:
2077 result = 0
2078 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
2079 except (requests.exceptions.ConnectionError):
2080 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
2081 result = -2
2082 except (KeyboardInterrupt):
2083 print 'Exiting openmano'
2084 result = -3
2085 except (SystemExit, ArgumentParserError):
2086 result = -4
2087 except OpenmanoCLIError as e:
2088 print str(e)
2089 result = -5
2090
2091 #print result
2092 exit(result)
2093