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