blob: 111df432858a1e616859172bd561e74ec59e43a9 [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'''
tierno72a08d72017-05-25 13:12:30 +020029__author__ = "Alfonso Tierno, Gerardo Garcia, Pablo Montes"
30__date__ = "$09-oct-2014 09:09:48$"
31__version__ = "0.4.14-r521"
32version_date = "May 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
tierno72a08d72017-05-25 13:12:30 +0200559 tenant = _get_tenant()
tierno7edb6752016-03-21 17:37:52 +0100560 headers_req = {'content-type': 'application/json'}
561 action = {}
562 action["verify"] = {}
563 action["verify"]["instance_name"] = "scen-verify-return5"
564 payload_req = json.dumps(action, indent=4)
565 #print payload_req
566
tierno72a08d72017-05-25 13:12:30 +0200567 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, tenant, args.scenario)
tierno7edb6752016-03-21 17:37:52 +0100568 logger.debug("openmano request: %s", payload_req)
569 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
570 logger.debug("openmano response: %s", mano_response.text )
571
572 result = 0 if mano_response.status_code==200 else mano_response.status_code
573 content = mano_response.json()
574 #print json.dumps(content, indent=4)
575 if mano_response.status_code == 200:
576 print content['result']
577 else:
578 print content['error']['description']
579 return result
580
581def instance_create(args):
582 tenant = _get_tenant()
583 headers_req = {'content-type': 'application/yaml'}
584 myInstance={"instance": {}, "schema_version": "0.1"}
585 if args.file:
586 instance_dict = _load_file_or_yaml(args.file)
587 if "instance" not in instance_dict:
588 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
589 else:
590 myInstance = instance_dict
591 if args.name:
592 myInstance["instance"]['name'] = args.name
593 if args.description:
594 myInstance["instance"]['description'] = args.description
595 if args.nostart:
596 myInstance["instance"]['action'] = "reserve"
597 #datacenter
598 datacenter = myInstance["instance"].get("datacenter")
599 if args.datacenter != None:
600 datacenter = args.datacenter
601 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
602 #scenario
603 scenario = myInstance["instance"].get("scenario")
604 if args.scenario != None:
605 scenario = args.scenario
606 if not scenario:
garciadeblased746032017-01-05 11:58:41 +0100607 print "you must provide a scenario in the file descriptor or with --scenario"
tierno7edb6752016-03-21 17:37:52 +0100608 return -1
609 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
610 if args.netmap_use:
611 if "networks" not in myInstance["instance"]:
612 myInstance["instance"]["networks"] = {}
613 for net in args.netmap_use:
614 net_comma_list = net.split(",")
615 for net_comma in net_comma_list:
616 net_tuple = net_comma.split("=")
617 if len(net_tuple) != 2:
618 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
619 return
620 net_scenario = net_tuple[0].strip()
621 net_datacenter = net_tuple[1].strip()
622 if net_scenario not in myInstance["instance"]["networks"]:
623 myInstance["instance"]["networks"][net_scenario] = {}
tiernobe41e222016-09-02 15:16:13 +0200624 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
625 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
626 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
tierno7edb6752016-03-21 17:37:52 +0100627 if args.netmap_create:
628 if "networks" not in myInstance["instance"]:
629 myInstance["instance"]["networks"] = {}
630 for net in args.netmap_create:
631 net_comma_list = net.split(",")
632 for net_comma in net_comma_list:
633 net_tuple = net_comma.split("=")
634 if len(net_tuple) == 1:
635 net_scenario = net_tuple[0].strip()
636 net_datacenter = None
637 elif len(net_tuple) == 2:
638 net_scenario = net_tuple[0].strip()
639 net_datacenter = net_tuple[1].strip()
640 else:
641 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
642 return
643 if net_scenario not in myInstance["instance"]["networks"]:
644 myInstance["instance"]["networks"][net_scenario] = {}
tiernobe41e222016-09-02 15:16:13 +0200645 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
646 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
647 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
tiernoa4e1a6e2016-08-31 14:19:40 +0200648 if args.keypair:
649 if "cloud-config" not in myInstance["instance"]:
650 myInstance["instance"]["cloud-config"] = {}
651 cloud_config = myInstance["instance"]["cloud-config"]
652 for key in args.keypair:
653 index = key.find(":")
654 if index<0:
655 if "key-pairs" not in cloud_config:
656 cloud_config["key-pairs"] = []
657 cloud_config["key-pairs"].append(key)
658 else:
659 user = key[:index]
660 key_ = key[index+1:]
661 key_list = key_.split(",")
662 if "users" not in cloud_config:
663 cloud_config["users"] = []
664 cloud_config["users"].append({"name": user, "key-pairs": key_list })
665 if args.keypair_auto:
666 try:
667 keys=[]
668 home = os.getenv("HOME")
669 user = os.getenv("USER")
670 files = os.listdir(home+'/.ssh')
671 for file in files:
672 if file[-4:] == ".pub":
673 with open(home+'/.ssh/'+file, 'r') as f:
674 keys.append(f.read())
675 if not keys:
676 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
677 return 1
678 except Exception as e:
679 print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
680 return 1
681
682 if "cloud-config" not in myInstance["instance"]:
683 myInstance["instance"]["cloud-config"] = {}
684 cloud_config = myInstance["instance"]["cloud-config"]
685 if "key-pairs" not in cloud_config:
686 cloud_config["key-pairs"] = []
687 if user:
688 if "users" not in cloud_config:
689 cloud_config["users"] = []
690 cloud_config["users"].append({"name": user, "key-pairs": keys })
tierno7edb6752016-03-21 17:37:52 +0100691
692 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
693 logger.debug("openmano request: %s", payload_req)
694 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
695 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
696 logger.debug("openmano response: %s", mano_response.text )
697 if args.verbose==None:
698 args.verbose=0
699
700 result = 0 if mano_response.status_code==200 else mano_response.status_code
701 content = mano_response.json()
702 #print json.dumps(content, indent=4)
703 if args.verbose >= 3:
704 print yaml.safe_dump(content, indent=4, default_flow_style=False)
705 return result
706
707 if mano_response.status_code == 200:
708 myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
709 if args.verbose >=1:
710 myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
711 if args.verbose >=2:
712 myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
713 print myoutput
714 else:
715 print content['error']['description']
716 return result
717
718def instance_scenario_list(args):
719 #print "instance-scenario-list",args
720 if args.all:
721 tenant = "any"
722 else:
723 tenant = _get_tenant()
724 if args.name:
725 toshow = _get_item_uuid("instances", args.name, tenant)
726 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
727 else:
728 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
729 mano_response = requests.get(URLrequest)
730 logger.debug("openmano response: %s", mano_response.text )
731 content = mano_response.json()
732 #print json.dumps(content, indent=4)
733 if args.verbose==None:
734 args.verbose=0
735
736 result = 0 if mano_response.status_code==200 else mano_response.status_code
737 if mano_response.status_code == 200:
738 if not args.name:
739 if args.verbose >= 3:
740 print yaml.safe_dump(content, indent=4, default_flow_style=False)
741 return result
742 if len(content['instances']) == 0:
743 print "No scenario instances were found."
744 return result
745 for instance in content['instances']:
746 myoutput = "%s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20))
747 if args.verbose >=1:
748 myoutput = "%s %s" %(myoutput, instance['created_at'].ljust(20))
749 print myoutput
750 if args.verbose >=2:
751 print "Description: %s" %instance['description']
752 else:
753 if args.verbose:
754 print yaml.safe_dump(content, indent=4, default_flow_style=False)
755 return result
756 instance = content
757 print "%s %s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20),instance['created_at'].ljust(20))
758 print "Description: %s" %instance['description']
759 print "Template scenario id: %s" %instance['scenario_id']
760 print "Template scenario name: %s" %instance['scenario_name']
761 print "---------------------------------------"
762 print "VNF instances: %d" %len(instance['vnfs'])
763 for vnf in instance['vnfs']:
764 #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))
765 print " %s %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
766 if len(instance['nets'])>0:
767 print "---------------------------------------"
768 print "Internal nets:"
769 for net in instance['nets']:
tierno5c7c4732016-09-26 13:38:55 +0000770 if net['created']:
tierno7edb6752016-03-21 17:37:52 +0100771 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
772 print "---------------------------------------"
773 print "External nets:"
774 for net in instance['nets']:
tierno5c7c4732016-09-26 13:38:55 +0000775 if not net['created']:
tierno7edb6752016-03-21 17:37:52 +0100776 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
777 print "---------------------------------------"
778 print "VM instances:"
779 for vnf in instance['vnfs']:
780 for vm in vnf['vms']:
781 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'])
782 else:
783 print content['error']['description']
784 if args.verbose:
785 print yaml.safe_dump(content, indent=4, default_flow_style=False)
786 return result
787
788def instance_scenario_status(args):
789 print "instance-scenario-status"
790 return 0
791
792def instance_scenario_delete(args):
793 if args.all:
794 tenant = "any"
795 else:
796 tenant = _get_tenant()
797 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
798 #print "instance-scenario-delete",args
799 if not args.force:
800 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
801 if not (len(r)>0 and r[0].lower()=="y"):
802 return
803 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
804 mano_response = requests.delete(URLrequest)
805 logger.debug("openmano response: %s", mano_response.text )
806 result = 0 if mano_response.status_code==200 else mano_response.status_code
807 content = mano_response.json()
808 #print json.dumps(content, indent=4)
809 if mano_response.status_code == 200:
810 print content['result']
811 else:
812 print content['error']['description']
813 return result
814
815def instance_scenario_action(args):
816 #print "instance-scenario-action", args
817 tenant = _get_tenant()
818 toact = _get_item_uuid("instances", args.name, tenant=tenant)
819 action={}
820 action[ args.action ] = args.param
821 if args.vnf:
822 action["vnfs"] = args.vnf
823 if args.vm:
824 action["vms"] = args.vm
825
826 headers_req = {'content-type': 'application/json'}
827 payload_req = json.dumps(action, indent=4)
828 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
829 logger.debug("openmano request: %s", payload_req)
830 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
831 logger.debug("openmano response: %s", mano_response.text )
832 result = 0 if mano_response.status_code==200 else mano_response.status_code
833 content = mano_response.json()
834 #print json.dumps(content, indent=4)
835 if mano_response.status_code == 200:
836 if args.verbose:
837 print yaml.safe_dump(content, indent=4, default_flow_style=False)
838 return result
839 for uuid,c in content.iteritems():
840 print "%s %s %s" %(uuid.ljust(38), c['name'].ljust(20),c['description'].ljust(20))
841 else:
842 print content['error']['description']
843 return result
844
845
846def instance_vnf_list(args):
847 print "instance-vnf-list"
848 return 0
849
850def instance_vnf_status(args):
851 print "instance-vnf-status"
852 return 0
853
854def tenant_create(args):
855 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
856 tenant_dict={"name": args.name}
857 if args.description!=None:
858 tenant_dict["description"] = args.description
859 payload_req = json.dumps( {"tenant": tenant_dict })
860
861 #print payload_req
862
863 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
864 logger.debug("openmano request: %s", payload_req)
865 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
866 logger.debug("openmano response: %s", mano_response.text )
867 return _print_verbose(mano_response, args.verbose)
868
869def tenant_list(args):
870 #print "tenant-list",args
871 if args.name:
tierno392f2852016-05-13 12:28:55 +0200872 toshow = _get_item_uuid("tenants", args.name)
tierno7edb6752016-03-21 17:37:52 +0100873 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
874 else:
875 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
876 mano_response = requests.get(URLrequest)
877 logger.debug("openmano response: %s", mano_response.text )
878 if args.verbose==None:
879 args.verbose=0
880 if args.name!=None:
881 args.verbose += 1
882 return _print_verbose(mano_response, args.verbose)
883
884def tenant_delete(args):
885 #print "tenant-delete",args
886 todelete = _get_item_uuid("tenants", args.name)
887 if not args.force:
888 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
889 if not (len(r)>0 and r[0].lower()=="y"):
890 return 0
891 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
892 mano_response = requests.delete(URLrequest)
893 logger.debug("openmano response: %s", mano_response.text )
894 result = 0 if mano_response.status_code==200 else mano_response.status_code
895 content = mano_response.json()
896 #print json.dumps(content, indent=4)
897 if mano_response.status_code == 200:
898 print content['result']
899 else:
900 print content['error']['description']
901 return result
902
903def datacenter_attach(args):
904 tenant = _get_tenant()
905 datacenter = _get_datacenter(args.name)
906 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
907
908 datacenter_dict={}
909 if args.vim_tenant_id != None:
910 datacenter_dict['vim_tenant'] = args.vim_tenant_id
911 if args.vim_tenant_name != None:
912 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
913 if args.user != None:
914 datacenter_dict['vim_username'] = args.user
915 if args.password != None:
916 datacenter_dict['vim_password'] = args.password
tierno8008c3a2016-10-13 15:34:28 +0000917 if args.config!=None:
918 datacenter_dict["config"] = _load_file_or_yaml(args.config)
tierno7edb6752016-03-21 17:37:52 +0100919 payload_req = json.dumps( {"datacenter": datacenter_dict })
920
921 #print payload_req
922
923 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
924 logger.debug("openmano request: %s", payload_req)
925 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
926 logger.debug("openmano response: %s", mano_response.text )
927 result = _print_verbose(mano_response, args.verbose)
928 #provide addional information if error
929 if mano_response.status_code != 200:
930 content = mano_response.json()
931 if "already in use for 'name'" in content['error']['description'] and \
932 "to database vim_tenants table" in content['error']['description']:
933 print "Try to specify a different name with --vim-tenant-name"
934 return result
935
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100936
937def datacenter_edit_vim_tenant(args):
938 tenant = _get_tenant()
939 datacenter = _get_datacenter(args.name)
940 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
941
942 if not (args.vim_tenant_id or args.vim_tenant_name or args.user or args.password or args.config):
943 raise OpenmanoCLIError("Error. At least one parameter must be updated.")
944
945 datacenter_dict = {}
946 if args.vim_tenant_id != None:
947 datacenter_dict['vim_tenant'] = args.vim_tenant_id
948 if args.vim_tenant_name != None:
949 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
950 if args.user != None:
951 datacenter_dict['vim_username'] = args.user
952 if args.password != None:
953 datacenter_dict['vim_password'] = args.password
954 if args.config != None:
955 datacenter_dict["config"] = _load_file_or_yaml(args.config)
956 payload_req = json.dumps({"datacenter": datacenter_dict})
957
958 # print payload_req
959
960 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" % (mano_host, mano_port, tenant, datacenter)
961 logger.debug("openmano request: %s", payload_req)
962 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
963 logger.debug("openmano response: %s", mano_response.text)
964 result = _print_verbose(mano_response, args.verbose)
965
966 return result
967
tierno7edb6752016-03-21 17:37:52 +0100968def datacenter_detach(args):
969 if args.all:
970 tenant = "any"
971 else:
972 tenant = _get_tenant()
973 datacenter = _get_datacenter(args.name, tenant)
974 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
975 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
976 mano_response = requests.delete(URLrequest, headers=headers_req)
977 logger.debug("openmano response: %s", mano_response.text )
978 content = mano_response.json()
979 #print json.dumps(content, indent=4)
980 result = 0 if mano_response.status_code==200 else mano_response.status_code
981 if mano_response.status_code == 200:
982 print content['result']
983 else:
984 print content['error']['description']
985 return result
986
987def datacenter_create(args):
988 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
989 datacenter_dict={"name": args.name, "vim_url": args.url}
990 if args.description!=None:
991 datacenter_dict["description"] = args.description
992 if args.type!=None:
993 datacenter_dict["type"] = args.type
994 if args.url!=None:
995 datacenter_dict["vim_url_admin"] = args.url_admin
996 if args.config!=None:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100997 datacenter_dict["config"] = _load_file_or_yaml(args.config)
998 if args.sdn_controller!=None:
999 tenant = _get_tenant()
1000 sdn_controller = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1001 if not 'config' in datacenter_dict:
1002 datacenter_dict['config'] = {}
1003 datacenter_dict['config']['sdn-controller'] = sdn_controller
tierno7edb6752016-03-21 17:37:52 +01001004 payload_req = json.dumps( {"datacenter": datacenter_dict })
1005
1006 #print payload_req
1007
1008 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
1009 logger.debug("openmano request: %s", payload_req)
1010 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1011 logger.debug("openmano response: %s", mano_response.text )
1012 return _print_verbose(mano_response, args.verbose)
1013
1014def datacenter_delete(args):
1015 #print "datacenter-delete",args
1016 todelete = _get_item_uuid("datacenters", args.name, "any")
1017 if not args.force:
1018 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
1019 if not (len(r)>0 and r[0].lower()=="y"):
1020 return 0
1021 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
1022 mano_response = requests.delete(URLrequest)
1023 logger.debug("openmano response: %s", mano_response.text )
1024 result = 0 if mano_response.status_code==200 else mano_response.status_code
1025 content = mano_response.json()
1026 #print json.dumps(content, indent=4)
1027 if mano_response.status_code == 200:
1028 print content['result']
1029 else:
1030 print content['error']['description']
1031 return result
1032
1033def datacenter_list(args):
1034 #print "datacenter-list",args
1035 tenant='any' if args.all else _get_tenant()
1036
1037 if args.name:
1038 toshow = _get_item_uuid("datacenters", args.name, tenant)
1039 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
1040 else:
1041 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
1042 mano_response = requests.get(URLrequest)
1043 logger.debug("openmano response: %s", mano_response.text )
1044 if args.verbose==None:
1045 args.verbose=0
1046 if args.name!=None:
1047 args.verbose += 1
1048 return _print_verbose(mano_response, args.verbose)
1049
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001050def datacenter_sdn_port_mapping_set(args):
1051 tenant = _get_tenant()
1052 datacenter = _get_datacenter(args.name, tenant)
1053 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1054
1055 if not args.file:
1056 raise OpenmanoCLIError(
1057 "No yaml/json has been provided specifying the SDN port mapping")
1058
1059 port_mapping = yaml.load(datacenter_sdn_port_mapping_list(args))
1060 if len(port_mapping["sdn_port_mapping"]["ports_mapping"]) > 0:
1061 if not args.force:
1062 r = raw_input("Datacenter %s already contains a port mapping. Overwrite? (y/N)? " % (datacenter))
1063 if not (len(r) > 0 and r[0].lower() == "y"):
1064 return 0
1065 args.force = True
1066 print datacenter_sdn_port_mapping_clear(args)
1067
1068 sdn_port_mapping = _load_file_or_yaml(args.file)
1069 payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping})
1070
1071 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1072 logger.debug("openmano request: %s", payload_req)
1073 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1074 logger.debug("openmano response: %s", mano_response.text)
1075
1076 if mano_response.status_code == 200:
1077 return yaml.safe_dump(mano_response.json())
1078 else:
1079 return mano_response.content
1080
1081def datacenter_sdn_port_mapping_list(args):
1082 tenant = _get_tenant()
1083 datacenter = _get_datacenter(args.name, tenant)
1084
1085 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1086 mano_response = requests.get(URLrequest)
1087 logger.debug("openmano response: %s", mano_response.text)
1088
1089 if mano_response.status_code != 200:
1090 return mano_response.content
1091
1092 return yaml.safe_dump(mano_response.json())
1093
1094def datacenter_sdn_port_mapping_clear(args):
1095 tenant = _get_tenant()
1096 datacenter = _get_datacenter(args.name, tenant)
1097
1098 if not args.force:
1099 r = raw_input("Clean SDN port mapping for datacenter %s (y/N)? " %(datacenter))
1100 if not (len(r)>0 and r[0].lower()=="y"):
1101 return 0
1102
1103 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1104 mano_response = requests.delete(URLrequest)
1105 logger.debug("openmano response: %s", mano_response.text)
1106
1107 if mano_response.status_code != 200:
1108 if "No port mapping for datacenter" in mano_response.content:
1109 return "No port mapping for datacenter " + datacenter + " has been found"
1110 return mano_response.content
1111
1112 return yaml.safe_dump(mano_response.json())
1113
1114def sdn_controller_create(args):
1115 tenant = _get_tenant()
1116 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1117
1118 if not (args.ip and args.port and args.dpid and args.type):
1119 raise OpenmanoCLIError("The following arguments are required: ip, port, dpid, type")
1120
1121 controller_dict = {}
1122 controller_dict['name'] = args.name
1123 controller_dict['ip'] = args.ip
1124 controller_dict['port'] = int(args.port)
1125 controller_dict['dpid'] = args.dpid
1126 controller_dict['type'] = args.type
1127 if args.description != None:
1128 controller_dict['description'] = args.description
1129 if args.user != None:
1130 controller_dict['user'] = args.user
1131 if args.password != None:
1132 controller_dict['password'] = args.password
1133
1134 payload_req = json.dumps({"sdn_controller": controller_dict})
1135
1136 # print payload_req
1137
1138 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" % (mano_host, mano_port, tenant)
1139 logger.debug("openmano request: %s", payload_req)
1140 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1141 logger.debug("openmano response: %s", mano_response.text)
1142 result = _print_verbose(mano_response, args.verbose)
1143
1144 return result
1145
1146def sdn_controller_edit(args):
1147 tenant = _get_tenant()
1148 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1149 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1150
1151 if not (args.new_name or args.ip or args.port or args.dpid or args.type):
1152 raise OpenmanoCLIError("At least one parameter must be editd")
1153
1154 if not args.force:
1155 r = raw_input("Update SDN controller %s (y/N)? " %(args.name))
1156 if not (len(r)>0 and r[0].lower()=="y"):
1157 return 0
1158
1159 controller_dict = {}
1160 if args.new_name != None:
1161 controller_dict['name'] = args.new_name
1162 if args.ip != None:
1163 controller_dict['ip'] = args.ip
1164 if args.port != None:
Pablo Montes Morenob12711f2017-04-06 11:54:34 +02001165 controller_dict['port'] = int(args.port)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001166 if args.dpid != None:
1167 controller_dict['dpid'] = args.dpid
1168 if args.type != None:
1169 controller_dict['type'] = args.type
1170 if args.description != None:
1171 controller_dict['description'] = args.description
1172 if args.user != None:
1173 controller_dict['user'] = args.user
1174 if args.password != None:
1175 controller_dict['password'] = args.password
1176
1177 payload_req = json.dumps({"sdn_controller": controller_dict})
1178
1179 # print payload_req
1180
1181 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1182 logger.debug("openmano request: %s", payload_req)
1183 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1184 logger.debug("openmano response: %s", mano_response.text)
1185 result = _print_verbose(mano_response, args.verbose)
1186
1187 return result
1188
1189def sdn_controller_list(args):
1190 tenant = _get_tenant()
1191 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1192
1193 if args.name:
1194 toshow = _get_item_uuid("sdn_controllers", args.name, tenant)
1195 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" %(mano_host, mano_port, tenant, toshow)
1196 else:
1197 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" %(mano_host, mano_port, tenant)
1198 #print URLrequest
1199 mano_response = requests.get(URLrequest)
1200 logger.debug("openmano response: %s", mano_response.text )
1201 if args.verbose==None:
1202 args.verbose=0
1203 if args.name!=None:
1204 args.verbose += 1
1205
1206 result = json.dumps(mano_response.json(), indent=4)
1207 return result
1208
1209def sdn_controller_delete(args):
1210 tenant = _get_tenant()
1211 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1212
1213 if not args.force:
1214 r = raw_input("Delete SDN controller %s (y/N)? " % (args.name))
1215 if not (len(r) > 0 and r[0].lower() == "y"):
1216 return 0
1217
1218 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1219 mano_response = requests.delete(URLrequest)
1220 logger.debug("openmano response: %s", mano_response.text)
1221 result = _print_verbose(mano_response, args.verbose)
1222
1223 return result
1224
tierno7edb6752016-03-21 17:37:52 +01001225def vim_action(args):
1226 #print "datacenter-net-action",args
1227 tenant = _get_tenant()
1228 datacenter = _get_datacenter(args.datacenter, tenant)
1229 if args.verbose==None:
1230 args.verbose=0
1231 if args.action=="list":
1232 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1233 if args.name!=None:
1234 args.verbose += 1
1235 URLrequest += "/" + args.name
1236 mano_response = requests.get(URLrequest)
1237 logger.debug("openmano response: %s", mano_response.text )
1238 return _print_verbose(mano_response, args.verbose)
1239 elif args.action=="delete":
1240 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1241 mano_response = requests.delete(URLrequest)
1242 logger.debug("openmano response: %s", mano_response.text )
1243 result = 0 if mano_response.status_code==200 else mano_response.status_code
1244 content = mano_response.json()
1245 #print json.dumps(content, indent=4)
1246 if mano_response.status_code == 200:
1247 print content['result']
1248 else:
1249 print content['error']['description']
1250 return result
1251 elif args.action=="create":
1252 headers_req = {'content-type': 'application/yaml'}
1253 if args.file:
1254 create_dict = _load_file_or_yaml(args.file)
1255 if args.item not in create_dict:
1256 create_dict = {args.item: create_dict}
1257 else:
1258 create_dict = {args.item:{}}
1259 if args.name:
1260 create_dict[args.item]['name'] = args.name
1261 #if args.description:
1262 # create_dict[args.item]['description'] = args.description
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001263 if args.item=="network":
tierno7edb6752016-03-21 17:37:52 +01001264 if args.bind_net:
1265 create_dict[args.item]['bind_net'] = args.bind_net
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001266 if args.type:
1267 create_dict[args.item]['type'] = args.type
tierno7edb6752016-03-21 17:37:52 +01001268 if args.shared:
1269 create_dict[args.item]['shared'] = args.shared
1270 if "name" not in create_dict[args.item]:
1271 print "You must provide a name in the descriptor file or with the --name option"
1272 return
1273 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1274 logger.debug("openmano request: %s", payload_req)
tierno72a08d72017-05-25 13:12:30 +02001275 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
tierno7edb6752016-03-21 17:37:52 +01001276 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1277 logger.debug("openmano response: %s", mano_response.text )
1278 if args.verbose==None:
1279 args.verbose=0
1280 return _print_verbose(mano_response, args.verbose)
1281
1282
1283def datacenter_net_action(args):
1284 if args.action == "net-update":
tierno5acf7202016-08-29 14:28:13 +02001285 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
tierno7edb6752016-03-21 17:37:52 +01001286 print
1287 args.action = "netmap-delete"
1288 args.netmap = None
1289 args.all = True
1290 r = datacenter_netmap_action(args)
1291 if r == 0:
1292 args.force = True
tierno5acf7202016-08-29 14:28:13 +02001293 args.action = "netmap-import"
tierno7edb6752016-03-21 17:37:52 +01001294 r = datacenter_netmap_action(args)
1295 return r
1296
1297 if args.action == "net-edit":
1298 args.netmap = args.net
1299 args.name = None
1300 elif args.action == "net-list":
1301 args.netmap = None
1302 elif args.action == "net-delete":
1303 args.netmap = args.net
1304 args.all = False
1305
1306 args.action = "netmap" + args.action[3:]
1307 args.vim_name=None
1308 args.vim_id=None
1309 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1310 print
1311 return datacenter_netmap_action(args)
1312
1313def datacenter_netmap_action(args):
1314 tenant = _get_tenant()
1315 datacenter = _get_datacenter(args.datacenter, tenant)
1316 #print "datacenter_netmap_action",args
1317 payload_req = None
1318 if args.verbose==None:
1319 args.verbose=0
1320 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1321 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1322
1323 if args.action=="netmap-list":
1324 if args.netmap:
1325 URLrequest += "/" + args.netmap
1326 args.verbose += 1
1327 mano_response = requests.get(URLrequest)
1328
1329 elif args.action=="netmap-delete":
1330 if args.netmap and args.all:
1331 print "you can not use a netmap name and the option --all at the same time"
1332 return 1
1333 if args.netmap:
1334 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1335 URLrequest += "/" + args.netmap
1336 elif args.all:
1337 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1338 else:
tiernoae4a8d12016-07-08 12:30:39 +02001339 print "you must specify a netmap name or the option --all"
tierno7edb6752016-03-21 17:37:52 +01001340 return 1
1341 if not args.force:
1342 r = raw_input(force_text)
1343 if len(r)>0 and r[0].lower()=="y":
1344 pass
1345 else:
1346 return 0
1347 mano_response = requests.delete(URLrequest, headers=headers_req)
tierno5acf7202016-08-29 14:28:13 +02001348 elif args.action=="netmap-import":
tierno7edb6752016-03-21 17:37:52 +01001349 if not args.force:
1350 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1351 if len(r)>0 and r[0].lower()=="y":
1352 pass
1353 else:
1354 return 0
1355 URLrequest += "/upload"
1356 mano_response = requests.post(URLrequest, headers=headers_req)
1357 elif args.action=="netmap-edit" or args.action=="netmap-create":
1358 if args.file:
1359 payload = _load_file_or_yaml(args.file)
1360 else:
1361 payload = {}
1362 if "netmap" not in payload:
1363 payload = {"netmap": payload}
1364 if args.name:
1365 payload["netmap"]["name"] = args.name
1366 if args.vim_id:
1367 payload["netmap"]["vim_id"] = args.vim_id
1368 if args.action=="netmap-create" and args.vim_name:
1369 payload["netmap"]["vim_name"] = args.vim_name
1370 payload_req = json.dumps(payload)
1371 logger.debug("openmano request: %s", payload_req)
1372
1373 if args.action=="netmap-edit" and not args.force:
1374 if len(payload["netmap"]) == 0:
1375 print "You must supply some parameter to edit"
1376 return 1
1377 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1378 if len(r)>0 and r[0].lower()=="y":
1379 pass
1380 else:
1381 return 0
1382 URLrequest += "/" + args.netmap
1383 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1384 else: #netmap-create
1385 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1386 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1387 return 1
1388 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1389
1390 logger.debug("openmano response: %s", mano_response.text )
1391 return _print_verbose(mano_response, args.verbose)
1392
1393def element_edit(args):
1394 element = _get_item_uuid(args.element, args.name)
1395 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1396 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1397 payload=_load_file_or_yaml(args.file)
1398 if args.element[:-1] not in payload:
1399 payload = {args.element[:-1]: payload }
1400 payload_req = json.dumps(payload)
1401
1402 #print payload_req
1403 if not args.force or (args.name==None and args.filer==None):
1404 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1405 if len(r)>0 and r[0].lower()=="y":
1406 pass
1407 else:
1408 return 0
1409 logger.debug("openmano request: %s", payload_req)
1410 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1411 logger.debug("openmano response: %s", mano_response.text )
1412 if args.verbose==None:
1413 args.verbose=0
1414 if args.name!=None:
1415 args.verbose += 1
1416 return _print_verbose(mano_response, args.verbose)
1417
1418
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001419def datacenter_edit(args):
1420 tenant = _get_tenant()
1421 element = _get_item_uuid('datacenters', args.name, tenant)
1422 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1423 URLrequest = "http://%s:%s/openmano/datacenters/%s" % (mano_host, mano_port, element)
1424
1425 has_arguments = False
1426 if args.file != None:
1427 has_arguments = True
1428 payload = _load_file_or_yaml(args.file)
1429 else:
1430 payload = {}
1431
1432 if args.sdn_controller != None:
1433 has_arguments = True
1434 if not 'config' in payload:
1435 payload['config'] = {}
1436 if not 'sdn-controller' in payload['config']:
1437 payload['config']['sdn-controller'] = {}
1438 if args.sdn_controller == 'null':
1439 payload['config']['sdn-controller'] = None
1440 else:
1441 payload['config']['sdn-controller'] = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1442
1443 if not has_arguments:
1444 raise OpenmanoCLIError("At least one argument must be provided to modify the datacenter")
1445
1446 if 'datacenter' not in payload:
1447 payload = {'datacenter': payload}
1448 payload_req = json.dumps(payload)
1449
1450 # print payload_req
1451 if not args.force or (args.name == None and args.filer == None):
1452 r = raw_input(" Edit datacenter " + args.name + " (y/N)? ")
1453 if len(r) > 0 and r[0].lower() == "y":
1454 pass
1455 else:
1456 return 0
1457 logger.debug("openmano request: %s", payload_req)
1458 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1459 logger.debug("openmano response: %s", mano_response.text)
1460 if args.verbose == None:
1461 args.verbose = 0
1462 if args.name != None:
1463 args.verbose += 1
1464 return _print_verbose(mano_response, args.verbose)
1465
tierno6ddeded2017-05-16 15:40:26 +02001466def version(args):
1467 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1468 URLrequest = "http://%s:%s/openmano/version" % (mano_host, mano_port)
1469
1470 mano_response = requests.get(URLrequest, headers=headers_req)
1471 logger.debug("openmano response: %s", mano_response.text)
1472 print mano_response.text
1473
1474
tierno7edb6752016-03-21 17:37:52 +01001475global mano_host
1476global mano_port
1477global mano_tenant
1478
1479if __name__=="__main__":
1480
1481 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1482 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1483 mano_port = os.getenv('OPENMANO_PORT',"9090")
1484 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1485
1486 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
tierno6ddeded2017-05-16 15:40:26 +02001487 main_parser.add_argument('--version', action='version', help="get version of this client",
1488 version='%(prog)s client version ' + __version__ +
1489 " (Note: use '%(prog)s version' to get server version)")
1490
tierno7edb6752016-03-21 17:37:52 +01001491 subparsers = main_parser.add_subparsers(help='commands')
1492
tierno7edb6752016-03-21 17:37:52 +01001493 parent_parser = argparse.ArgumentParser(add_help=False)
1494 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1495 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1496
garciadeblas0e9fd832016-07-08 15:20:18 +02001497 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1498 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1499 config_parser.set_defaults(func=config)
1500
tierno6ddeded2017-05-16 15:40:26 +02001501 version_parser = subparsers.add_parser('version', parents=[parent_parser], help="get server version")
1502 version_parser.set_defaults(func=version)
1503
tierno7edb6752016-03-21 17:37:52 +01001504 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1505 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1506 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1507 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1508 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
garciadeblas14480452017-01-10 13:08:07 +01001509 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1510 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
tierno7edb6752016-03-21 17:37:52 +01001511 vnf_create_parser.set_defaults(func=vnf_create)
1512
1513 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1514 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1515 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1516 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1517 vnf_list_parser.set_defaults(func=vnf_list)
1518
1519 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1520 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1521 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1522 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1523 vnf_delete_parser.set_defaults(func=vnf_delete)
1524
1525 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1526 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1527 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1528 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1529 scenario_create_parser.set_defaults(func=scenario_create)
1530
1531 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1532 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1533 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1534 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1535 scenario_list_parser.set_defaults(func=scenario_list)
1536
1537 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1538 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1539 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1540 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1541 scenario_delete_parser.set_defaults(func=scenario_delete)
1542
1543 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1544 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1545 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1546 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1547 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1548 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1549 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1550
1551 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1552 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1553 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1554 scenario_deploy_parser.set_defaults(func=scenario_verify)
1555
1556 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1557 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1558 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1559 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1560 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1561 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1562 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")
1563 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 +02001564 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")
1565 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 +01001566 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1567 instance_scenario_create_parser.set_defaults(func=instance_create)
1568
1569 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1570 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1571 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1572 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1573
1574 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)")
1575 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1576 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1577 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1578 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1579
1580 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1581 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1582 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1583 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console"],\
1584 help="action to send")
1585 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1586 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1587 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1588 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1589
1590 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1591 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1592 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1593
1594 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1595 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1596 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1597 tenant_create_parser.set_defaults(func=tenant_create)
1598
1599 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1600 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1601 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1602 tenant_delete_parser.set_defaults(func=tenant_delete)
1603
1604 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1605 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1606 tenant_list_parser.set_defaults(func=tenant_list)
1607
tierno161c24b2017-05-16 15:45:56 +02001608 element_edit_parser = subparsers.add_parser('tenant-edit', parents=[parent_parser], help="edits one tenant")
1609 element_edit_parser.add_argument("name", help="name or uuid of the tenant")
1610 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1611 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1612 element_edit_parser.set_defaults(func=element_edit, element='tenants')
tierno7edb6752016-03-21 17:37:52 +01001613
1614 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1615 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1616 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1617 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1618 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1619 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1620 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001621 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 +01001622 datacenter_create_parser.set_defaults(func=datacenter_create)
1623
1624 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1625 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1626 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1627 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1628
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001629 datacenter_edit_parser = subparsers.add_parser('datacenter-edit', parents=[parent_parser], help="Edit datacenter")
1630 datacenter_edit_parser.add_argument("name", help="name or uuid of the datacenter")
1631 datacenter_edit_parser.add_argument("--file", help="json/yaml text or file with the changes").completer = FilesCompleter
1632 datacenter_edit_parser.add_argument("--sdn-controller", action="store",
1633 help="Name or uuid of the SDN controller to be used. Specify 'null' to clear entry", dest='sdn_controller')
1634 datacenter_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1635 datacenter_edit_parser.set_defaults(func=datacenter_edit)
1636
tierno7edb6752016-03-21 17:37:52 +01001637 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1638 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1639 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1640 datacenter_list_parser.set_defaults(func=datacenter_list)
1641
1642 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1643 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1644 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1645 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1646 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1647 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
tierno8008c3a2016-10-13 15:34:28 +00001648 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
tierno7edb6752016-03-21 17:37:52 +01001649 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1650
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001651 datacenter_edit_vim_tenant_parser = subparsers.add_parser('datacenter-edit-vim-tenant', parents=[parent_parser],
1652 help="Edit the association of a datacenter to the operating tenant")
1653 datacenter_edit_vim_tenant_parser.add_argument("name", help="name or uuid of the datacenter")
1654 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-id', action='store',
1655 help="specify a datacenter tenant to use. A new one is created by default")
1656 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1657 datacenter_edit_vim_tenant_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1658 datacenter_edit_vim_tenant_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1659 datacenter_edit_vim_tenant_parser.add_argument("--config", action="store",
1660 help="aditional configuration in json/yaml format")
1661 datacenter_edit_vim_tenant_parser.set_defaults(func=datacenter_edit_vim_tenant)
1662
tierno7edb6752016-03-21 17:37:52 +01001663 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1664 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1665 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1666 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1667
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001668 #=======================datacenter_sdn_port_mapping_xxx section=======================
1669 #datacenter_sdn_port_mapping_set
1670 datacenter_sdn_port_mapping_set_parser = subparsers.add_parser('datacenter-sdn-port-mapping-set',
1671 parents=[parent_parser],
1672 help="Load a file with the mapping of physical ports "
1673 "and the ports of the dataplaneswitch controlled "
1674 "by a datacenter")
1675 datacenter_sdn_port_mapping_set_parser.add_argument("name", action="store", help="specifies the datacenter")
1676 datacenter_sdn_port_mapping_set_parser.add_argument("file",
1677 help="json/yaml text or file with the port mapping").completer = FilesCompleter
1678 datacenter_sdn_port_mapping_set_parser.add_argument("-f", "--force", action="store_true",
1679 help="forces overwriting without asking")
1680 datacenter_sdn_port_mapping_set_parser.set_defaults(func=datacenter_sdn_port_mapping_set)
1681
1682 #datacenter_sdn_port_mapping_list
1683 datacenter_sdn_port_mapping_list_parser = subparsers.add_parser('datacenter-sdn-port-mapping-list',
1684 parents=[parent_parser],
1685 help="Show the SDN port mapping in a datacenter")
1686 datacenter_sdn_port_mapping_list_parser.add_argument("name", action="store", help="specifies the datacenter")
1687 datacenter_sdn_port_mapping_list_parser.set_defaults(func=datacenter_sdn_port_mapping_list)
1688
1689 # datacenter_sdn_port_mapping_clear
1690 datacenter_sdn_port_mapping_clear_parser = subparsers.add_parser('datacenter-sdn-port-mapping-clear',
1691 parents=[parent_parser],
1692 help="Clean the the SDN port mapping in a datacenter")
1693 datacenter_sdn_port_mapping_clear_parser.add_argument("name", action="store",
1694 help="specifies the datacenter")
1695 datacenter_sdn_port_mapping_clear_parser.add_argument("-f", "--force", action="store_true",
1696 help="forces clearing without asking")
1697 datacenter_sdn_port_mapping_clear_parser.set_defaults(func=datacenter_sdn_port_mapping_clear)
1698 # =======================
1699
1700 # =======================sdn_controller_xxx section=======================
1701 # sdn_controller_create
1702 sdn_controller_create_parser = subparsers.add_parser('sdn-controller-create', parents=[parent_parser],
1703 help="Creates an SDN controller entity within RO")
1704 sdn_controller_create_parser.add_argument("name", help="name of the SDN controller")
1705 sdn_controller_create_parser.add_argument("--description", action="store", help="description of the SDN controller")
1706 sdn_controller_create_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1707 sdn_controller_create_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1708 sdn_controller_create_parser.add_argument("--dpid", action="store",
1709 help="DPID of the dataplane switch controlled by this SDN controller")
1710 sdn_controller_create_parser.add_argument("--type", action="store",
1711 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1712 sdn_controller_create_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1713 sdn_controller_create_parser.add_argument("--passwd", action="store", dest='password',
1714 help="password credentials for the SDN controller")
1715 sdn_controller_create_parser.set_defaults(func=sdn_controller_create)
1716
1717 # sdn_controller_edit
1718 sdn_controller_edit_parser = subparsers.add_parser('sdn-controller-edit', parents=[parent_parser],
1719 help="Update one or more options of a SDN controller")
1720 sdn_controller_edit_parser.add_argument("name", help="name or uuid of the SDN controller", )
1721 sdn_controller_edit_parser.add_argument("--name", action="store", help="Update the name of the SDN controller",
1722 dest='new_name')
1723 sdn_controller_edit_parser.add_argument("--description", action="store", help="description of the SDN controller")
1724 sdn_controller_edit_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1725 sdn_controller_edit_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1726 sdn_controller_edit_parser.add_argument("--dpid", action="store",
1727 help="DPID of the dataplane switch controlled by this SDN controller")
1728 sdn_controller_edit_parser.add_argument("--type", action="store",
1729 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1730 sdn_controller_edit_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1731 sdn_controller_edit_parser.add_argument("--password", action="store",
1732 help="password credentials for the SDN controller", dest='password')
1733 sdn_controller_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1734 #TODO: include option --file
1735 sdn_controller_edit_parser.set_defaults(func=sdn_controller_edit)
1736
1737 #sdn_controller_list
1738 sdn_controller_list_parser = subparsers.add_parser('sdn-controller-list',
1739 parents=[parent_parser],
1740 help="List the SDN controllers")
1741 sdn_controller_list_parser.add_argument("name", nargs='?', help="name or uuid of the SDN controller")
1742 sdn_controller_list_parser.set_defaults(func=sdn_controller_list)
1743
1744 # sdn_controller_delete
1745 sdn_controller_delete_parser = subparsers.add_parser('sdn-controller-delete',
1746 parents=[parent_parser],
1747 help="Delete the the SDN controller")
1748 sdn_controller_delete_parser.add_argument("name", help="name or uuid of the SDN controller")
1749 sdn_controller_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1750 sdn_controller_delete_parser.set_defaults(func=sdn_controller_delete)
1751 # =======================
tierno7edb6752016-03-21 17:37:52 +01001752
1753 action_dict={'net-update': 'retrieves external networks from datacenter',
1754 'net-edit': 'edits an external network',
1755 'net-delete': 'deletes an external network',
1756 'net-list': 'lists external networks from a datacenter'
1757 }
1758 for item in action_dict:
1759 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1760 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1761 if item=='net-edit' or item=='net-delete':
1762 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1763 if item=='net-edit':
1764 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1765 if item!='net-list':
1766 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1767 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1768
1769
tierno5acf7202016-08-29 14:28:13 +02001770 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
tierno7edb6752016-03-21 17:37:52 +01001771 'netmap-create': 'create a new network senario netmap',
1772 'netmap-edit': 'edit name of a network senario netmap',
1773 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1774 'netmap-list': 'list/show network scenario netmaps'
1775 }
1776 for item in action_dict:
1777 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1778 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1779 #if item=='net-add':
1780 # datacenter_action_parser.add_argument("net", help="name of the network")
1781 if item=='netmap-delete':
1782 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1783 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1784 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1785 if item=='netmap-edit':
1786 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1787 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1788 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1789 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1790 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1791 if item=='netmap-list':
1792 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1793 if item=='netmap-create':
1794 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1795 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1796 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1797 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
tierno5acf7202016-08-29 14:28:13 +02001798 if item=='netmap-import':
tierno7edb6752016-03-21 17:37:52 +01001799 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1800 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
1801
tierno4540ea52017-01-18 17:44:32 +01001802 for item in ("network", "tenant", "image"):
tierno7edb6752016-03-21 17:37:52 +01001803 if item=="network":
1804 commnad_name = 'vim-net'
1805 else:
1806 commnad_name = 'vim-'+item
1807 vim_item_list_parser = subparsers.add_parser(commnad_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
1808 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
1809 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1810 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
1811
1812 vim_item_del_parser = subparsers.add_parser(commnad_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
1813 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
1814 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1815 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
1816
tierno4540ea52017-01-18 17:44:32 +01001817 if item == "network" or item == "tenant":
1818 vim_item_create_parser = subparsers.add_parser(commnad_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
1819 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
1820 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
1821 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1822 if item=="network":
1823 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
1824 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
1825 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>'")
1826 else:
1827 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
1828 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
tierno7edb6752016-03-21 17:37:52 +01001829
1830 argcomplete.autocomplete(main_parser)
1831
1832 try:
1833 args = main_parser.parse_args()
1834 #logging info
1835 level = logging.CRITICAL
1836 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
1837 if "debug" in args and args.debug:
1838 level = logging.DEBUG
1839 logging.basicConfig(format=streamformat, level= level)
1840 logger = logging.getLogger('mano')
1841 logger.setLevel(level)
1842 result = args.func(args)
1843 if result == None:
1844 result = 0
1845 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
1846 except (requests.exceptions.ConnectionError):
1847 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
1848 result = -2
1849 except (KeyboardInterrupt):
1850 print 'Exiting openmano'
1851 result = -3
1852 except (SystemExit, ArgumentParserError):
1853 result = -4
1854 except OpenmanoCLIError as e:
1855 print str(e)
1856 result = -5
1857
1858 #print result
1859 exit(result)
1860