blob: 1e90cad4817a7f747c80bc0a787f869f5a0543e0 [file] [log] [blame]
tierno7edb6752016-03-21 17:37:52 +01001#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# PYTHON_ARGCOMPLETE_OK
4
5##
6# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
7# This file is part of openmano
8# All Rights Reserved.
9#
10# Licensed under the Apache License, Version 2.0 (the "License"); you may
11# not use this file except in compliance with the License. You may obtain
12# a copy of the License at
13#
14# http://www.apache.org/licenses/LICENSE-2.0
15#
16# Unless required by applicable law or agreed to in writing, software
17# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
18# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
19# License for the specific language governing permissions and limitations
20# under the License.
21#
22# For those usages not covered by the Apache License, Version 2.0 please
23# contact with: nfvlabs@tid.es
24##
25
26'''
27openmano client used to interact with openmano-server (openmanod)
28'''
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +010029__author__="Alfonso Tierno, Gerardo Garcia, Pablo Montes"
tierno7edb6752016-03-21 17:37:52 +010030__date__ ="$09-oct-2014 09:09:48$"
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +010031__version__="0.4.13-r519"
32version_date="Mar 2017"
tierno7edb6752016-03-21 17:37:52 +010033
34from argcomplete.completers import FilesCompleter
35import os
36import argparse
37import argcomplete
38import requests
39import json
40import yaml
41import logging
42#from jsonschema import validate as js_v, exceptions as js_e
43
44class ArgumentParserError(Exception): pass
45
46class OpenmanoCLIError(Exception): pass
47
48class ThrowingArgumentParser(argparse.ArgumentParser):
49 def error(self, message):
50 print "Error: %s" %message
51 print
52 self.print_usage()
53 #self.print_help()
54 print
55 print "Type 'openmano -h' for help"
56 raise ArgumentParserError
57
58
59def config(args):
60 print "OPENMANO_HOST: %s" %mano_host
61 print "OPENMANO_PORT: %s" %mano_port
garciadeblas0e9fd832016-07-08 15:20:18 +020062 if args.n:
63 logger.debug("resolving tenant and datacenter names")
64 mano_tenant_id = "None"
65 mano_tenant_name = "None"
66 mano_datacenter_id = "None"
67 mano_datacenter_name = "None"
68 try:
69 mano_tenant_id = _get_item_uuid("tenants", mano_tenant)
70 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, mano_tenant_id)
71 mano_response = requests.get(URLrequest)
72 logger.debug("openmano response: %s", mano_response.text )
73 content = mano_response.json()
74 mano_tenant_name = content["tenant"]["name"]
75 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, mano_tenant_id, mano_datacenter)
76 mano_response = requests.get(URLrequest)
77 logger.debug("openmano response: %s", mano_response.text )
78 content = mano_response.json()
79 if "error" not in content:
80 mano_datacenter_id = content["datacenter"]["uuid"]
81 mano_datacenter_name = content["datacenter"]["name"]
82 except OpenmanoCLIError:
83 pass
84 print "OPENMANO_TENANT: %s" %mano_tenant
85 print " Id: %s" %mano_tenant_id
86 print " Name: %s" %mano_tenant_name
87 print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
88 print " Id: %s" %mano_datacenter_id
89 print " Name: %s" %mano_datacenter_name
90 else:
91 print "OPENMANO_TENANT: %s" %mano_tenant
92 print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
tierno7edb6752016-03-21 17:37:52 +010093
94def _print_verbose(mano_response, verbose_level=0):
95 content = mano_response.json()
96 result = 0 if mano_response.status_code==200 else mano_response.status_code
97 if type(content)!=dict or len(content)!=1:
98 #print "Non expected format output"
99 print str(content)
100 return result
101
102 val=content.values()[0]
103 if type(val)==str:
104 print val
105 return result
106 elif type(val) == list:
107 content_list = val
108 elif type(val)==dict:
109 content_list = [val]
110 else:
111 #print "Non expected dict/list format output"
112 print str(content)
113 return result
114
115 #print content_list
116 if verbose_level==None:
117 verbose_level=0
118 if verbose_level >= 3:
119 print yaml.safe_dump(content, indent=4, default_flow_style=False)
120 return result
121
122 if mano_response.status_code == 200:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100123 uuid = None
tierno7edb6752016-03-21 17:37:52 +0100124 for content in content_list:
125 if "uuid" in content:
126 uuid = content['uuid']
127 elif "id" in content:
128 uuid = content['id']
129 elif "vim_id" in content:
130 uuid = content['vim_id']
tierno250954a2017-01-31 14:25:57 +0100131 name = content.get('name');
132 if not uuid:
133 uuid = ""
134 if not name:
135 name = ""
136 myoutput = "%s %s" %(uuid.ljust(38),name.ljust(20))
137 if content.get("status"):
tierno7edb6752016-03-21 17:37:52 +0100138 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:
tierno250954a2017-01-31 14:25:57 +0100142 if content.get('created_at'):
143 myoutput += " " + content['created_at'].ljust(20)
tierno7edb6752016-03-21 17:37:52 +0100144 if verbose_level >=2:
145 new_line='\n'
tierno250954a2017-01-31 14:25:57 +0100146 if content.get('type'):
tierno7edb6752016-03-21 17:37:52 +0100147 myoutput += new_line + " Type: " + content['type'].ljust(29)
148 new_line=''
tierno250954a2017-01-31 14:25:57 +0100149 if content.get('description'):
tierno7edb6752016-03-21 17:37:52 +0100150 myoutput += new_line + " Description: " + content['description'].ljust(20)
151 print myoutput
152 else:
153 print content['error']['description']
154 return result
155
156def parser_json_yaml(file_name):
157 try:
158 f = file(file_name, "r")
159 text = f.read()
160 f.close()
161 except Exception as e:
162 return (False, str(e))
163
164 #Read and parse file
165 if file_name[-5:]=='.yaml' or file_name[-4:]=='.yml' or (file_name[-5:]!='.json' and '\t' not in text):
166 try:
167 config = yaml.load(text)
168 except yaml.YAMLError as exc:
169 error_pos = ""
170 if hasattr(exc, 'problem_mark'):
171 mark = exc.problem_mark
172 error_pos = " at line:%s column:%s" % (mark.line+1, mark.column+1)
173 return (False, "Error loading file '"+file_name+"' yaml format error" + error_pos)
174 else: #json
175 try:
176 config = json.loads(text)
177 except Exception as e:
178 return (False, "Error loading file '"+file_name+"' json format error " + str(e) )
179
180 return True, config
181
182def _load_file_or_yaml(content):
183 '''
184 'content' can be or a yaml/json file or a text containing a yaml/json text format
185 This function autodetect, trying to load and parse the file,
186 if fails trying to parse the 'content' text
187 Returns the dictionary once parsed, or print an error and finish the program
188 '''
189 #Check config file exists
190 if os.path.isfile(content):
191 r,payload = parser_json_yaml(content)
192 if not r:
193 print payload
194 exit(-1)
195 elif "{" in content or ":" in content:
196 try:
197 payload = yaml.load(content)
198 except yaml.YAMLError as exc:
199 error_pos = ""
200 if hasattr(exc, 'problem_mark'):
201 mark = exc.problem_mark
202 error_pos = " at position: (%s:%s)" % (mark.line+1, mark.column+1)
203 print "Error loading yaml/json text"+error_pos
204 exit (-1)
205 else:
206 print "'%s' is neither a valid file nor a yaml/json content" % content
207 exit(-1)
208 return payload
209
210def _get_item_uuid(item, item_name_id, tenant=None):
211 if tenant:
212 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, tenant, item)
213 else:
214 URLrequest = "http://%s:%s/openmano/%s" %(mano_host, mano_port, item)
215 mano_response = requests.get(URLrequest)
216 logger.debug("openmano response: %s", mano_response.text )
217 content = mano_response.json()
218 #print content
219 found = 0
220 for i in content[item]:
221 if i["uuid"] == item_name_id:
222 return item_name_id
223 if i["name"] == item_name_id:
224 uuid = i["uuid"]
225 found += 1
226 if found == 0:
227 raise OpenmanoCLIError("No %s found with name/uuid '%s'" %(item[:-1], item_name_id))
228 elif found > 1:
229 raise OpenmanoCLIError("%d %s found with name '%s'. uuid must be used" %(found, item, item_name_id))
230 return uuid
231#
232# def check_valid_uuid(uuid):
233# id_schema = {"type" : "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
234# try:
235# js_v(uuid, id_schema)
236# return True
237# except js_e.ValidationError:
238# return False
239
240def _get_tenant(tenant_name_id = None):
241 if not tenant_name_id:
242 tenant_name_id = mano_tenant
243 if not mano_tenant:
244 raise OpenmanoCLIError("'OPENMANO_TENANT' environment variable is not set")
245 return _get_item_uuid("tenants", tenant_name_id)
246
247def _get_datacenter(datacenter_name_id = None, tenant = "any"):
248 if not datacenter_name_id:
249 datacenter_name_id = mano_datacenter
250 if not datacenter_name_id:
251 raise OpenmanoCLIError("neither 'OPENMANO_DATACENTER' environment variable is set nor --datacenter option is used")
252 return _get_item_uuid("datacenters", datacenter_name_id, tenant)
253
254def vnf_create(args):
255 #print "vnf-create",args
256 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
257 tenant = _get_tenant()
258 myvnf = _load_file_or_yaml(args.file)
259
garciadeblas14480452017-01-10 13:08:07 +0100260 if args.name or args.description or args.image_path or args.image_name or args.image_checksum:
tierno7edb6752016-03-21 17:37:52 +0100261 #print args.name
262 try:
263 if args.name:
264 myvnf['vnf']['name'] = args.name
265 if args.description:
266 myvnf['vnf']['description'] = args.description
267 if args.image_path:
268 index=0
269 for image_path_ in args.image_path.split(","):
270 #print "image-path", image_path_
271 myvnf['vnf']['VNFC'][index]['VNFC image']=image_path_
tierno941551b2017-01-12 18:26:26 +0100272 if "image name" in myvnf['vnf']['VNFC'][index]:
273 del myvnf['vnf']['VNFC'][index]["image name"]
274 if "image checksum" in myvnf['vnf']['VNFC'][index]:
275 del myvnf['vnf']['VNFC'][index]["image checksum"]
tierno7edb6752016-03-21 17:37:52 +0100276 index=index+1
tierno941551b2017-01-12 18:26:26 +0100277 if args.image_name: #image name precedes if both are supplied
garciadeblas14480452017-01-10 13:08:07 +0100278 index=0
279 for image_name_ in args.image_name.split(","):
280 myvnf['vnf']['VNFC'][index]['image name']=image_name_
tierno941551b2017-01-12 18:26:26 +0100281 if "VNFC image" in myvnf['vnf']['VNFC'][index]:
282 del myvnf['vnf']['VNFC'][index]["VNFC image"]
garciadeblas14480452017-01-10 13:08:07 +0100283 index=index+1
284 if args.image_checksum:
285 index=0
286 for image_checksum_ in args.image_checksum.split(","):
287 myvnf['vnf']['VNFC'][index]['image checksum']=image_checksum_
288 index=index+1
tierno7edb6752016-03-21 17:37:52 +0100289 except (KeyError, TypeError), e:
290 if str(e)=='vnf': error_pos= "missing field 'vnf'"
291 elif str(e)=='name': error_pos= "missing field 'vnf':'name'"
292 elif str(e)=='description': error_pos= "missing field 'vnf':'description'"
293 elif str(e)=='VNFC': error_pos= "missing field 'vnf':'VNFC'"
294 elif str(e)==str(index): error_pos= "field 'vnf':'VNFC' must be an array"
295 elif str(e)=='VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
garciadeblas14480452017-01-10 13:08:07 +0100296 elif str(e)=='image name': error_pos= "missing field 'vnf':'VNFC'['image name']"
297 elif str(e)=='image checksum': error_pos= "missing field 'vnf':'VNFC'['image checksum']"
tierno7edb6752016-03-21 17:37:52 +0100298 else: error_pos="wrong format"
299 print "Wrong VNF descriptor: " + error_pos
300 return -1
301 payload_req = json.dumps(myvnf)
302
303 #print payload_req
304
305 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
306 logger.debug("openmano request: %s", payload_req)
307 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
308 logger.debug("openmano response: %s", mano_response.text )
309
310 return _print_verbose(mano_response, args.verbose)
311
312def vnf_list(args):
313 #print "vnf-list",args
314 if args.all:
315 tenant = "any"
316 else:
317 tenant = _get_tenant()
318 if args.name:
319 toshow = _get_item_uuid("vnfs", args.name, tenant)
320 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
321 else:
322 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
323 mano_response = requests.get(URLrequest)
324 logger.debug("openmano response: %s", mano_response.text )
325 content = mano_response.json()
326 #print json.dumps(content, indent=4)
327 if args.verbose==None:
328 args.verbose=0
329 result = 0 if mano_response.status_code==200 else mano_response.status_code
330 if mano_response.status_code == 200:
331 if not args.name:
332 if args.verbose >= 3:
333 print yaml.safe_dump(content, indent=4, default_flow_style=False)
334 return result
335 if len(content['vnfs']) == 0:
336 print "No VNFs were found."
337 return 404 #HTTP_Not_Found
338 for vnf in content['vnfs']:
339 myoutput = "%s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20))
340 if args.verbose >=1:
341 myoutput = "%s %s" %(myoutput, vnf['created_at'].ljust(20))
342 print myoutput
343 if args.verbose >=2:
344 print " Description: %s" %vnf['description']
345 print " VNF descriptor file: %s" %vnf['path']
346 else:
347 if args.verbose:
348 print yaml.safe_dump(content, indent=4, default_flow_style=False)
349 return result
350 vnf = content['vnf']
351 print "%s %s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20), vnf['created_at'].ljust(20))
352 print " Description: %s" %vnf['description']
353 #print " VNF descriptor file: %s" %vnf['path']
354 print " VMs:"
355 for vm in vnf['VNFC']:
356 #print " %s %s %s" %(vm['name'].ljust(20), vm['uuid'].ljust(38), vm['description'].ljust(30))
357 print " %s %s" %(vm['name'].ljust(20), vm['description'])
358 if len(vnf['nets'])>0:
359 print " Internal nets:"
360 for net in vnf['nets']:
361 print " %s %s" %(net['name'].ljust(20), net['description'])
362 if len(vnf['external-connections'])>0:
363 print " External interfaces:"
364 for interface in vnf['external-connections']:
365 print " %s %s %s %s" %(interface['external_name'].ljust(20), interface['vm_name'].ljust(20), interface['internal_name'].ljust(20), \
tierno933fea52017-01-23 13:07:09 +0100366 interface.get('vpci',"").ljust(14))
tierno7edb6752016-03-21 17:37:52 +0100367 else:
368 print content['error']['description']
369 if args.verbose:
370 print yaml.safe_dump(content, indent=4, default_flow_style=False)
371 return result
372
373def vnf_delete(args):
374 #print "vnf-delete",args
375 if args.all:
376 tenant = "any"
377 else:
378 tenant = _get_tenant()
379 todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
380 if not args.force:
381 r = raw_input("Delete VNF %s (y/N)? " %(todelete))
382 if not (len(r)>0 and r[0].lower()=="y"):
383 return 0
384 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
385 mano_response = requests.delete(URLrequest)
386 logger.debug("openmano response: %s", mano_response.text )
387 result = 0 if mano_response.status_code==200 else mano_response.status_code
388 content = mano_response.json()
389 #print json.dumps(content, indent=4)
390 if mano_response.status_code == 200:
391 print content['result']
392 else:
393 print content['error']['description']
394 return result
395
396def scenario_create(args):
397 #print "scenario-create",args
398 tenant = _get_tenant()
399 headers_req = {'content-type': 'application/yaml'}
400 myscenario = _load_file_or_yaml(args.file)
401
402 if args.name:
403 myscenario['name'] = args.name
404 if args.description:
405 myscenario['description'] = args.description
406 payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
407
408 #print payload_req
409
410 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
411 logger.debug("openmano request: %s", payload_req)
412 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
413 logger.debug("openmano response: %s", mano_response.text )
414 return _print_verbose(mano_response, args.verbose)
415
416def scenario_list(args):
417 #print "scenario-list",args
418 if args.all:
419 tenant = "any"
420 else:
421 tenant = _get_tenant()
422 if args.name:
423 toshow = _get_item_uuid("scenarios", args.name, tenant)
424 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
425 else:
426 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
427 mano_response = requests.get(URLrequest)
428 logger.debug("openmano response: %s", mano_response.text )
429 content = mano_response.json()
430 #print json.dumps(content, indent=4)
431 if args.verbose==None:
432 args.verbose=0
433
434 result = 0 if mano_response.status_code==200 else mano_response.status_code
435 if mano_response.status_code == 200:
436 if not args.name:
437 if args.verbose >= 3:
438 print yaml.safe_dump(content, indent=4, default_flow_style=False)
439 return result
440 if len(content['scenarios']) == 0:
441 print "No scenarios were found."
442 return 404 #HTTP_Not_Found
443 for scenario in content['scenarios']:
444 myoutput = "%s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20))
445 if args.verbose >=1:
446 myoutput = "%s %s" %(myoutput, scenario['created_at'].ljust(20))
447 print myoutput
448 if args.verbose >=2:
449 print " Description: %s" %scenario['description']
450 else:
451 if args.verbose:
452 print yaml.safe_dump(content, indent=4, default_flow_style=False)
453 return result
454 scenario = content['scenario']
455 myoutput = "%s %s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20), scenario['created_at'].ljust(20))
456 print myoutput
457 print " Description: %s" %scenario['description']
458 print " VNFs:"
459 for vnf in scenario['vnfs']:
460 print " %s %s %s" %(vnf['name'].ljust(20), vnf['vnf_id'].ljust(38), vnf['description'])
461 if len(scenario['nets'])>0:
462 print " Internal nets:"
463 for net in scenario['nets']:
464 if net['description'] is None: #if description does not exist, description is "-". Valid for external and internal nets.
465 net['description'] = '-'
466 if not net['external']:
467 print " %s %s %s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30))
468 print " External nets:"
469 for net in scenario['nets']:
470 if net['external']:
471 print " %s %s %s vim-id:%s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30), net['vim_id'])
472 else:
473 print content['error']['description']
474 if args.verbose:
475 print yaml.safe_dump(content, indent=4, default_flow_style=False)
476 return result
477
478def scenario_delete(args):
479 #print "scenario-delete",args
480 if args.all:
481 tenant = "any"
482 else:
483 tenant = _get_tenant()
484 todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
485 if not args.force:
486 r = raw_input("Delete scenario %s (y/N)? " %(args.name))
487 if not (len(r)>0 and r[0].lower()=="y"):
488 return 0
489 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
490 mano_response = requests.delete(URLrequest)
491 logger.debug("openmano response: %s", mano_response.text )
492 result = 0 if mano_response.status_code==200 else mano_response.status_code
493 content = mano_response.json()
494 #print json.dumps(content, indent=4)
495 if mano_response.status_code == 200:
496 print content['result']
497 else:
498 print content['error']['description']
499 return result
500
501def scenario_deploy(args):
502 print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
503 print
504 args.file = None
505 args.netmap_use = None
506 args.netmap_create = None
tiernobe41e222016-09-02 15:16:13 +0200507 args.keypair = None
508 args.keypair_auto = None
tierno7edb6752016-03-21 17:37:52 +0100509 return instance_create(args)
510
511# #print "scenario-deploy",args
512# headers_req = {'content-type': 'application/json'}
513# action = {}
514# actionCmd="start"
515# if args.nostart:
516# actionCmd="reserve"
517# action[actionCmd] = {}
518# action[actionCmd]["instance_name"] = args.name
519# if args.datacenter != None:
520# action[actionCmd]["datacenter"] = args.datacenter
521# elif mano_datacenter != None:
522# action[actionCmd]["datacenter"] = mano_datacenter
523#
524# if args.description:
525# action[actionCmd]["description"] = args.description
526# payload_req = json.dumps(action, indent=4)
527# #print payload_req
528#
529# URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
530# logger.debug("openmano request: %s", payload_req)
531# mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
532# logger.debug("openmano response: %s", mano_response.text )
533# if args.verbose==None:
534# args.verbose=0
535#
536# result = 0 if mano_response.status_code==200 else mano_response.status_code
537# content = mano_response.json()
538# #print json.dumps(content, indent=4)
539# if args.verbose >= 3:
540# print yaml.safe_dump(content, indent=4, default_flow_style=False)
541# return result
542#
543# if mano_response.status_code == 200:
544# myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
545# if args.verbose >=1:
546# myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
547# if args.verbose >=2:
548# myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
549# print myoutput
550# print ""
551# print "To check the status, run the following command:"
552# print "openmano instance-scenario-list <instance_id>"
553# else:
554# print content['error']['description']
555# return result
556
557def scenario_verify(args):
558 #print "scenario-verify",args
559 headers_req = {'content-type': 'application/json'}
560 action = {}
561 action["verify"] = {}
562 action["verify"]["instance_name"] = "scen-verify-return5"
563 payload_req = json.dumps(action, indent=4)
564 #print payload_req
565
566 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
567 logger.debug("openmano request: %s", payload_req)
568 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
569 logger.debug("openmano response: %s", mano_response.text )
570
571 result = 0 if mano_response.status_code==200 else mano_response.status_code
572 content = mano_response.json()
573 #print json.dumps(content, indent=4)
574 if mano_response.status_code == 200:
575 print content['result']
576 else:
577 print content['error']['description']
578 return result
579
580def instance_create(args):
581 tenant = _get_tenant()
582 headers_req = {'content-type': 'application/yaml'}
583 myInstance={"instance": {}, "schema_version": "0.1"}
584 if args.file:
585 instance_dict = _load_file_or_yaml(args.file)
586 if "instance" not in instance_dict:
587 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
588 else:
589 myInstance = instance_dict
590 if args.name:
591 myInstance["instance"]['name'] = args.name
592 if args.description:
593 myInstance["instance"]['description'] = args.description
594 if args.nostart:
595 myInstance["instance"]['action'] = "reserve"
596 #datacenter
597 datacenter = myInstance["instance"].get("datacenter")
598 if args.datacenter != None:
599 datacenter = args.datacenter
600 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
601 #scenario
602 scenario = myInstance["instance"].get("scenario")
603 if args.scenario != None:
604 scenario = args.scenario
605 if not scenario:
garciadeblased746032017-01-05 11:58:41 +0100606 print "you must provide a scenario in the file descriptor or with --scenario"
tierno7edb6752016-03-21 17:37:52 +0100607 return -1
608 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
609 if args.netmap_use:
610 if "networks" not in myInstance["instance"]:
611 myInstance["instance"]["networks"] = {}
612 for net in args.netmap_use:
613 net_comma_list = net.split(",")
614 for net_comma in net_comma_list:
615 net_tuple = net_comma.split("=")
616 if len(net_tuple) != 2:
617 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
618 return
619 net_scenario = net_tuple[0].strip()
620 net_datacenter = net_tuple[1].strip()
621 if net_scenario not in myInstance["instance"]["networks"]:
622 myInstance["instance"]["networks"][net_scenario] = {}
tiernobe41e222016-09-02 15:16:13 +0200623 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
624 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
625 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
tierno7edb6752016-03-21 17:37:52 +0100626 if args.netmap_create:
627 if "networks" not in myInstance["instance"]:
628 myInstance["instance"]["networks"] = {}
629 for net in args.netmap_create:
630 net_comma_list = net.split(",")
631 for net_comma in net_comma_list:
632 net_tuple = net_comma.split("=")
633 if len(net_tuple) == 1:
634 net_scenario = net_tuple[0].strip()
635 net_datacenter = None
636 elif len(net_tuple) == 2:
637 net_scenario = net_tuple[0].strip()
638 net_datacenter = net_tuple[1].strip()
639 else:
640 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
641 return
642 if net_scenario not in myInstance["instance"]["networks"]:
643 myInstance["instance"]["networks"][net_scenario] = {}
tiernobe41e222016-09-02 15:16:13 +0200644 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
645 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
646 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
tiernoa4e1a6e2016-08-31 14:19:40 +0200647 if args.keypair:
648 if "cloud-config" not in myInstance["instance"]:
649 myInstance["instance"]["cloud-config"] = {}
650 cloud_config = myInstance["instance"]["cloud-config"]
651 for key in args.keypair:
652 index = key.find(":")
653 if index<0:
654 if "key-pairs" not in cloud_config:
655 cloud_config["key-pairs"] = []
656 cloud_config["key-pairs"].append(key)
657 else:
658 user = key[:index]
659 key_ = key[index+1:]
660 key_list = key_.split(",")
661 if "users" not in cloud_config:
662 cloud_config["users"] = []
663 cloud_config["users"].append({"name": user, "key-pairs": key_list })
664 if args.keypair_auto:
665 try:
666 keys=[]
667 home = os.getenv("HOME")
668 user = os.getenv("USER")
669 files = os.listdir(home+'/.ssh')
670 for file in files:
671 if file[-4:] == ".pub":
672 with open(home+'/.ssh/'+file, 'r') as f:
673 keys.append(f.read())
674 if not keys:
675 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
676 return 1
677 except Exception as e:
678 print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
679 return 1
680
681 if "cloud-config" not in myInstance["instance"]:
682 myInstance["instance"]["cloud-config"] = {}
683 cloud_config = myInstance["instance"]["cloud-config"]
684 if "key-pairs" not in cloud_config:
685 cloud_config["key-pairs"] = []
686 if user:
687 if "users" not in cloud_config:
688 cloud_config["users"] = []
689 cloud_config["users"].append({"name": user, "key-pairs": keys })
tierno7edb6752016-03-21 17:37:52 +0100690
691 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
692 logger.debug("openmano request: %s", payload_req)
693 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
694 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
695 logger.debug("openmano response: %s", mano_response.text )
696 if args.verbose==None:
697 args.verbose=0
698
699 result = 0 if mano_response.status_code==200 else mano_response.status_code
700 content = mano_response.json()
701 #print json.dumps(content, indent=4)
702 if args.verbose >= 3:
703 print yaml.safe_dump(content, indent=4, default_flow_style=False)
704 return result
705
706 if mano_response.status_code == 200:
707 myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
708 if args.verbose >=1:
709 myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
710 if args.verbose >=2:
711 myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
712 print myoutput
713 else:
714 print content['error']['description']
715 return result
716
717def instance_scenario_list(args):
718 #print "instance-scenario-list",args
719 if args.all:
720 tenant = "any"
721 else:
722 tenant = _get_tenant()
723 if args.name:
724 toshow = _get_item_uuid("instances", args.name, tenant)
725 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
726 else:
727 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
728 mano_response = requests.get(URLrequest)
729 logger.debug("openmano response: %s", mano_response.text )
730 content = mano_response.json()
731 #print json.dumps(content, indent=4)
732 if args.verbose==None:
733 args.verbose=0
734
735 result = 0 if mano_response.status_code==200 else mano_response.status_code
736 if mano_response.status_code == 200:
737 if not args.name:
738 if args.verbose >= 3:
739 print yaml.safe_dump(content, indent=4, default_flow_style=False)
740 return result
741 if len(content['instances']) == 0:
742 print "No scenario instances were found."
743 return result
744 for instance in content['instances']:
745 myoutput = "%s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20))
746 if args.verbose >=1:
747 myoutput = "%s %s" %(myoutput, instance['created_at'].ljust(20))
748 print myoutput
749 if args.verbose >=2:
750 print "Description: %s" %instance['description']
751 else:
752 if args.verbose:
753 print yaml.safe_dump(content, indent=4, default_flow_style=False)
754 return result
755 instance = content
756 print "%s %s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20),instance['created_at'].ljust(20))
757 print "Description: %s" %instance['description']
758 print "Template scenario id: %s" %instance['scenario_id']
759 print "Template scenario name: %s" %instance['scenario_name']
760 print "---------------------------------------"
761 print "VNF instances: %d" %len(instance['vnfs'])
762 for vnf in instance['vnfs']:
763 #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))
764 print " %s %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
765 if len(instance['nets'])>0:
766 print "---------------------------------------"
767 print "Internal nets:"
768 for net in instance['nets']:
tierno5c7c4732016-09-26 13:38:55 +0000769 if net['created']:
tierno7edb6752016-03-21 17:37:52 +0100770 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
771 print "---------------------------------------"
772 print "External nets:"
773 for net in instance['nets']:
tierno5c7c4732016-09-26 13:38:55 +0000774 if not net['created']:
tierno7edb6752016-03-21 17:37:52 +0100775 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
776 print "---------------------------------------"
777 print "VM instances:"
778 for vnf in instance['vnfs']:
779 for vm in vnf['vms']:
780 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'])
781 else:
782 print content['error']['description']
783 if args.verbose:
784 print yaml.safe_dump(content, indent=4, default_flow_style=False)
785 return result
786
787def instance_scenario_status(args):
788 print "instance-scenario-status"
789 return 0
790
791def instance_scenario_delete(args):
792 if args.all:
793 tenant = "any"
794 else:
795 tenant = _get_tenant()
796 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
797 #print "instance-scenario-delete",args
798 if not args.force:
799 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
800 if not (len(r)>0 and r[0].lower()=="y"):
801 return
802 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
803 mano_response = requests.delete(URLrequest)
804 logger.debug("openmano response: %s", mano_response.text )
805 result = 0 if mano_response.status_code==200 else mano_response.status_code
806 content = mano_response.json()
807 #print json.dumps(content, indent=4)
808 if mano_response.status_code == 200:
809 print content['result']
810 else:
811 print content['error']['description']
812 return result
813
814def instance_scenario_action(args):
815 #print "instance-scenario-action", args
816 tenant = _get_tenant()
817 toact = _get_item_uuid("instances", args.name, tenant=tenant)
818 action={}
819 action[ args.action ] = args.param
820 if args.vnf:
821 action["vnfs"] = args.vnf
822 if args.vm:
823 action["vms"] = args.vm
824
825 headers_req = {'content-type': 'application/json'}
826 payload_req = json.dumps(action, indent=4)
827 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
828 logger.debug("openmano request: %s", payload_req)
829 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
830 logger.debug("openmano response: %s", mano_response.text )
831 result = 0 if mano_response.status_code==200 else mano_response.status_code
832 content = mano_response.json()
833 #print json.dumps(content, indent=4)
834 if mano_response.status_code == 200:
835 if args.verbose:
836 print yaml.safe_dump(content, indent=4, default_flow_style=False)
837 return result
838 for uuid,c in content.iteritems():
839 print "%s %s %s" %(uuid.ljust(38), c['name'].ljust(20),c['description'].ljust(20))
840 else:
841 print content['error']['description']
842 return result
843
844
845def instance_vnf_list(args):
846 print "instance-vnf-list"
847 return 0
848
849def instance_vnf_status(args):
850 print "instance-vnf-status"
851 return 0
852
853def tenant_create(args):
854 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
855 tenant_dict={"name": args.name}
856 if args.description!=None:
857 tenant_dict["description"] = args.description
858 payload_req = json.dumps( {"tenant": tenant_dict })
859
860 #print payload_req
861
862 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
863 logger.debug("openmano request: %s", payload_req)
864 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
865 logger.debug("openmano response: %s", mano_response.text )
866 return _print_verbose(mano_response, args.verbose)
867
868def tenant_list(args):
869 #print "tenant-list",args
870 if args.name:
tierno392f2852016-05-13 12:28:55 +0200871 toshow = _get_item_uuid("tenants", args.name)
tierno7edb6752016-03-21 17:37:52 +0100872 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
873 else:
874 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
875 mano_response = requests.get(URLrequest)
876 logger.debug("openmano response: %s", mano_response.text )
877 if args.verbose==None:
878 args.verbose=0
879 if args.name!=None:
880 args.verbose += 1
881 return _print_verbose(mano_response, args.verbose)
882
883def tenant_delete(args):
884 #print "tenant-delete",args
885 todelete = _get_item_uuid("tenants", args.name)
886 if not args.force:
887 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
888 if not (len(r)>0 and r[0].lower()=="y"):
889 return 0
890 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
891 mano_response = requests.delete(URLrequest)
892 logger.debug("openmano response: %s", mano_response.text )
893 result = 0 if mano_response.status_code==200 else mano_response.status_code
894 content = mano_response.json()
895 #print json.dumps(content, indent=4)
896 if mano_response.status_code == 200:
897 print content['result']
898 else:
899 print content['error']['description']
900 return result
901
902def datacenter_attach(args):
903 tenant = _get_tenant()
904 datacenter = _get_datacenter(args.name)
905 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
906
907 datacenter_dict={}
908 if args.vim_tenant_id != None:
909 datacenter_dict['vim_tenant'] = args.vim_tenant_id
910 if args.vim_tenant_name != None:
911 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
912 if args.user != None:
913 datacenter_dict['vim_username'] = args.user
914 if args.password != None:
915 datacenter_dict['vim_password'] = args.password
tierno8008c3a2016-10-13 15:34:28 +0000916 if args.config!=None:
917 datacenter_dict["config"] = _load_file_or_yaml(args.config)
tierno7edb6752016-03-21 17:37:52 +0100918 payload_req = json.dumps( {"datacenter": datacenter_dict })
919
920 #print payload_req
921
922 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
923 logger.debug("openmano request: %s", payload_req)
924 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
925 logger.debug("openmano response: %s", mano_response.text )
926 result = _print_verbose(mano_response, args.verbose)
927 #provide addional information if error
928 if mano_response.status_code != 200:
929 content = mano_response.json()
930 if "already in use for 'name'" in content['error']['description'] and \
931 "to database vim_tenants table" in content['error']['description']:
932 print "Try to specify a different name with --vim-tenant-name"
933 return result
934
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100935
936def datacenter_edit_vim_tenant(args):
937 tenant = _get_tenant()
938 datacenter = _get_datacenter(args.name)
939 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
940
941 if not (args.vim_tenant_id or args.vim_tenant_name or args.user or args.password or args.config):
942 raise OpenmanoCLIError("Error. At least one parameter must be updated.")
943
944 datacenter_dict = {}
945 if args.vim_tenant_id != None:
946 datacenter_dict['vim_tenant'] = args.vim_tenant_id
947 if args.vim_tenant_name != None:
948 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
949 if args.user != None:
950 datacenter_dict['vim_username'] = args.user
951 if args.password != None:
952 datacenter_dict['vim_password'] = args.password
953 if args.config != None:
954 datacenter_dict["config"] = _load_file_or_yaml(args.config)
955 payload_req = json.dumps({"datacenter": datacenter_dict})
956
957 # print payload_req
958
959 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" % (mano_host, mano_port, tenant, datacenter)
960 logger.debug("openmano request: %s", payload_req)
961 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
962 logger.debug("openmano response: %s", mano_response.text)
963 result = _print_verbose(mano_response, args.verbose)
964
965 return result
966
tierno7edb6752016-03-21 17:37:52 +0100967def datacenter_detach(args):
968 if args.all:
969 tenant = "any"
970 else:
971 tenant = _get_tenant()
972 datacenter = _get_datacenter(args.name, tenant)
973 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
974 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
975 mano_response = requests.delete(URLrequest, headers=headers_req)
976 logger.debug("openmano response: %s", mano_response.text )
977 content = mano_response.json()
978 #print json.dumps(content, indent=4)
979 result = 0 if mano_response.status_code==200 else mano_response.status_code
980 if mano_response.status_code == 200:
981 print content['result']
982 else:
983 print content['error']['description']
984 return result
985
986def datacenter_create(args):
987 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
988 datacenter_dict={"name": args.name, "vim_url": args.url}
989 if args.description!=None:
990 datacenter_dict["description"] = args.description
991 if args.type!=None:
992 datacenter_dict["type"] = args.type
993 if args.url!=None:
994 datacenter_dict["vim_url_admin"] = args.url_admin
995 if args.config!=None:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100996 datacenter_dict["config"] = _load_file_or_yaml(args.config)
997 if args.sdn_controller!=None:
998 tenant = _get_tenant()
999 sdn_controller = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1000 if not 'config' in datacenter_dict:
1001 datacenter_dict['config'] = {}
1002 datacenter_dict['config']['sdn-controller'] = sdn_controller
tierno7edb6752016-03-21 17:37:52 +01001003 payload_req = json.dumps( {"datacenter": datacenter_dict })
1004
1005 #print payload_req
1006
1007 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
1008 logger.debug("openmano request: %s", payload_req)
1009 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1010 logger.debug("openmano response: %s", mano_response.text )
1011 return _print_verbose(mano_response, args.verbose)
1012
1013def datacenter_delete(args):
1014 #print "datacenter-delete",args
1015 todelete = _get_item_uuid("datacenters", args.name, "any")
1016 if not args.force:
1017 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
1018 if not (len(r)>0 and r[0].lower()=="y"):
1019 return 0
1020 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
1021 mano_response = requests.delete(URLrequest)
1022 logger.debug("openmano response: %s", mano_response.text )
1023 result = 0 if mano_response.status_code==200 else mano_response.status_code
1024 content = mano_response.json()
1025 #print json.dumps(content, indent=4)
1026 if mano_response.status_code == 200:
1027 print content['result']
1028 else:
1029 print content['error']['description']
1030 return result
1031
1032def datacenter_list(args):
1033 #print "datacenter-list",args
1034 tenant='any' if args.all else _get_tenant()
1035
1036 if args.name:
1037 toshow = _get_item_uuid("datacenters", args.name, tenant)
1038 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
1039 else:
1040 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
1041 mano_response = requests.get(URLrequest)
1042 logger.debug("openmano response: %s", mano_response.text )
1043 if args.verbose==None:
1044 args.verbose=0
1045 if args.name!=None:
1046 args.verbose += 1
1047 return _print_verbose(mano_response, args.verbose)
1048
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001049def datacenter_sdn_port_mapping_set(args):
1050 tenant = _get_tenant()
1051 datacenter = _get_datacenter(args.name, tenant)
1052 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1053
1054 if not args.file:
1055 raise OpenmanoCLIError(
1056 "No yaml/json has been provided specifying the SDN port mapping")
1057
1058 port_mapping = yaml.load(datacenter_sdn_port_mapping_list(args))
1059 if len(port_mapping["sdn_port_mapping"]["ports_mapping"]) > 0:
1060 if not args.force:
1061 r = raw_input("Datacenter %s already contains a port mapping. Overwrite? (y/N)? " % (datacenter))
1062 if not (len(r) > 0 and r[0].lower() == "y"):
1063 return 0
1064 args.force = True
1065 print datacenter_sdn_port_mapping_clear(args)
1066
1067 sdn_port_mapping = _load_file_or_yaml(args.file)
1068 payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping})
1069
1070 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1071 logger.debug("openmano request: %s", payload_req)
1072 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1073 logger.debug("openmano response: %s", mano_response.text)
1074
1075 if mano_response.status_code == 200:
1076 return yaml.safe_dump(mano_response.json())
1077 else:
1078 return mano_response.content
1079
1080def datacenter_sdn_port_mapping_list(args):
1081 tenant = _get_tenant()
1082 datacenter = _get_datacenter(args.name, tenant)
1083
1084 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1085 mano_response = requests.get(URLrequest)
1086 logger.debug("openmano response: %s", mano_response.text)
1087
1088 if mano_response.status_code != 200:
1089 return mano_response.content
1090
1091 return yaml.safe_dump(mano_response.json())
1092
1093def datacenter_sdn_port_mapping_clear(args):
1094 tenant = _get_tenant()
1095 datacenter = _get_datacenter(args.name, tenant)
1096
1097 if not args.force:
1098 r = raw_input("Clean SDN port mapping for datacenter %s (y/N)? " %(datacenter))
1099 if not (len(r)>0 and r[0].lower()=="y"):
1100 return 0
1101
1102 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1103 mano_response = requests.delete(URLrequest)
1104 logger.debug("openmano response: %s", mano_response.text)
1105
1106 if mano_response.status_code != 200:
1107 if "No port mapping for datacenter" in mano_response.content:
1108 return "No port mapping for datacenter " + datacenter + " has been found"
1109 return mano_response.content
1110
1111 return yaml.safe_dump(mano_response.json())
1112
1113def sdn_controller_create(args):
1114 tenant = _get_tenant()
1115 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1116
1117 if not (args.ip and args.port and args.dpid and args.type):
1118 raise OpenmanoCLIError("The following arguments are required: ip, port, dpid, type")
1119
1120 controller_dict = {}
1121 controller_dict['name'] = args.name
1122 controller_dict['ip'] = args.ip
1123 controller_dict['port'] = int(args.port)
1124 controller_dict['dpid'] = args.dpid
1125 controller_dict['type'] = args.type
1126 if args.description != None:
1127 controller_dict['description'] = args.description
1128 if args.user != None:
1129 controller_dict['user'] = args.user
1130 if args.password != None:
1131 controller_dict['password'] = args.password
1132
1133 payload_req = json.dumps({"sdn_controller": controller_dict})
1134
1135 # print payload_req
1136
1137 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" % (mano_host, mano_port, tenant)
1138 logger.debug("openmano request: %s", payload_req)
1139 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1140 logger.debug("openmano response: %s", mano_response.text)
1141 result = _print_verbose(mano_response, args.verbose)
1142
1143 return result
1144
1145def sdn_controller_edit(args):
1146 tenant = _get_tenant()
1147 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1148 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1149
1150 if not (args.new_name or args.ip or args.port or args.dpid or args.type):
1151 raise OpenmanoCLIError("At least one parameter must be editd")
1152
1153 if not args.force:
1154 r = raw_input("Update SDN controller %s (y/N)? " %(args.name))
1155 if not (len(r)>0 and r[0].lower()=="y"):
1156 return 0
1157
1158 controller_dict = {}
1159 if args.new_name != None:
1160 controller_dict['name'] = args.new_name
1161 if args.ip != None:
1162 controller_dict['ip'] = args.ip
1163 if args.port != None:
Pablo Montes Morenob12711f2017-04-06 11:54:34 +02001164 controller_dict['port'] = int(args.port)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001165 if args.dpid != None:
1166 controller_dict['dpid'] = args.dpid
1167 if args.type != None:
1168 controller_dict['type'] = args.type
1169 if args.description != None:
1170 controller_dict['description'] = args.description
1171 if args.user != None:
1172 controller_dict['user'] = args.user
1173 if args.password != None:
1174 controller_dict['password'] = args.password
1175
1176 payload_req = json.dumps({"sdn_controller": controller_dict})
1177
1178 # print payload_req
1179
1180 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1181 logger.debug("openmano request: %s", payload_req)
1182 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1183 logger.debug("openmano response: %s", mano_response.text)
1184 result = _print_verbose(mano_response, args.verbose)
1185
1186 return result
1187
1188def sdn_controller_list(args):
1189 tenant = _get_tenant()
1190 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1191
1192 if args.name:
1193 toshow = _get_item_uuid("sdn_controllers", args.name, tenant)
1194 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" %(mano_host, mano_port, tenant, toshow)
1195 else:
1196 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" %(mano_host, mano_port, tenant)
1197 #print URLrequest
1198 mano_response = requests.get(URLrequest)
1199 logger.debug("openmano response: %s", mano_response.text )
1200 if args.verbose==None:
1201 args.verbose=0
1202 if args.name!=None:
1203 args.verbose += 1
1204
1205 result = json.dumps(mano_response.json(), indent=4)
1206 return result
1207
1208def sdn_controller_delete(args):
1209 tenant = _get_tenant()
1210 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1211
1212 if not args.force:
1213 r = raw_input("Delete SDN controller %s (y/N)? " % (args.name))
1214 if not (len(r) > 0 and r[0].lower() == "y"):
1215 return 0
1216
1217 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1218 mano_response = requests.delete(URLrequest)
1219 logger.debug("openmano response: %s", mano_response.text)
1220 result = _print_verbose(mano_response, args.verbose)
1221
1222 return result
1223
tierno7edb6752016-03-21 17:37:52 +01001224def vim_action(args):
1225 #print "datacenter-net-action",args
1226 tenant = _get_tenant()
1227 datacenter = _get_datacenter(args.datacenter, tenant)
1228 if args.verbose==None:
1229 args.verbose=0
1230 if args.action=="list":
1231 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1232 if args.name!=None:
1233 args.verbose += 1
1234 URLrequest += "/" + args.name
1235 mano_response = requests.get(URLrequest)
1236 logger.debug("openmano response: %s", mano_response.text )
1237 return _print_verbose(mano_response, args.verbose)
1238 elif args.action=="delete":
1239 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1240 mano_response = requests.delete(URLrequest)
1241 logger.debug("openmano response: %s", mano_response.text )
1242 result = 0 if mano_response.status_code==200 else mano_response.status_code
1243 content = mano_response.json()
1244 #print json.dumps(content, indent=4)
1245 if mano_response.status_code == 200:
1246 print content['result']
1247 else:
1248 print content['error']['description']
1249 return result
1250 elif args.action=="create":
1251 headers_req = {'content-type': 'application/yaml'}
1252 if args.file:
1253 create_dict = _load_file_or_yaml(args.file)
1254 if args.item not in create_dict:
1255 create_dict = {args.item: create_dict}
1256 else:
1257 create_dict = {args.item:{}}
1258 if args.name:
1259 create_dict[args.item]['name'] = args.name
1260 #if args.description:
1261 # create_dict[args.item]['description'] = args.description
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001262 if args.item=="network":
tierno7edb6752016-03-21 17:37:52 +01001263 if args.bind_net:
1264 create_dict[args.item]['bind_net'] = args.bind_net
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001265 if args.type:
1266 create_dict[args.item]['type'] = args.type
tierno7edb6752016-03-21 17:37:52 +01001267 if args.shared:
1268 create_dict[args.item]['shared'] = args.shared
1269 if "name" not in create_dict[args.item]:
1270 print "You must provide a name in the descriptor file or with the --name option"
1271 return
1272 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1273 logger.debug("openmano request: %s", payload_req)
1274 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, mano_tenant, datacenter, args.item)
1275 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1276 logger.debug("openmano response: %s", mano_response.text )
1277 if args.verbose==None:
1278 args.verbose=0
1279 return _print_verbose(mano_response, args.verbose)
1280
1281
1282def datacenter_net_action(args):
1283 if args.action == "net-update":
tierno5acf7202016-08-29 14:28:13 +02001284 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
tierno7edb6752016-03-21 17:37:52 +01001285 print
1286 args.action = "netmap-delete"
1287 args.netmap = None
1288 args.all = True
1289 r = datacenter_netmap_action(args)
1290 if r == 0:
1291 args.force = True
tierno5acf7202016-08-29 14:28:13 +02001292 args.action = "netmap-import"
tierno7edb6752016-03-21 17:37:52 +01001293 r = datacenter_netmap_action(args)
1294 return r
1295
1296 if args.action == "net-edit":
1297 args.netmap = args.net
1298 args.name = None
1299 elif args.action == "net-list":
1300 args.netmap = None
1301 elif args.action == "net-delete":
1302 args.netmap = args.net
1303 args.all = False
1304
1305 args.action = "netmap" + args.action[3:]
1306 args.vim_name=None
1307 args.vim_id=None
1308 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1309 print
1310 return datacenter_netmap_action(args)
1311
1312def datacenter_netmap_action(args):
1313 tenant = _get_tenant()
1314 datacenter = _get_datacenter(args.datacenter, tenant)
1315 #print "datacenter_netmap_action",args
1316 payload_req = None
1317 if args.verbose==None:
1318 args.verbose=0
1319 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1320 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1321
1322 if args.action=="netmap-list":
1323 if args.netmap:
1324 URLrequest += "/" + args.netmap
1325 args.verbose += 1
1326 mano_response = requests.get(URLrequest)
1327
1328 elif args.action=="netmap-delete":
1329 if args.netmap and args.all:
1330 print "you can not use a netmap name and the option --all at the same time"
1331 return 1
1332 if args.netmap:
1333 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1334 URLrequest += "/" + args.netmap
1335 elif args.all:
1336 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1337 else:
tiernoae4a8d12016-07-08 12:30:39 +02001338 print "you must specify a netmap name or the option --all"
tierno7edb6752016-03-21 17:37:52 +01001339 return 1
1340 if not args.force:
1341 r = raw_input(force_text)
1342 if len(r)>0 and r[0].lower()=="y":
1343 pass
1344 else:
1345 return 0
1346 mano_response = requests.delete(URLrequest, headers=headers_req)
tierno5acf7202016-08-29 14:28:13 +02001347 elif args.action=="netmap-import":
tierno7edb6752016-03-21 17:37:52 +01001348 if not args.force:
1349 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1350 if len(r)>0 and r[0].lower()=="y":
1351 pass
1352 else:
1353 return 0
1354 URLrequest += "/upload"
1355 mano_response = requests.post(URLrequest, headers=headers_req)
1356 elif args.action=="netmap-edit" or args.action=="netmap-create":
1357 if args.file:
1358 payload = _load_file_or_yaml(args.file)
1359 else:
1360 payload = {}
1361 if "netmap" not in payload:
1362 payload = {"netmap": payload}
1363 if args.name:
1364 payload["netmap"]["name"] = args.name
1365 if args.vim_id:
1366 payload["netmap"]["vim_id"] = args.vim_id
1367 if args.action=="netmap-create" and args.vim_name:
1368 payload["netmap"]["vim_name"] = args.vim_name
1369 payload_req = json.dumps(payload)
1370 logger.debug("openmano request: %s", payload_req)
1371
1372 if args.action=="netmap-edit" and not args.force:
1373 if len(payload["netmap"]) == 0:
1374 print "You must supply some parameter to edit"
1375 return 1
1376 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1377 if len(r)>0 and r[0].lower()=="y":
1378 pass
1379 else:
1380 return 0
1381 URLrequest += "/" + args.netmap
1382 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1383 else: #netmap-create
1384 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1385 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1386 return 1
1387 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1388
1389 logger.debug("openmano response: %s", mano_response.text )
1390 return _print_verbose(mano_response, args.verbose)
1391
1392def element_edit(args):
1393 element = _get_item_uuid(args.element, args.name)
1394 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1395 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1396 payload=_load_file_or_yaml(args.file)
1397 if args.element[:-1] not in payload:
1398 payload = {args.element[:-1]: payload }
1399 payload_req = json.dumps(payload)
1400
1401 #print payload_req
1402 if not args.force or (args.name==None and args.filer==None):
1403 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1404 if len(r)>0 and r[0].lower()=="y":
1405 pass
1406 else:
1407 return 0
1408 logger.debug("openmano request: %s", payload_req)
1409 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1410 logger.debug("openmano response: %s", mano_response.text )
1411 if args.verbose==None:
1412 args.verbose=0
1413 if args.name!=None:
1414 args.verbose += 1
1415 return _print_verbose(mano_response, args.verbose)
1416
1417
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001418def datacenter_edit(args):
1419 tenant = _get_tenant()
1420 element = _get_item_uuid('datacenters', args.name, tenant)
1421 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1422 URLrequest = "http://%s:%s/openmano/datacenters/%s" % (mano_host, mano_port, element)
1423
1424 has_arguments = False
1425 if args.file != None:
1426 has_arguments = True
1427 payload = _load_file_or_yaml(args.file)
1428 else:
1429 payload = {}
1430
1431 if args.sdn_controller != None:
1432 has_arguments = True
1433 if not 'config' in payload:
1434 payload['config'] = {}
1435 if not 'sdn-controller' in payload['config']:
1436 payload['config']['sdn-controller'] = {}
1437 if args.sdn_controller == 'null':
1438 payload['config']['sdn-controller'] = None
1439 else:
1440 payload['config']['sdn-controller'] = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1441
1442 if not has_arguments:
1443 raise OpenmanoCLIError("At least one argument must be provided to modify the datacenter")
1444
1445 if 'datacenter' not in payload:
1446 payload = {'datacenter': payload}
1447 payload_req = json.dumps(payload)
1448
1449 # print payload_req
1450 if not args.force or (args.name == None and args.filer == None):
1451 r = raw_input(" Edit datacenter " + args.name + " (y/N)? ")
1452 if len(r) > 0 and r[0].lower() == "y":
1453 pass
1454 else:
1455 return 0
1456 logger.debug("openmano request: %s", payload_req)
1457 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1458 logger.debug("openmano response: %s", mano_response.text)
1459 if args.verbose == None:
1460 args.verbose = 0
1461 if args.name != None:
1462 args.verbose += 1
1463 return _print_verbose(mano_response, args.verbose)
1464
tierno7edb6752016-03-21 17:37:52 +01001465global mano_host
1466global mano_port
1467global mano_tenant
1468
1469if __name__=="__main__":
1470
1471 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1472 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1473 mano_port = os.getenv('OPENMANO_PORT',"9090")
1474 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1475
1476 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1477 main_parser.add_argument('--version', action='version', version='%(prog)s ' + __version__ )
1478
1479 subparsers = main_parser.add_subparsers(help='commands')
1480
tierno7edb6752016-03-21 17:37:52 +01001481 parent_parser = argparse.ArgumentParser(add_help=False)
1482 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1483 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1484
garciadeblas0e9fd832016-07-08 15:20:18 +02001485 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1486 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1487 config_parser.set_defaults(func=config)
1488
tierno7edb6752016-03-21 17:37:52 +01001489 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1490 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1491 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1492 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1493 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
garciadeblas14480452017-01-10 13:08:07 +01001494 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1495 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
tierno7edb6752016-03-21 17:37:52 +01001496 vnf_create_parser.set_defaults(func=vnf_create)
1497
1498 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1499 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1500 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1501 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1502 vnf_list_parser.set_defaults(func=vnf_list)
1503
1504 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1505 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1506 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1507 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1508 vnf_delete_parser.set_defaults(func=vnf_delete)
1509
1510 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1511 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1512 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1513 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1514 scenario_create_parser.set_defaults(func=scenario_create)
1515
1516 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1517 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1518 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1519 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1520 scenario_list_parser.set_defaults(func=scenario_list)
1521
1522 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1523 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1524 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1525 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1526 scenario_delete_parser.set_defaults(func=scenario_delete)
1527
1528 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1529 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1530 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1531 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1532 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1533 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1534 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1535
1536 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1537 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1538 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1539 scenario_deploy_parser.set_defaults(func=scenario_verify)
1540
1541 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1542 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1543 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1544 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1545 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1546 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1547 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")
1548 instance_scenario_create_parser.add_argument("--netmap-create", action="append", type=str, dest="netmap_create", help="the scenario network must be created at datacenter 'scenario-network[=datacenter-network-name]' . Can be used several times")
tiernoa4e1a6e2016-08-31 14:19:40 +02001549 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")
1550 instance_scenario_create_parser.add_argument("--keypair-auto", action="store_true", dest="keypair_auto", help="Inject the user ssh-keys found at $HOME/.ssh directory")
tierno7edb6752016-03-21 17:37:52 +01001551 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1552 instance_scenario_create_parser.set_defaults(func=instance_create)
1553
1554 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1555 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1556 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1557 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1558
1559 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)")
1560 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1561 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1562 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1563 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1564
1565 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1566 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1567 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1568 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console"],\
1569 help="action to send")
1570 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1571 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1572 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1573 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1574
1575 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1576 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1577 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1578
1579 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1580 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1581 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1582 tenant_create_parser.set_defaults(func=tenant_create)
1583
1584 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1585 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1586 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1587 tenant_delete_parser.set_defaults(func=tenant_delete)
1588
1589 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1590 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1591 tenant_list_parser.set_defaults(func=tenant_list)
1592
tierno161c24b2017-05-16 15:45:56 +02001593 element_edit_parser = subparsers.add_parser('tenant-edit', parents=[parent_parser], help="edits one tenant")
1594 element_edit_parser.add_argument("name", help="name or uuid of the tenant")
1595 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1596 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1597 element_edit_parser.set_defaults(func=element_edit, element='tenants')
tierno7edb6752016-03-21 17:37:52 +01001598
1599 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1600 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1601 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1602 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1603 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1604 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1605 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001606 datacenter_create_parser.add_argument("--sdn-controller", action="store", help="Name or uuid of the SDN controller to be used", dest='sdn_controller')
tierno7edb6752016-03-21 17:37:52 +01001607 datacenter_create_parser.set_defaults(func=datacenter_create)
1608
1609 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1610 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1611 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1612 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1613
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001614 datacenter_edit_parser = subparsers.add_parser('datacenter-edit', parents=[parent_parser], help="Edit datacenter")
1615 datacenter_edit_parser.add_argument("name", help="name or uuid of the datacenter")
1616 datacenter_edit_parser.add_argument("--file", help="json/yaml text or file with the changes").completer = FilesCompleter
1617 datacenter_edit_parser.add_argument("--sdn-controller", action="store",
1618 help="Name or uuid of the SDN controller to be used. Specify 'null' to clear entry", dest='sdn_controller')
1619 datacenter_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1620 datacenter_edit_parser.set_defaults(func=datacenter_edit)
1621
tierno7edb6752016-03-21 17:37:52 +01001622 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1623 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1624 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1625 datacenter_list_parser.set_defaults(func=datacenter_list)
1626
1627 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1628 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1629 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1630 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1631 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1632 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
tierno8008c3a2016-10-13 15:34:28 +00001633 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
tierno7edb6752016-03-21 17:37:52 +01001634 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1635
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001636 datacenter_edit_vim_tenant_parser = subparsers.add_parser('datacenter-edit-vim-tenant', parents=[parent_parser],
1637 help="Edit the association of a datacenter to the operating tenant")
1638 datacenter_edit_vim_tenant_parser.add_argument("name", help="name or uuid of the datacenter")
1639 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-id', action='store',
1640 help="specify a datacenter tenant to use. A new one is created by default")
1641 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1642 datacenter_edit_vim_tenant_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1643 datacenter_edit_vim_tenant_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1644 datacenter_edit_vim_tenant_parser.add_argument("--config", action="store",
1645 help="aditional configuration in json/yaml format")
1646 datacenter_edit_vim_tenant_parser.set_defaults(func=datacenter_edit_vim_tenant)
1647
tierno7edb6752016-03-21 17:37:52 +01001648 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1649 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1650 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1651 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1652
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001653 #=======================datacenter_sdn_port_mapping_xxx section=======================
1654 #datacenter_sdn_port_mapping_set
1655 datacenter_sdn_port_mapping_set_parser = subparsers.add_parser('datacenter-sdn-port-mapping-set',
1656 parents=[parent_parser],
1657 help="Load a file with the mapping of physical ports "
1658 "and the ports of the dataplaneswitch controlled "
1659 "by a datacenter")
1660 datacenter_sdn_port_mapping_set_parser.add_argument("name", action="store", help="specifies the datacenter")
1661 datacenter_sdn_port_mapping_set_parser.add_argument("file",
1662 help="json/yaml text or file with the port mapping").completer = FilesCompleter
1663 datacenter_sdn_port_mapping_set_parser.add_argument("-f", "--force", action="store_true",
1664 help="forces overwriting without asking")
1665 datacenter_sdn_port_mapping_set_parser.set_defaults(func=datacenter_sdn_port_mapping_set)
1666
1667 #datacenter_sdn_port_mapping_list
1668 datacenter_sdn_port_mapping_list_parser = subparsers.add_parser('datacenter-sdn-port-mapping-list',
1669 parents=[parent_parser],
1670 help="Show the SDN port mapping in a datacenter")
1671 datacenter_sdn_port_mapping_list_parser.add_argument("name", action="store", help="specifies the datacenter")
1672 datacenter_sdn_port_mapping_list_parser.set_defaults(func=datacenter_sdn_port_mapping_list)
1673
1674 # datacenter_sdn_port_mapping_clear
1675 datacenter_sdn_port_mapping_clear_parser = subparsers.add_parser('datacenter-sdn-port-mapping-clear',
1676 parents=[parent_parser],
1677 help="Clean the the SDN port mapping in a datacenter")
1678 datacenter_sdn_port_mapping_clear_parser.add_argument("name", action="store",
1679 help="specifies the datacenter")
1680 datacenter_sdn_port_mapping_clear_parser.add_argument("-f", "--force", action="store_true",
1681 help="forces clearing without asking")
1682 datacenter_sdn_port_mapping_clear_parser.set_defaults(func=datacenter_sdn_port_mapping_clear)
1683 # =======================
1684
1685 # =======================sdn_controller_xxx section=======================
1686 # sdn_controller_create
1687 sdn_controller_create_parser = subparsers.add_parser('sdn-controller-create', parents=[parent_parser],
1688 help="Creates an SDN controller entity within RO")
1689 sdn_controller_create_parser.add_argument("name", help="name of the SDN controller")
1690 sdn_controller_create_parser.add_argument("--description", action="store", help="description of the SDN controller")
1691 sdn_controller_create_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1692 sdn_controller_create_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1693 sdn_controller_create_parser.add_argument("--dpid", action="store",
1694 help="DPID of the dataplane switch controlled by this SDN controller")
1695 sdn_controller_create_parser.add_argument("--type", action="store",
1696 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1697 sdn_controller_create_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1698 sdn_controller_create_parser.add_argument("--passwd", action="store", dest='password',
1699 help="password credentials for the SDN controller")
1700 sdn_controller_create_parser.set_defaults(func=sdn_controller_create)
1701
1702 # sdn_controller_edit
1703 sdn_controller_edit_parser = subparsers.add_parser('sdn-controller-edit', parents=[parent_parser],
1704 help="Update one or more options of a SDN controller")
1705 sdn_controller_edit_parser.add_argument("name", help="name or uuid of the SDN controller", )
1706 sdn_controller_edit_parser.add_argument("--name", action="store", help="Update the name of the SDN controller",
1707 dest='new_name')
1708 sdn_controller_edit_parser.add_argument("--description", action="store", help="description of the SDN controller")
1709 sdn_controller_edit_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1710 sdn_controller_edit_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1711 sdn_controller_edit_parser.add_argument("--dpid", action="store",
1712 help="DPID of the dataplane switch controlled by this SDN controller")
1713 sdn_controller_edit_parser.add_argument("--type", action="store",
1714 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1715 sdn_controller_edit_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1716 sdn_controller_edit_parser.add_argument("--password", action="store",
1717 help="password credentials for the SDN controller", dest='password')
1718 sdn_controller_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1719 #TODO: include option --file
1720 sdn_controller_edit_parser.set_defaults(func=sdn_controller_edit)
1721
1722 #sdn_controller_list
1723 sdn_controller_list_parser = subparsers.add_parser('sdn-controller-list',
1724 parents=[parent_parser],
1725 help="List the SDN controllers")
1726 sdn_controller_list_parser.add_argument("name", nargs='?', help="name or uuid of the SDN controller")
1727 sdn_controller_list_parser.set_defaults(func=sdn_controller_list)
1728
1729 # sdn_controller_delete
1730 sdn_controller_delete_parser = subparsers.add_parser('sdn-controller-delete',
1731 parents=[parent_parser],
1732 help="Delete the the SDN controller")
1733 sdn_controller_delete_parser.add_argument("name", help="name or uuid of the SDN controller")
1734 sdn_controller_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1735 sdn_controller_delete_parser.set_defaults(func=sdn_controller_delete)
1736 # =======================
tierno7edb6752016-03-21 17:37:52 +01001737
1738 action_dict={'net-update': 'retrieves external networks from datacenter',
1739 'net-edit': 'edits an external network',
1740 'net-delete': 'deletes an external network',
1741 'net-list': 'lists external networks from a datacenter'
1742 }
1743 for item in action_dict:
1744 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1745 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1746 if item=='net-edit' or item=='net-delete':
1747 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1748 if item=='net-edit':
1749 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1750 if item!='net-list':
1751 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1752 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1753
1754
tierno5acf7202016-08-29 14:28:13 +02001755 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
tierno7edb6752016-03-21 17:37:52 +01001756 'netmap-create': 'create a new network senario netmap',
1757 'netmap-edit': 'edit name of a network senario netmap',
1758 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1759 'netmap-list': 'list/show network scenario netmaps'
1760 }
1761 for item in action_dict:
1762 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1763 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1764 #if item=='net-add':
1765 # datacenter_action_parser.add_argument("net", help="name of the network")
1766 if item=='netmap-delete':
1767 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1768 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1769 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1770 if item=='netmap-edit':
1771 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1772 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1773 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1774 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1775 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1776 if item=='netmap-list':
1777 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1778 if item=='netmap-create':
1779 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1780 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1781 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1782 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
tierno5acf7202016-08-29 14:28:13 +02001783 if item=='netmap-import':
tierno7edb6752016-03-21 17:37:52 +01001784 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1785 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
1786
tierno4540ea52017-01-18 17:44:32 +01001787 for item in ("network", "tenant", "image"):
tierno7edb6752016-03-21 17:37:52 +01001788 if item=="network":
1789 commnad_name = 'vim-net'
1790 else:
1791 commnad_name = 'vim-'+item
1792 vim_item_list_parser = subparsers.add_parser(commnad_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
1793 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
1794 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1795 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
1796
1797 vim_item_del_parser = subparsers.add_parser(commnad_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
1798 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
1799 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1800 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
1801
tierno4540ea52017-01-18 17:44:32 +01001802 if item == "network" or item == "tenant":
1803 vim_item_create_parser = subparsers.add_parser(commnad_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
1804 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
1805 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
1806 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1807 if item=="network":
1808 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
1809 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
1810 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>'")
1811 else:
1812 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
1813 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
tierno7edb6752016-03-21 17:37:52 +01001814
1815 argcomplete.autocomplete(main_parser)
1816
1817 try:
1818 args = main_parser.parse_args()
1819 #logging info
1820 level = logging.CRITICAL
1821 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
1822 if "debug" in args and args.debug:
1823 level = logging.DEBUG
1824 logging.basicConfig(format=streamformat, level= level)
1825 logger = logging.getLogger('mano')
1826 logger.setLevel(level)
1827 result = args.func(args)
1828 if result == None:
1829 result = 0
1830 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
1831 except (requests.exceptions.ConnectionError):
1832 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
1833 result = -2
1834 except (KeyboardInterrupt):
1835 print 'Exiting openmano'
1836 result = -3
1837 except (SystemExit, ArgumentParserError):
1838 result = -4
1839 except OpenmanoCLIError as e:
1840 print str(e)
1841 result = -5
1842
1843 #print result
1844 exit(result)
1845