new API v3 that consumes OSM IM models
[osm/RO.git] / openmano
1 #!/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 """
27 openmano client used to interact with openmano-server (openmanod) 
28 """
29 __author__ = "Alfonso Tierno, Gerardo Garcia, Pablo Montes"
30 __date__ = "$09-oct-2014 09:09:48$"
31 __version__ = "0.4.20-r530"
32 version_date = "Sep 2017"
33
34 from argcomplete.completers import FilesCompleter
35 import os
36 import argparse
37 import argcomplete
38 import requests
39 import json
40 import yaml
41 import logging
42 #from jsonschema import validate as js_v, exceptions as js_e
43
44 class ArgumentParserError(Exception): pass
45
46 class OpenmanoCLIError(Exception): pass
47
48 class 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
59 def config(args):
60     print "OPENMANO_HOST: %s" %mano_host
61     print "OPENMANO_PORT: %s" %mano_port
62     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)
93
94 def _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         uuid = None
124         for content in content_list:
125             if "uuid" in content:
126                 uuid = content['uuid']
127             elif "id" in content:
128                 uuid = content['id']
129             elif "vim_id" in content:
130                 uuid = content['vim_id']
131             name = content.get('name');
132             if not uuid:
133                 uuid = ""
134             if not name:
135                 name = ""
136             myoutput = "%s %s" %(uuid.ljust(38),name.ljust(20))
137             if content.get("status"):
138                 myoutput += " " + content['status'].ljust(20)
139             elif "enabled" in content and not content["enabled"]:
140                 myoutput += " enabled=False".ljust(20)
141             if verbose_level >=1:
142                 if content.get('created_at'):
143                     myoutput += " " + content['created_at'].ljust(20)
144                 if content.get('sdn_attached_ports'):
145                     #myoutput += " " + str(content['sdn_attached_ports']).ljust(20)
146                     myoutput += "\nsdn_attached_ports:\n" + yaml.safe_dump(content['sdn_attached_ports'], indent=4, default_flow_style=False)
147                 if verbose_level >=2:
148                     new_line='\n'
149                     if content.get('type'):
150                         myoutput += new_line + "  Type: " + content['type'].ljust(29)
151                         new_line=''
152                     if content.get('description'):
153                         myoutput += new_line + "  Description: " + content['description'].ljust(20)
154             print myoutput
155     else:
156         print content['error']['description']
157     return result
158
159 def parser_json_yaml(file_name):
160     try:
161         f = file(file_name, "r")
162         text = f.read()
163         f.close()
164     except Exception as e:
165         return (False, str(e))
166            
167     #Read and parse file
168     if file_name[-5:]=='.yaml' or file_name[-4:]=='.yml' or (file_name[-5:]!='.json' and '\t' not in text):
169         try:
170             config = yaml.load(text)
171         except yaml.YAMLError as exc:
172             error_pos = ""
173             if hasattr(exc, 'problem_mark'):
174                 mark = exc.problem_mark
175                 error_pos = " at line:%s column:%s" % (mark.line+1, mark.column+1)
176             return (False, "Error loading file '"+file_name+"' yaml format error" + error_pos)
177     else: #json
178         try:
179             config = json.loads(text) 
180         except Exception as e:
181             return (False, "Error loading file '"+file_name+"' json format error " + str(e) )
182
183     return True, config
184
185 def _load_file_or_yaml(content):
186     '''
187     'content' can be or a yaml/json file or a text containing a yaml/json text format
188     This function autodetect, trying to load and parse the file,
189     if fails trying to parse the 'content' text
190     Returns the dictionary once parsed, or print an error and finish the program
191     '''
192     #Check config file exists
193     if os.path.isfile(content):
194         r,payload = parser_json_yaml(content)
195         if not r:
196             print payload
197             exit(-1)
198     elif "{" in content or ":" in content:
199         try:
200             payload = yaml.load(content)
201         except yaml.YAMLError as exc:
202             error_pos = ""
203             if hasattr(exc, 'problem_mark'):
204                 mark = exc.problem_mark
205                 error_pos = " at position: (%s:%s)" % (mark.line+1, mark.column+1)
206             print "Error loading yaml/json text"+error_pos
207             exit (-1)
208     else:
209         print "'%s' is neither a valid file nor a yaml/json content" % content
210         exit(-1)
211     return payload
212
213 def _get_item_uuid(item, item_name_id, tenant=None):
214     if tenant:
215         URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, tenant, item)
216     else:
217         URLrequest = "http://%s:%s/openmano/%s" %(mano_host, mano_port, item)
218     mano_response = requests.get(URLrequest)
219     logger.debug("openmano response: %s", mano_response.text )
220     content = mano_response.json()
221     #print content
222     found = 0
223     for i in content[item]:
224         if i["uuid"] == item_name_id:
225             return item_name_id
226         if i["name"] == item_name_id:
227             uuid = i["uuid"]
228             found += 1
229         if item_name_id.startswith("osm_id=") and i.get("osm_id") == item_name_id[7:]:
230             uuid = i["uuid"]
231             found += 1
232     if found == 0:
233         raise OpenmanoCLIError("No %s found with name/uuid '%s'" %(item[:-1], item_name_id))
234     elif found > 1:
235         raise OpenmanoCLIError("%d %s found with name '%s'. uuid must be used" %(found, item, item_name_id))
236     return uuid
237
238 # def check_valid_uuid(uuid):
239 #     id_schema = {"type" : "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
240 #     try:
241 #         js_v(uuid, id_schema)
242 #         return True
243 #     except js_e.ValidationError:
244 #         return False
245     
246 def _get_tenant(tenant_name_id = None):
247     if not tenant_name_id:
248         tenant_name_id = mano_tenant
249         if not mano_tenant:
250             raise OpenmanoCLIError("'OPENMANO_TENANT' environment variable is not set")
251     return _get_item_uuid("tenants", tenant_name_id)
252
253 def _get_datacenter(datacenter_name_id = None, tenant = "any"):
254     if not datacenter_name_id:
255         datacenter_name_id = mano_datacenter
256         if not datacenter_name_id:
257             raise OpenmanoCLIError("neither 'OPENMANO_DATACENTER' environment variable is set nor --datacenter option is used")
258     return _get_item_uuid("datacenters", datacenter_name_id, tenant)
259
260 def vnf_create(args):
261     #print "vnf-create",args
262     headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
263     tenant = _get_tenant()
264     myvnf = _load_file_or_yaml(args.file)
265     api_version = ""
266     if "vnfd:vnfd-catalog" in myvnf or "vnfd-catalog" in myvnf:
267         api_version = "/v3"
268         token = "vnfd"
269         vnfd_catalog = myvnf.get("vnfd:vnfd-catalog")
270         if not vnfd_catalog:
271             vnfd_catalog = myvnf.get("vnfd-catalog")
272         vnfds = vnfd_catalog.get("vnfd:vnfd")
273         if not vnfds:
274             vnfds = vnfd_catalog.get("vnfd")
275         vnfd = vnfds[0]
276         vdu_list = vnfd["vdu"]
277
278     else:  # old API
279         api_version = ""
280         token = "vnfs"
281         vnfd = myvnf['vnf']
282         vdu_list = vnfd["VNFC"]
283
284     if args.name or args.description or args.image_path or args.image_name or args.image_checksum:
285         # TODO, change this for API v3
286         # print args.name
287         try:
288             if args.name:
289                 vnfd['name'] = args.name
290             if args.description:
291                 vnfd['description'] = args.description
292             if args.image_path:
293                 index = 0
294                 for image_path_ in args.image_path.split(","):
295                     # print "image-path", image_path_
296                     if api_version == "/v3":
297                         if vdu_list[index].get("image"):
298                             vdu_list[index]['image'] = image_path_
299                             if "image-checksum" in vdu_list[index]:
300                                 del vdu_list[index]["image-checksum"]
301                         else:  # image name in volumes
302                             vdu_list[index]["volumes"][0]["image"] = image_path_
303                             if "image-checksum" in vdu_list[index]["volumes"][0]:
304                                 del vdu_list[index]["volumes"][0]["image-checksum"]
305                     else:
306                         vdu_list[index]['VNFC image'] = image_path_
307                         if "image name" in vdu_list[index]:
308                             del vdu_list[index]["image name"]
309                         if "image checksum" in vdu_list[index]:
310                             del vdu_list[index]["image checksum"]
311                     index += 1
312             if args.image_name:  # image name precedes if both are supplied
313                 index = 0
314                 for image_name_ in args.image_name.split(","):
315                     if api_version == "/v3":
316                         if vdu_list[index].get("image"):
317                             vdu_list[index]['image'] = image_name_
318                             if "image-checksum" in vdu_list[index]:
319                                 del vdu_list[index]["image-checksum"]
320                         else:  # image name in volumes
321                             vdu_list[index]["volumes"][0]["image"] = image_name_
322                             if "image-checksum" in vdu_list[index]["volumes"][0]:
323                                 del vdu_list[index]["volumes"][0]["image-checksum"]
324                     else:
325                         vdu_list[index]['image name'] = image_name_
326                         if "VNFC image" in vdu_list[index]:
327                             del vdu_list[index]["VNFC image"]
328                     index += 1
329             if args.image_checksum:
330                 index = 0
331                 for image_checksum_ in args.image_checksum.split(","):
332                     if api_version == "/v3":
333                         if vdu_list[index].get("image"):
334                             vdu_list[index]['image-checksum'] = image_checksum_
335                         else:  # image name in volumes
336                             vdu_list[index]["volumes"][0]["image-checksum"] = image_checksum_
337                     else:
338                         vdu_list[index]['image checksum'] = image_checksum_
339                     index += 1
340         except (KeyError, TypeError), e:
341             if str(e) == 'vnf':           error_pos= "missing field 'vnf'"
342             elif str(e) == 'name':        error_pos= "missing field  'vnf':'name'"
343             elif str(e) == 'description': error_pos= "missing field  'vnf':'description'"
344             elif str(e) == 'VNFC':        error_pos= "missing field  'vnf':'VNFC'"
345             elif str(e) == str(index):    error_pos= "field  'vnf':'VNFC' must be an array"
346             elif str(e) == 'VNFC image':  error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
347             elif str(e) == 'image name':  error_pos= "missing field 'vnf':'VNFC'['image name']"
348             elif str(e) == 'image checksum':  error_pos= "missing field 'vnf':'VNFC'['image checksum']"
349             else:                       error_pos="wrong format"
350             print "Wrong VNF descriptor: " + error_pos
351             return -1 
352     payload_req = json.dumps(myvnf)
353         
354     #print payload_req
355         
356     URLrequest = "http://{}:{}/openmano{}/{}/{token}".format(mano_host, mano_port, api_version, tenant, token=token)
357     logger.debug("openmano request: %s", payload_req)
358     mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
359     logger.debug("openmano response: %s", mano_response.text )
360
361     return _print_verbose(mano_response, args.verbose)
362
363 def vnf_list(args):
364     #print "vnf-list",args
365     if args.all:
366         tenant = "any"
367     else:
368         tenant = _get_tenant()
369     if args.name:
370         toshow = _get_item_uuid("vnfs", args.name, tenant)
371         URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
372     else:
373         URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
374     mano_response = requests.get(URLrequest)
375     logger.debug("openmano response: %s", mano_response.text )
376     content = mano_response.json()
377     # print json.dumps(content, indent=4)
378     if args.verbose==None:
379         args.verbose=0
380     result = 0 if mano_response.status_code==200 else mano_response.status_code
381     if mano_response.status_code == 200:
382         if not args.name:
383             if args.verbose >= 3:
384                 print yaml.safe_dump(content, indent=4, default_flow_style=False)
385                 return result
386             if len(content['vnfs']) == 0:
387                 print "No VNFs were found."
388                 return 404   # HTTP_Not_Found
389             for vnf in content['vnfs']:
390                 myoutput = "{:38} {:20}".format(vnf['uuid'], vnf['name'])
391                 if vnf.get('osm_id') or args.verbose >= 1:
392                     myoutput += " osm_id={:20}".format(vnf.get('osm_id'))
393                 if args.verbose >= 1:
394                     myoutput += " {}".format(vnf['created_at'])
395                 print (myoutput)
396                 if args.verbose >= 2:
397                     print ("  Description: {}".format(vnf['description']))
398                     # print ("  VNF descriptor file: {}".format(vnf['path']))
399         else:
400             if args.verbose:
401                 print yaml.safe_dump(content, indent=4, default_flow_style=False)
402                 return result
403             vnf = content['vnf']
404             print ("{:38} {:20} osm_id={:20} {:20}".format(vnf['uuid'], vnf['name'], vnf.get('osm_id'),
405                                                            vnf['created_at']))
406             print ("  Description: {}".format(vnf['description']))
407             # print "  VNF descriptor file: %s" %vnf['path']
408             print ("  VMs:")
409             for vm in vnf['VNFC']:
410                 print ("    {:20} osm_id={:20} {}".format(vm['name'], vm.get('osm_id'), vm['description']))
411             if len(vnf['nets']) > 0:
412                 print ("  Internal nets:")
413                 for net in vnf['nets']:
414                     print ("    {:20} {}".format(net['name'], net['description']))
415             if len(vnf['external-connections']) > 0:
416                 print ("  External interfaces:")
417                 for interface in vnf['external-connections']:
418                     print ("    {:20} {:20} {:20} {:14}".format(
419                         interface['external_name'], interface['vm_name'],
420                         interface['internal_name'],
421                         interface.get('vpci') if interface.get('vpci') else ""))
422     else:
423         print content['error']['description']
424         if args.verbose:
425             print yaml.safe_dump(content, indent=4, default_flow_style=False)
426     return result
427
428 def vnf_delete(args):
429     #print "vnf-delete",args
430     if args.all:
431         tenant = "any"
432     else:
433         tenant = _get_tenant()
434     todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
435     if not args.force:
436         r = raw_input("Delete VNF %s (y/N)? " %(todelete))
437         if  not (len(r)>0  and r[0].lower()=="y"):
438             return 0
439     URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
440     mano_response = requests.delete(URLrequest)
441     logger.debug("openmano response: %s", mano_response.text )
442     result = 0 if mano_response.status_code==200 else mano_response.status_code
443     content = mano_response.json()
444     #print json.dumps(content, indent=4)
445     if mano_response.status_code == 200:
446         print content['result']
447     else:
448         print content['error']['description']
449     return result
450
451 def scenario_create(args):
452     # print "scenario-create",args
453     tenant = _get_tenant()
454     headers_req = {'content-type': 'application/yaml'}
455     myscenario = _load_file_or_yaml(args.file)
456     if "nsd:nsd-catalog" in myscenario or "nsd-catalog" in myscenario:
457         api_version = "/v3"
458         token = "nsd"
459         nsd_catalog = myscenario.get("nsd:nsd-catalog")
460         if not nsd_catalog:
461             nsd_catalog = myscenario.get("nsd-catalog")
462         nsds = nsd_catalog.get("nsd:nsd")
463         if not nsds:
464             nsds = nsd_catalog.get("nsd")
465         nsd = nsds[0]
466     else:  # API<v3
467         api_version = ""
468         token = "scenarios"
469         if "scenario" in myscenario:
470             nsd = myscenario["scenario"]
471         else:
472             nsd = myscenario
473     # TODO modify for API v3
474     if args.name:
475         nsd['name'] = args.name
476     if args.description:
477         nsd['description'] = args.description
478     payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False,
479                                  encoding='utf-8', allow_unicode=True)
480     
481     # print payload_req
482     URLrequest = "http://{host}:{port}/openmano{api}/{tenant}/{token}".format(
483         host=mano_host, port=mano_port, api=api_version, tenant=tenant, token=token)
484     logger.debug("openmano request: %s", payload_req)
485     mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
486     logger.debug("openmano response: %s", mano_response.text )
487     return _print_verbose(mano_response, args.verbose)
488
489 def scenario_list(args):
490     #print "scenario-list",args
491     if args.all:
492         tenant = "any"
493     else:
494         tenant = _get_tenant()
495     if args.name:
496         toshow = _get_item_uuid("scenarios", args.name, tenant)
497         URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
498     else:
499         URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
500     mano_response = requests.get(URLrequest)
501     logger.debug("openmano response: %s", mano_response.text )
502     content = mano_response.json()
503     #print json.dumps(content, indent=4)
504     if args.verbose==None:
505         args.verbose=0
506
507     result = 0 if mano_response.status_code==200 else mano_response.status_code
508     if mano_response.status_code == 200:
509         if not args.name:
510             if args.verbose >= 3:
511                 print yaml.safe_dump(content, indent=4, default_flow_style=False)
512                 return result
513             if len(content['scenarios']) == 0:
514                 print "No scenarios were found."
515                 return 404 #HTTP_Not_Found
516             for scenario in content['scenarios']:
517                 myoutput = "{:38} {:20}".format(scenario['uuid'], scenario['name'])
518                 if scenario.get('osm_id') or args.verbose >= 1:
519                     myoutput += " osm_id={:20}".format(scenario.get('osm_id'))
520                 if args.verbose >= 1:
521                     myoutput += " {}".format(scenario['created_at'])
522                 print (myoutput)
523                 if args.verbose >=2:
524                     print ("  Description: {}".format(scenario['description']))
525         else:
526             if args.verbose:
527                 print yaml.safe_dump(content, indent=4, default_flow_style=False)
528                 return result
529             scenario = content['scenario']
530             print ("{:38} {:20} osm_id={:20} {:20}".format(scenario['uuid'], scenario['name'], scenario.get('osm_id'),
531                                                            scenario['created_at']))
532             print ("  Description: {}".format(scenario['description']))
533             print ("  VNFs:")
534             for vnf in scenario['vnfs']:
535                 print ("    {:38} {:20} vnf_index={} {}".format(vnf['vnf_id'], vnf['name'], vnf.get("member_vnf_index"),
536                                                                 vnf['description']))
537             if len(scenario['nets']) > 0:
538                 print ("  nets:")
539                 for net in scenario['nets']:
540                     description = net['description']
541                     if not description:   # if description does not exist, description is "-". Valid for external and internal nets.
542                         description = '-'
543                     vim_id = ""
544                     if net.get('vim_id'):
545                         vim_id = " vim_id=" + net["vim_id"]
546                     external = ""
547                     if net["external"]:
548                         external = " external"
549                     print ("    {:20} {:38} {:30}{}{}".format(net['name'], net['uuid'], description, vim_id, external))
550     else:
551         print (content['error']['description'])
552         if args.verbose:
553             print yaml.safe_dump(content, indent=4, default_flow_style=False)
554     return result
555
556 def scenario_delete(args):
557     #print "scenario-delete",args
558     if args.all:
559         tenant = "any"
560     else:
561         tenant = _get_tenant()
562     todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
563     if not args.force:
564         r = raw_input("Delete scenario %s (y/N)? " %(args.name))
565         if  not (len(r)>0  and r[0].lower()=="y"):
566             return 0
567     URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
568     mano_response = requests.delete(URLrequest)
569     logger.debug("openmano response: %s", mano_response.text )
570     result = 0 if mano_response.status_code==200 else mano_response.status_code
571     content = mano_response.json()
572     #print json.dumps(content, indent=4)
573     if mano_response.status_code == 200:
574         print content['result']
575     else:
576         print content['error']['description']
577     return result
578
579 def scenario_deploy(args):
580     print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
581     print
582     args.file = None
583     args.netmap_use = None
584     args.netmap_create = None
585     args.keypair = None
586     args.keypair_auto = None
587     return instance_create(args)
588
589 #     #print "scenario-deploy",args
590 #     headers_req = {'content-type': 'application/json'}
591 #     action = {}
592 #     actionCmd="start"
593 #     if args.nostart:
594 #         actionCmd="reserve"
595 #     action[actionCmd] = {}
596 #     action[actionCmd]["instance_name"] = args.name
597 #     if args.datacenter != None:
598 #         action[actionCmd]["datacenter"] = args.datacenter
599 #     elif mano_datacenter != None:
600 #         action[actionCmd]["datacenter"] = mano_datacenter
601 #         
602 #     if args.description:
603 #         action[actionCmd]["description"] = args.description
604 #     payload_req = json.dumps(action, indent=4)
605 #     #print payload_req
606
607 #     URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
608 #     logger.debug("openmano request: %s", payload_req)
609 #     mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
610 #     logger.debug("openmano response: %s", mano_response.text )
611 #     if args.verbose==None:
612 #         args.verbose=0
613 #     
614 #     result = 0 if mano_response.status_code==200 else mano_response.status_code
615 #     content = mano_response.json()
616 #     #print json.dumps(content, indent=4)
617 #     if args.verbose >= 3:
618 #         print yaml.safe_dump(content, indent=4, default_flow_style=False)
619 #         return result
620
621 #     if mano_response.status_code == 200:
622 #         myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
623 #         if args.verbose >=1:
624 #             myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
625 #         if args.verbose >=2:
626 #             myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
627 #         print myoutput
628 #         print ""
629 #         print "To check the status, run the following command:"
630 #         print "openmano instance-scenario-list <instance_id>"
631 #     else:
632 #         print content['error']['description']
633 #     return result
634
635 def scenario_verify(args):
636     #print "scenario-verify",args
637     tenant = _get_tenant()
638     headers_req = {'content-type': 'application/json'}
639     action = {}
640     action["verify"] = {}
641     action["verify"]["instance_name"] = "scen-verify-return5"
642     payload_req = json.dumps(action, indent=4)
643     #print payload_req
644
645     URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, tenant, args.scenario)
646     logger.debug("openmano request: %s", payload_req)
647     mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
648     logger.debug("openmano response: %s", mano_response.text )
649     
650     result = 0 if mano_response.status_code==200 else mano_response.status_code
651     content = mano_response.json()
652     #print json.dumps(content, indent=4)
653     if mano_response.status_code == 200:
654         print content['result']
655     else:
656         print content['error']['description']
657     return result
658
659 def instance_create(args):
660     tenant = _get_tenant()
661     headers_req = {'content-type': 'application/yaml'}
662     myInstance={"instance": {}, "schema_version": "0.1"}
663     if args.file:
664         instance_dict = _load_file_or_yaml(args.file)
665         if "instance" not in instance_dict:
666             myInstance = {"instance": instance_dict, "schema_version": "0.1"}
667         else:
668             myInstance = instance_dict
669     if args.name:
670         myInstance["instance"]['name'] = args.name
671     if args.description:
672         myInstance["instance"]['description'] = args.description
673     if args.nostart:
674         myInstance["instance"]['action'] = "reserve"
675     #datacenter
676     datacenter = myInstance["instance"].get("datacenter")
677     if args.datacenter != None:
678         datacenter = args.datacenter
679     myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
680     #scenario
681     scenario = myInstance["instance"].get("scenario")
682     if args.scenario != None:
683         scenario = args.scenario
684     if not scenario:
685         print "you must provide a scenario in the file descriptor or with --scenario"
686         return -1
687     myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
688     if args.netmap_use:
689         if "networks" not in myInstance["instance"]:
690             myInstance["instance"]["networks"] = {}
691         for net in args.netmap_use:
692             net_comma_list = net.split(",")
693             for net_comma in net_comma_list:
694                 net_tuple = net_comma.split("=")
695                 if len(net_tuple) != 2:
696                     print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
697                     return
698                 net_scenario   = net_tuple[0].strip()
699                 net_datacenter = net_tuple[1].strip()
700                 if net_scenario not in myInstance["instance"]["networks"]:
701                     myInstance["instance"]["networks"][net_scenario] = {} 
702                 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
703                     myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
704                 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
705     if args.netmap_create:
706         if "networks" not in myInstance["instance"]:
707             myInstance["instance"]["networks"] = {}
708         for net in args.netmap_create:
709             net_comma_list = net.split(",")
710             for net_comma in net_comma_list:
711                 net_tuple = net_comma.split("=")
712                 if len(net_tuple) == 1:
713                     net_scenario   = net_tuple[0].strip()
714                     net_datacenter = None
715                 elif len(net_tuple) == 2:
716                     net_scenario   = net_tuple[0].strip()
717                     net_datacenter = net_tuple[1].strip()
718                 else:
719                     print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
720                     return
721                 if net_scenario not in myInstance["instance"]["networks"]:
722                     myInstance["instance"]["networks"][net_scenario] = {} 
723                 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
724                     myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
725                 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
726     if args.keypair:
727         if "cloud-config" not in myInstance["instance"]:
728             myInstance["instance"]["cloud-config"] = {}
729         cloud_config = myInstance["instance"]["cloud-config"]
730         for key in args.keypair:
731             index = key.find(":")
732             if index<0:
733                 if "key-pairs" not in cloud_config:
734                     cloud_config["key-pairs"] = []
735                 cloud_config["key-pairs"].append(key)
736             else:
737                 user = key[:index]
738                 key_ = key[index+1:]
739                 key_list = key_.split(",")
740                 if "users" not in cloud_config:
741                     cloud_config["users"] = []
742                 cloud_config["users"].append({"name": user, "key-pairs": key_list  })
743     if args.keypair_auto:
744         try:
745             keys=[]
746             home = os.getenv("HOME")
747             user = os.getenv("USER")
748             files = os.listdir(home+'/.ssh')
749             for file in files:
750                 if file[-4:] == ".pub":
751                     with open(home+'/.ssh/'+file, 'r') as f:
752                         keys.append(f.read())
753             if not keys:
754                 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
755                 return 1
756         except Exception as e:
757             print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
758             return 1
759         
760         if "cloud-config" not in myInstance["instance"]:
761             myInstance["instance"]["cloud-config"] = {}
762         cloud_config = myInstance["instance"]["cloud-config"]
763         if "key-pairs" not in cloud_config:
764             cloud_config["key-pairs"] = []
765         if user:
766             if "users" not in cloud_config:
767                 cloud_config["users"] = []
768             cloud_config["users"].append({"name": user, "key-pairs": keys })                    
769                         
770     payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
771     logger.debug("openmano request: %s", payload_req)
772     URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
773     mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
774     logger.debug("openmano response: %s", mano_response.text )
775     if args.verbose==None:
776         args.verbose=0
777     
778     result = 0 if mano_response.status_code==200 else mano_response.status_code
779     content = mano_response.json()
780     #print json.dumps(content, indent=4)
781     if args.verbose >= 3:
782         print yaml.safe_dump(content, indent=4, default_flow_style=False)
783         return result
784
785     if mano_response.status_code == 200:
786         myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
787         if args.verbose >=1:
788             myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
789         if args.verbose >=2:
790             myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
791         print myoutput
792     else:
793         print content['error']['description']
794     return result
795
796 def instance_scenario_list(args):
797     #print "instance-scenario-list",args
798     if args.all:
799         tenant = "any"
800     else:
801         tenant = _get_tenant()
802     if args.name:
803         toshow = _get_item_uuid("instances", args.name, tenant)
804         URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
805     else:
806         URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
807     mano_response = requests.get(URLrequest)
808     logger.debug("openmano response: %s", mano_response.text )
809     content = mano_response.json()
810     #print json.dumps(content, indent=4)
811     if args.verbose==None:
812         args.verbose=0
813
814     result = 0 if mano_response.status_code==200 else mano_response.status_code
815     if mano_response.status_code == 200:
816         if not args.name:
817             if args.verbose >= 3:
818                 print yaml.safe_dump(content, indent=4, default_flow_style=False)
819                 return result
820             if len(content['instances']) == 0:
821                 print "No scenario instances were found."
822                 return result
823             for instance in content['instances']:
824                 myoutput = "%s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20))
825                 if args.verbose >=1:
826                     myoutput = "%s %s" %(myoutput, instance['created_at'].ljust(20))
827                 print myoutput
828                 if args.verbose >=2:
829                     print "Description: %s" %instance['description']
830         else:
831             if args.verbose:
832                 print yaml.safe_dump(content, indent=4, default_flow_style=False)
833                 return result
834             instance = content
835             print "%s %s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20),instance['created_at'].ljust(20))
836             print "Description: %s" %instance['description']
837             print "Template scenario id: %s" %instance['scenario_id']
838             print "Template scenario name: %s" %instance['scenario_name']
839             print "---------------------------------------"
840             print "VNF instances: %d" %len(instance['vnfs'])
841             for vnf in instance['vnfs']:
842                 #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))
843                 print "    %s %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
844             if len(instance['nets'])>0:
845                 print "---------------------------------------"
846                 print "Internal nets:"
847                 for net in instance['nets']:
848                     if net['created']:
849                         print "    %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
850                 print "---------------------------------------"
851                 print "External nets:"
852                 for net in instance['nets']:
853                     if not net['created']:
854                         print "    %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
855             print "---------------------------------------"
856             print "VM instances:"
857             for vnf in instance['vnfs']:
858                 for vm in vnf['vms']:
859                     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'])
860     else:
861         print content['error']['description']
862         if args.verbose:
863             print yaml.safe_dump(content, indent=4, default_flow_style=False)
864     return result
865
866 def instance_scenario_status(args):
867     print "instance-scenario-status"
868     return 0
869
870 def instance_scenario_delete(args):
871     if args.all:
872         tenant = "any"
873     else:
874         tenant = _get_tenant()
875     todelete = _get_item_uuid("instances", args.name, tenant=tenant)
876     #print "instance-scenario-delete",args
877     if not args.force:
878         r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
879         if  not (len(r)>0  and r[0].lower()=="y"):
880             return
881     URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
882     mano_response = requests.delete(URLrequest)
883     logger.debug("openmano response: %s", mano_response.text )
884     result = 0 if mano_response.status_code==200 else mano_response.status_code
885     content = mano_response.json()
886     #print json.dumps(content, indent=4)
887     if mano_response.status_code == 200:
888         print content['result']
889     else:
890         print content['error']['description']
891     return result
892
893 def instance_scenario_action(args):
894     #print "instance-scenario-action", args
895     tenant = _get_tenant()
896     toact = _get_item_uuid("instances", args.name, tenant=tenant)
897     action={}
898     action[ args.action ] = args.param
899     if args.vnf:
900         action["vnfs"] = args.vnf
901     if args.vm:
902         action["vms"] = args.vm
903     
904     headers_req = {'content-type': 'application/json'}
905     payload_req = json.dumps(action, indent=4)
906     URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
907     logger.debug("openmano request: %s", payload_req)
908     mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
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         if args.verbose:
915             print yaml.safe_dump(content, indent=4, default_flow_style=False)
916             return result
917         for uuid,c in content.iteritems():
918             print "%s %s %s" %(uuid.ljust(38), c['name'].ljust(20),c['description'].ljust(20))
919     else:
920         print content['error']['description']
921     return result
922
923
924 def instance_vnf_list(args):
925     print "instance-vnf-list"
926     return 0
927
928 def instance_vnf_status(args):
929     print "instance-vnf-status"
930     return 0
931
932 def tenant_create(args):
933     headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
934     tenant_dict={"name": args.name}
935     if args.description!=None:
936         tenant_dict["description"] = args.description 
937     payload_req = json.dumps( {"tenant": tenant_dict })
938     
939     #print payload_req
940         
941     URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
942     logger.debug("openmano request: %s", payload_req)
943     mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
944     logger.debug("openmano response: %s", mano_response.text )
945     return _print_verbose(mano_response, args.verbose)
946
947 def tenant_list(args):
948     #print "tenant-list",args
949     if args.name:
950         toshow = _get_item_uuid("tenants", args.name)
951         URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
952     else:
953         URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
954     mano_response = requests.get(URLrequest)
955     logger.debug("openmano response: %s", mano_response.text )
956     if args.verbose==None:
957         args.verbose=0
958     if args.name!=None:
959         args.verbose += 1
960     return _print_verbose(mano_response, args.verbose)
961
962 def tenant_delete(args):
963     #print "tenant-delete",args
964     todelete = _get_item_uuid("tenants", args.name)
965     if not args.force:
966         r = raw_input("Delete tenant %s (y/N)? " %(args.name))
967         if  not (len(r)>0  and r[0].lower()=="y"):
968             return 0
969     URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
970     mano_response = requests.delete(URLrequest)
971     logger.debug("openmano response: %s", mano_response.text )
972     result = 0 if mano_response.status_code==200 else mano_response.status_code
973     content = mano_response.json()
974     #print json.dumps(content, indent=4)
975     if mano_response.status_code == 200:
976         print content['result']
977     else:
978         print content['error']['description']
979     return result
980
981 def datacenter_attach(args):
982     tenant = _get_tenant()
983     datacenter = _get_datacenter(args.name)
984     headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
985     
986     datacenter_dict={}
987     if args.vim_tenant_id != None:
988         datacenter_dict['vim_tenant'] = args.vim_tenant_id
989     if args.vim_tenant_name != None:
990         datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
991     if args.user != None:
992         datacenter_dict['vim_username'] = args.user
993     if args.password != None:
994         datacenter_dict['vim_password'] = args.password
995     if args.config!=None:
996         datacenter_dict["config"] = _load_file_or_yaml(args.config)
997     payload_req = json.dumps( {"datacenter": datacenter_dict })
998     
999     #print payload_req
1000         
1001     URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1002     logger.debug("openmano request: %s", payload_req)
1003     mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1004     logger.debug("openmano response: %s", mano_response.text )
1005     result = _print_verbose(mano_response, args.verbose)
1006     #provide addional information if error
1007     if mano_response.status_code != 200:
1008         content = mano_response.json()
1009         if "already in use for  'name'" in content['error']['description'] and \
1010                 "to database vim_tenants table" in content['error']['description']:
1011             print "Try to specify a different name with --vim-tenant-name"
1012     return result
1013
1014
1015 def datacenter_edit_vim_tenant(args):
1016     tenant = _get_tenant()
1017     datacenter = _get_datacenter(args.name)
1018     headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1019
1020     if not (args.vim_tenant_id or args.vim_tenant_name or args.user or args.password or args.config):
1021         raise OpenmanoCLIError("Error. At least one parameter must be updated.")
1022
1023     datacenter_dict = {}
1024     if args.vim_tenant_id != None:
1025         datacenter_dict['vim_tenant'] = args.vim_tenant_id
1026     if args.vim_tenant_name != None:
1027         datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1028     if args.user != None:
1029         datacenter_dict['vim_username'] = args.user
1030     if args.password != None:
1031         datacenter_dict['vim_password'] = args.password
1032     if args.config != None:
1033         datacenter_dict["config"] = _load_file_or_yaml(args.config)
1034     payload_req = json.dumps({"datacenter": datacenter_dict})
1035
1036     # print payload_req
1037
1038     URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" % (mano_host, mano_port, tenant, datacenter)
1039     logger.debug("openmano request: %s", payload_req)
1040     mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1041     logger.debug("openmano response: %s", mano_response.text)
1042     result = _print_verbose(mano_response, args.verbose)
1043
1044     return result
1045
1046 def datacenter_detach(args):
1047     if args.all:
1048         tenant = "any"
1049     else:
1050         tenant = _get_tenant()
1051     datacenter = _get_datacenter(args.name, tenant)
1052     headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1053     URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1054     mano_response = requests.delete(URLrequest, headers=headers_req)
1055     logger.debug("openmano response: %s", mano_response.text )
1056     content = mano_response.json()
1057     #print json.dumps(content, indent=4)
1058     result = 0 if mano_response.status_code==200 else mano_response.status_code
1059     if mano_response.status_code == 200:
1060         print content['result']
1061     else:
1062         print content['error']['description']
1063     return result
1064
1065 def datacenter_create(args):
1066     headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1067     datacenter_dict={"name": args.name, "vim_url": args.url}
1068     if args.description!=None:
1069         datacenter_dict["description"] = args.description 
1070     if args.type!=None:
1071         datacenter_dict["type"] = args.type 
1072     if args.url!=None:
1073         datacenter_dict["vim_url_admin"] = args.url_admin 
1074     if args.config!=None:
1075         datacenter_dict["config"] = _load_file_or_yaml(args.config)
1076     if args.sdn_controller!=None:
1077         tenant = _get_tenant()
1078         sdn_controller = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1079         if not 'config' in datacenter_dict:
1080             datacenter_dict['config'] = {}
1081         datacenter_dict['config']['sdn-controller'] = sdn_controller
1082     payload_req = json.dumps( {"datacenter": datacenter_dict })
1083     
1084     #print payload_req
1085         
1086     URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
1087     logger.debug("openmano request: %s", payload_req)
1088     mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1089     logger.debug("openmano response: %s", mano_response.text )
1090     return _print_verbose(mano_response, args.verbose)
1091
1092 def datacenter_delete(args):
1093     #print "datacenter-delete",args
1094     todelete = _get_item_uuid("datacenters", args.name, "any")
1095     if not args.force:
1096         r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
1097         if  not (len(r)>0  and r[0].lower()=="y"):
1098             return 0
1099     URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
1100     mano_response = requests.delete(URLrequest)
1101     logger.debug("openmano response: %s", mano_response.text )
1102     result = 0 if mano_response.status_code==200 else mano_response.status_code
1103     content = mano_response.json()
1104     #print json.dumps(content, indent=4)
1105     if mano_response.status_code == 200:
1106         print content['result']
1107     else:
1108         print content['error']['description']
1109     return result
1110
1111
1112 def datacenter_list(args):
1113     #print "datacenter-list",args
1114     tenant='any' if args.all else _get_tenant()
1115     
1116     if args.name:
1117         toshow = _get_item_uuid("datacenters", args.name, tenant) 
1118         URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
1119     else:
1120         URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
1121     mano_response = requests.get(URLrequest)
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
1130 def datacenter_sdn_port_mapping_set(args):
1131     tenant = _get_tenant()
1132     datacenter = _get_datacenter(args.name, tenant)
1133     headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1134
1135     if not args.file:
1136         raise OpenmanoCLIError(
1137             "No yaml/json has been provided specifying the SDN port mapping")
1138     sdn_port_mapping = _load_file_or_yaml(args.file)
1139     payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping})
1140
1141     # read
1142     URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1143     mano_response = requests.get(URLrequest)
1144     logger.debug("openmano response: %s", mano_response.text)
1145     port_mapping = mano_response.json()
1146     if mano_response.status_code != 200:
1147         str(mano_response.json())
1148         raise OpenmanoCLIError("openmano client error: {}".format(port_mapping['error']['description']))
1149     if len(port_mapping["sdn_port_mapping"]["ports_mapping"]) > 0:
1150         if not args.force:
1151             r = raw_input("Datacenter %s already contains a port mapping. Overwrite? (y/N)? " % (datacenter))
1152             if not (len(r) > 0 and r[0].lower() == "y"):
1153                 return 0
1154
1155         # clear
1156         URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1157         mano_response = requests.delete(URLrequest)
1158         logger.debug("openmano response: %s", mano_response.text)
1159         if mano_response.status_code != 200:
1160             return _print_verbose(mano_response, args.verbose)
1161
1162     # set
1163     URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1164     logger.debug("openmano request: %s", payload_req)
1165     mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1166     logger.debug("openmano response: %s", mano_response.text)
1167     return _print_verbose(mano_response, args.verbose)
1168
1169
1170 def datacenter_sdn_port_mapping_list(args):
1171     tenant = _get_tenant()
1172     datacenter = _get_datacenter(args.name, tenant)
1173
1174     URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1175     mano_response = requests.get(URLrequest)
1176     logger.debug("openmano response: %s", mano_response.text)
1177
1178     return _print_verbose(mano_response, 4)
1179
1180
1181 def datacenter_sdn_port_mapping_clear(args):
1182     tenant = _get_tenant()
1183     datacenter = _get_datacenter(args.name, tenant)
1184
1185     if not args.force:
1186         r = raw_input("Clean SDN port mapping for datacenter %s (y/N)? " %(datacenter))
1187         if not (len(r) > 0 and r[0].lower() == "y"):
1188             return 0
1189
1190     URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1191     mano_response = requests.delete(URLrequest)
1192     logger.debug("openmano response: %s", mano_response.text)
1193
1194     return _print_verbose(mano_response, args.verbose)
1195
1196
1197 def sdn_controller_create(args):
1198     tenant = _get_tenant()
1199     headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1200
1201     error_msg=[]
1202     if not args.ip: error_msg.append("'ip'")
1203     if not args.port: error_msg.append("'port'")
1204     if not args.dpid: error_msg.append("'dpid'")
1205     if not args.type: error_msg.append("'type'")
1206     if error_msg:
1207         raise OpenmanoCLIError("The following arguments are required: " + ",".join(error_msg))
1208
1209     controller_dict = {}
1210     controller_dict['name'] = args.name
1211     controller_dict['ip'] = args.ip
1212     controller_dict['port'] = int(args.port)
1213     controller_dict['dpid'] = args.dpid
1214     controller_dict['type'] = args.type
1215     if args.description != None:
1216         controller_dict['description'] = args.description
1217     if args.user != None:
1218         controller_dict['user'] = args.user
1219     if args.password != None:
1220         controller_dict['password'] = args.password
1221
1222     payload_req = json.dumps({"sdn_controller": controller_dict})
1223
1224     # print payload_req
1225
1226     URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" % (mano_host, mano_port, tenant)
1227     logger.debug("openmano request: %s", payload_req)
1228     mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1229     logger.debug("openmano response: %s", mano_response.text)
1230     result = _print_verbose(mano_response, args.verbose)
1231     return result
1232
1233
1234 def sdn_controller_edit(args):
1235     tenant = _get_tenant()
1236     controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1237     headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1238
1239     controller_dict = {}
1240     if args.new_name:
1241         controller_dict['name'] = args.new_name
1242     if args.ip:
1243         controller_dict['ip'] = args.ip
1244     if args.port:
1245         controller_dict['port'] = int(args.port)
1246     if args.dpid:
1247         controller_dict['dpid'] = args.dpid
1248     if args.type:
1249         controller_dict['type'] = args.type
1250     if args.description:
1251         controller_dict['description'] = args.description
1252     if args.user:
1253         controller_dict['user'] = args.user
1254     if args.password:
1255         controller_dict['password'] = args.password
1256
1257     if not controller_dict:
1258         raise OpenmanoCLIError("At least one parameter must be edited")
1259
1260     if not args.force:
1261         r = raw_input("Update SDN controller {} (y/N)? ".format(args.name))
1262         if not (len(r) > 0 and r[0].lower() == "y"):
1263             return 0
1264
1265     payload_req = json.dumps({"sdn_controller": controller_dict})
1266     # print payload_req
1267
1268     URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1269     logger.debug("openmano request: %s", payload_req)
1270     mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1271     logger.debug("openmano response: %s", mano_response.text)
1272     result = _print_verbose(mano_response, args.verbose)
1273     return result
1274
1275
1276 def sdn_controller_list(args):
1277     tenant = _get_tenant()
1278     headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1279
1280     if args.name:
1281         toshow = _get_item_uuid("sdn_controllers", args.name, tenant)
1282         URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" %(mano_host, mano_port, tenant, toshow)
1283     else:
1284         URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" %(mano_host, mano_port, tenant)
1285     #print URLrequest
1286     mano_response = requests.get(URLrequest)
1287     logger.debug("openmano response: %s", mano_response.text )
1288     if args.verbose==None:
1289         args.verbose=0
1290     if args.name!=None:
1291         args.verbose += 1
1292
1293     # json.dumps(mano_response.json(), indent=4)
1294     return _print_verbose(mano_response, args.verbose)
1295
1296
1297 def sdn_controller_delete(args):
1298     tenant = _get_tenant()
1299     controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1300
1301     if not args.force:
1302         r = raw_input("Delete SDN controller %s (y/N)? " % (args.name))
1303         if not (len(r) > 0 and r[0].lower() == "y"):
1304             return 0
1305
1306     URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1307     mano_response = requests.delete(URLrequest)
1308     logger.debug("openmano response: %s", mano_response.text)
1309     return _print_verbose(mano_response, args.verbose)
1310
1311 def vim_action(args):
1312     #print "datacenter-net-action",args
1313     tenant = _get_tenant()
1314     datacenter = _get_datacenter(args.datacenter, tenant)
1315     if args.verbose==None:
1316         args.verbose=0
1317     if args.action=="list":
1318         URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1319         if args.name!=None:
1320             args.verbose += 1
1321             URLrequest += "/" + args.name
1322         mano_response = requests.get(URLrequest)
1323         logger.debug("openmano response: %s", mano_response.text )
1324         return _print_verbose(mano_response, args.verbose)
1325     elif args.action=="delete":
1326         URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1327         mano_response = requests.delete(URLrequest)
1328         logger.debug("openmano response: %s", mano_response.text )
1329         result = 0 if mano_response.status_code==200 else mano_response.status_code
1330         content = mano_response.json()
1331         #print json.dumps(content, indent=4)
1332         if mano_response.status_code == 200:
1333             print content['result']
1334         else:
1335             print content['error']['description']
1336         return result
1337     elif args.action=="create":
1338         headers_req = {'content-type': 'application/yaml'}
1339         if args.file:
1340             create_dict = _load_file_or_yaml(args.file)
1341             if args.item not in create_dict:
1342                 create_dict = {args.item: create_dict}
1343         else:
1344             create_dict = {args.item:{}}
1345         if args.name:
1346             create_dict[args.item]['name'] = args.name
1347         #if args.description:
1348         #    create_dict[args.item]['description'] = args.description
1349         if args.item=="network":
1350             if args.bind_net:
1351                 create_dict[args.item]['bind_net'] = args.bind_net
1352             if args.type:
1353                 create_dict[args.item]['type'] = args.type
1354             if args.shared:
1355                 create_dict[args.item]['shared'] = args.shared
1356         if "name" not in create_dict[args.item]:
1357             print "You must provide a name in the descriptor file or with the --name option"
1358             return
1359         payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1360         logger.debug("openmano request: %s", payload_req)
1361         URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1362         mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1363         logger.debug("openmano response: %s", mano_response.text )
1364         if args.verbose==None:
1365             args.verbose=0
1366         return _print_verbose(mano_response, args.verbose)
1367
1368
1369 def _get_items(item, item_name_id=None, datacenter=None, tenant=None):
1370     URLrequest = "http://%s:%s/openmano" %(mano_host, mano_port)
1371     if tenant:
1372         URLrequest += "/" + tenant
1373     if datacenter:
1374         URLrequest += "/vim/" + datacenter
1375     if item:
1376         URLrequest += "/" + item +"s"
1377     if item_name_id:
1378         URLrequest += "/" + item_name_id
1379     mano_response = requests.get(URLrequest)
1380     logger.debug("openmano response: %s", mano_response.text )
1381
1382     return mano_response
1383
1384
1385 def vim_net_sdn_attach(args):
1386     #Verify the network exists in the vim
1387     tenant = _get_tenant()
1388     datacenter = _get_datacenter(args.datacenter, tenant)
1389     result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1390     content = yaml.load(result.content)
1391     if 'networks' in content:
1392         raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1393     if 'error' in content:
1394         raise OpenmanoCLIError(yaml.safe_dump(content))
1395     network_uuid = content['network']['id']
1396
1397     #Make call to attach the dataplane port to the SND network associated to the vim network
1398     headers_req = {'content-type': 'application/yaml'}
1399     payload_req = {'port': args.port}
1400     if args.vlan:
1401         payload_req['vlan'] = int(args.vlan)
1402     if args.mac:
1403         payload_req['mac'] = args.mac
1404
1405     URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/attach" % (mano_host, mano_port, tenant, datacenter, network_uuid)
1406     logger.debug("openmano request: %s", payload_req)
1407     mano_response = requests.post(URLrequest, headers=headers_req, data=json.dumps(payload_req))
1408     logger.debug("openmano response: %s", mano_response.text)
1409     result = _print_verbose(mano_response, args.verbose)
1410     return result
1411
1412
1413 def vim_net_sdn_detach(args):
1414     if not args.all and not args.id:
1415         print "--all or --id must be used"
1416         return 1
1417
1418     # Verify the network exists in the vim
1419     tenant = _get_tenant()
1420     datacenter = _get_datacenter(args.datacenter, tenant)
1421     result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1422     content = yaml.load(result.content)
1423     if 'networks' in content:
1424         raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1425     if 'error' in content:
1426         raise OpenmanoCLIError(yaml.safe_dump(content))
1427     network_uuid = content['network']['id']
1428
1429     if not args.force:
1430         r = raw_input("Confirm action' (y/N)? ")
1431         if len(r) == 0 or r[0].lower() != "y":
1432             return 0
1433
1434     if args.id:
1435         URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach/%s" % (
1436             mano_host, mano_port, tenant, datacenter, network_uuid, args.id)
1437     else:
1438         URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach" % (
1439             mano_host, mano_port, tenant, datacenter, network_uuid)
1440     mano_response = requests.delete(URLrequest)
1441     logger.debug("openmano response: %s", mano_response.text)
1442     result = _print_verbose(mano_response, args.verbose)
1443     return result
1444
1445
1446 def datacenter_net_action(args):
1447     if args.action == "net-update":
1448         print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
1449         print
1450         args.action = "netmap-delete"
1451         args.netmap = None
1452         args.all = True
1453         r = datacenter_netmap_action(args)
1454         if r == 0:
1455             args.force = True
1456             args.action = "netmap-import"
1457             r = datacenter_netmap_action(args)
1458         return r
1459
1460     if args.action == "net-edit":
1461         args.netmap = args.net
1462         args.name = None
1463     elif args.action == "net-list":
1464         args.netmap = None
1465     elif args.action == "net-delete":
1466         args.netmap = args.net
1467         args.all = False
1468           
1469     args.action = "netmap" + args.action[3:]
1470     args.vim_name=None
1471     args.vim_id=None
1472     print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1473     print
1474     return datacenter_netmap_action(args)
1475
1476 def datacenter_netmap_action(args):
1477     tenant = _get_tenant()
1478     datacenter = _get_datacenter(args.datacenter, tenant)
1479     #print "datacenter_netmap_action",args
1480     payload_req = None
1481     if args.verbose==None:
1482         args.verbose=0
1483     headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1484     URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1485         
1486     if args.action=="netmap-list":
1487         if args.netmap:
1488             URLrequest += "/" + args.netmap
1489             args.verbose += 1
1490         mano_response = requests.get(URLrequest)
1491             
1492     elif args.action=="netmap-delete":
1493         if args.netmap and args.all:
1494             print "you can not use a netmap name and the option --all at the same time"
1495             return 1
1496         if args.netmap:
1497             force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1498             URLrequest += "/" + args.netmap
1499         elif args.all: 
1500             force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1501         else:
1502             print "you must specify a netmap name or the option --all"
1503             return 1
1504         if not args.force:
1505             r = raw_input(force_text)
1506             if  len(r)>0  and r[0].lower()=="y":
1507                 pass
1508             else:
1509                 return 0
1510         mano_response = requests.delete(URLrequest, headers=headers_req)
1511     elif args.action=="netmap-import":
1512         if not args.force:
1513             r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1514             if  len(r)>0  and r[0].lower()=="y":
1515                 pass
1516             else:
1517                 return 0
1518         URLrequest += "/upload"
1519         mano_response = requests.post(URLrequest, headers=headers_req)
1520     elif args.action=="netmap-edit" or args.action=="netmap-create":
1521         if args.file:
1522             payload = _load_file_or_yaml(args.file)
1523         else:
1524             payload = {}
1525         if "netmap" not in payload:
1526             payload = {"netmap": payload}
1527         if args.name:
1528             payload["netmap"]["name"] = args.name
1529         if args.vim_id:
1530             payload["netmap"]["vim_id"] = args.vim_id
1531         if args.action=="netmap-create" and args.vim_name:
1532             payload["netmap"]["vim_name"] = args.vim_name
1533         payload_req = json.dumps(payload)
1534         logger.debug("openmano request: %s", payload_req)
1535         
1536         if args.action=="netmap-edit" and not args.force:
1537             if len(payload["netmap"]) == 0:
1538                 print "You must supply some parameter to edit"
1539                 return 1
1540             r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1541             if  len(r)>0  and r[0].lower()=="y":
1542                 pass
1543             else:
1544                 return 0
1545             URLrequest += "/" + args.netmap
1546             mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1547         else: #netmap-create
1548             if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1549                 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1550                 return 1
1551             mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1552
1553     logger.debug("openmano response: %s", mano_response.text )
1554     return _print_verbose(mano_response, args.verbose)
1555
1556
1557 def element_edit(args):
1558     element = _get_item_uuid(args.element, args.name)
1559     headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1560     URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1561     payload=_load_file_or_yaml(args.file)
1562     if args.element[:-1] not in payload:
1563         payload = {args.element[:-1]: payload }
1564     payload_req = json.dumps(payload)
1565     
1566     #print payload_req
1567     if not args.force or (args.name==None and args.filer==None):
1568         r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1569         if  len(r)>0  and r[0].lower()=="y":
1570             pass
1571         else:
1572             return 0
1573     logger.debug("openmano request: %s", payload_req)
1574     mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1575     logger.debug("openmano response: %s", mano_response.text )
1576     if args.verbose==None:
1577         args.verbose=0
1578     if args.name!=None:
1579         args.verbose += 1
1580     return _print_verbose(mano_response, args.verbose)
1581
1582
1583 def datacenter_edit(args):
1584     tenant = _get_tenant()
1585     element = _get_item_uuid('datacenters', args.name, tenant)
1586     headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1587     URLrequest = "http://%s:%s/openmano/datacenters/%s" % (mano_host, mano_port, element)
1588
1589     has_arguments = False
1590     if args.file != None:
1591         has_arguments = True
1592         payload = _load_file_or_yaml(args.file)
1593     else:
1594         payload = {}
1595
1596     if args.sdn_controller != None:
1597         has_arguments = True
1598         if not 'config' in payload:
1599             payload['config'] = {}
1600         if not 'sdn-controller' in payload['config']:
1601             payload['config']['sdn-controller'] = {}
1602         if args.sdn_controller == 'null':
1603             payload['config']['sdn-controller'] = None
1604         else:
1605             payload['config']['sdn-controller'] = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1606
1607     if not has_arguments:
1608         raise OpenmanoCLIError("At least one argument must be provided to modify the datacenter")
1609
1610     if 'datacenter' not in payload:
1611         payload = {'datacenter': payload}
1612     payload_req = json.dumps(payload)
1613
1614     # print payload_req
1615     if not args.force or (args.name == None and args.filer == None):
1616         r = raw_input(" Edit datacenter " + args.name + " (y/N)? ")
1617         if len(r) > 0 and r[0].lower() == "y":
1618             pass
1619         else:
1620             return 0
1621     logger.debug("openmano request: %s", payload_req)
1622     mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1623     logger.debug("openmano response: %s", mano_response.text)
1624     if args.verbose == None:
1625         args.verbose = 0
1626     if args.name != None:
1627         args.verbose += 1
1628     return _print_verbose(mano_response, args.verbose)
1629
1630
1631 def version(args):
1632     headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1633     URLrequest = "http://%s:%s/openmano/version" % (mano_host, mano_port)
1634
1635     mano_response = requests.get(URLrequest, headers=headers_req)
1636     logger.debug("openmano response: %s", mano_response.text)
1637     print mano_response.text
1638
1639
1640 global mano_host
1641 global mano_port
1642 global mano_tenant
1643
1644 if __name__=="__main__":
1645     
1646     mano_tenant = os.getenv('OPENMANO_TENANT', None)
1647     mano_host = os.getenv('OPENMANO_HOST',"localhost")
1648     mano_port = os.getenv('OPENMANO_PORT',"9090")
1649     mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1650     
1651     main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1652     main_parser.add_argument('--version', action='version', help="get version of this client",
1653                             version='%(prog)s client version ' + __version__ +
1654                                     " (Note: use '%(prog)s version' to get server version)")
1655
1656     subparsers = main_parser.add_subparsers(help='commands')
1657     
1658     parent_parser = argparse.ArgumentParser(add_help=False)
1659     parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1660     parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1661
1662     config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1663     config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1664     config_parser.set_defaults(func=config)
1665
1666     version_parser = subparsers.add_parser('version', parents=[parent_parser], help="get server version")
1667     version_parser.set_defaults(func=version)
1668
1669     vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1670     vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1671     vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1672     vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1673     vnf_create_parser.add_argument("--image-path", action="store",  help="change image path locations (overwritten)")
1674     vnf_create_parser.add_argument("--image-name", action="store",  help="change image name (overwritten)")
1675     vnf_create_parser.add_argument("--image-checksum", action="store",  help="change image checksum (overwritten)")
1676     vnf_create_parser.set_defaults(func=vnf_create)
1677
1678     vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1679     vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1680     vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1681     #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1682     vnf_list_parser.set_defaults(func=vnf_list)
1683     
1684     vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1685     vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1686     vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1687     vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1688     vnf_delete_parser.set_defaults(func=vnf_delete)
1689     
1690     scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1691     scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1692     scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1693     scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1694     scenario_create_parser.set_defaults(func=scenario_create)
1695
1696     scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1697     scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1698     #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1699     scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1700     scenario_list_parser.set_defaults(func=scenario_list)
1701     
1702     scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1703     scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1704     scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1705     scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1706     scenario_delete_parser.set_defaults(func=scenario_delete)
1707
1708     scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1709     scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1710     scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1711     scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1712     scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1713     scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1714     scenario_deploy_parser.set_defaults(func=scenario_deploy)
1715     
1716     scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1717     scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1718     scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1719     scenario_deploy_parser.set_defaults(func=scenario_verify)
1720     
1721     instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1722     instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1723     instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1724     instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1725     instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1726     instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1727     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")
1728     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")
1729     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")
1730     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")
1731     instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1732     instance_scenario_create_parser.set_defaults(func=instance_create)
1733
1734     instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1735     instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1736     instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1737     instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1738
1739     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)")
1740     instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1741     instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1742     instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1743     instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1744     
1745     instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1746     instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1747     instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1748             choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console"],\
1749             help="action to send")
1750     instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1751     instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1752     instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1753     instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1754
1755     #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1756     #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1757     #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1758     
1759     tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1760     tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1761     tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1762     tenant_create_parser.set_defaults(func=tenant_create)
1763
1764     tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1765     tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1766     tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1767     tenant_delete_parser.set_defaults(func=tenant_delete)
1768
1769     tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1770     tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1771     tenant_list_parser.set_defaults(func=tenant_list)
1772
1773     element_edit_parser = subparsers.add_parser('tenant-edit', parents=[parent_parser], help="edits one tenant")
1774     element_edit_parser.add_argument("name", help="name or uuid of the tenant")
1775     element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1776     element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1777     element_edit_parser.set_defaults(func=element_edit, element='tenants')
1778
1779     datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1780     datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1781     datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1782     datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1783     datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1784     datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1785     datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
1786     datacenter_create_parser.add_argument("--sdn-controller", action="store", help="Name or uuid of the SDN controller to be used", dest='sdn_controller')
1787     datacenter_create_parser.set_defaults(func=datacenter_create)
1788
1789     datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1790     datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1791     datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1792     datacenter_delete_parser.set_defaults(func=datacenter_delete)
1793
1794     datacenter_edit_parser = subparsers.add_parser('datacenter-edit', parents=[parent_parser], help="Edit datacenter")
1795     datacenter_edit_parser.add_argument("name", help="name or uuid of the datacenter")
1796     datacenter_edit_parser.add_argument("--file", help="json/yaml text or file with the changes").completer = FilesCompleter
1797     datacenter_edit_parser.add_argument("--sdn-controller", action="store",
1798                                           help="Name or uuid of the SDN controller to be used. Specify 'null' to clear entry", dest='sdn_controller')
1799     datacenter_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1800     datacenter_edit_parser.set_defaults(func=datacenter_edit)
1801
1802     datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1803     datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1804     datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1805     datacenter_list_parser.set_defaults(func=datacenter_list)
1806
1807     datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1808     datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1809     datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1810     datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1811     datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1812     datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1813     datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1814     datacenter_attach_parser.set_defaults(func=datacenter_attach)
1815
1816     datacenter_edit_vim_tenant_parser = subparsers.add_parser('datacenter-edit-vim-tenant', parents=[parent_parser],
1817                                                      help="Edit the association of a datacenter to the operating tenant")
1818     datacenter_edit_vim_tenant_parser.add_argument("name", help="name or uuid of the datacenter")
1819     datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-id', action='store',
1820                                           help="specify a datacenter tenant to use. A new one is created by default")
1821     datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1822     datacenter_edit_vim_tenant_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1823     datacenter_edit_vim_tenant_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1824     datacenter_edit_vim_tenant_parser.add_argument("--config", action="store",
1825                                           help="aditional configuration in json/yaml format")
1826     datacenter_edit_vim_tenant_parser.set_defaults(func=datacenter_edit_vim_tenant)
1827
1828     datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1829     datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1830     datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1831     datacenter_detach_parser.set_defaults(func=datacenter_detach)
1832
1833     #=======================datacenter_sdn_port_mapping_xxx section=======================
1834     #datacenter_sdn_port_mapping_set
1835     datacenter_sdn_port_mapping_set_parser = subparsers.add_parser('datacenter-sdn-port-mapping-set',
1836                                                                    parents=[parent_parser],
1837                                                                    help="Load a file with the mapping of physical ports "
1838                                                                         "and the ports of the dataplaneswitch controlled "
1839                                                                         "by a datacenter")
1840     datacenter_sdn_port_mapping_set_parser.add_argument("name", action="store", help="specifies the datacenter")
1841     datacenter_sdn_port_mapping_set_parser.add_argument("file",
1842                                                         help="json/yaml text or file with the port mapping").completer = FilesCompleter
1843     datacenter_sdn_port_mapping_set_parser.add_argument("-f", "--force", action="store_true",
1844                                                           help="forces overwriting without asking")
1845     datacenter_sdn_port_mapping_set_parser.set_defaults(func=datacenter_sdn_port_mapping_set)
1846
1847     #datacenter_sdn_port_mapping_list
1848     datacenter_sdn_port_mapping_list_parser = subparsers.add_parser('datacenter-sdn-port-mapping-list',
1849                                                                     parents=[parent_parser],
1850                                                                     help="Show the SDN port mapping in a datacenter")
1851     datacenter_sdn_port_mapping_list_parser.add_argument("name", action="store", help="specifies the datacenter")
1852     datacenter_sdn_port_mapping_list_parser.set_defaults(func=datacenter_sdn_port_mapping_list)
1853
1854     # datacenter_sdn_port_mapping_clear
1855     datacenter_sdn_port_mapping_clear_parser = subparsers.add_parser('datacenter-sdn-port-mapping-clear',
1856                                                                     parents=[parent_parser],
1857                                                                     help="Clean the the SDN port mapping in a datacenter")
1858     datacenter_sdn_port_mapping_clear_parser.add_argument("name", action="store",
1859                                                          help="specifies the datacenter")
1860     datacenter_sdn_port_mapping_clear_parser.add_argument("-f", "--force", action="store_true",
1861                                               help="forces clearing without asking")
1862     datacenter_sdn_port_mapping_clear_parser.set_defaults(func=datacenter_sdn_port_mapping_clear)
1863     # =======================
1864
1865     # =======================sdn_controller_xxx section=======================
1866     # sdn_controller_create
1867     sdn_controller_create_parser = subparsers.add_parser('sdn-controller-create', parents=[parent_parser],
1868                                                         help="Creates an SDN controller entity within RO")
1869     sdn_controller_create_parser.add_argument("name", help="name of the SDN controller")
1870     sdn_controller_create_parser.add_argument("--description", action="store", help="description of the SDN controller")
1871     sdn_controller_create_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1872     sdn_controller_create_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1873     sdn_controller_create_parser.add_argument("--dpid", action="store",
1874                                              help="DPID of the dataplane switch controlled by this SDN controller")
1875     sdn_controller_create_parser.add_argument("--type", action="store",
1876                                              help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1877     sdn_controller_create_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1878     sdn_controller_create_parser.add_argument("--passwd", action="store", dest='password',
1879                                              help="password credentials for the SDN controller")
1880     sdn_controller_create_parser.set_defaults(func=sdn_controller_create)
1881
1882     # sdn_controller_edit
1883     sdn_controller_edit_parser = subparsers.add_parser('sdn-controller-edit', parents=[parent_parser],
1884                                                         help="Update one or more options of a SDN controller")
1885     sdn_controller_edit_parser.add_argument("name", help="name or uuid of the SDN controller", )
1886     sdn_controller_edit_parser.add_argument("--name", action="store", help="Update the name of the SDN controller",
1887                                               dest='new_name')
1888     sdn_controller_edit_parser.add_argument("--description", action="store", help="description of the SDN controller")
1889     sdn_controller_edit_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1890     sdn_controller_edit_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1891     sdn_controller_edit_parser.add_argument("--dpid", action="store",
1892                                              help="DPID of the dataplane switch controlled by this SDN controller")
1893     sdn_controller_edit_parser.add_argument("--type", action="store",
1894                                              help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1895     sdn_controller_edit_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1896     sdn_controller_edit_parser.add_argument("--password", action="store",
1897                                              help="password credentials for the SDN controller", dest='password')
1898     sdn_controller_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1899     #TODO: include option --file
1900     sdn_controller_edit_parser.set_defaults(func=sdn_controller_edit)
1901
1902     #sdn_controller_list
1903     sdn_controller_list_parser = subparsers.add_parser('sdn-controller-list',
1904                                                                     parents=[parent_parser],
1905                                                                     help="List the SDN controllers")
1906     sdn_controller_list_parser.add_argument("name", nargs='?', help="name or uuid of the SDN controller")
1907     sdn_controller_list_parser.set_defaults(func=sdn_controller_list)
1908
1909     # sdn_controller_delete
1910     sdn_controller_delete_parser = subparsers.add_parser('sdn-controller-delete',
1911                                                                     parents=[parent_parser],
1912                                                                     help="Delete the the SDN controller")
1913     sdn_controller_delete_parser.add_argument("name", help="name or uuid of the SDN controller")
1914     sdn_controller_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1915     sdn_controller_delete_parser.set_defaults(func=sdn_controller_delete)
1916     # =======================
1917
1918     action_dict={'net-update': 'retrieves external networks from datacenter',
1919                  'net-edit': 'edits an external network',
1920                  'net-delete': 'deletes an external network',
1921                  'net-list': 'lists external networks from a datacenter'
1922                  }
1923     for item in action_dict:
1924         datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1925         datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1926         if item=='net-edit' or item=='net-delete':
1927             datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1928         if item=='net-edit':
1929             datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1930         if item!='net-list':
1931             datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1932         datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1933
1934
1935     action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
1936                  'netmap-create': 'create a new network senario netmap',
1937                  'netmap-edit':   'edit name of a network senario netmap',
1938                  'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1939                  'netmap-list':   'list/show network scenario netmaps'
1940                  }
1941     for item in action_dict:
1942         datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1943         datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1944         #if item=='net-add':
1945         #    datacenter_action_parser.add_argument("net", help="name of the network")
1946         if item=='netmap-delete':
1947             datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1948             datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1949             datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1950         if item=='netmap-edit':
1951             datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1952             datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1953             datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1954             datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1955             datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1956         if item=='netmap-list':
1957             datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1958         if item=='netmap-create':
1959             datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1960             datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1961             datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1962             datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
1963         if item=='netmap-import':
1964             datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1965         datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
1966
1967     # =======================vim_net_sdn_xxx section=======================
1968     # vim_net_sdn_attach
1969     vim_net_sdn_attach_parser = subparsers.add_parser('vim-net-sdn-attach',
1970                                                       parents=[parent_parser],
1971                                                       help="Specify the port to access to an external network using SDN")
1972     vim_net_sdn_attach_parser.add_argument("vim_net", action="store",
1973                                                 help="Name/id of the network in the vim that will be used to connect to the external network")
1974     vim_net_sdn_attach_parser.add_argument("port", action="store", help="Specifies the port in the dataplane switch to access to the external network")
1975     vim_net_sdn_attach_parser.add_argument("--vlan", action="store", help="Specifies the vlan (if any) to use in the defined port")
1976     vim_net_sdn_attach_parser.add_argument("--mac", action="store", help="Specifies the MAC (if known) of the physical device that will be reachable by this external port")
1977     vim_net_sdn_attach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1978     vim_net_sdn_attach_parser.set_defaults(func=vim_net_sdn_attach)
1979
1980     # vim_net_sdn_detach
1981     vim_net_sdn_detach_parser = subparsers.add_parser('vim-net-sdn-detach',
1982                                                            parents=[parent_parser],
1983                                                            help="Remove the port information to access to an external network using SDN")
1984
1985     vim_net_sdn_detach_parser.add_argument("vim_net", action="store", help="Name/id of the vim network")
1986     vim_net_sdn_detach_parser.add_argument("--id", action="store",help="Specify the uuid of the external ports from this network to be detached")
1987     vim_net_sdn_detach_parser.add_argument("--all", action="store_true", help="Detach all external ports from this network")
1988     vim_net_sdn_detach_parser.add_argument("-f", "--force", action="store_true", help="forces clearing without asking")
1989     vim_net_sdn_detach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1990     vim_net_sdn_detach_parser.set_defaults(func=vim_net_sdn_detach)
1991     # =======================
1992
1993     for item in ("network", "tenant", "image"):
1994         if item=="network":
1995             command_name = 'vim-net'
1996         else:
1997             command_name = 'vim-'+item
1998         vim_item_list_parser = subparsers.add_parser(command_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
1999         vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
2000         vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2001         vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
2002
2003         vim_item_del_parser = subparsers.add_parser(command_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
2004         vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
2005         vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2006         vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
2007
2008         if item == "network" or item == "tenant":
2009             vim_item_create_parser = subparsers.add_parser(command_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
2010             vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
2011             vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item  )
2012             vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2013             if item=="network":
2014                 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
2015                 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
2016                 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>'")
2017             else:
2018                 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
2019             vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
2020
2021     argcomplete.autocomplete(main_parser)
2022     
2023     try:
2024         args = main_parser.parse_args()
2025         #logging info
2026         level = logging.CRITICAL
2027         streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
2028         if "debug" in args and args.debug:
2029             level = logging.DEBUG
2030         logging.basicConfig(format=streamformat, level= level)
2031         logger = logging.getLogger('mano')
2032         logger.setLevel(level)
2033         result = args.func(args)
2034         if result == None:
2035             result = 0
2036         #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
2037     except (requests.exceptions.ConnectionError):
2038         print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
2039         result = -2
2040     except (KeyboardInterrupt):
2041         print 'Exiting openmano'
2042         result = -3
2043     except (SystemExit, ArgumentParserError):
2044         result = -4
2045     except OpenmanoCLIError as e:
2046         print str(e)
2047         result = -5
2048     
2049     #print result
2050     exit(result)
2051