blob: ab492f6dcef5e4ba6f22741f18c42639fac06306 [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$"
tierno941551b2017-01-12 18:26:26 +010031__version__="0.4.9-r515"
32version_date="Jan 2017"
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
garciadeblas14480452017-01-10 13:08:07 +0100254 if args.name or args.description or args.image_path or args.image_name or args.image_checksum:
tierno7edb6752016-03-21 17:37:52 +0100255 #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_
tierno941551b2017-01-12 18:26:26 +0100266 if "image name" in myvnf['vnf']['VNFC'][index]:
267 del myvnf['vnf']['VNFC'][index]["image name"]
268 if "image checksum" in myvnf['vnf']['VNFC'][index]:
269 del myvnf['vnf']['VNFC'][index]["image checksum"]
tierno7edb6752016-03-21 17:37:52 +0100270 index=index+1
tierno941551b2017-01-12 18:26:26 +0100271 if args.image_name: #image name precedes if both are supplied
garciadeblas14480452017-01-10 13:08:07 +0100272 index=0
273 for image_name_ in args.image_name.split(","):
274 myvnf['vnf']['VNFC'][index]['image name']=image_name_
tierno941551b2017-01-12 18:26:26 +0100275 if "VNFC image" in myvnf['vnf']['VNFC'][index]:
276 del myvnf['vnf']['VNFC'][index]["VNFC image"]
garciadeblas14480452017-01-10 13:08:07 +0100277 index=index+1
278 if args.image_checksum:
279 index=0
280 for image_checksum_ in args.image_checksum.split(","):
281 myvnf['vnf']['VNFC'][index]['image checksum']=image_checksum_
282 index=index+1
tierno7edb6752016-03-21 17:37:52 +0100283 except (KeyError, TypeError), e:
284 if str(e)=='vnf': error_pos= "missing field 'vnf'"
285 elif str(e)=='name': error_pos= "missing field 'vnf':'name'"
286 elif str(e)=='description': error_pos= "missing field 'vnf':'description'"
287 elif str(e)=='VNFC': error_pos= "missing field 'vnf':'VNFC'"
288 elif str(e)==str(index): error_pos= "field 'vnf':'VNFC' must be an array"
289 elif str(e)=='VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
garciadeblas14480452017-01-10 13:08:07 +0100290 elif str(e)=='image name': error_pos= "missing field 'vnf':'VNFC'['image name']"
291 elif str(e)=='image checksum': error_pos= "missing field 'vnf':'VNFC'['image checksum']"
tierno7edb6752016-03-21 17:37:52 +0100292 else: error_pos="wrong format"
293 print "Wrong VNF descriptor: " + error_pos
294 return -1
295 payload_req = json.dumps(myvnf)
296
297 #print payload_req
298
299 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
300 logger.debug("openmano request: %s", payload_req)
301 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
302 logger.debug("openmano response: %s", mano_response.text )
303
304 return _print_verbose(mano_response, args.verbose)
305
306def vnf_list(args):
307 #print "vnf-list",args
308 if args.all:
309 tenant = "any"
310 else:
311 tenant = _get_tenant()
312 if args.name:
313 toshow = _get_item_uuid("vnfs", args.name, tenant)
314 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
315 else:
316 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
317 mano_response = requests.get(URLrequest)
318 logger.debug("openmano response: %s", mano_response.text )
319 content = mano_response.json()
320 #print json.dumps(content, indent=4)
321 if args.verbose==None:
322 args.verbose=0
323 result = 0 if mano_response.status_code==200 else mano_response.status_code
324 if mano_response.status_code == 200:
325 if not args.name:
326 if args.verbose >= 3:
327 print yaml.safe_dump(content, indent=4, default_flow_style=False)
328 return result
329 if len(content['vnfs']) == 0:
330 print "No VNFs were found."
331 return 404 #HTTP_Not_Found
332 for vnf in content['vnfs']:
333 myoutput = "%s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20))
334 if args.verbose >=1:
335 myoutput = "%s %s" %(myoutput, vnf['created_at'].ljust(20))
336 print myoutput
337 if args.verbose >=2:
338 print " Description: %s" %vnf['description']
339 print " VNF descriptor file: %s" %vnf['path']
340 else:
341 if args.verbose:
342 print yaml.safe_dump(content, indent=4, default_flow_style=False)
343 return result
344 vnf = content['vnf']
345 print "%s %s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20), vnf['created_at'].ljust(20))
346 print " Description: %s" %vnf['description']
347 #print " VNF descriptor file: %s" %vnf['path']
348 print " VMs:"
349 for vm in vnf['VNFC']:
350 #print " %s %s %s" %(vm['name'].ljust(20), vm['uuid'].ljust(38), vm['description'].ljust(30))
351 print " %s %s" %(vm['name'].ljust(20), vm['description'])
352 if len(vnf['nets'])>0:
353 print " Internal nets:"
354 for net in vnf['nets']:
355 print " %s %s" %(net['name'].ljust(20), net['description'])
356 if len(vnf['external-connections'])>0:
357 print " External interfaces:"
358 for interface in vnf['external-connections']:
359 print " %s %s %s %s" %(interface['external_name'].ljust(20), interface['vm_name'].ljust(20), interface['internal_name'].ljust(20), \
360 interface['vpci'].ljust(14))
361 else:
362 print content['error']['description']
363 if args.verbose:
364 print yaml.safe_dump(content, indent=4, default_flow_style=False)
365 return result
366
367def vnf_delete(args):
368 #print "vnf-delete",args
369 if args.all:
370 tenant = "any"
371 else:
372 tenant = _get_tenant()
373 todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
374 if not args.force:
375 r = raw_input("Delete VNF %s (y/N)? " %(todelete))
376 if not (len(r)>0 and r[0].lower()=="y"):
377 return 0
378 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
379 mano_response = requests.delete(URLrequest)
380 logger.debug("openmano response: %s", mano_response.text )
381 result = 0 if mano_response.status_code==200 else mano_response.status_code
382 content = mano_response.json()
383 #print json.dumps(content, indent=4)
384 if mano_response.status_code == 200:
385 print content['result']
386 else:
387 print content['error']['description']
388 return result
389
390def scenario_create(args):
391 #print "scenario-create",args
392 tenant = _get_tenant()
393 headers_req = {'content-type': 'application/yaml'}
394 myscenario = _load_file_or_yaml(args.file)
395
396 if args.name:
397 myscenario['name'] = args.name
398 if args.description:
399 myscenario['description'] = args.description
400 payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
401
402 #print payload_req
403
404 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
405 logger.debug("openmano request: %s", payload_req)
406 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
407 logger.debug("openmano response: %s", mano_response.text )
408 return _print_verbose(mano_response, args.verbose)
409
410def scenario_list(args):
411 #print "scenario-list",args
412 if args.all:
413 tenant = "any"
414 else:
415 tenant = _get_tenant()
416 if args.name:
417 toshow = _get_item_uuid("scenarios", args.name, tenant)
418 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
419 else:
420 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
421 mano_response = requests.get(URLrequest)
422 logger.debug("openmano response: %s", mano_response.text )
423 content = mano_response.json()
424 #print json.dumps(content, indent=4)
425 if args.verbose==None:
426 args.verbose=0
427
428 result = 0 if mano_response.status_code==200 else mano_response.status_code
429 if mano_response.status_code == 200:
430 if not args.name:
431 if args.verbose >= 3:
432 print yaml.safe_dump(content, indent=4, default_flow_style=False)
433 return result
434 if len(content['scenarios']) == 0:
435 print "No scenarios were found."
436 return 404 #HTTP_Not_Found
437 for scenario in content['scenarios']:
438 myoutput = "%s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20))
439 if args.verbose >=1:
440 myoutput = "%s %s" %(myoutput, scenario['created_at'].ljust(20))
441 print myoutput
442 if args.verbose >=2:
443 print " Description: %s" %scenario['description']
444 else:
445 if args.verbose:
446 print yaml.safe_dump(content, indent=4, default_flow_style=False)
447 return result
448 scenario = content['scenario']
449 myoutput = "%s %s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20), scenario['created_at'].ljust(20))
450 print myoutput
451 print " Description: %s" %scenario['description']
452 print " VNFs:"
453 for vnf in scenario['vnfs']:
454 print " %s %s %s" %(vnf['name'].ljust(20), vnf['vnf_id'].ljust(38), vnf['description'])
455 if len(scenario['nets'])>0:
456 print " Internal nets:"
457 for net in scenario['nets']:
458 if net['description'] is None: #if description does not exist, description is "-". Valid for external and internal nets.
459 net['description'] = '-'
460 if not net['external']:
461 print " %s %s %s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30))
462 print " External nets:"
463 for net in scenario['nets']:
464 if net['external']:
465 print " %s %s %s vim-id:%s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30), net['vim_id'])
466 else:
467 print content['error']['description']
468 if args.verbose:
469 print yaml.safe_dump(content, indent=4, default_flow_style=False)
470 return result
471
472def scenario_delete(args):
473 #print "scenario-delete",args
474 if args.all:
475 tenant = "any"
476 else:
477 tenant = _get_tenant()
478 todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
479 if not args.force:
480 r = raw_input("Delete scenario %s (y/N)? " %(args.name))
481 if not (len(r)>0 and r[0].lower()=="y"):
482 return 0
483 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
484 mano_response = requests.delete(URLrequest)
485 logger.debug("openmano response: %s", mano_response.text )
486 result = 0 if mano_response.status_code==200 else mano_response.status_code
487 content = mano_response.json()
488 #print json.dumps(content, indent=4)
489 if mano_response.status_code == 200:
490 print content['result']
491 else:
492 print content['error']['description']
493 return result
494
495def scenario_deploy(args):
496 print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
497 print
498 args.file = None
499 args.netmap_use = None
500 args.netmap_create = None
tiernobe41e222016-09-02 15:16:13 +0200501 args.keypair = None
502 args.keypair_auto = None
tierno7edb6752016-03-21 17:37:52 +0100503 return instance_create(args)
504
505# #print "scenario-deploy",args
506# headers_req = {'content-type': 'application/json'}
507# action = {}
508# actionCmd="start"
509# if args.nostart:
510# actionCmd="reserve"
511# action[actionCmd] = {}
512# action[actionCmd]["instance_name"] = args.name
513# if args.datacenter != None:
514# action[actionCmd]["datacenter"] = args.datacenter
515# elif mano_datacenter != None:
516# action[actionCmd]["datacenter"] = mano_datacenter
517#
518# if args.description:
519# action[actionCmd]["description"] = args.description
520# payload_req = json.dumps(action, indent=4)
521# #print payload_req
522#
523# URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
524# logger.debug("openmano request: %s", payload_req)
525# mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
526# logger.debug("openmano response: %s", mano_response.text )
527# if args.verbose==None:
528# args.verbose=0
529#
530# result = 0 if mano_response.status_code==200 else mano_response.status_code
531# content = mano_response.json()
532# #print json.dumps(content, indent=4)
533# if args.verbose >= 3:
534# print yaml.safe_dump(content, indent=4, default_flow_style=False)
535# return result
536#
537# if mano_response.status_code == 200:
538# myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
539# if args.verbose >=1:
540# myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
541# if args.verbose >=2:
542# myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
543# print myoutput
544# print ""
545# print "To check the status, run the following command:"
546# print "openmano instance-scenario-list <instance_id>"
547# else:
548# print content['error']['description']
549# return result
550
551def scenario_verify(args):
552 #print "scenario-verify",args
553 headers_req = {'content-type': 'application/json'}
554 action = {}
555 action["verify"] = {}
556 action["verify"]["instance_name"] = "scen-verify-return5"
557 payload_req = json.dumps(action, indent=4)
558 #print payload_req
559
560 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
561 logger.debug("openmano request: %s", payload_req)
562 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
563 logger.debug("openmano response: %s", mano_response.text )
564
565 result = 0 if mano_response.status_code==200 else mano_response.status_code
566 content = mano_response.json()
567 #print json.dumps(content, indent=4)
568 if mano_response.status_code == 200:
569 print content['result']
570 else:
571 print content['error']['description']
572 return result
573
574def instance_create(args):
575 tenant = _get_tenant()
576 headers_req = {'content-type': 'application/yaml'}
577 myInstance={"instance": {}, "schema_version": "0.1"}
578 if args.file:
579 instance_dict = _load_file_or_yaml(args.file)
580 if "instance" not in instance_dict:
581 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
582 else:
583 myInstance = instance_dict
584 if args.name:
585 myInstance["instance"]['name'] = args.name
586 if args.description:
587 myInstance["instance"]['description'] = args.description
588 if args.nostart:
589 myInstance["instance"]['action'] = "reserve"
590 #datacenter
591 datacenter = myInstance["instance"].get("datacenter")
592 if args.datacenter != None:
593 datacenter = args.datacenter
594 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
595 #scenario
596 scenario = myInstance["instance"].get("scenario")
597 if args.scenario != None:
598 scenario = args.scenario
599 if not scenario:
garciadeblased746032017-01-05 11:58:41 +0100600 print "you must provide a scenario in the file descriptor or with --scenario"
tierno7edb6752016-03-21 17:37:52 +0100601 return -1
602 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
603 if args.netmap_use:
604 if "networks" not in myInstance["instance"]:
605 myInstance["instance"]["networks"] = {}
606 for net in args.netmap_use:
607 net_comma_list = net.split(",")
608 for net_comma in net_comma_list:
609 net_tuple = net_comma.split("=")
610 if len(net_tuple) != 2:
611 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
612 return
613 net_scenario = net_tuple[0].strip()
614 net_datacenter = net_tuple[1].strip()
615 if net_scenario not in myInstance["instance"]["networks"]:
616 myInstance["instance"]["networks"][net_scenario] = {}
tiernobe41e222016-09-02 15:16:13 +0200617 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
618 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
619 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
tierno7edb6752016-03-21 17:37:52 +0100620 if args.netmap_create:
621 if "networks" not in myInstance["instance"]:
622 myInstance["instance"]["networks"] = {}
623 for net in args.netmap_create:
624 net_comma_list = net.split(",")
625 for net_comma in net_comma_list:
626 net_tuple = net_comma.split("=")
627 if len(net_tuple) == 1:
628 net_scenario = net_tuple[0].strip()
629 net_datacenter = None
630 elif len(net_tuple) == 2:
631 net_scenario = net_tuple[0].strip()
632 net_datacenter = net_tuple[1].strip()
633 else:
634 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
635 return
636 if net_scenario not in myInstance["instance"]["networks"]:
637 myInstance["instance"]["networks"][net_scenario] = {}
tiernobe41e222016-09-02 15:16:13 +0200638 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
639 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
640 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
tiernoa4e1a6e2016-08-31 14:19:40 +0200641 if args.keypair:
642 if "cloud-config" not in myInstance["instance"]:
643 myInstance["instance"]["cloud-config"] = {}
644 cloud_config = myInstance["instance"]["cloud-config"]
645 for key in args.keypair:
646 index = key.find(":")
647 if index<0:
648 if "key-pairs" not in cloud_config:
649 cloud_config["key-pairs"] = []
650 cloud_config["key-pairs"].append(key)
651 else:
652 user = key[:index]
653 key_ = key[index+1:]
654 key_list = key_.split(",")
655 if "users" not in cloud_config:
656 cloud_config["users"] = []
657 cloud_config["users"].append({"name": user, "key-pairs": key_list })
658 if args.keypair_auto:
659 try:
660 keys=[]
661 home = os.getenv("HOME")
662 user = os.getenv("USER")
663 files = os.listdir(home+'/.ssh')
664 for file in files:
665 if file[-4:] == ".pub":
666 with open(home+'/.ssh/'+file, 'r') as f:
667 keys.append(f.read())
668 if not keys:
669 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
670 return 1
671 except Exception as e:
672 print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
673 return 1
674
675 if "cloud-config" not in myInstance["instance"]:
676 myInstance["instance"]["cloud-config"] = {}
677 cloud_config = myInstance["instance"]["cloud-config"]
678 if "key-pairs" not in cloud_config:
679 cloud_config["key-pairs"] = []
680 if user:
681 if "users" not in cloud_config:
682 cloud_config["users"] = []
683 cloud_config["users"].append({"name": user, "key-pairs": keys })
tierno7edb6752016-03-21 17:37:52 +0100684
685 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
686 logger.debug("openmano request: %s", payload_req)
687 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
688 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
689 logger.debug("openmano response: %s", mano_response.text )
690 if args.verbose==None:
691 args.verbose=0
692
693 result = 0 if mano_response.status_code==200 else mano_response.status_code
694 content = mano_response.json()
695 #print json.dumps(content, indent=4)
696 if args.verbose >= 3:
697 print yaml.safe_dump(content, indent=4, default_flow_style=False)
698 return result
699
700 if mano_response.status_code == 200:
701 myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
702 if args.verbose >=1:
703 myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
704 if args.verbose >=2:
705 myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
706 print myoutput
707 else:
708 print content['error']['description']
709 return result
710
711def instance_scenario_list(args):
712 #print "instance-scenario-list",args
713 if args.all:
714 tenant = "any"
715 else:
716 tenant = _get_tenant()
717 if args.name:
718 toshow = _get_item_uuid("instances", args.name, tenant)
719 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
720 else:
721 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
722 mano_response = requests.get(URLrequest)
723 logger.debug("openmano response: %s", mano_response.text )
724 content = mano_response.json()
725 #print json.dumps(content, indent=4)
726 if args.verbose==None:
727 args.verbose=0
728
729 result = 0 if mano_response.status_code==200 else mano_response.status_code
730 if mano_response.status_code == 200:
731 if not args.name:
732 if args.verbose >= 3:
733 print yaml.safe_dump(content, indent=4, default_flow_style=False)
734 return result
735 if len(content['instances']) == 0:
736 print "No scenario instances were found."
737 return result
738 for instance in content['instances']:
739 myoutput = "%s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20))
740 if args.verbose >=1:
741 myoutput = "%s %s" %(myoutput, instance['created_at'].ljust(20))
742 print myoutput
743 if args.verbose >=2:
744 print "Description: %s" %instance['description']
745 else:
746 if args.verbose:
747 print yaml.safe_dump(content, indent=4, default_flow_style=False)
748 return result
749 instance = content
750 print "%s %s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20),instance['created_at'].ljust(20))
751 print "Description: %s" %instance['description']
752 print "Template scenario id: %s" %instance['scenario_id']
753 print "Template scenario name: %s" %instance['scenario_name']
754 print "---------------------------------------"
755 print "VNF instances: %d" %len(instance['vnfs'])
756 for vnf in instance['vnfs']:
757 #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))
758 print " %s %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
759 if len(instance['nets'])>0:
760 print "---------------------------------------"
761 print "Internal nets:"
762 for net in instance['nets']:
tierno5c7c4732016-09-26 13:38:55 +0000763 if net['created']:
tierno7edb6752016-03-21 17:37:52 +0100764 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
765 print "---------------------------------------"
766 print "External nets:"
767 for net in instance['nets']:
tierno5c7c4732016-09-26 13:38:55 +0000768 if not net['created']:
tierno7edb6752016-03-21 17:37:52 +0100769 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
770 print "---------------------------------------"
771 print "VM instances:"
772 for vnf in instance['vnfs']:
773 for vm in vnf['vms']:
774 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'])
775 else:
776 print content['error']['description']
777 if args.verbose:
778 print yaml.safe_dump(content, indent=4, default_flow_style=False)
779 return result
780
781def instance_scenario_status(args):
782 print "instance-scenario-status"
783 return 0
784
785def instance_scenario_delete(args):
786 if args.all:
787 tenant = "any"
788 else:
789 tenant = _get_tenant()
790 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
791 #print "instance-scenario-delete",args
792 if not args.force:
793 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
794 if not (len(r)>0 and r[0].lower()=="y"):
795 return
796 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
797 mano_response = requests.delete(URLrequest)
798 logger.debug("openmano response: %s", mano_response.text )
799 result = 0 if mano_response.status_code==200 else mano_response.status_code
800 content = mano_response.json()
801 #print json.dumps(content, indent=4)
802 if mano_response.status_code == 200:
803 print content['result']
804 else:
805 print content['error']['description']
806 return result
807
808def instance_scenario_action(args):
809 #print "instance-scenario-action", args
810 tenant = _get_tenant()
811 toact = _get_item_uuid("instances", args.name, tenant=tenant)
812 action={}
813 action[ args.action ] = args.param
814 if args.vnf:
815 action["vnfs"] = args.vnf
816 if args.vm:
817 action["vms"] = args.vm
818
819 headers_req = {'content-type': 'application/json'}
820 payload_req = json.dumps(action, indent=4)
821 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
822 logger.debug("openmano request: %s", payload_req)
823 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
824 logger.debug("openmano response: %s", mano_response.text )
825 result = 0 if mano_response.status_code==200 else mano_response.status_code
826 content = mano_response.json()
827 #print json.dumps(content, indent=4)
828 if mano_response.status_code == 200:
829 if args.verbose:
830 print yaml.safe_dump(content, indent=4, default_flow_style=False)
831 return result
832 for uuid,c in content.iteritems():
833 print "%s %s %s" %(uuid.ljust(38), c['name'].ljust(20),c['description'].ljust(20))
834 else:
835 print content['error']['description']
836 return result
837
838
839def instance_vnf_list(args):
840 print "instance-vnf-list"
841 return 0
842
843def instance_vnf_status(args):
844 print "instance-vnf-status"
845 return 0
846
847def tenant_create(args):
848 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
849 tenant_dict={"name": args.name}
850 if args.description!=None:
851 tenant_dict["description"] = args.description
852 payload_req = json.dumps( {"tenant": tenant_dict })
853
854 #print payload_req
855
856 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
857 logger.debug("openmano request: %s", payload_req)
858 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
859 logger.debug("openmano response: %s", mano_response.text )
860 return _print_verbose(mano_response, args.verbose)
861
862def tenant_list(args):
863 #print "tenant-list",args
864 if args.name:
tierno392f2852016-05-13 12:28:55 +0200865 toshow = _get_item_uuid("tenants", args.name)
tierno7edb6752016-03-21 17:37:52 +0100866 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
867 else:
868 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
869 mano_response = requests.get(URLrequest)
870 logger.debug("openmano response: %s", mano_response.text )
871 if args.verbose==None:
872 args.verbose=0
873 if args.name!=None:
874 args.verbose += 1
875 return _print_verbose(mano_response, args.verbose)
876
877def tenant_delete(args):
878 #print "tenant-delete",args
879 todelete = _get_item_uuid("tenants", args.name)
880 if not args.force:
881 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
882 if not (len(r)>0 and r[0].lower()=="y"):
883 return 0
884 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
885 mano_response = requests.delete(URLrequest)
886 logger.debug("openmano response: %s", mano_response.text )
887 result = 0 if mano_response.status_code==200 else mano_response.status_code
888 content = mano_response.json()
889 #print json.dumps(content, indent=4)
890 if mano_response.status_code == 200:
891 print content['result']
892 else:
893 print content['error']['description']
894 return result
895
896def datacenter_attach(args):
897 tenant = _get_tenant()
898 datacenter = _get_datacenter(args.name)
899 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
900
901 datacenter_dict={}
902 if args.vim_tenant_id != None:
903 datacenter_dict['vim_tenant'] = args.vim_tenant_id
904 if args.vim_tenant_name != None:
905 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
906 if args.user != None:
907 datacenter_dict['vim_username'] = args.user
908 if args.password != None:
909 datacenter_dict['vim_password'] = args.password
tierno8008c3a2016-10-13 15:34:28 +0000910 if args.config!=None:
911 datacenter_dict["config"] = _load_file_or_yaml(args.config)
tierno7edb6752016-03-21 17:37:52 +0100912 payload_req = json.dumps( {"datacenter": datacenter_dict })
913
914 #print payload_req
915
916 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
917 logger.debug("openmano request: %s", payload_req)
918 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
919 logger.debug("openmano response: %s", mano_response.text )
920 result = _print_verbose(mano_response, args.verbose)
921 #provide addional information if error
922 if mano_response.status_code != 200:
923 content = mano_response.json()
924 if "already in use for 'name'" in content['error']['description'] and \
925 "to database vim_tenants table" in content['error']['description']:
926 print "Try to specify a different name with --vim-tenant-name"
927 return result
928
929def datacenter_detach(args):
930 if args.all:
931 tenant = "any"
932 else:
933 tenant = _get_tenant()
934 datacenter = _get_datacenter(args.name, tenant)
935 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
936 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
937 mano_response = requests.delete(URLrequest, headers=headers_req)
938 logger.debug("openmano response: %s", mano_response.text )
939 content = mano_response.json()
940 #print json.dumps(content, indent=4)
941 result = 0 if mano_response.status_code==200 else mano_response.status_code
942 if mano_response.status_code == 200:
943 print content['result']
944 else:
945 print content['error']['description']
946 return result
947
948def datacenter_create(args):
949 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
950 datacenter_dict={"name": args.name, "vim_url": args.url}
951 if args.description!=None:
952 datacenter_dict["description"] = args.description
953 if args.type!=None:
954 datacenter_dict["type"] = args.type
955 if args.url!=None:
956 datacenter_dict["vim_url_admin"] = args.url_admin
957 if args.config!=None:
958 datacenter_dict["config"] = _load_file_or_yaml(args.config)
959 payload_req = json.dumps( {"datacenter": datacenter_dict })
960
961 #print payload_req
962
963 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
964 logger.debug("openmano request: %s", payload_req)
965 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
966 logger.debug("openmano response: %s", mano_response.text )
967 return _print_verbose(mano_response, args.verbose)
968
969def datacenter_delete(args):
970 #print "datacenter-delete",args
971 todelete = _get_item_uuid("datacenters", args.name, "any")
972 if not args.force:
973 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
974 if not (len(r)>0 and r[0].lower()=="y"):
975 return 0
976 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
977 mano_response = requests.delete(URLrequest)
978 logger.debug("openmano response: %s", mano_response.text )
979 result = 0 if mano_response.status_code==200 else mano_response.status_code
980 content = mano_response.json()
981 #print json.dumps(content, indent=4)
982 if mano_response.status_code == 200:
983 print content['result']
984 else:
985 print content['error']['description']
986 return result
987
988def datacenter_list(args):
989 #print "datacenter-list",args
990 tenant='any' if args.all else _get_tenant()
991
992 if args.name:
993 toshow = _get_item_uuid("datacenters", args.name, tenant)
994 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
995 else:
996 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
997 mano_response = requests.get(URLrequest)
998 logger.debug("openmano response: %s", mano_response.text )
999 if args.verbose==None:
1000 args.verbose=0
1001 if args.name!=None:
1002 args.verbose += 1
1003 return _print_verbose(mano_response, args.verbose)
1004
1005def vim_action(args):
1006 #print "datacenter-net-action",args
1007 tenant = _get_tenant()
1008 datacenter = _get_datacenter(args.datacenter, tenant)
1009 if args.verbose==None:
1010 args.verbose=0
1011 if args.action=="list":
1012 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1013 if args.name!=None:
1014 args.verbose += 1
1015 URLrequest += "/" + args.name
1016 mano_response = requests.get(URLrequest)
1017 logger.debug("openmano response: %s", mano_response.text )
1018 return _print_verbose(mano_response, args.verbose)
1019 elif args.action=="delete":
1020 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1021 mano_response = requests.delete(URLrequest)
1022 logger.debug("openmano response: %s", mano_response.text )
1023 result = 0 if mano_response.status_code==200 else mano_response.status_code
1024 content = mano_response.json()
1025 #print json.dumps(content, indent=4)
1026 if mano_response.status_code == 200:
1027 print content['result']
1028 else:
1029 print content['error']['description']
1030 return result
1031 elif args.action=="create":
1032 headers_req = {'content-type': 'application/yaml'}
1033 if args.file:
1034 create_dict = _load_file_or_yaml(args.file)
1035 if args.item not in create_dict:
1036 create_dict = {args.item: create_dict}
1037 else:
1038 create_dict = {args.item:{}}
1039 if args.name:
1040 create_dict[args.item]['name'] = args.name
1041 #if args.description:
1042 # create_dict[args.item]['description'] = args.description
1043 if args.item=="vim-net":
1044 if args.bind_net:
1045 create_dict[args.item]['bind_net'] = args.bind_net
1046 if args.bind_type:
1047 create_dict[args.item]['bind_type'] = args.bind_type
1048 if args.shared:
1049 create_dict[args.item]['shared'] = args.shared
1050 if "name" not in create_dict[args.item]:
1051 print "You must provide a name in the descriptor file or with the --name option"
1052 return
1053 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1054 logger.debug("openmano request: %s", payload_req)
1055 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, mano_tenant, datacenter, args.item)
1056 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1057 logger.debug("openmano response: %s", mano_response.text )
1058 if args.verbose==None:
1059 args.verbose=0
1060 return _print_verbose(mano_response, args.verbose)
1061
1062
1063def datacenter_net_action(args):
1064 if args.action == "net-update":
tierno5acf7202016-08-29 14:28:13 +02001065 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
tierno7edb6752016-03-21 17:37:52 +01001066 print
1067 args.action = "netmap-delete"
1068 args.netmap = None
1069 args.all = True
1070 r = datacenter_netmap_action(args)
1071 if r == 0:
1072 args.force = True
tierno5acf7202016-08-29 14:28:13 +02001073 args.action = "netmap-import"
tierno7edb6752016-03-21 17:37:52 +01001074 r = datacenter_netmap_action(args)
1075 return r
1076
1077 if args.action == "net-edit":
1078 args.netmap = args.net
1079 args.name = None
1080 elif args.action == "net-list":
1081 args.netmap = None
1082 elif args.action == "net-delete":
1083 args.netmap = args.net
1084 args.all = False
1085
1086 args.action = "netmap" + args.action[3:]
1087 args.vim_name=None
1088 args.vim_id=None
1089 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1090 print
1091 return datacenter_netmap_action(args)
1092
1093def datacenter_netmap_action(args):
1094 tenant = _get_tenant()
1095 datacenter = _get_datacenter(args.datacenter, tenant)
1096 #print "datacenter_netmap_action",args
1097 payload_req = None
1098 if args.verbose==None:
1099 args.verbose=0
1100 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1101 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1102
1103 if args.action=="netmap-list":
1104 if args.netmap:
1105 URLrequest += "/" + args.netmap
1106 args.verbose += 1
1107 mano_response = requests.get(URLrequest)
1108
1109 elif args.action=="netmap-delete":
1110 if args.netmap and args.all:
1111 print "you can not use a netmap name and the option --all at the same time"
1112 return 1
1113 if args.netmap:
1114 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1115 URLrequest += "/" + args.netmap
1116 elif args.all:
1117 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1118 else:
tiernoae4a8d12016-07-08 12:30:39 +02001119 print "you must specify a netmap name or the option --all"
tierno7edb6752016-03-21 17:37:52 +01001120 return 1
1121 if not args.force:
1122 r = raw_input(force_text)
1123 if len(r)>0 and r[0].lower()=="y":
1124 pass
1125 else:
1126 return 0
1127 mano_response = requests.delete(URLrequest, headers=headers_req)
tierno5acf7202016-08-29 14:28:13 +02001128 elif args.action=="netmap-import":
tierno7edb6752016-03-21 17:37:52 +01001129 if not args.force:
1130 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1131 if len(r)>0 and r[0].lower()=="y":
1132 pass
1133 else:
1134 return 0
1135 URLrequest += "/upload"
1136 mano_response = requests.post(URLrequest, headers=headers_req)
1137 elif args.action=="netmap-edit" or args.action=="netmap-create":
1138 if args.file:
1139 payload = _load_file_or_yaml(args.file)
1140 else:
1141 payload = {}
1142 if "netmap" not in payload:
1143 payload = {"netmap": payload}
1144 if args.name:
1145 payload["netmap"]["name"] = args.name
1146 if args.vim_id:
1147 payload["netmap"]["vim_id"] = args.vim_id
1148 if args.action=="netmap-create" and args.vim_name:
1149 payload["netmap"]["vim_name"] = args.vim_name
1150 payload_req = json.dumps(payload)
1151 logger.debug("openmano request: %s", payload_req)
1152
1153 if args.action=="netmap-edit" and not args.force:
1154 if len(payload["netmap"]) == 0:
1155 print "You must supply some parameter to edit"
1156 return 1
1157 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1158 if len(r)>0 and r[0].lower()=="y":
1159 pass
1160 else:
1161 return 0
1162 URLrequest += "/" + args.netmap
1163 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1164 else: #netmap-create
1165 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1166 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1167 return 1
1168 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1169
1170 logger.debug("openmano response: %s", mano_response.text )
1171 return _print_verbose(mano_response, args.verbose)
1172
1173def element_edit(args):
1174 element = _get_item_uuid(args.element, args.name)
1175 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1176 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1177 payload=_load_file_or_yaml(args.file)
1178 if args.element[:-1] not in payload:
1179 payload = {args.element[:-1]: payload }
1180 payload_req = json.dumps(payload)
1181
1182 #print payload_req
1183 if not args.force or (args.name==None and args.filer==None):
1184 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1185 if len(r)>0 and r[0].lower()=="y":
1186 pass
1187 else:
1188 return 0
1189 logger.debug("openmano request: %s", payload_req)
1190 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1191 logger.debug("openmano response: %s", mano_response.text )
1192 if args.verbose==None:
1193 args.verbose=0
1194 if args.name!=None:
1195 args.verbose += 1
1196 return _print_verbose(mano_response, args.verbose)
1197
1198
1199global mano_host
1200global mano_port
1201global mano_tenant
1202
1203if __name__=="__main__":
1204
1205 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1206 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1207 mano_port = os.getenv('OPENMANO_PORT',"9090")
1208 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1209
1210 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1211 main_parser.add_argument('--version', action='version', version='%(prog)s ' + __version__ )
1212
1213 subparsers = main_parser.add_subparsers(help='commands')
1214
tierno7edb6752016-03-21 17:37:52 +01001215 parent_parser = argparse.ArgumentParser(add_help=False)
1216 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1217 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1218
garciadeblas0e9fd832016-07-08 15:20:18 +02001219 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1220 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1221 config_parser.set_defaults(func=config)
1222
tierno7edb6752016-03-21 17:37:52 +01001223 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1224 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1225 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1226 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1227 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
garciadeblas14480452017-01-10 13:08:07 +01001228 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1229 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
tierno7edb6752016-03-21 17:37:52 +01001230 vnf_create_parser.set_defaults(func=vnf_create)
1231
1232 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1233 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1234 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1235 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1236 vnf_list_parser.set_defaults(func=vnf_list)
1237
1238 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1239 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1240 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1241 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1242 vnf_delete_parser.set_defaults(func=vnf_delete)
1243
1244 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1245 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1246 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1247 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1248 scenario_create_parser.set_defaults(func=scenario_create)
1249
1250 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1251 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1252 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1253 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1254 scenario_list_parser.set_defaults(func=scenario_list)
1255
1256 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1257 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1258 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1259 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1260 scenario_delete_parser.set_defaults(func=scenario_delete)
1261
1262 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1263 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1264 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1265 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1266 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1267 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1268 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1269
1270 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1271 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1272 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1273 scenario_deploy_parser.set_defaults(func=scenario_verify)
1274
1275 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1276 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1277 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1278 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1279 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1280 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1281 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")
1282 instance_scenario_create_parser.add_argument("--netmap-create", action="append", type=str, dest="netmap_create", help="the scenario network must be created at datacenter 'scenario-network[=datacenter-network-name]' . Can be used several times")
tiernoa4e1a6e2016-08-31 14:19:40 +02001283 instance_scenario_create_parser.add_argument("--keypair", action="append", type=str, dest="keypair", help="public key for ssh access. Format '[user:]key1[,key2...]'. Can be used several times")
1284 instance_scenario_create_parser.add_argument("--keypair-auto", action="store_true", dest="keypair_auto", help="Inject the user ssh-keys found at $HOME/.ssh directory")
tierno7edb6752016-03-21 17:37:52 +01001285 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1286 instance_scenario_create_parser.set_defaults(func=instance_create)
1287
1288 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1289 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1290 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1291 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1292
1293 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)")
1294 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1295 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1296 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1297 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1298
1299 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1300 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1301 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1302 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console"],\
1303 help="action to send")
1304 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1305 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1306 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1307 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1308
1309 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1310 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1311 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1312
1313 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1314 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1315 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1316 tenant_create_parser.set_defaults(func=tenant_create)
1317
1318 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1319 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1320 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1321 tenant_delete_parser.set_defaults(func=tenant_delete)
1322
1323 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1324 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1325 tenant_list_parser.set_defaults(func=tenant_list)
1326
1327 item_list=('tenant','datacenter') #put tenant before so that help appear in order
1328 for item in item_list:
1329 element_edit_parser = subparsers.add_parser(item+'-edit', parents=[parent_parser], help="edits one "+item)
1330 element_edit_parser.add_argument("name", help="name or uuid of the "+item)
1331 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1332 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1333 element_edit_parser.set_defaults(func=element_edit, element=item + 's')
1334
1335 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1336 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1337 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1338 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1339 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1340 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1341 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
1342 datacenter_create_parser.set_defaults(func=datacenter_create)
1343
1344 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1345 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1346 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1347 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1348
1349 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1350 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1351 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1352 datacenter_list_parser.set_defaults(func=datacenter_list)
1353
1354 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1355 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1356 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1357 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1358 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1359 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
tierno8008c3a2016-10-13 15:34:28 +00001360 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
tierno7edb6752016-03-21 17:37:52 +01001361 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1362
1363 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1364 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1365 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1366 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1367
1368
1369 action_dict={'net-update': 'retrieves external networks from datacenter',
1370 'net-edit': 'edits an external network',
1371 'net-delete': 'deletes an external network',
1372 'net-list': 'lists external networks from a datacenter'
1373 }
1374 for item in action_dict:
1375 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1376 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1377 if item=='net-edit' or item=='net-delete':
1378 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1379 if item=='net-edit':
1380 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1381 if item!='net-list':
1382 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1383 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1384
1385
tierno5acf7202016-08-29 14:28:13 +02001386 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
tierno7edb6752016-03-21 17:37:52 +01001387 'netmap-create': 'create a new network senario netmap',
1388 'netmap-edit': 'edit name of a network senario netmap',
1389 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1390 'netmap-list': 'list/show network scenario netmaps'
1391 }
1392 for item in action_dict:
1393 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1394 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1395 #if item=='net-add':
1396 # datacenter_action_parser.add_argument("net", help="name of the network")
1397 if item=='netmap-delete':
1398 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1399 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1400 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1401 if item=='netmap-edit':
1402 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1403 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1404 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1405 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1406 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1407 if item=='netmap-list':
1408 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1409 if item=='netmap-create':
1410 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1411 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1412 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1413 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
tierno5acf7202016-08-29 14:28:13 +02001414 if item=='netmap-import':
tierno7edb6752016-03-21 17:37:52 +01001415 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1416 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
1417
1418 for item in ("network", "tenant"):
1419 if item=="network":
1420 commnad_name = 'vim-net'
1421 else:
1422 commnad_name = 'vim-'+item
1423 vim_item_list_parser = subparsers.add_parser(commnad_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
1424 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
1425 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1426 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
1427
1428 vim_item_del_parser = subparsers.add_parser(commnad_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
1429 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
1430 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1431 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
1432
1433 vim_item_create_parser = subparsers.add_parser(commnad_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
1434 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
1435 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
1436 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1437 if item=="network":
1438 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
1439 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
1440 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>'")
1441 else:
1442 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
1443 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
1444
1445 argcomplete.autocomplete(main_parser)
1446
1447 try:
1448 args = main_parser.parse_args()
1449 #logging info
1450 level = logging.CRITICAL
1451 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
1452 if "debug" in args and args.debug:
1453 level = logging.DEBUG
1454 logging.basicConfig(format=streamformat, level= level)
1455 logger = logging.getLogger('mano')
1456 logger.setLevel(level)
1457 result = args.func(args)
1458 if result == None:
1459 result = 0
1460 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
1461 except (requests.exceptions.ConnectionError):
1462 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
1463 result = -2
1464 except (KeyboardInterrupt):
1465 print 'Exiting openmano'
1466 result = -3
1467 except (SystemExit, ArgumentParserError):
1468 result = -4
1469 except OpenmanoCLIError as e:
1470 print str(e)
1471 result = -5
1472
1473 #print result
1474 exit(result)
1475