blob: 93c5d6bb004eb19672abaa536c12dafe9e5e4c91 [file] [log] [blame]
tierno7edb6752016-03-21 17:37:52 +01001#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# PYTHON_ARGCOMPLETE_OK
4
5##
6# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
7# 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
26'''
27openmano client used to interact with openmano-server (openmanod)
28'''
29__author__="Alfonso Tierno, Gerardo Garcia"
30__date__ ="$09-oct-2014 09:09:48$"
31__version__="0.4.3-r467"
32version_date="Mar 2016"
33
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
62 print "OPENMANO_TENANT: %s" %mano_tenant
63 print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
64
65def _print_verbose(mano_response, verbose_level=0):
66 content = mano_response.json()
67 result = 0 if mano_response.status_code==200 else mano_response.status_code
68 if type(content)!=dict or len(content)!=1:
69 #print "Non expected format output"
70 print str(content)
71 return result
72
73 val=content.values()[0]
74 if type(val)==str:
75 print val
76 return result
77 elif type(val) == list:
78 content_list = val
79 elif type(val)==dict:
80 content_list = [val]
81 else:
82 #print "Non expected dict/list format output"
83 print str(content)
84 return result
85
86 #print content_list
87 if verbose_level==None:
88 verbose_level=0
89 if verbose_level >= 3:
90 print yaml.safe_dump(content, indent=4, default_flow_style=False)
91 return result
92
93 if mano_response.status_code == 200:
94 for content in content_list:
95 if "uuid" in content:
96 uuid = content['uuid']
97 elif "id" in content:
98 uuid = content['id']
99 elif "vim_id" in content:
100 uuid = content['vim_id']
101 myoutput = "%s %s" %(uuid.ljust(38),content['name'].ljust(20))
102 if "status" in content:
103 myoutput += " " + content['status'].ljust(20)
104 elif "enabled" in content and not content["enabled"]:
105 myoutput += " enabled=False".ljust(20)
106 if verbose_level >=1:
107 if 'created_at' in content:
108 myoutput += " " + content['created_at'].ljust(20)
109 if verbose_level >=2:
110 new_line='\n'
111 if 'type' in content and content['type']!=None:
112 myoutput += new_line + " Type: " + content['type'].ljust(29)
113 new_line=''
114 if 'description' in content and content['description']!=None:
115 myoutput += new_line + " Description: " + content['description'].ljust(20)
116 print myoutput
117 else:
118 print content['error']['description']
119 return result
120
121def parser_json_yaml(file_name):
122 try:
123 f = file(file_name, "r")
124 text = f.read()
125 f.close()
126 except Exception as e:
127 return (False, str(e))
128
129 #Read and parse file
130 if file_name[-5:]=='.yaml' or file_name[-4:]=='.yml' or (file_name[-5:]!='.json' and '\t' not in text):
131 try:
132 config = yaml.load(text)
133 except yaml.YAMLError as exc:
134 error_pos = ""
135 if hasattr(exc, 'problem_mark'):
136 mark = exc.problem_mark
137 error_pos = " at line:%s column:%s" % (mark.line+1, mark.column+1)
138 return (False, "Error loading file '"+file_name+"' yaml format error" + error_pos)
139 else: #json
140 try:
141 config = json.loads(text)
142 except Exception as e:
143 return (False, "Error loading file '"+file_name+"' json format error " + str(e) )
144
145 return True, config
146
147def _load_file_or_yaml(content):
148 '''
149 'content' can be or a yaml/json file or a text containing a yaml/json text format
150 This function autodetect, trying to load and parse the file,
151 if fails trying to parse the 'content' text
152 Returns the dictionary once parsed, or print an error and finish the program
153 '''
154 #Check config file exists
155 if os.path.isfile(content):
156 r,payload = parser_json_yaml(content)
157 if not r:
158 print payload
159 exit(-1)
160 elif "{" in content or ":" in content:
161 try:
162 payload = yaml.load(content)
163 except yaml.YAMLError as exc:
164 error_pos = ""
165 if hasattr(exc, 'problem_mark'):
166 mark = exc.problem_mark
167 error_pos = " at position: (%s:%s)" % (mark.line+1, mark.column+1)
168 print "Error loading yaml/json text"+error_pos
169 exit (-1)
170 else:
171 print "'%s' is neither a valid file nor a yaml/json content" % content
172 exit(-1)
173 return payload
174
175def _get_item_uuid(item, item_name_id, tenant=None):
176 if tenant:
177 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, tenant, item)
178 else:
179 URLrequest = "http://%s:%s/openmano/%s" %(mano_host, mano_port, item)
180 mano_response = requests.get(URLrequest)
181 logger.debug("openmano response: %s", mano_response.text )
182 content = mano_response.json()
183 #print content
184 found = 0
185 for i in content[item]:
186 if i["uuid"] == item_name_id:
187 return item_name_id
188 if i["name"] == item_name_id:
189 uuid = i["uuid"]
190 found += 1
191 if found == 0:
192 raise OpenmanoCLIError("No %s found with name/uuid '%s'" %(item[:-1], item_name_id))
193 elif found > 1:
194 raise OpenmanoCLIError("%d %s found with name '%s'. uuid must be used" %(found, item, item_name_id))
195 return uuid
196#
197# def check_valid_uuid(uuid):
198# id_schema = {"type" : "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
199# try:
200# js_v(uuid, id_schema)
201# return True
202# except js_e.ValidationError:
203# return False
204
205def _get_tenant(tenant_name_id = None):
206 if not tenant_name_id:
207 tenant_name_id = mano_tenant
208 if not mano_tenant:
209 raise OpenmanoCLIError("'OPENMANO_TENANT' environment variable is not set")
210 return _get_item_uuid("tenants", tenant_name_id)
211
212def _get_datacenter(datacenter_name_id = None, tenant = "any"):
213 if not datacenter_name_id:
214 datacenter_name_id = mano_datacenter
215 if not datacenter_name_id:
216 raise OpenmanoCLIError("neither 'OPENMANO_DATACENTER' environment variable is set nor --datacenter option is used")
217 return _get_item_uuid("datacenters", datacenter_name_id, tenant)
218
219def vnf_create(args):
220 #print "vnf-create",args
221 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
222 tenant = _get_tenant()
223 myvnf = _load_file_or_yaml(args.file)
224
225 if args.name or args.description or args.image_path:
226 #print args.name
227 try:
228 if args.name:
229 myvnf['vnf']['name'] = args.name
230 if args.description:
231 myvnf['vnf']['description'] = args.description
232 if args.image_path:
233 index=0
234 for image_path_ in args.image_path.split(","):
235 #print "image-path", image_path_
236 myvnf['vnf']['VNFC'][index]['VNFC image']=image_path_
237 index=index+1
238 except (KeyError, TypeError), e:
239 if str(e)=='vnf': error_pos= "missing field 'vnf'"
240 elif str(e)=='name': error_pos= "missing field 'vnf':'name'"
241 elif str(e)=='description': error_pos= "missing field 'vnf':'description'"
242 elif str(e)=='VNFC': error_pos= "missing field 'vnf':'VNFC'"
243 elif str(e)==str(index): error_pos= "field 'vnf':'VNFC' must be an array"
244 elif str(e)=='VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
245 else: error_pos="wrong format"
246 print "Wrong VNF descriptor: " + error_pos
247 return -1
248 payload_req = json.dumps(myvnf)
249
250 #print payload_req
251
252 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
253 logger.debug("openmano request: %s", payload_req)
254 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
255 logger.debug("openmano response: %s", mano_response.text )
256
257 return _print_verbose(mano_response, args.verbose)
258
259def vnf_list(args):
260 #print "vnf-list",args
261 if args.all:
262 tenant = "any"
263 else:
264 tenant = _get_tenant()
265 if args.name:
266 toshow = _get_item_uuid("vnfs", args.name, tenant)
267 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
268 else:
269 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
270 mano_response = requests.get(URLrequest)
271 logger.debug("openmano response: %s", mano_response.text )
272 content = mano_response.json()
273 #print json.dumps(content, indent=4)
274 if args.verbose==None:
275 args.verbose=0
276 result = 0 if mano_response.status_code==200 else mano_response.status_code
277 if mano_response.status_code == 200:
278 if not args.name:
279 if args.verbose >= 3:
280 print yaml.safe_dump(content, indent=4, default_flow_style=False)
281 return result
282 if len(content['vnfs']) == 0:
283 print "No VNFs were found."
284 return 404 #HTTP_Not_Found
285 for vnf in content['vnfs']:
286 myoutput = "%s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20))
287 if args.verbose >=1:
288 myoutput = "%s %s" %(myoutput, vnf['created_at'].ljust(20))
289 print myoutput
290 if args.verbose >=2:
291 print " Description: %s" %vnf['description']
292 print " VNF descriptor file: %s" %vnf['path']
293 else:
294 if args.verbose:
295 print yaml.safe_dump(content, indent=4, default_flow_style=False)
296 return result
297 vnf = content['vnf']
298 print "%s %s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20), vnf['created_at'].ljust(20))
299 print " Description: %s" %vnf['description']
300 #print " VNF descriptor file: %s" %vnf['path']
301 print " VMs:"
302 for vm in vnf['VNFC']:
303 #print " %s %s %s" %(vm['name'].ljust(20), vm['uuid'].ljust(38), vm['description'].ljust(30))
304 print " %s %s" %(vm['name'].ljust(20), vm['description'])
305 if len(vnf['nets'])>0:
306 print " Internal nets:"
307 for net in vnf['nets']:
308 print " %s %s" %(net['name'].ljust(20), net['description'])
309 if len(vnf['external-connections'])>0:
310 print " External interfaces:"
311 for interface in vnf['external-connections']:
312 print " %s %s %s %s" %(interface['external_name'].ljust(20), interface['vm_name'].ljust(20), interface['internal_name'].ljust(20), \
313 interface['vpci'].ljust(14))
314 else:
315 print content['error']['description']
316 if args.verbose:
317 print yaml.safe_dump(content, indent=4, default_flow_style=False)
318 return result
319
320def vnf_delete(args):
321 #print "vnf-delete",args
322 if args.all:
323 tenant = "any"
324 else:
325 tenant = _get_tenant()
326 todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
327 if not args.force:
328 r = raw_input("Delete VNF %s (y/N)? " %(todelete))
329 if not (len(r)>0 and r[0].lower()=="y"):
330 return 0
331 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
332 mano_response = requests.delete(URLrequest)
333 logger.debug("openmano response: %s", mano_response.text )
334 result = 0 if mano_response.status_code==200 else mano_response.status_code
335 content = mano_response.json()
336 #print json.dumps(content, indent=4)
337 if mano_response.status_code == 200:
338 print content['result']
339 else:
340 print content['error']['description']
341 return result
342
343def scenario_create(args):
344 #print "scenario-create",args
345 tenant = _get_tenant()
346 headers_req = {'content-type': 'application/yaml'}
347 myscenario = _load_file_or_yaml(args.file)
348
349 if args.name:
350 myscenario['name'] = args.name
351 if args.description:
352 myscenario['description'] = args.description
353 payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
354
355 #print payload_req
356
357 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
358 logger.debug("openmano request: %s", payload_req)
359 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
360 logger.debug("openmano response: %s", mano_response.text )
361 return _print_verbose(mano_response, args.verbose)
362
363def scenario_list(args):
364 #print "scenario-list",args
365 if args.all:
366 tenant = "any"
367 else:
368 tenant = _get_tenant()
369 if args.name:
370 toshow = _get_item_uuid("scenarios", args.name, tenant)
371 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
372 else:
373 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
374 mano_response = requests.get(URLrequest)
375 logger.debug("openmano response: %s", mano_response.text )
376 content = mano_response.json()
377 #print json.dumps(content, indent=4)
378 if args.verbose==None:
379 args.verbose=0
380
381 result = 0 if mano_response.status_code==200 else mano_response.status_code
382 if mano_response.status_code == 200:
383 if not args.name:
384 if args.verbose >= 3:
385 print yaml.safe_dump(content, indent=4, default_flow_style=False)
386 return result
387 if len(content['scenarios']) == 0:
388 print "No scenarios were found."
389 return 404 #HTTP_Not_Found
390 for scenario in content['scenarios']:
391 myoutput = "%s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20))
392 if args.verbose >=1:
393 myoutput = "%s %s" %(myoutput, scenario['created_at'].ljust(20))
394 print myoutput
395 if args.verbose >=2:
396 print " Description: %s" %scenario['description']
397 else:
398 if args.verbose:
399 print yaml.safe_dump(content, indent=4, default_flow_style=False)
400 return result
401 scenario = content['scenario']
402 myoutput = "%s %s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20), scenario['created_at'].ljust(20))
403 print myoutput
404 print " Description: %s" %scenario['description']
405 print " VNFs:"
406 for vnf in scenario['vnfs']:
407 print " %s %s %s" %(vnf['name'].ljust(20), vnf['vnf_id'].ljust(38), vnf['description'])
408 if len(scenario['nets'])>0:
409 print " Internal nets:"
410 for net in scenario['nets']:
411 if net['description'] is None: #if description does not exist, description is "-". Valid for external and internal nets.
412 net['description'] = '-'
413 if not net['external']:
414 print " %s %s %s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30))
415 print " External nets:"
416 for net in scenario['nets']:
417 if net['external']:
418 print " %s %s %s vim-id:%s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30), net['vim_id'])
419 else:
420 print content['error']['description']
421 if args.verbose:
422 print yaml.safe_dump(content, indent=4, default_flow_style=False)
423 return result
424
425def scenario_delete(args):
426 #print "scenario-delete",args
427 if args.all:
428 tenant = "any"
429 else:
430 tenant = _get_tenant()
431 todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
432 if not args.force:
433 r = raw_input("Delete scenario %s (y/N)? " %(args.name))
434 if not (len(r)>0 and r[0].lower()=="y"):
435 return 0
436 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
437 mano_response = requests.delete(URLrequest)
438 logger.debug("openmano response: %s", mano_response.text )
439 result = 0 if mano_response.status_code==200 else mano_response.status_code
440 content = mano_response.json()
441 #print json.dumps(content, indent=4)
442 if mano_response.status_code == 200:
443 print content['result']
444 else:
445 print content['error']['description']
446 return result
447
448def scenario_deploy(args):
449 print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
450 print
451 args.file = None
452 args.netmap_use = None
453 args.netmap_create = None
454 return instance_create(args)
455
456# #print "scenario-deploy",args
457# headers_req = {'content-type': 'application/json'}
458# action = {}
459# actionCmd="start"
460# if args.nostart:
461# actionCmd="reserve"
462# action[actionCmd] = {}
463# action[actionCmd]["instance_name"] = args.name
464# if args.datacenter != None:
465# action[actionCmd]["datacenter"] = args.datacenter
466# elif mano_datacenter != None:
467# action[actionCmd]["datacenter"] = mano_datacenter
468#
469# if args.description:
470# action[actionCmd]["description"] = args.description
471# payload_req = json.dumps(action, indent=4)
472# #print payload_req
473#
474# URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
475# logger.debug("openmano request: %s", payload_req)
476# mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
477# logger.debug("openmano response: %s", mano_response.text )
478# if args.verbose==None:
479# args.verbose=0
480#
481# result = 0 if mano_response.status_code==200 else mano_response.status_code
482# content = mano_response.json()
483# #print json.dumps(content, indent=4)
484# if args.verbose >= 3:
485# print yaml.safe_dump(content, indent=4, default_flow_style=False)
486# return result
487#
488# if mano_response.status_code == 200:
489# myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
490# if args.verbose >=1:
491# myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
492# if args.verbose >=2:
493# myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
494# print myoutput
495# print ""
496# print "To check the status, run the following command:"
497# print "openmano instance-scenario-list <instance_id>"
498# else:
499# print content['error']['description']
500# return result
501
502def scenario_verify(args):
503 #print "scenario-verify",args
504 headers_req = {'content-type': 'application/json'}
505 action = {}
506 action["verify"] = {}
507 action["verify"]["instance_name"] = "scen-verify-return5"
508 payload_req = json.dumps(action, indent=4)
509 #print payload_req
510
511 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
512 logger.debug("openmano request: %s", payload_req)
513 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
514 logger.debug("openmano response: %s", mano_response.text )
515
516 result = 0 if mano_response.status_code==200 else mano_response.status_code
517 content = mano_response.json()
518 #print json.dumps(content, indent=4)
519 if mano_response.status_code == 200:
520 print content['result']
521 else:
522 print content['error']['description']
523 return result
524
525def instance_create(args):
526 tenant = _get_tenant()
527 headers_req = {'content-type': 'application/yaml'}
528 myInstance={"instance": {}, "schema_version": "0.1"}
529 if args.file:
530 instance_dict = _load_file_or_yaml(args.file)
531 if "instance" not in instance_dict:
532 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
533 else:
534 myInstance = instance_dict
535 if args.name:
536 myInstance["instance"]['name'] = args.name
537 if args.description:
538 myInstance["instance"]['description'] = args.description
539 if args.nostart:
540 myInstance["instance"]['action'] = "reserve"
541 #datacenter
542 datacenter = myInstance["instance"].get("datacenter")
543 if args.datacenter != None:
544 datacenter = args.datacenter
545 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
546 #scenario
547 scenario = myInstance["instance"].get("scenario")
548 if args.scenario != None:
549 scenario = args.scenario
550 if not scenario:
551 print "you must provide an scenario in the file descriptor or with --scenario"
552 return -1
553 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
554 if args.netmap_use:
555 if "networks" not in myInstance["instance"]:
556 myInstance["instance"]["networks"] = {}
557 for net in args.netmap_use:
558 net_comma_list = net.split(",")
559 for net_comma in net_comma_list:
560 net_tuple = net_comma.split("=")
561 if len(net_tuple) != 2:
562 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
563 return
564 net_scenario = net_tuple[0].strip()
565 net_datacenter = net_tuple[1].strip()
566 if net_scenario not in myInstance["instance"]["networks"]:
567 myInstance["instance"]["networks"][net_scenario] = {}
568 myInstance["instance"]["networks"][net_scenario]["netmap-use"] = net_datacenter
569 if args.netmap_create:
570 if "networks" not in myInstance["instance"]:
571 myInstance["instance"]["networks"] = {}
572 for net in args.netmap_create:
573 net_comma_list = net.split(",")
574 for net_comma in net_comma_list:
575 net_tuple = net_comma.split("=")
576 if len(net_tuple) == 1:
577 net_scenario = net_tuple[0].strip()
578 net_datacenter = None
579 elif len(net_tuple) == 2:
580 net_scenario = net_tuple[0].strip()
581 net_datacenter = net_tuple[1].strip()
582 else:
583 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
584 return
585 if net_scenario not in myInstance["instance"]["networks"]:
586 myInstance["instance"]["networks"][net_scenario] = {}
587 myInstance["instance"]["networks"][net_scenario]["netmap-create"] = net_datacenter
588
589 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
590 logger.debug("openmano request: %s", payload_req)
591 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
592 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
593 logger.debug("openmano response: %s", mano_response.text )
594 if args.verbose==None:
595 args.verbose=0
596
597 result = 0 if mano_response.status_code==200 else mano_response.status_code
598 content = mano_response.json()
599 #print json.dumps(content, indent=4)
600 if args.verbose >= 3:
601 print yaml.safe_dump(content, indent=4, default_flow_style=False)
602 return result
603
604 if mano_response.status_code == 200:
605 myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
606 if args.verbose >=1:
607 myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
608 if args.verbose >=2:
609 myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
610 print myoutput
611 else:
612 print content['error']['description']
613 return result
614
615def instance_scenario_list(args):
616 #print "instance-scenario-list",args
617 if args.all:
618 tenant = "any"
619 else:
620 tenant = _get_tenant()
621 if args.name:
622 toshow = _get_item_uuid("instances", args.name, tenant)
623 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
624 else:
625 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
626 mano_response = requests.get(URLrequest)
627 logger.debug("openmano response: %s", mano_response.text )
628 content = mano_response.json()
629 #print json.dumps(content, indent=4)
630 if args.verbose==None:
631 args.verbose=0
632
633 result = 0 if mano_response.status_code==200 else mano_response.status_code
634 if mano_response.status_code == 200:
635 if not args.name:
636 if args.verbose >= 3:
637 print yaml.safe_dump(content, indent=4, default_flow_style=False)
638 return result
639 if len(content['instances']) == 0:
640 print "No scenario instances were found."
641 return result
642 for instance in content['instances']:
643 myoutput = "%s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20))
644 if args.verbose >=1:
645 myoutput = "%s %s" %(myoutput, instance['created_at'].ljust(20))
646 print myoutput
647 if args.verbose >=2:
648 print "Description: %s" %instance['description']
649 else:
650 if args.verbose:
651 print yaml.safe_dump(content, indent=4, default_flow_style=False)
652 return result
653 instance = content
654 print "%s %s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20),instance['created_at'].ljust(20))
655 print "Description: %s" %instance['description']
656 print "Template scenario id: %s" %instance['scenario_id']
657 print "Template scenario name: %s" %instance['scenario_name']
658 print "---------------------------------------"
659 print "VNF instances: %d" %len(instance['vnfs'])
660 for vnf in instance['vnfs']:
661 #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))
662 print " %s %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
663 if len(instance['nets'])>0:
664 print "---------------------------------------"
665 print "Internal nets:"
666 for net in instance['nets']:
667 if not net['external']:
668 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
669 print "---------------------------------------"
670 print "External nets:"
671 for net in instance['nets']:
672 if net['external']:
673 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
674 print "---------------------------------------"
675 print "VM instances:"
676 for vnf in instance['vnfs']:
677 for vm in vnf['vms']:
678 print " %s %s %s %s VIM ID: %s" %(vm['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vm['name'].ljust(20), vm['status'].ljust(12), vm['vim_vm_id'])
679 else:
680 print content['error']['description']
681 if args.verbose:
682 print yaml.safe_dump(content, indent=4, default_flow_style=False)
683 return result
684
685def instance_scenario_status(args):
686 print "instance-scenario-status"
687 return 0
688
689def instance_scenario_delete(args):
690 if args.all:
691 tenant = "any"
692 else:
693 tenant = _get_tenant()
694 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
695 #print "instance-scenario-delete",args
696 if not args.force:
697 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
698 if not (len(r)>0 and r[0].lower()=="y"):
699 return
700 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
701 mano_response = requests.delete(URLrequest)
702 logger.debug("openmano response: %s", mano_response.text )
703 result = 0 if mano_response.status_code==200 else mano_response.status_code
704 content = mano_response.json()
705 #print json.dumps(content, indent=4)
706 if mano_response.status_code == 200:
707 print content['result']
708 else:
709 print content['error']['description']
710 return result
711
712def instance_scenario_action(args):
713 #print "instance-scenario-action", args
714 tenant = _get_tenant()
715 toact = _get_item_uuid("instances", args.name, tenant=tenant)
716 action={}
717 action[ args.action ] = args.param
718 if args.vnf:
719 action["vnfs"] = args.vnf
720 if args.vm:
721 action["vms"] = args.vm
722
723 headers_req = {'content-type': 'application/json'}
724 payload_req = json.dumps(action, indent=4)
725 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
726 logger.debug("openmano request: %s", payload_req)
727 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
728 logger.debug("openmano response: %s", mano_response.text )
729 result = 0 if mano_response.status_code==200 else mano_response.status_code
730 content = mano_response.json()
731 #print json.dumps(content, indent=4)
732 if mano_response.status_code == 200:
733 if args.verbose:
734 print yaml.safe_dump(content, indent=4, default_flow_style=False)
735 return result
736 for uuid,c in content.iteritems():
737 print "%s %s %s" %(uuid.ljust(38), c['name'].ljust(20),c['description'].ljust(20))
738 else:
739 print content['error']['description']
740 return result
741
742
743def instance_vnf_list(args):
744 print "instance-vnf-list"
745 return 0
746
747def instance_vnf_status(args):
748 print "instance-vnf-status"
749 return 0
750
751def tenant_create(args):
752 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
753 tenant_dict={"name": args.name}
754 if args.description!=None:
755 tenant_dict["description"] = args.description
756 payload_req = json.dumps( {"tenant": tenant_dict })
757
758 #print payload_req
759
760 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
761 logger.debug("openmano request: %s", payload_req)
762 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
763 logger.debug("openmano response: %s", mano_response.text )
764 return _print_verbose(mano_response, args.verbose)
765
766def tenant_list(args):
767 #print "tenant-list",args
768 if args.name:
tierno392f2852016-05-13 12:28:55 +0200769 toshow = _get_item_uuid("tenants", args.name)
tierno7edb6752016-03-21 17:37:52 +0100770 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
771 else:
772 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
773 mano_response = requests.get(URLrequest)
774 logger.debug("openmano response: %s", mano_response.text )
775 if args.verbose==None:
776 args.verbose=0
777 if args.name!=None:
778 args.verbose += 1
779 return _print_verbose(mano_response, args.verbose)
780
781def tenant_delete(args):
782 #print "tenant-delete",args
783 todelete = _get_item_uuid("tenants", args.name)
784 if not args.force:
785 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
786 if not (len(r)>0 and r[0].lower()=="y"):
787 return 0
788 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
789 mano_response = requests.delete(URLrequest)
790 logger.debug("openmano response: %s", mano_response.text )
791 result = 0 if mano_response.status_code==200 else mano_response.status_code
792 content = mano_response.json()
793 #print json.dumps(content, indent=4)
794 if mano_response.status_code == 200:
795 print content['result']
796 else:
797 print content['error']['description']
798 return result
799
800def datacenter_attach(args):
801 tenant = _get_tenant()
802 datacenter = _get_datacenter(args.name)
803 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
804
805 datacenter_dict={}
806 if args.vim_tenant_id != None:
807 datacenter_dict['vim_tenant'] = args.vim_tenant_id
808 if args.vim_tenant_name != None:
809 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
810 if args.user != None:
811 datacenter_dict['vim_username'] = args.user
812 if args.password != None:
813 datacenter_dict['vim_password'] = args.password
814 payload_req = json.dumps( {"datacenter": datacenter_dict })
815
816 #print payload_req
817
818 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
819 logger.debug("openmano request: %s", payload_req)
820 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
821 logger.debug("openmano response: %s", mano_response.text )
822 result = _print_verbose(mano_response, args.verbose)
823 #provide addional information if error
824 if mano_response.status_code != 200:
825 content = mano_response.json()
826 if "already in use for 'name'" in content['error']['description'] and \
827 "to database vim_tenants table" in content['error']['description']:
828 print "Try to specify a different name with --vim-tenant-name"
829 return result
830
831def datacenter_detach(args):
832 if args.all:
833 tenant = "any"
834 else:
835 tenant = _get_tenant()
836 datacenter = _get_datacenter(args.name, tenant)
837 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
838 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
839 mano_response = requests.delete(URLrequest, headers=headers_req)
840 logger.debug("openmano response: %s", mano_response.text )
841 content = mano_response.json()
842 #print json.dumps(content, indent=4)
843 result = 0 if mano_response.status_code==200 else mano_response.status_code
844 if mano_response.status_code == 200:
845 print content['result']
846 else:
847 print content['error']['description']
848 return result
849
850def datacenter_create(args):
851 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
852 datacenter_dict={"name": args.name, "vim_url": args.url}
853 if args.description!=None:
854 datacenter_dict["description"] = args.description
855 if args.type!=None:
856 datacenter_dict["type"] = args.type
857 if args.url!=None:
858 datacenter_dict["vim_url_admin"] = args.url_admin
859 if args.config!=None:
860 datacenter_dict["config"] = _load_file_or_yaml(args.config)
861 payload_req = json.dumps( {"datacenter": datacenter_dict })
862
863 #print payload_req
864
865 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
866 logger.debug("openmano request: %s", payload_req)
867 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
868 logger.debug("openmano response: %s", mano_response.text )
869 return _print_verbose(mano_response, args.verbose)
870
871def datacenter_delete(args):
872 #print "datacenter-delete",args
873 todelete = _get_item_uuid("datacenters", args.name, "any")
874 if not args.force:
875 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
876 if not (len(r)>0 and r[0].lower()=="y"):
877 return 0
878 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
879 mano_response = requests.delete(URLrequest)
880 logger.debug("openmano response: %s", mano_response.text )
881 result = 0 if mano_response.status_code==200 else mano_response.status_code
882 content = mano_response.json()
883 #print json.dumps(content, indent=4)
884 if mano_response.status_code == 200:
885 print content['result']
886 else:
887 print content['error']['description']
888 return result
889
890def datacenter_list(args):
891 #print "datacenter-list",args
892 tenant='any' if args.all else _get_tenant()
893
894 if args.name:
895 toshow = _get_item_uuid("datacenters", args.name, tenant)
896 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
897 else:
898 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
899 mano_response = requests.get(URLrequest)
900 logger.debug("openmano response: %s", mano_response.text )
901 if args.verbose==None:
902 args.verbose=0
903 if args.name!=None:
904 args.verbose += 1
905 return _print_verbose(mano_response, args.verbose)
906
907def vim_action(args):
908 #print "datacenter-net-action",args
909 tenant = _get_tenant()
910 datacenter = _get_datacenter(args.datacenter, tenant)
911 if args.verbose==None:
912 args.verbose=0
913 if args.action=="list":
914 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
915 if args.name!=None:
916 args.verbose += 1
917 URLrequest += "/" + args.name
918 mano_response = requests.get(URLrequest)
919 logger.debug("openmano response: %s", mano_response.text )
920 return _print_verbose(mano_response, args.verbose)
921 elif args.action=="delete":
922 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
923 mano_response = requests.delete(URLrequest)
924 logger.debug("openmano response: %s", mano_response.text )
925 result = 0 if mano_response.status_code==200 else mano_response.status_code
926 content = mano_response.json()
927 #print json.dumps(content, indent=4)
928 if mano_response.status_code == 200:
929 print content['result']
930 else:
931 print content['error']['description']
932 return result
933 elif args.action=="create":
934 headers_req = {'content-type': 'application/yaml'}
935 if args.file:
936 create_dict = _load_file_or_yaml(args.file)
937 if args.item not in create_dict:
938 create_dict = {args.item: create_dict}
939 else:
940 create_dict = {args.item:{}}
941 if args.name:
942 create_dict[args.item]['name'] = args.name
943 #if args.description:
944 # create_dict[args.item]['description'] = args.description
945 if args.item=="vim-net":
946 if args.bind_net:
947 create_dict[args.item]['bind_net'] = args.bind_net
948 if args.bind_type:
949 create_dict[args.item]['bind_type'] = args.bind_type
950 if args.shared:
951 create_dict[args.item]['shared'] = args.shared
952 if "name" not in create_dict[args.item]:
953 print "You must provide a name in the descriptor file or with the --name option"
954 return
955 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
956 logger.debug("openmano request: %s", payload_req)
957 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, mano_tenant, datacenter, args.item)
958 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
959 logger.debug("openmano response: %s", mano_response.text )
960 if args.verbose==None:
961 args.verbose=0
962 return _print_verbose(mano_response, args.verbose)
963
964
965def datacenter_net_action(args):
966 if args.action == "net-update":
967 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-upload' instead!!!"
968 print
969 args.action = "netmap-delete"
970 args.netmap = None
971 args.all = True
972 r = datacenter_netmap_action(args)
973 if r == 0:
974 args.force = True
975 args.action = "netmap-upload"
976 r = datacenter_netmap_action(args)
977 return r
978
979 if args.action == "net-edit":
980 args.netmap = args.net
981 args.name = None
982 elif args.action == "net-list":
983 args.netmap = None
984 elif args.action == "net-delete":
985 args.netmap = args.net
986 args.all = False
987
988 args.action = "netmap" + args.action[3:]
989 args.vim_name=None
990 args.vim_id=None
991 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
992 print
993 return datacenter_netmap_action(args)
994
995def datacenter_netmap_action(args):
996 tenant = _get_tenant()
997 datacenter = _get_datacenter(args.datacenter, tenant)
998 #print "datacenter_netmap_action",args
999 payload_req = None
1000 if args.verbose==None:
1001 args.verbose=0
1002 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1003 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1004
1005 if args.action=="netmap-list":
1006 if args.netmap:
1007 URLrequest += "/" + args.netmap
1008 args.verbose += 1
1009 mano_response = requests.get(URLrequest)
1010
1011 elif args.action=="netmap-delete":
1012 if args.netmap and args.all:
1013 print "you can not use a netmap name and the option --all at the same time"
1014 return 1
1015 if args.netmap:
1016 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1017 URLrequest += "/" + args.netmap
1018 elif args.all:
1019 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1020 else:
tiernoae4a8d12016-07-08 12:30:39 +02001021 print "you must specify a netmap name or the option --all"
tierno7edb6752016-03-21 17:37:52 +01001022 return 1
1023 if not args.force:
1024 r = raw_input(force_text)
1025 if len(r)>0 and r[0].lower()=="y":
1026 pass
1027 else:
1028 return 0
1029 mano_response = requests.delete(URLrequest, headers=headers_req)
1030 elif args.action=="netmap-upload":
1031 if not args.force:
1032 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1033 if len(r)>0 and r[0].lower()=="y":
1034 pass
1035 else:
1036 return 0
1037 URLrequest += "/upload"
1038 mano_response = requests.post(URLrequest, headers=headers_req)
1039 elif args.action=="netmap-edit" or args.action=="netmap-create":
1040 if args.file:
1041 payload = _load_file_or_yaml(args.file)
1042 else:
1043 payload = {}
1044 if "netmap" not in payload:
1045 payload = {"netmap": payload}
1046 if args.name:
1047 payload["netmap"]["name"] = args.name
1048 if args.vim_id:
1049 payload["netmap"]["vim_id"] = args.vim_id
1050 if args.action=="netmap-create" and args.vim_name:
1051 payload["netmap"]["vim_name"] = args.vim_name
1052 payload_req = json.dumps(payload)
1053 logger.debug("openmano request: %s", payload_req)
1054
1055 if args.action=="netmap-edit" and not args.force:
1056 if len(payload["netmap"]) == 0:
1057 print "You must supply some parameter to edit"
1058 return 1
1059 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1060 if len(r)>0 and r[0].lower()=="y":
1061 pass
1062 else:
1063 return 0
1064 URLrequest += "/" + args.netmap
1065 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1066 else: #netmap-create
1067 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1068 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1069 return 1
1070 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1071
1072 logger.debug("openmano response: %s", mano_response.text )
1073 return _print_verbose(mano_response, args.verbose)
1074
1075def element_edit(args):
1076 element = _get_item_uuid(args.element, args.name)
1077 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1078 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1079 payload=_load_file_or_yaml(args.file)
1080 if args.element[:-1] not in payload:
1081 payload = {args.element[:-1]: payload }
1082 payload_req = json.dumps(payload)
1083
1084 #print payload_req
1085 if not args.force or (args.name==None and args.filer==None):
1086 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1087 if len(r)>0 and r[0].lower()=="y":
1088 pass
1089 else:
1090 return 0
1091 logger.debug("openmano request: %s", payload_req)
1092 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1093 logger.debug("openmano response: %s", mano_response.text )
1094 if args.verbose==None:
1095 args.verbose=0
1096 if args.name!=None:
1097 args.verbose += 1
1098 return _print_verbose(mano_response, args.verbose)
1099
1100
1101global mano_host
1102global mano_port
1103global mano_tenant
1104
1105if __name__=="__main__":
1106
1107 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1108 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1109 mano_port = os.getenv('OPENMANO_PORT',"9090")
1110 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1111
1112 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1113 main_parser.add_argument('--version', action='version', version='%(prog)s ' + __version__ )
1114
1115 subparsers = main_parser.add_subparsers(help='commands')
1116
1117 config_parser = subparsers.add_parser('config', help="prints configuration values")
1118 config_parser.set_defaults(func=config)
1119
1120 parent_parser = argparse.ArgumentParser(add_help=False)
1121 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1122 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1123
1124 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1125 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1126 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1127 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1128 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
1129 vnf_create_parser.set_defaults(func=vnf_create)
1130
1131 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1132 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1133 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1134 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1135 vnf_list_parser.set_defaults(func=vnf_list)
1136
1137 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1138 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1139 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1140 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1141 vnf_delete_parser.set_defaults(func=vnf_delete)
1142
1143 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1144 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1145 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1146 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1147 scenario_create_parser.set_defaults(func=scenario_create)
1148
1149 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1150 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1151 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1152 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1153 scenario_list_parser.set_defaults(func=scenario_list)
1154
1155 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1156 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1157 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1158 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1159 scenario_delete_parser.set_defaults(func=scenario_delete)
1160
1161 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1162 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1163 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1164 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1165 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1166 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1167 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1168
1169 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1170 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1171 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1172 scenario_deploy_parser.set_defaults(func=scenario_verify)
1173
1174 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1175 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1176 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1177 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1178 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1179 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1180 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")
1181 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")
1182 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1183 instance_scenario_create_parser.set_defaults(func=instance_create)
1184
1185 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1186 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1187 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1188 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1189
1190 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)")
1191 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1192 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1193 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1194 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1195
1196 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1197 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1198 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1199 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console"],\
1200 help="action to send")
1201 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1202 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1203 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1204 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1205
1206 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1207 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1208 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1209
1210 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1211 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1212 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1213 tenant_create_parser.set_defaults(func=tenant_create)
1214
1215 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1216 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1217 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1218 tenant_delete_parser.set_defaults(func=tenant_delete)
1219
1220 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1221 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1222 tenant_list_parser.set_defaults(func=tenant_list)
1223
1224 item_list=('tenant','datacenter') #put tenant before so that help appear in order
1225 for item in item_list:
1226 element_edit_parser = subparsers.add_parser(item+'-edit', parents=[parent_parser], help="edits one "+item)
1227 element_edit_parser.add_argument("name", help="name or uuid of the "+item)
1228 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1229 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1230 element_edit_parser.set_defaults(func=element_edit, element=item + 's')
1231
1232 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1233 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1234 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1235 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1236 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1237 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1238 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
1239 datacenter_create_parser.set_defaults(func=datacenter_create)
1240
1241 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1242 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1243 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1244 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1245
1246 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1247 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1248 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1249 datacenter_list_parser.set_defaults(func=datacenter_list)
1250
1251 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1252 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1253 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1254 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1255 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1256 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1257 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1258
1259 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1260 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1261 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1262 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1263
1264
1265 action_dict={'net-update': 'retrieves external networks from datacenter',
1266 'net-edit': 'edits an external network',
1267 'net-delete': 'deletes an external network',
1268 'net-list': 'lists external networks from a datacenter'
1269 }
1270 for item in action_dict:
1271 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1272 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1273 if item=='net-edit' or item=='net-delete':
1274 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1275 if item=='net-edit':
1276 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1277 if item!='net-list':
1278 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1279 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1280
1281
1282 action_dict={'netmap-upload': 'create network senario netmap base on the datacenter networks',
1283 'netmap-create': 'create a new network senario netmap',
1284 'netmap-edit': 'edit name of a network senario netmap',
1285 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1286 'netmap-list': 'list/show network scenario netmaps'
1287 }
1288 for item in action_dict:
1289 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1290 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1291 #if item=='net-add':
1292 # datacenter_action_parser.add_argument("net", help="name of the network")
1293 if item=='netmap-delete':
1294 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1295 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1296 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1297 if item=='netmap-edit':
1298 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1299 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1300 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1301 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1302 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1303 if item=='netmap-list':
1304 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1305 if item=='netmap-create':
1306 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1307 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1308 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1309 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
1310 if item=='netmap-upload':
1311 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1312 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
1313
1314 for item in ("network", "tenant"):
1315 if item=="network":
1316 commnad_name = 'vim-net'
1317 else:
1318 commnad_name = 'vim-'+item
1319 vim_item_list_parser = subparsers.add_parser(commnad_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
1320 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
1321 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1322 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
1323
1324 vim_item_del_parser = subparsers.add_parser(commnad_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
1325 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
1326 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1327 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
1328
1329 vim_item_create_parser = subparsers.add_parser(commnad_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
1330 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
1331 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
1332 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1333 if item=="network":
1334 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
1335 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
1336 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>'")
1337 else:
1338 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
1339 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
1340
1341 argcomplete.autocomplete(main_parser)
1342
1343 try:
1344 args = main_parser.parse_args()
1345 #logging info
1346 level = logging.CRITICAL
1347 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
1348 if "debug" in args and args.debug:
1349 level = logging.DEBUG
1350 logging.basicConfig(format=streamformat, level= level)
1351 logger = logging.getLogger('mano')
1352 logger.setLevel(level)
1353 result = args.func(args)
1354 if result == None:
1355 result = 0
1356 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
1357 except (requests.exceptions.ConnectionError):
1358 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
1359 result = -2
1360 except (KeyboardInterrupt):
1361 print 'Exiting openmano'
1362 result = -3
1363 except (SystemExit, ArgumentParserError):
1364 result = -4
1365 except OpenmanoCLIError as e:
1366 print str(e)
1367 result = -5
1368
1369 #print result
1370 exit(result)
1371