blob: 357b91addf82405ed60809ea0eb741b143993ea7 [file] [log] [blame]
tierno7edb6752016-03-21 17:37:52 +01001#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# PYTHON_ARGCOMPLETE_OK
4
5##
tierno92021022018-09-12 16:29:23 +02006# Copyright 2015 Telefonica Investigacion y Desarrollo, S.A.U.
tierno7edb6752016-03-21 17:37:52 +01007# 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
tierno20df3bb2017-07-07 14:31:00 +020026"""
tierno7edb6752016-03-21 17:37:52 +010027openmano client used to interact with openmano-server (openmanod)
tierno20df3bb2017-07-07 14:31:00 +020028"""
tierno72a08d72017-05-25 13:12:30 +020029__author__ = "Alfonso Tierno, Gerardo Garcia, Pablo Montes"
30__date__ = "$09-oct-2014 09:09:48$"
tierno7fe82642018-11-26 14:14:51 +000031__version__ = "0.4.24-r534"
32version_date = "Nov 2018"
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 = ""
tiernoa15c4b92017-10-05 12:41:44 +0200136 myoutput = "{:38} {:20}".format(uuid, name)
tierno250954a2017-01-31 14:25:57 +0100137 if content.get("status"):
tiernoa15c4b92017-10-05 12:41:44 +0200138 myoutput += " {:20}".format(content['status'])
tierno7edb6752016-03-21 17:37:52 +0100139 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'):
tiernoa15c4b92017-10-05 12:41:44 +0200143 myoutput += " {:20}".format(content['created_at'])
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +0200144 if content.get('sdn_attached_ports'):
145 #myoutput += " " + str(content['sdn_attached_ports']).ljust(20)
146 myoutput += "\nsdn_attached_ports:\n" + yaml.safe_dump(content['sdn_attached_ports'], indent=4, default_flow_style=False)
tierno7edb6752016-03-21 17:37:52 +0100147 if verbose_level >=2:
148 new_line='\n'
tierno250954a2017-01-31 14:25:57 +0100149 if content.get('type'):
tiernoa15c4b92017-10-05 12:41:44 +0200150 myoutput += new_line + " Type: {:29}".format(content['type'])
tierno7edb6752016-03-21 17:37:52 +0100151 new_line=''
tierno250954a2017-01-31 14:25:57 +0100152 if content.get('description'):
tiernoa15c4b92017-10-05 12:41:44 +0200153 myoutput += new_line + " Description: {:20}".format(content['description'])
tierno7edb6752016-03-21 17:37:52 +0100154 print myoutput
155 else:
156 print content['error']['description']
157 return result
158
159def parser_json_yaml(file_name):
160 try:
161 f = file(file_name, "r")
162 text = f.read()
163 f.close()
164 except Exception as e:
165 return (False, str(e))
166
167 #Read and parse file
168 if file_name[-5:]=='.yaml' or file_name[-4:]=='.yml' or (file_name[-5:]!='.json' and '\t' not in text):
169 try:
170 config = yaml.load(text)
171 except yaml.YAMLError as exc:
172 error_pos = ""
173 if hasattr(exc, 'problem_mark'):
174 mark = exc.problem_mark
175 error_pos = " at line:%s column:%s" % (mark.line+1, mark.column+1)
176 return (False, "Error loading file '"+file_name+"' yaml format error" + error_pos)
177 else: #json
178 try:
179 config = json.loads(text)
180 except Exception as e:
181 return (False, "Error loading file '"+file_name+"' json format error " + str(e) )
182
183 return True, config
184
185def _load_file_or_yaml(content):
186 '''
187 'content' can be or a yaml/json file or a text containing a yaml/json text format
188 This function autodetect, trying to load and parse the file,
189 if fails trying to parse the 'content' text
190 Returns the dictionary once parsed, or print an error and finish the program
191 '''
192 #Check config file exists
193 if os.path.isfile(content):
194 r,payload = parser_json_yaml(content)
195 if not r:
196 print payload
197 exit(-1)
198 elif "{" in content or ":" in content:
199 try:
200 payload = yaml.load(content)
201 except yaml.YAMLError as exc:
202 error_pos = ""
203 if hasattr(exc, 'problem_mark'):
204 mark = exc.problem_mark
205 error_pos = " at position: (%s:%s)" % (mark.line+1, mark.column+1)
206 print "Error loading yaml/json text"+error_pos
207 exit (-1)
208 else:
209 print "'%s' is neither a valid file nor a yaml/json content" % content
210 exit(-1)
211 return payload
212
213def _get_item_uuid(item, item_name_id, tenant=None):
214 if tenant:
215 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, tenant, item)
216 else:
217 URLrequest = "http://%s:%s/openmano/%s" %(mano_host, mano_port, item)
218 mano_response = requests.get(URLrequest)
219 logger.debug("openmano response: %s", mano_response.text )
220 content = mano_response.json()
221 #print content
222 found = 0
223 for i in content[item]:
224 if i["uuid"] == item_name_id:
225 return item_name_id
226 if i["name"] == item_name_id:
227 uuid = i["uuid"]
228 found += 1
tiernof1ba57e2017-09-07 12:23:19 +0200229 if item_name_id.startswith("osm_id=") and i.get("osm_id") == item_name_id[7:]:
230 uuid = i["uuid"]
231 found += 1
tierno7edb6752016-03-21 17:37:52 +0100232 if found == 0:
233 raise OpenmanoCLIError("No %s found with name/uuid '%s'" %(item[:-1], item_name_id))
234 elif found > 1:
235 raise OpenmanoCLIError("%d %s found with name '%s'. uuid must be used" %(found, item, item_name_id))
236 return uuid
237#
238# def check_valid_uuid(uuid):
239# id_schema = {"type" : "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
240# try:
241# js_v(uuid, id_schema)
242# return True
243# except js_e.ValidationError:
244# return False
245
246def _get_tenant(tenant_name_id = None):
247 if not tenant_name_id:
248 tenant_name_id = mano_tenant
249 if not mano_tenant:
250 raise OpenmanoCLIError("'OPENMANO_TENANT' environment variable is not set")
251 return _get_item_uuid("tenants", tenant_name_id)
252
253def _get_datacenter(datacenter_name_id = None, tenant = "any"):
254 if not datacenter_name_id:
255 datacenter_name_id = mano_datacenter
256 if not datacenter_name_id:
257 raise OpenmanoCLIError("neither 'OPENMANO_DATACENTER' environment variable is set nor --datacenter option is used")
258 return _get_item_uuid("datacenters", datacenter_name_id, tenant)
259
260def vnf_create(args):
261 #print "vnf-create",args
262 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
263 tenant = _get_tenant()
264 myvnf = _load_file_or_yaml(args.file)
tiernof1ba57e2017-09-07 12:23:19 +0200265 api_version = ""
266 if "vnfd:vnfd-catalog" in myvnf or "vnfd-catalog" in myvnf:
267 api_version = "/v3"
268 token = "vnfd"
269 vnfd_catalog = myvnf.get("vnfd:vnfd-catalog")
270 if not vnfd_catalog:
271 vnfd_catalog = myvnf.get("vnfd-catalog")
272 vnfds = vnfd_catalog.get("vnfd:vnfd")
273 if not vnfds:
274 vnfds = vnfd_catalog.get("vnfd")
275 vnfd = vnfds[0]
gcalvino319b8a52018-11-05 15:33:23 +0100276 vdu_list = vnfd.get("vdu")
tiernof1ba57e2017-09-07 12:23:19 +0200277
278 else: # old API
279 api_version = ""
280 token = "vnfs"
281 vnfd = myvnf['vnf']
gcalvino319b8a52018-11-05 15:33:23 +0100282 vdu_list = vnfd.get("VNFC")
tierno7edb6752016-03-21 17:37:52 +0100283
garciadeblas14480452017-01-10 13:08:07 +0100284 if args.name or args.description or args.image_path or args.image_name or args.image_checksum:
tiernof1ba57e2017-09-07 12:23:19 +0200285 # TODO, change this for API v3
286 # print args.name
tierno7edb6752016-03-21 17:37:52 +0100287 try:
288 if args.name:
tiernof1ba57e2017-09-07 12:23:19 +0200289 vnfd['name'] = args.name
tierno7edb6752016-03-21 17:37:52 +0100290 if args.description:
tiernof1ba57e2017-09-07 12:23:19 +0200291 vnfd['description'] = args.description
gcalvino319b8a52018-11-05 15:33:23 +0100292 if vdu_list:
293 if args.image_path:
294 index = 0
295 for image_path_ in args.image_path.split(","):
296 # print "image-path", image_path_
297 if api_version == "/v3":
298 if vdu_list[index].get("image"):
299 vdu_list[index]['image'] = image_path_
300 if "image-checksum" in vdu_list[index]:
301 del vdu_list[index]["image-checksum"]
302 else: # image name in volumes
303 vdu_list[index]["volumes"][0]["image"] = image_path_
304 if "image-checksum" in vdu_list[index]["volumes"][0]:
305 del vdu_list[index]["volumes"][0]["image-checksum"]
306 else:
307 vdu_list[index]['VNFC image'] = image_path_
308 if "image name" in vdu_list[index]:
309 del vdu_list[index]["image name"]
310 if "image checksum" in vdu_list[index]:
311 del vdu_list[index]["image checksum"]
312 index += 1
313 if args.image_name: # image name precedes if both are supplied
314 index = 0
315 for image_name_ in args.image_name.split(","):
316 if api_version == "/v3":
317 if vdu_list[index].get("image"):
318 vdu_list[index]['image'] = image_name_
319 if "image-checksum" in vdu_list[index]:
320 del vdu_list[index]["image-checksum"]
321 if vdu_list[index].get("alternative-images"):
322 for a_image in vdu_list[index]["alternative-images"]:
323 a_image['image'] = image_name_
324 if "image-checksum" in a_image:
325 del a_image["image-checksum"]
326 else: # image name in volumes
327 vdu_list[index]["volumes"][0]["image"] = image_name_
328 if "image-checksum" in vdu_list[index]["volumes"][0]:
329 del vdu_list[index]["volumes"][0]["image-checksum"]
330 else:
331 vdu_list[index]['image name'] = image_name_
332 if "VNFC image" in vdu_list[index]:
333 del vdu_list[index]["VNFC image"]
334 index += 1
335 if args.image_checksum:
336 index = 0
337 for image_checksum_ in args.image_checksum.split(","):
338 if api_version == "/v3":
339 if vdu_list[index].get("image"):
340 vdu_list[index]['image-checksum'] = image_checksum_
341 if vdu_list[index].get("alternative-images"):
342 for a_image in vdu_list[index]["alternative-images"]:
343 a_image['image-checksum'] = image_checksum_
344 else: # image name in volumes
345 vdu_list[index]["volumes"][0]["image-checksum"] = image_checksum_
346 else:
347 vdu_list[index]['image checksum'] = image_checksum_
348 index += 1
tierno7edb6752016-03-21 17:37:52 +0100349 except (KeyError, TypeError), e:
tiernof1ba57e2017-09-07 12:23:19 +0200350 if str(e) == 'vnf': error_pos= "missing field 'vnf'"
351 elif str(e) == 'name': error_pos= "missing field 'vnf':'name'"
352 elif str(e) == 'description': error_pos= "missing field 'vnf':'description'"
353 elif str(e) == 'VNFC': error_pos= "missing field 'vnf':'VNFC'"
354 elif str(e) == str(index): error_pos= "field 'vnf':'VNFC' must be an array"
355 elif str(e) == 'VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
356 elif str(e) == 'image name': error_pos= "missing field 'vnf':'VNFC'['image name']"
357 elif str(e) == 'image checksum': error_pos= "missing field 'vnf':'VNFC'['image checksum']"
tierno7edb6752016-03-21 17:37:52 +0100358 else: error_pos="wrong format"
359 print "Wrong VNF descriptor: " + error_pos
360 return -1
361 payload_req = json.dumps(myvnf)
362
363 #print payload_req
364
tiernof1ba57e2017-09-07 12:23:19 +0200365 URLrequest = "http://{}:{}/openmano{}/{}/{token}".format(mano_host, mano_port, api_version, tenant, token=token)
tierno7edb6752016-03-21 17:37:52 +0100366 logger.debug("openmano request: %s", payload_req)
367 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
368 logger.debug("openmano response: %s", mano_response.text )
369
370 return _print_verbose(mano_response, args.verbose)
371
372def vnf_list(args):
373 #print "vnf-list",args
374 if args.all:
375 tenant = "any"
376 else:
377 tenant = _get_tenant()
378 if args.name:
379 toshow = _get_item_uuid("vnfs", args.name, tenant)
380 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
381 else:
382 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
383 mano_response = requests.get(URLrequest)
384 logger.debug("openmano response: %s", mano_response.text )
385 content = mano_response.json()
tiernof1ba57e2017-09-07 12:23:19 +0200386 # print json.dumps(content, indent=4)
tierno7edb6752016-03-21 17:37:52 +0100387 if args.verbose==None:
388 args.verbose=0
389 result = 0 if mano_response.status_code==200 else mano_response.status_code
390 if mano_response.status_code == 200:
391 if not args.name:
392 if args.verbose >= 3:
393 print yaml.safe_dump(content, indent=4, default_flow_style=False)
394 return result
395 if len(content['vnfs']) == 0:
396 print "No VNFs were found."
tiernof1ba57e2017-09-07 12:23:19 +0200397 return 404 # HTTP_Not_Found
tierno7edb6752016-03-21 17:37:52 +0100398 for vnf in content['vnfs']:
tiernof1ba57e2017-09-07 12:23:19 +0200399 myoutput = "{:38} {:20}".format(vnf['uuid'], vnf['name'])
400 if vnf.get('osm_id') or args.verbose >= 1:
401 myoutput += " osm_id={:20}".format(vnf.get('osm_id'))
402 if args.verbose >= 1:
403 myoutput += " {}".format(vnf['created_at'])
404 print (myoutput)
405 if args.verbose >= 2:
406 print (" Description: {}".format(vnf['description']))
407 # print (" VNF descriptor file: {}".format(vnf['path']))
tierno7edb6752016-03-21 17:37:52 +0100408 else:
409 if args.verbose:
410 print yaml.safe_dump(content, indent=4, default_flow_style=False)
411 return result
412 vnf = content['vnf']
tiernof1ba57e2017-09-07 12:23:19 +0200413 print ("{:38} {:20} osm_id={:20} {:20}".format(vnf['uuid'], vnf['name'], vnf.get('osm_id'),
414 vnf['created_at']))
415 print (" Description: {}".format(vnf['description']))
416 # print " VNF descriptor file: %s" %vnf['path']
417 print (" VMs:")
tierno7edb6752016-03-21 17:37:52 +0100418 for vm in vnf['VNFC']:
tiernof1ba57e2017-09-07 12:23:19 +0200419 print (" {:20} osm_id={:20} {}".format(vm['name'], vm.get('osm_id'), vm['description']))
420 if len(vnf['nets']) > 0:
421 print (" Internal nets:")
tierno7edb6752016-03-21 17:37:52 +0100422 for net in vnf['nets']:
tiernof1ba57e2017-09-07 12:23:19 +0200423 print (" {:20} {}".format(net['name'], net['description']))
424 if len(vnf['external-connections']) > 0:
425 print (" External interfaces:")
tierno7edb6752016-03-21 17:37:52 +0100426 for interface in vnf['external-connections']:
tiernof1ba57e2017-09-07 12:23:19 +0200427 print (" {:20} {:20} {:20} {:14}".format(
428 interface['external_name'], interface['vm_name'],
429 interface['internal_name'],
430 interface.get('vpci') if interface.get('vpci') else ""))
tierno7edb6752016-03-21 17:37:52 +0100431 else:
432 print content['error']['description']
433 if args.verbose:
434 print yaml.safe_dump(content, indent=4, default_flow_style=False)
435 return result
436
437def vnf_delete(args):
438 #print "vnf-delete",args
439 if args.all:
440 tenant = "any"
441 else:
442 tenant = _get_tenant()
443 todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
444 if not args.force:
445 r = raw_input("Delete VNF %s (y/N)? " %(todelete))
446 if not (len(r)>0 and r[0].lower()=="y"):
447 return 0
448 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
449 mano_response = requests.delete(URLrequest)
450 logger.debug("openmano response: %s", mano_response.text )
451 result = 0 if mano_response.status_code==200 else mano_response.status_code
452 content = mano_response.json()
453 #print json.dumps(content, indent=4)
454 if mano_response.status_code == 200:
455 print content['result']
456 else:
457 print content['error']['description']
458 return result
459
460def scenario_create(args):
tiernof1ba57e2017-09-07 12:23:19 +0200461 # print "scenario-create",args
tierno7edb6752016-03-21 17:37:52 +0100462 tenant = _get_tenant()
463 headers_req = {'content-type': 'application/yaml'}
464 myscenario = _load_file_or_yaml(args.file)
tiernof1ba57e2017-09-07 12:23:19 +0200465 if "nsd:nsd-catalog" in myscenario or "nsd-catalog" in myscenario:
466 api_version = "/v3"
467 token = "nsd"
468 nsd_catalog = myscenario.get("nsd:nsd-catalog")
469 if not nsd_catalog:
470 nsd_catalog = myscenario.get("nsd-catalog")
471 nsds = nsd_catalog.get("nsd:nsd")
472 if not nsds:
473 nsds = nsd_catalog.get("nsd")
474 nsd = nsds[0]
475 else: # API<v3
476 api_version = ""
477 token = "scenarios"
478 if "scenario" in myscenario:
479 nsd = myscenario["scenario"]
480 else:
481 nsd = myscenario
482 # TODO modify for API v3
tierno7edb6752016-03-21 17:37:52 +0100483 if args.name:
tiernof1ba57e2017-09-07 12:23:19 +0200484 nsd['name'] = args.name
tierno7edb6752016-03-21 17:37:52 +0100485 if args.description:
tiernof1ba57e2017-09-07 12:23:19 +0200486 nsd['description'] = args.description
487 payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False,
488 encoding='utf-8', allow_unicode=True)
tierno7edb6752016-03-21 17:37:52 +0100489
tiernof1ba57e2017-09-07 12:23:19 +0200490 # print payload_req
491 URLrequest = "http://{host}:{port}/openmano{api}/{tenant}/{token}".format(
492 host=mano_host, port=mano_port, api=api_version, tenant=tenant, token=token)
tierno7edb6752016-03-21 17:37:52 +0100493 logger.debug("openmano request: %s", payload_req)
494 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
495 logger.debug("openmano response: %s", mano_response.text )
496 return _print_verbose(mano_response, args.verbose)
497
498def scenario_list(args):
499 #print "scenario-list",args
500 if args.all:
501 tenant = "any"
502 else:
503 tenant = _get_tenant()
504 if args.name:
505 toshow = _get_item_uuid("scenarios", args.name, tenant)
506 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
507 else:
508 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
509 mano_response = requests.get(URLrequest)
510 logger.debug("openmano response: %s", mano_response.text )
511 content = mano_response.json()
512 #print json.dumps(content, indent=4)
513 if args.verbose==None:
514 args.verbose=0
515
516 result = 0 if mano_response.status_code==200 else mano_response.status_code
517 if mano_response.status_code == 200:
518 if not args.name:
519 if args.verbose >= 3:
520 print yaml.safe_dump(content, indent=4, default_flow_style=False)
521 return result
522 if len(content['scenarios']) == 0:
523 print "No scenarios were found."
524 return 404 #HTTP_Not_Found
525 for scenario in content['scenarios']:
tiernof1ba57e2017-09-07 12:23:19 +0200526 myoutput = "{:38} {:20}".format(scenario['uuid'], scenario['name'])
527 if scenario.get('osm_id') or args.verbose >= 1:
528 myoutput += " osm_id={:20}".format(scenario.get('osm_id'))
529 if args.verbose >= 1:
530 myoutput += " {}".format(scenario['created_at'])
531 print (myoutput)
tierno7edb6752016-03-21 17:37:52 +0100532 if args.verbose >=2:
tiernof1ba57e2017-09-07 12:23:19 +0200533 print (" Description: {}".format(scenario['description']))
tierno7edb6752016-03-21 17:37:52 +0100534 else:
535 if args.verbose:
536 print yaml.safe_dump(content, indent=4, default_flow_style=False)
537 return result
538 scenario = content['scenario']
tiernof1ba57e2017-09-07 12:23:19 +0200539 print ("{:38} {:20} osm_id={:20} {:20}".format(scenario['uuid'], scenario['name'], scenario.get('osm_id'),
540 scenario['created_at']))
541 print (" Description: {}".format(scenario['description']))
542 print (" VNFs:")
tierno7edb6752016-03-21 17:37:52 +0100543 for vnf in scenario['vnfs']:
tiernof1ba57e2017-09-07 12:23:19 +0200544 print (" {:38} {:20} vnf_index={} {}".format(vnf['vnf_id'], vnf['name'], vnf.get("member_vnf_index"),
545 vnf['description']))
546 if len(scenario['nets']) > 0:
547 print (" nets:")
tierno7edb6752016-03-21 17:37:52 +0100548 for net in scenario['nets']:
tiernof1ba57e2017-09-07 12:23:19 +0200549 description = net['description']
550 if not description: # if description does not exist, description is "-". Valid for external and internal nets.
551 description = '-'
552 vim_id = ""
553 if net.get('vim_id'):
554 vim_id = " vim_id=" + net["vim_id"]
555 external = ""
556 if net["external"]:
557 external = " external"
558 print (" {:20} {:38} {:30}{}{}".format(net['name'], net['uuid'], description, vim_id, external))
tierno7edb6752016-03-21 17:37:52 +0100559 else:
tiernof1ba57e2017-09-07 12:23:19 +0200560 print (content['error']['description'])
tierno7edb6752016-03-21 17:37:52 +0100561 if args.verbose:
562 print yaml.safe_dump(content, indent=4, default_flow_style=False)
563 return result
564
565def scenario_delete(args):
566 #print "scenario-delete",args
567 if args.all:
568 tenant = "any"
569 else:
570 tenant = _get_tenant()
571 todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
572 if not args.force:
573 r = raw_input("Delete scenario %s (y/N)? " %(args.name))
574 if not (len(r)>0 and r[0].lower()=="y"):
575 return 0
576 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
577 mano_response = requests.delete(URLrequest)
578 logger.debug("openmano response: %s", mano_response.text )
579 result = 0 if mano_response.status_code==200 else mano_response.status_code
580 content = mano_response.json()
581 #print json.dumps(content, indent=4)
582 if mano_response.status_code == 200:
583 print content['result']
584 else:
585 print content['error']['description']
586 return result
587
588def scenario_deploy(args):
589 print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
590 print
591 args.file = None
592 args.netmap_use = None
593 args.netmap_create = None
tiernobe41e222016-09-02 15:16:13 +0200594 args.keypair = None
595 args.keypair_auto = None
tierno7edb6752016-03-21 17:37:52 +0100596 return instance_create(args)
597
598# #print "scenario-deploy",args
599# headers_req = {'content-type': 'application/json'}
600# action = {}
601# actionCmd="start"
602# if args.nostart:
603# actionCmd="reserve"
604# action[actionCmd] = {}
605# action[actionCmd]["instance_name"] = args.name
606# if args.datacenter != None:
607# action[actionCmd]["datacenter"] = args.datacenter
608# elif mano_datacenter != None:
609# action[actionCmd]["datacenter"] = mano_datacenter
610#
611# if args.description:
612# action[actionCmd]["description"] = args.description
613# payload_req = json.dumps(action, indent=4)
614# #print payload_req
615#
616# URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
617# logger.debug("openmano request: %s", payload_req)
618# mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
619# logger.debug("openmano response: %s", mano_response.text )
620# if args.verbose==None:
621# args.verbose=0
622#
623# result = 0 if mano_response.status_code==200 else mano_response.status_code
624# content = mano_response.json()
625# #print json.dumps(content, indent=4)
626# if args.verbose >= 3:
627# print yaml.safe_dump(content, indent=4, default_flow_style=False)
628# return result
629#
630# if mano_response.status_code == 200:
631# myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
632# if args.verbose >=1:
633# myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
634# if args.verbose >=2:
635# myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
636# print myoutput
637# print ""
638# print "To check the status, run the following command:"
639# print "openmano instance-scenario-list <instance_id>"
640# else:
641# print content['error']['description']
642# return result
643
644def scenario_verify(args):
645 #print "scenario-verify",args
tierno72a08d72017-05-25 13:12:30 +0200646 tenant = _get_tenant()
tierno7edb6752016-03-21 17:37:52 +0100647 headers_req = {'content-type': 'application/json'}
648 action = {}
649 action["verify"] = {}
650 action["verify"]["instance_name"] = "scen-verify-return5"
651 payload_req = json.dumps(action, indent=4)
652 #print payload_req
653
tierno72a08d72017-05-25 13:12:30 +0200654 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, tenant, args.scenario)
tierno7edb6752016-03-21 17:37:52 +0100655 logger.debug("openmano request: %s", payload_req)
656 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
657 logger.debug("openmano response: %s", mano_response.text )
658
659 result = 0 if mano_response.status_code==200 else mano_response.status_code
660 content = mano_response.json()
661 #print json.dumps(content, indent=4)
662 if mano_response.status_code == 200:
663 print content['result']
664 else:
665 print content['error']['description']
666 return result
667
668def instance_create(args):
669 tenant = _get_tenant()
670 headers_req = {'content-type': 'application/yaml'}
671 myInstance={"instance": {}, "schema_version": "0.1"}
672 if args.file:
673 instance_dict = _load_file_or_yaml(args.file)
674 if "instance" not in instance_dict:
675 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
676 else:
677 myInstance = instance_dict
678 if args.name:
679 myInstance["instance"]['name'] = args.name
680 if args.description:
681 myInstance["instance"]['description'] = args.description
682 if args.nostart:
683 myInstance["instance"]['action'] = "reserve"
684 #datacenter
685 datacenter = myInstance["instance"].get("datacenter")
686 if args.datacenter != None:
687 datacenter = args.datacenter
688 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
689 #scenario
690 scenario = myInstance["instance"].get("scenario")
691 if args.scenario != None:
692 scenario = args.scenario
693 if not scenario:
garciadeblased746032017-01-05 11:58:41 +0100694 print "you must provide a scenario in the file descriptor or with --scenario"
tierno7edb6752016-03-21 17:37:52 +0100695 return -1
tierno7fe82642018-11-26 14:14:51 +0000696 if isinstance(scenario, str):
697 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
tierno7edb6752016-03-21 17:37:52 +0100698 if args.netmap_use:
699 if "networks" not in myInstance["instance"]:
700 myInstance["instance"]["networks"] = {}
701 for net in args.netmap_use:
702 net_comma_list = net.split(",")
703 for net_comma in net_comma_list:
704 net_tuple = net_comma.split("=")
705 if len(net_tuple) != 2:
706 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
707 return
708 net_scenario = net_tuple[0].strip()
709 net_datacenter = net_tuple[1].strip()
710 if net_scenario not in myInstance["instance"]["networks"]:
711 myInstance["instance"]["networks"][net_scenario] = {}
tiernobe41e222016-09-02 15:16:13 +0200712 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
713 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
714 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
tierno7edb6752016-03-21 17:37:52 +0100715 if args.netmap_create:
716 if "networks" not in myInstance["instance"]:
717 myInstance["instance"]["networks"] = {}
718 for net in args.netmap_create:
719 net_comma_list = net.split(",")
720 for net_comma in net_comma_list:
721 net_tuple = net_comma.split("=")
722 if len(net_tuple) == 1:
723 net_scenario = net_tuple[0].strip()
724 net_datacenter = None
725 elif len(net_tuple) == 2:
726 net_scenario = net_tuple[0].strip()
727 net_datacenter = net_tuple[1].strip()
728 else:
729 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
730 return
731 if net_scenario not in myInstance["instance"]["networks"]:
732 myInstance["instance"]["networks"][net_scenario] = {}
tiernobe41e222016-09-02 15:16:13 +0200733 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
734 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
735 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
tiernoa4e1a6e2016-08-31 14:19:40 +0200736 if args.keypair:
737 if "cloud-config" not in myInstance["instance"]:
738 myInstance["instance"]["cloud-config"] = {}
739 cloud_config = myInstance["instance"]["cloud-config"]
740 for key in args.keypair:
741 index = key.find(":")
742 if index<0:
743 if "key-pairs" not in cloud_config:
744 cloud_config["key-pairs"] = []
745 cloud_config["key-pairs"].append(key)
746 else:
747 user = key[:index]
748 key_ = key[index+1:]
749 key_list = key_.split(",")
750 if "users" not in cloud_config:
751 cloud_config["users"] = []
752 cloud_config["users"].append({"name": user, "key-pairs": key_list })
753 if args.keypair_auto:
754 try:
755 keys=[]
756 home = os.getenv("HOME")
757 user = os.getenv("USER")
758 files = os.listdir(home+'/.ssh')
759 for file in files:
760 if file[-4:] == ".pub":
761 with open(home+'/.ssh/'+file, 'r') as f:
762 keys.append(f.read())
763 if not keys:
764 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
765 return 1
766 except Exception as e:
767 print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
768 return 1
769
770 if "cloud-config" not in myInstance["instance"]:
771 myInstance["instance"]["cloud-config"] = {}
772 cloud_config = myInstance["instance"]["cloud-config"]
773 if "key-pairs" not in cloud_config:
774 cloud_config["key-pairs"] = []
775 if user:
776 if "users" not in cloud_config:
777 cloud_config["users"] = []
778 cloud_config["users"].append({"name": user, "key-pairs": keys })
tierno7edb6752016-03-21 17:37:52 +0100779
780 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
781 logger.debug("openmano request: %s", payload_req)
782 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
783 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
784 logger.debug("openmano response: %s", mano_response.text )
785 if args.verbose==None:
786 args.verbose=0
787
788 result = 0 if mano_response.status_code==200 else mano_response.status_code
789 content = mano_response.json()
790 #print json.dumps(content, indent=4)
791 if args.verbose >= 3:
792 print yaml.safe_dump(content, indent=4, default_flow_style=False)
793 return result
794
795 if mano_response.status_code == 200:
tiernoa15c4b92017-10-05 12:41:44 +0200796 myoutput = "{:38} {:20}".format(content['uuid'], content['name'])
tierno7edb6752016-03-21 17:37:52 +0100797 if args.verbose >=1:
tiernoa15c4b92017-10-05 12:41:44 +0200798 myoutput = "{} {:20}".format(myoutput, content['created_at'])
tierno7edb6752016-03-21 17:37:52 +0100799 if args.verbose >=2:
tiernoa15c4b92017-10-05 12:41:44 +0200800 myoutput = "{} {:30}".format(myoutput, content['description'])
tierno7edb6752016-03-21 17:37:52 +0100801 print myoutput
802 else:
803 print content['error']['description']
804 return result
805
806def instance_scenario_list(args):
807 #print "instance-scenario-list",args
808 if args.all:
809 tenant = "any"
810 else:
811 tenant = _get_tenant()
812 if args.name:
813 toshow = _get_item_uuid("instances", args.name, tenant)
814 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
815 else:
816 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
817 mano_response = requests.get(URLrequest)
818 logger.debug("openmano response: %s", mano_response.text )
819 content = mano_response.json()
820 #print json.dumps(content, indent=4)
821 if args.verbose==None:
822 args.verbose=0
823
824 result = 0 if mano_response.status_code==200 else mano_response.status_code
825 if mano_response.status_code == 200:
826 if not args.name:
827 if args.verbose >= 3:
828 print yaml.safe_dump(content, indent=4, default_flow_style=False)
829 return result
830 if len(content['instances']) == 0:
831 print "No scenario instances were found."
832 return result
833 for instance in content['instances']:
tiernoa15c4b92017-10-05 12:41:44 +0200834 myoutput = "{:38} {:20}".format(instance['uuid'], instance['name'])
tierno7edb6752016-03-21 17:37:52 +0100835 if args.verbose >=1:
tiernoa15c4b92017-10-05 12:41:44 +0200836 myoutput = "{} {:20}".format(myoutput, instance['created_at'])
tierno7edb6752016-03-21 17:37:52 +0100837 print myoutput
838 if args.verbose >=2:
839 print "Description: %s" %instance['description']
840 else:
841 if args.verbose:
842 print yaml.safe_dump(content, indent=4, default_flow_style=False)
843 return result
844 instance = content
tiernoa15c4b92017-10-05 12:41:44 +0200845 print ("{:38} {:20} {:20}".format(instance['uuid'],instance['name'],instance['created_at']))
846 print ("Description: %s" %instance['description'])
847 print ("Template scenario id: {}".format(instance['scenario_id']))
848 print ("Template scenario name: {}".format(instance['scenario_name']))
849 print ("---------------------------------------")
850 print ("VNF instances: {}".format(len(instance['vnfs'])))
tierno7edb6752016-03-21 17:37:52 +0100851 for vnf in instance['vnfs']:
852 #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))
tiernoa15c4b92017-10-05 12:41:44 +0200853 print (" {:38} {:20} Template vnf id: {:38}".format(vnf['uuid'], vnf['vnf_name'], vnf['vnf_id']))
tierno7edb6752016-03-21 17:37:52 +0100854 if len(instance['nets'])>0:
855 print "---------------------------------------"
856 print "Internal nets:"
857 for net in instance['nets']:
tierno5c7c4732016-09-26 13:38:55 +0000858 if net['created']:
tiernoa15c4b92017-10-05 12:41:44 +0200859 print (" {:38} {:12} VIM ID: {}".format(net['uuid'], net['status'], net['vim_net_id']))
tierno7edb6752016-03-21 17:37:52 +0100860 print "---------------------------------------"
861 print "External nets:"
862 for net in instance['nets']:
tierno5c7c4732016-09-26 13:38:55 +0000863 if not net['created']:
tiernoa15c4b92017-10-05 12:41:44 +0200864 print (" {:38} {:12} VIM ID: {}".format(net['uuid'], net['status'], net['vim_net_id']))
865 print ("---------------------------------------")
866 print ("VM instances:")
tierno7edb6752016-03-21 17:37:52 +0100867 for vnf in instance['vnfs']:
868 for vm in vnf['vms']:
tiernoa15c4b92017-10-05 12:41:44 +0200869 print (" {:38} {:20} {:20} {:12} VIM ID: {}".format(vm['uuid'], vnf['vnf_name'], vm['name'],
870 vm['status'], vm['vim_vm_id']))
tierno7edb6752016-03-21 17:37:52 +0100871 else:
872 print content['error']['description']
873 if args.verbose:
874 print yaml.safe_dump(content, indent=4, default_flow_style=False)
875 return result
876
877def instance_scenario_status(args):
878 print "instance-scenario-status"
879 return 0
880
881def instance_scenario_delete(args):
882 if args.all:
883 tenant = "any"
884 else:
885 tenant = _get_tenant()
886 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
887 #print "instance-scenario-delete",args
888 if not args.force:
889 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
890 if not (len(r)>0 and r[0].lower()=="y"):
891 return
892 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
893 mano_response = requests.delete(URLrequest)
894 logger.debug("openmano response: %s", mano_response.text )
895 result = 0 if mano_response.status_code==200 else mano_response.status_code
896 content = mano_response.json()
897 #print json.dumps(content, indent=4)
898 if mano_response.status_code == 200:
899 print content['result']
900 else:
901 print content['error']['description']
902 return result
903
tierno868220c2017-09-26 00:11:05 +0200904def get_action(args):
905 if not args.all:
906 tenant = _get_tenant()
907 else:
908 tenant = "any"
909 if not args.instance:
910 instance_id = "any"
911 else:
912 instance_id =args.instance
913 action_id = ""
914 if args.id:
915 action_id = "/" + args.id
916 URLrequest = "http://{}:{}/openmano/{}/instances/{}/action{}".format(mano_host, mano_port, tenant, instance_id,
917 action_id)
918 mano_response = requests.get(URLrequest)
919 logger.debug("openmano response: %s", mano_response.text )
920 if args.verbose == None:
921 args.verbose = 0
922 if args.id != None:
923 args.verbose += 1
924 return _print_verbose(mano_response, args.verbose)
925
tierno7edb6752016-03-21 17:37:52 +0100926def instance_scenario_action(args):
927 #print "instance-scenario-action", args
928 tenant = _get_tenant()
929 toact = _get_item_uuid("instances", args.name, tenant=tenant)
930 action={}
tiernofc5f80b2018-05-29 16:00:43 +0200931 action[ args.action ] = yaml.safe_load(args.param)
tierno7edb6752016-03-21 17:37:52 +0100932 if args.vnf:
933 action["vnfs"] = args.vnf
934 if args.vm:
935 action["vms"] = args.vm
936
937 headers_req = {'content-type': 'application/json'}
938 payload_req = json.dumps(action, indent=4)
939 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
940 logger.debug("openmano request: %s", payload_req)
941 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
942 logger.debug("openmano response: %s", mano_response.text )
943 result = 0 if mano_response.status_code==200 else mano_response.status_code
944 content = mano_response.json()
tiernofc5f80b2018-05-29 16:00:43 +0200945 # print json.dumps(content, indent=4)
tierno7edb6752016-03-21 17:37:52 +0100946 if mano_response.status_code == 200:
947 if args.verbose:
948 print yaml.safe_dump(content, indent=4, default_flow_style=False)
949 return result
tiernofc5f80b2018-05-29 16:00:43 +0200950 if "instance_action_id" in content:
951 print("instance_action_id={}".format(content["instance_action_id"]))
952 else:
953 for uuid,c in content.iteritems():
954 print ("{:38} {:20} {:20}".format(uuid, c.get('name'), c.get('description')))
tierno7edb6752016-03-21 17:37:52 +0100955 else:
956 print content['error']['description']
957 return result
958
959
960def instance_vnf_list(args):
961 print "instance-vnf-list"
962 return 0
963
964def instance_vnf_status(args):
965 print "instance-vnf-status"
966 return 0
967
968def tenant_create(args):
969 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
970 tenant_dict={"name": args.name}
971 if args.description!=None:
972 tenant_dict["description"] = args.description
973 payload_req = json.dumps( {"tenant": tenant_dict })
974
975 #print payload_req
976
977 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
978 logger.debug("openmano request: %s", payload_req)
979 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
980 logger.debug("openmano response: %s", mano_response.text )
981 return _print_verbose(mano_response, args.verbose)
982
983def tenant_list(args):
984 #print "tenant-list",args
985 if args.name:
tierno392f2852016-05-13 12:28:55 +0200986 toshow = _get_item_uuid("tenants", args.name)
tierno7edb6752016-03-21 17:37:52 +0100987 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
988 else:
989 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
990 mano_response = requests.get(URLrequest)
991 logger.debug("openmano response: %s", mano_response.text )
992 if args.verbose==None:
993 args.verbose=0
994 if args.name!=None:
995 args.verbose += 1
996 return _print_verbose(mano_response, args.verbose)
997
998def tenant_delete(args):
999 #print "tenant-delete",args
1000 todelete = _get_item_uuid("tenants", args.name)
1001 if not args.force:
1002 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
1003 if not (len(r)>0 and r[0].lower()=="y"):
1004 return 0
1005 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
1006 mano_response = requests.delete(URLrequest)
1007 logger.debug("openmano response: %s", mano_response.text )
1008 result = 0 if mano_response.status_code==200 else mano_response.status_code
1009 content = mano_response.json()
1010 #print json.dumps(content, indent=4)
1011 if mano_response.status_code == 200:
1012 print content['result']
1013 else:
1014 print content['error']['description']
1015 return result
1016
1017def datacenter_attach(args):
1018 tenant = _get_tenant()
1019 datacenter = _get_datacenter(args.name)
1020 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1021
1022 datacenter_dict={}
1023 if args.vim_tenant_id != None:
1024 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1025 if args.vim_tenant_name != None:
1026 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1027 if args.user != None:
1028 datacenter_dict['vim_username'] = args.user
1029 if args.password != None:
1030 datacenter_dict['vim_password'] = args.password
tierno8008c3a2016-10-13 15:34:28 +00001031 if args.config!=None:
1032 datacenter_dict["config"] = _load_file_or_yaml(args.config)
gcalvinoc62cfa52017-10-05 18:21:25 +02001033
tierno7edb6752016-03-21 17:37:52 +01001034 payload_req = json.dumps( {"datacenter": datacenter_dict })
gcalvinoc62cfa52017-10-05 18:21:25 +02001035
tierno7edb6752016-03-21 17:37:52 +01001036 #print payload_req
1037
1038 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1039 logger.debug("openmano request: %s", payload_req)
1040 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1041 logger.debug("openmano response: %s", mano_response.text )
1042 result = _print_verbose(mano_response, args.verbose)
1043 #provide addional information if error
1044 if mano_response.status_code != 200:
1045 content = mano_response.json()
1046 if "already in use for 'name'" in content['error']['description'] and \
1047 "to database vim_tenants table" in content['error']['description']:
1048 print "Try to specify a different name with --vim-tenant-name"
1049 return result
1050
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001051
1052def datacenter_edit_vim_tenant(args):
1053 tenant = _get_tenant()
1054 datacenter = _get_datacenter(args.name)
1055 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1056
1057 if not (args.vim_tenant_id or args.vim_tenant_name or args.user or args.password or args.config):
1058 raise OpenmanoCLIError("Error. At least one parameter must be updated.")
1059
1060 datacenter_dict = {}
1061 if args.vim_tenant_id != None:
1062 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1063 if args.vim_tenant_name != None:
1064 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1065 if args.user != None:
1066 datacenter_dict['vim_username'] = args.user
1067 if args.password != None:
1068 datacenter_dict['vim_password'] = args.password
1069 if args.config != None:
1070 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1071 payload_req = json.dumps({"datacenter": datacenter_dict})
1072
1073 # print payload_req
1074
1075 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" % (mano_host, mano_port, tenant, datacenter)
1076 logger.debug("openmano request: %s", payload_req)
1077 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1078 logger.debug("openmano response: %s", mano_response.text)
1079 result = _print_verbose(mano_response, args.verbose)
1080
1081 return result
1082
tierno7edb6752016-03-21 17:37:52 +01001083def datacenter_detach(args):
1084 if args.all:
1085 tenant = "any"
1086 else:
1087 tenant = _get_tenant()
1088 datacenter = _get_datacenter(args.name, tenant)
1089 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1090 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1091 mano_response = requests.delete(URLrequest, headers=headers_req)
1092 logger.debug("openmano response: %s", mano_response.text )
1093 content = mano_response.json()
1094 #print json.dumps(content, indent=4)
1095 result = 0 if mano_response.status_code==200 else mano_response.status_code
1096 if mano_response.status_code == 200:
1097 print content['result']
1098 else:
1099 print content['error']['description']
1100 return result
1101
1102def datacenter_create(args):
1103 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1104 datacenter_dict={"name": args.name, "vim_url": args.url}
1105 if args.description!=None:
1106 datacenter_dict["description"] = args.description
1107 if args.type!=None:
1108 datacenter_dict["type"] = args.type
1109 if args.url!=None:
1110 datacenter_dict["vim_url_admin"] = args.url_admin
1111 if args.config!=None:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001112 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1113 if args.sdn_controller!=None:
1114 tenant = _get_tenant()
1115 sdn_controller = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1116 if not 'config' in datacenter_dict:
1117 datacenter_dict['config'] = {}
1118 datacenter_dict['config']['sdn-controller'] = sdn_controller
tierno7edb6752016-03-21 17:37:52 +01001119 payload_req = json.dumps( {"datacenter": datacenter_dict })
1120
1121 #print payload_req
1122
1123 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
1124 logger.debug("openmano request: %s", payload_req)
1125 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1126 logger.debug("openmano response: %s", mano_response.text )
1127 return _print_verbose(mano_response, args.verbose)
1128
1129def datacenter_delete(args):
1130 #print "datacenter-delete",args
1131 todelete = _get_item_uuid("datacenters", args.name, "any")
1132 if not args.force:
1133 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
1134 if not (len(r)>0 and r[0].lower()=="y"):
1135 return 0
1136 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
1137 mano_response = requests.delete(URLrequest)
1138 logger.debug("openmano response: %s", mano_response.text )
1139 result = 0 if mano_response.status_code==200 else mano_response.status_code
1140 content = mano_response.json()
1141 #print json.dumps(content, indent=4)
1142 if mano_response.status_code == 200:
1143 print content['result']
1144 else:
1145 print content['error']['description']
1146 return result
1147
tierno20df3bb2017-07-07 14:31:00 +02001148
tierno7edb6752016-03-21 17:37:52 +01001149def datacenter_list(args):
1150 #print "datacenter-list",args
1151 tenant='any' if args.all else _get_tenant()
1152
1153 if args.name:
1154 toshow = _get_item_uuid("datacenters", args.name, tenant)
1155 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
1156 else:
1157 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
1158 mano_response = requests.get(URLrequest)
1159 logger.debug("openmano response: %s", mano_response.text )
1160 if args.verbose==None:
1161 args.verbose=0
1162 if args.name!=None:
1163 args.verbose += 1
1164 return _print_verbose(mano_response, args.verbose)
1165
tierno20df3bb2017-07-07 14:31:00 +02001166
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001167def datacenter_sdn_port_mapping_set(args):
1168 tenant = _get_tenant()
1169 datacenter = _get_datacenter(args.name, tenant)
1170 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1171
1172 if not args.file:
1173 raise OpenmanoCLIError(
1174 "No yaml/json has been provided specifying the SDN port mapping")
tierno20df3bb2017-07-07 14:31:00 +02001175 sdn_port_mapping = _load_file_or_yaml(args.file)
1176 payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping})
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001177
tierno20df3bb2017-07-07 14:31:00 +02001178 # read
1179 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1180 mano_response = requests.get(URLrequest)
1181 logger.debug("openmano response: %s", mano_response.text)
1182 port_mapping = mano_response.json()
1183 if mano_response.status_code != 200:
1184 str(mano_response.json())
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001185 raise OpenmanoCLIError("openmano client error: {}".format(port_mapping['error']['description']))
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001186 if len(port_mapping["sdn_port_mapping"]["ports_mapping"]) > 0:
1187 if not args.force:
1188 r = raw_input("Datacenter %s already contains a port mapping. Overwrite? (y/N)? " % (datacenter))
1189 if not (len(r) > 0 and r[0].lower() == "y"):
1190 return 0
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001191
tierno20df3bb2017-07-07 14:31:00 +02001192 # clear
1193 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1194 mano_response = requests.delete(URLrequest)
1195 logger.debug("openmano response: %s", mano_response.text)
1196 if mano_response.status_code != 200:
1197 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001198
tierno20df3bb2017-07-07 14:31:00 +02001199 # set
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001200 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1201 logger.debug("openmano request: %s", payload_req)
1202 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1203 logger.debug("openmano response: %s", mano_response.text)
tierno20df3bb2017-07-07 14:31:00 +02001204 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001205
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001206
1207def datacenter_sdn_port_mapping_list(args):
1208 tenant = _get_tenant()
1209 datacenter = _get_datacenter(args.name, tenant)
1210
1211 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1212 mano_response = requests.get(URLrequest)
1213 logger.debug("openmano response: %s", mano_response.text)
1214
tierno20df3bb2017-07-07 14:31:00 +02001215 return _print_verbose(mano_response, 4)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001216
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001217
1218def datacenter_sdn_port_mapping_clear(args):
1219 tenant = _get_tenant()
1220 datacenter = _get_datacenter(args.name, tenant)
1221
1222 if not args.force:
1223 r = raw_input("Clean SDN port mapping for datacenter %s (y/N)? " %(datacenter))
tierno20df3bb2017-07-07 14:31:00 +02001224 if not (len(r) > 0 and r[0].lower() == "y"):
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001225 return 0
1226
1227 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1228 mano_response = requests.delete(URLrequest)
1229 logger.debug("openmano response: %s", mano_response.text)
1230
tierno20df3bb2017-07-07 14:31:00 +02001231 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001232
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001233
1234def sdn_controller_create(args):
1235 tenant = _get_tenant()
1236 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1237
tierno8fe7a492017-07-11 13:50:04 +02001238 error_msg=[]
1239 if not args.ip: error_msg.append("'ip'")
1240 if not args.port: error_msg.append("'port'")
1241 if not args.dpid: error_msg.append("'dpid'")
1242 if not args.type: error_msg.append("'type'")
1243 if error_msg:
1244 raise OpenmanoCLIError("The following arguments are required: " + ",".join(error_msg))
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001245
1246 controller_dict = {}
1247 controller_dict['name'] = args.name
1248 controller_dict['ip'] = args.ip
1249 controller_dict['port'] = int(args.port)
1250 controller_dict['dpid'] = args.dpid
1251 controller_dict['type'] = args.type
1252 if args.description != None:
1253 controller_dict['description'] = args.description
1254 if args.user != None:
1255 controller_dict['user'] = args.user
1256 if args.password != None:
1257 controller_dict['password'] = args.password
1258
1259 payload_req = json.dumps({"sdn_controller": controller_dict})
1260
1261 # print payload_req
1262
1263 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" % (mano_host, mano_port, tenant)
1264 logger.debug("openmano request: %s", payload_req)
1265 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1266 logger.debug("openmano response: %s", mano_response.text)
1267 result = _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001268 return result
1269
tierno20df3bb2017-07-07 14:31:00 +02001270
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001271def sdn_controller_edit(args):
1272 tenant = _get_tenant()
1273 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1274 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1275
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001276 controller_dict = {}
tierno20df3bb2017-07-07 14:31:00 +02001277 if args.new_name:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001278 controller_dict['name'] = args.new_name
tierno20df3bb2017-07-07 14:31:00 +02001279 if args.ip:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001280 controller_dict['ip'] = args.ip
tierno20df3bb2017-07-07 14:31:00 +02001281 if args.port:
Pablo Montes Morenob12711f2017-04-06 11:54:34 +02001282 controller_dict['port'] = int(args.port)
tierno20df3bb2017-07-07 14:31:00 +02001283 if args.dpid:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001284 controller_dict['dpid'] = args.dpid
tierno20df3bb2017-07-07 14:31:00 +02001285 if args.type:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001286 controller_dict['type'] = args.type
tierno20df3bb2017-07-07 14:31:00 +02001287 if args.description:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001288 controller_dict['description'] = args.description
tierno20df3bb2017-07-07 14:31:00 +02001289 if args.user:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001290 controller_dict['user'] = args.user
tierno20df3bb2017-07-07 14:31:00 +02001291 if args.password:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001292 controller_dict['password'] = args.password
1293
tierno20df3bb2017-07-07 14:31:00 +02001294 if not controller_dict:
1295 raise OpenmanoCLIError("At least one parameter must be edited")
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001296
tierno20df3bb2017-07-07 14:31:00 +02001297 if not args.force:
1298 r = raw_input("Update SDN controller {} (y/N)? ".format(args.name))
1299 if not (len(r) > 0 and r[0].lower() == "y"):
1300 return 0
1301
1302 payload_req = json.dumps({"sdn_controller": controller_dict})
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001303 # print payload_req
1304
1305 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1306 logger.debug("openmano request: %s", payload_req)
1307 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1308 logger.debug("openmano response: %s", mano_response.text)
1309 result = _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001310 return result
1311
tierno20df3bb2017-07-07 14:31:00 +02001312
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001313def sdn_controller_list(args):
1314 tenant = _get_tenant()
1315 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1316
1317 if args.name:
1318 toshow = _get_item_uuid("sdn_controllers", args.name, tenant)
1319 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" %(mano_host, mano_port, tenant, toshow)
1320 else:
1321 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" %(mano_host, mano_port, tenant)
1322 #print URLrequest
1323 mano_response = requests.get(URLrequest)
1324 logger.debug("openmano response: %s", mano_response.text )
1325 if args.verbose==None:
1326 args.verbose=0
1327 if args.name!=None:
1328 args.verbose += 1
1329
tierno20df3bb2017-07-07 14:31:00 +02001330 # json.dumps(mano_response.json(), indent=4)
1331 return _print_verbose(mano_response, args.verbose)
1332
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001333
1334def sdn_controller_delete(args):
1335 tenant = _get_tenant()
1336 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1337
1338 if not args.force:
1339 r = raw_input("Delete SDN controller %s (y/N)? " % (args.name))
1340 if not (len(r) > 0 and r[0].lower() == "y"):
1341 return 0
1342
1343 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1344 mano_response = requests.delete(URLrequest)
1345 logger.debug("openmano response: %s", mano_response.text)
tierno20df3bb2017-07-07 14:31:00 +02001346 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001347
tierno7edb6752016-03-21 17:37:52 +01001348def vim_action(args):
1349 #print "datacenter-net-action",args
1350 tenant = _get_tenant()
1351 datacenter = _get_datacenter(args.datacenter, tenant)
1352 if args.verbose==None:
1353 args.verbose=0
1354 if args.action=="list":
1355 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1356 if args.name!=None:
1357 args.verbose += 1
1358 URLrequest += "/" + args.name
1359 mano_response = requests.get(URLrequest)
1360 logger.debug("openmano response: %s", mano_response.text )
1361 return _print_verbose(mano_response, args.verbose)
1362 elif args.action=="delete":
1363 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1364 mano_response = requests.delete(URLrequest)
1365 logger.debug("openmano response: %s", mano_response.text )
1366 result = 0 if mano_response.status_code==200 else mano_response.status_code
1367 content = mano_response.json()
1368 #print json.dumps(content, indent=4)
1369 if mano_response.status_code == 200:
1370 print content['result']
1371 else:
1372 print content['error']['description']
1373 return result
1374 elif args.action=="create":
1375 headers_req = {'content-type': 'application/yaml'}
1376 if args.file:
1377 create_dict = _load_file_or_yaml(args.file)
1378 if args.item not in create_dict:
1379 create_dict = {args.item: create_dict}
1380 else:
1381 create_dict = {args.item:{}}
1382 if args.name:
1383 create_dict[args.item]['name'] = args.name
1384 #if args.description:
1385 # create_dict[args.item]['description'] = args.description
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001386 if args.item=="network":
tierno7edb6752016-03-21 17:37:52 +01001387 if args.bind_net:
1388 create_dict[args.item]['bind_net'] = args.bind_net
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001389 if args.type:
1390 create_dict[args.item]['type'] = args.type
tierno7edb6752016-03-21 17:37:52 +01001391 if args.shared:
1392 create_dict[args.item]['shared'] = args.shared
1393 if "name" not in create_dict[args.item]:
1394 print "You must provide a name in the descriptor file or with the --name option"
1395 return
1396 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1397 logger.debug("openmano request: %s", payload_req)
tierno72a08d72017-05-25 13:12:30 +02001398 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
tierno7edb6752016-03-21 17:37:52 +01001399 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1400 logger.debug("openmano response: %s", mano_response.text )
1401 if args.verbose==None:
1402 args.verbose=0
1403 return _print_verbose(mano_response, args.verbose)
1404
tierno20df3bb2017-07-07 14:31:00 +02001405
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001406def _get_items(item, item_name_id=None, datacenter=None, tenant=None):
1407 URLrequest = "http://%s:%s/openmano" %(mano_host, mano_port)
1408 if tenant:
1409 URLrequest += "/" + tenant
1410 if datacenter:
1411 URLrequest += "/vim/" + datacenter
1412 if item:
1413 URLrequest += "/" + item +"s"
1414 if item_name_id:
1415 URLrequest += "/" + item_name_id
1416 mano_response = requests.get(URLrequest)
1417 logger.debug("openmano response: %s", mano_response.text )
1418
1419 return mano_response
1420
tierno20df3bb2017-07-07 14:31:00 +02001421
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001422def vim_net_sdn_attach(args):
1423 #Verify the network exists in the vim
1424 tenant = _get_tenant()
1425 datacenter = _get_datacenter(args.datacenter, tenant)
1426 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1427 content = yaml.load(result.content)
1428 if 'networks' in content:
1429 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1430 if 'error' in content:
1431 raise OpenmanoCLIError(yaml.safe_dump(content))
1432 network_uuid = content['network']['id']
1433
1434 #Make call to attach the dataplane port to the SND network associated to the vim network
1435 headers_req = {'content-type': 'application/yaml'}
1436 payload_req = {'port': args.port}
1437 if args.vlan:
1438 payload_req['vlan'] = int(args.vlan)
1439 if args.mac:
1440 payload_req['mac'] = args.mac
1441
1442 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/attach" % (mano_host, mano_port, tenant, datacenter, network_uuid)
1443 logger.debug("openmano request: %s", payload_req)
1444 mano_response = requests.post(URLrequest, headers=headers_req, data=json.dumps(payload_req))
1445 logger.debug("openmano response: %s", mano_response.text)
1446 result = _print_verbose(mano_response, args.verbose)
tierno20df3bb2017-07-07 14:31:00 +02001447 return result
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001448
1449
1450def vim_net_sdn_detach(args):
1451 if not args.all and not args.id:
1452 print "--all or --id must be used"
1453 return 1
1454
1455 # Verify the network exists in the vim
1456 tenant = _get_tenant()
1457 datacenter = _get_datacenter(args.datacenter, tenant)
1458 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1459 content = yaml.load(result.content)
1460 if 'networks' in content:
1461 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1462 if 'error' in content:
1463 raise OpenmanoCLIError(yaml.safe_dump(content))
1464 network_uuid = content['network']['id']
1465
1466 if not args.force:
1467 r = raw_input("Confirm action' (y/N)? ")
1468 if len(r) == 0 or r[0].lower() != "y":
1469 return 0
1470
1471 if args.id:
1472 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach/%s" % (
1473 mano_host, mano_port, tenant, datacenter, network_uuid, args.id)
1474 else:
1475 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach" % (
1476 mano_host, mano_port, tenant, datacenter, network_uuid)
1477 mano_response = requests.delete(URLrequest)
1478 logger.debug("openmano response: %s", mano_response.text)
1479 result = _print_verbose(mano_response, args.verbose)
tierno20df3bb2017-07-07 14:31:00 +02001480 return result
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001481
tierno7edb6752016-03-21 17:37:52 +01001482
1483def datacenter_net_action(args):
1484 if args.action == "net-update":
tierno5acf7202016-08-29 14:28:13 +02001485 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
tierno7edb6752016-03-21 17:37:52 +01001486 print
1487 args.action = "netmap-delete"
1488 args.netmap = None
1489 args.all = True
1490 r = datacenter_netmap_action(args)
1491 if r == 0:
1492 args.force = True
tierno5acf7202016-08-29 14:28:13 +02001493 args.action = "netmap-import"
tierno7edb6752016-03-21 17:37:52 +01001494 r = datacenter_netmap_action(args)
1495 return r
1496
1497 if args.action == "net-edit":
1498 args.netmap = args.net
1499 args.name = None
1500 elif args.action == "net-list":
1501 args.netmap = None
1502 elif args.action == "net-delete":
1503 args.netmap = args.net
1504 args.all = False
1505
1506 args.action = "netmap" + args.action[3:]
1507 args.vim_name=None
1508 args.vim_id=None
1509 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1510 print
1511 return datacenter_netmap_action(args)
1512
1513def datacenter_netmap_action(args):
1514 tenant = _get_tenant()
1515 datacenter = _get_datacenter(args.datacenter, tenant)
1516 #print "datacenter_netmap_action",args
1517 payload_req = None
1518 if args.verbose==None:
1519 args.verbose=0
1520 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1521 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1522
1523 if args.action=="netmap-list":
1524 if args.netmap:
1525 URLrequest += "/" + args.netmap
1526 args.verbose += 1
1527 mano_response = requests.get(URLrequest)
1528
1529 elif args.action=="netmap-delete":
1530 if args.netmap and args.all:
1531 print "you can not use a netmap name and the option --all at the same time"
1532 return 1
1533 if args.netmap:
1534 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1535 URLrequest += "/" + args.netmap
1536 elif args.all:
1537 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1538 else:
tiernoae4a8d12016-07-08 12:30:39 +02001539 print "you must specify a netmap name or the option --all"
tierno7edb6752016-03-21 17:37:52 +01001540 return 1
1541 if not args.force:
1542 r = raw_input(force_text)
1543 if len(r)>0 and r[0].lower()=="y":
1544 pass
1545 else:
1546 return 0
1547 mano_response = requests.delete(URLrequest, headers=headers_req)
tierno5acf7202016-08-29 14:28:13 +02001548 elif args.action=="netmap-import":
tierno7edb6752016-03-21 17:37:52 +01001549 if not args.force:
1550 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1551 if len(r)>0 and r[0].lower()=="y":
1552 pass
1553 else:
1554 return 0
1555 URLrequest += "/upload"
1556 mano_response = requests.post(URLrequest, headers=headers_req)
1557 elif args.action=="netmap-edit" or args.action=="netmap-create":
1558 if args.file:
1559 payload = _load_file_or_yaml(args.file)
1560 else:
1561 payload = {}
1562 if "netmap" not in payload:
1563 payload = {"netmap": payload}
1564 if args.name:
1565 payload["netmap"]["name"] = args.name
1566 if args.vim_id:
1567 payload["netmap"]["vim_id"] = args.vim_id
1568 if args.action=="netmap-create" and args.vim_name:
1569 payload["netmap"]["vim_name"] = args.vim_name
1570 payload_req = json.dumps(payload)
1571 logger.debug("openmano request: %s", payload_req)
1572
1573 if args.action=="netmap-edit" and not args.force:
1574 if len(payload["netmap"]) == 0:
1575 print "You must supply some parameter to edit"
1576 return 1
1577 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1578 if len(r)>0 and r[0].lower()=="y":
1579 pass
1580 else:
1581 return 0
1582 URLrequest += "/" + args.netmap
1583 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1584 else: #netmap-create
1585 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1586 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1587 return 1
1588 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1589
1590 logger.debug("openmano response: %s", mano_response.text )
1591 return _print_verbose(mano_response, args.verbose)
1592
tierno20df3bb2017-07-07 14:31:00 +02001593
tierno7edb6752016-03-21 17:37:52 +01001594def element_edit(args):
1595 element = _get_item_uuid(args.element, args.name)
1596 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1597 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1598 payload=_load_file_or_yaml(args.file)
1599 if args.element[:-1] not in payload:
1600 payload = {args.element[:-1]: payload }
1601 payload_req = json.dumps(payload)
1602
1603 #print payload_req
1604 if not args.force or (args.name==None and args.filer==None):
1605 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1606 if len(r)>0 and r[0].lower()=="y":
1607 pass
1608 else:
1609 return 0
1610 logger.debug("openmano request: %s", payload_req)
1611 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1612 logger.debug("openmano response: %s", mano_response.text )
1613 if args.verbose==None:
1614 args.verbose=0
1615 if args.name!=None:
1616 args.verbose += 1
1617 return _print_verbose(mano_response, args.verbose)
1618
1619
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001620def datacenter_edit(args):
1621 tenant = _get_tenant()
1622 element = _get_item_uuid('datacenters', args.name, tenant)
1623 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1624 URLrequest = "http://%s:%s/openmano/datacenters/%s" % (mano_host, mano_port, element)
1625
1626 has_arguments = False
1627 if args.file != None:
1628 has_arguments = True
1629 payload = _load_file_or_yaml(args.file)
1630 else:
1631 payload = {}
1632
1633 if args.sdn_controller != None:
1634 has_arguments = True
1635 if not 'config' in payload:
1636 payload['config'] = {}
1637 if not 'sdn-controller' in payload['config']:
1638 payload['config']['sdn-controller'] = {}
1639 if args.sdn_controller == 'null':
1640 payload['config']['sdn-controller'] = None
1641 else:
1642 payload['config']['sdn-controller'] = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1643
1644 if not has_arguments:
1645 raise OpenmanoCLIError("At least one argument must be provided to modify the datacenter")
1646
1647 if 'datacenter' not in payload:
1648 payload = {'datacenter': payload}
1649 payload_req = json.dumps(payload)
1650
1651 # print payload_req
1652 if not args.force or (args.name == None and args.filer == None):
1653 r = raw_input(" Edit datacenter " + args.name + " (y/N)? ")
1654 if len(r) > 0 and r[0].lower() == "y":
1655 pass
1656 else:
1657 return 0
1658 logger.debug("openmano request: %s", payload_req)
1659 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1660 logger.debug("openmano response: %s", mano_response.text)
1661 if args.verbose == None:
1662 args.verbose = 0
1663 if args.name != None:
1664 args.verbose += 1
1665 return _print_verbose(mano_response, args.verbose)
1666
tierno20df3bb2017-07-07 14:31:00 +02001667
tierno6ddeded2017-05-16 15:40:26 +02001668def version(args):
1669 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1670 URLrequest = "http://%s:%s/openmano/version" % (mano_host, mano_port)
1671
1672 mano_response = requests.get(URLrequest, headers=headers_req)
1673 logger.debug("openmano response: %s", mano_response.text)
1674 print mano_response.text
1675
1676
tierno7edb6752016-03-21 17:37:52 +01001677global mano_host
1678global mano_port
1679global mano_tenant
1680
1681if __name__=="__main__":
1682
1683 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1684 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1685 mano_port = os.getenv('OPENMANO_PORT',"9090")
1686 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1687
1688 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
tierno6ddeded2017-05-16 15:40:26 +02001689 main_parser.add_argument('--version', action='version', help="get version of this client",
1690 version='%(prog)s client version ' + __version__ +
1691 " (Note: use '%(prog)s version' to get server version)")
1692
tierno7edb6752016-03-21 17:37:52 +01001693 subparsers = main_parser.add_subparsers(help='commands')
1694
tierno7edb6752016-03-21 17:37:52 +01001695 parent_parser = argparse.ArgumentParser(add_help=False)
1696 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1697 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1698
garciadeblas0e9fd832016-07-08 15:20:18 +02001699 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1700 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1701 config_parser.set_defaults(func=config)
1702
tierno6ddeded2017-05-16 15:40:26 +02001703 version_parser = subparsers.add_parser('version', parents=[parent_parser], help="get server version")
1704 version_parser.set_defaults(func=version)
1705
tierno7edb6752016-03-21 17:37:52 +01001706 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1707 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1708 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1709 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1710 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
garciadeblas14480452017-01-10 13:08:07 +01001711 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1712 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
tierno7edb6752016-03-21 17:37:52 +01001713 vnf_create_parser.set_defaults(func=vnf_create)
1714
1715 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1716 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1717 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1718 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1719 vnf_list_parser.set_defaults(func=vnf_list)
1720
1721 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1722 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1723 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1724 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1725 vnf_delete_parser.set_defaults(func=vnf_delete)
1726
1727 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1728 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1729 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1730 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1731 scenario_create_parser.set_defaults(func=scenario_create)
1732
1733 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1734 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1735 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1736 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1737 scenario_list_parser.set_defaults(func=scenario_list)
1738
1739 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1740 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1741 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1742 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1743 scenario_delete_parser.set_defaults(func=scenario_delete)
1744
1745 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1746 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1747 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1748 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1749 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1750 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1751 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1752
1753 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1754 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1755 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1756 scenario_deploy_parser.set_defaults(func=scenario_verify)
1757
1758 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1759 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1760 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1761 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1762 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1763 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1764 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")
1765 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 +02001766 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")
1767 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 +01001768 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1769 instance_scenario_create_parser.set_defaults(func=instance_create)
1770
1771 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1772 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1773 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1774 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1775
1776 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)")
1777 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1778 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1779 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1780 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1781
1782 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1783 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1784 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
tiernofc5f80b2018-05-29 16:00:43 +02001785 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console", "add_public_key","vdu-scaling"],\
tierno7edb6752016-03-21 17:37:52 +01001786 help="action to send")
tiernofc5f80b2018-05-29 16:00:43 +02001787 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console: novnc; reboot: type; vdu-scaling: '[{vdu-id: xxx, type: create|delete, count: 1}]'")
tierno7edb6752016-03-21 17:37:52 +01001788 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1789 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1790 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1791
tierno868220c2017-09-26 00:11:05 +02001792 action_parser = subparsers.add_parser('action-list', parents=[parent_parser], help="get action over an instance status")
1793 action_parser.add_argument("id", nargs='?', action="store", help="action id")
1794 action_parser.add_argument("--instance", action="store", help="fitler by this instance_id")
1795 action_parser.add_argument("--all", action="store", help="Not filter by tenant")
1796 action_parser.set_defaults(func=get_action)
1797
tierno7edb6752016-03-21 17:37:52 +01001798 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1799 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1800 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1801
1802 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1803 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1804 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1805 tenant_create_parser.set_defaults(func=tenant_create)
1806
1807 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1808 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1809 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1810 tenant_delete_parser.set_defaults(func=tenant_delete)
1811
1812 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1813 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1814 tenant_list_parser.set_defaults(func=tenant_list)
1815
tierno161c24b2017-05-16 15:45:56 +02001816 element_edit_parser = subparsers.add_parser('tenant-edit', parents=[parent_parser], help="edits one tenant")
1817 element_edit_parser.add_argument("name", help="name or uuid of the tenant")
1818 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1819 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1820 element_edit_parser.set_defaults(func=element_edit, element='tenants')
tierno7edb6752016-03-21 17:37:52 +01001821
1822 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1823 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1824 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1825 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1826 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1827 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1828 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001829 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 +01001830 datacenter_create_parser.set_defaults(func=datacenter_create)
1831
1832 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1833 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1834 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1835 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1836
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001837 datacenter_edit_parser = subparsers.add_parser('datacenter-edit', parents=[parent_parser], help="Edit datacenter")
1838 datacenter_edit_parser.add_argument("name", help="name or uuid of the datacenter")
1839 datacenter_edit_parser.add_argument("--file", help="json/yaml text or file with the changes").completer = FilesCompleter
1840 datacenter_edit_parser.add_argument("--sdn-controller", action="store",
1841 help="Name or uuid of the SDN controller to be used. Specify 'null' to clear entry", dest='sdn_controller')
1842 datacenter_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1843 datacenter_edit_parser.set_defaults(func=datacenter_edit)
1844
tierno7edb6752016-03-21 17:37:52 +01001845 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1846 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1847 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1848 datacenter_list_parser.set_defaults(func=datacenter_list)
1849
1850 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1851 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1852 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1853 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1854 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1855 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
tierno8008c3a2016-10-13 15:34:28 +00001856 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
tierno7edb6752016-03-21 17:37:52 +01001857 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1858
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001859 datacenter_edit_vim_tenant_parser = subparsers.add_parser('datacenter-edit-vim-tenant', parents=[parent_parser],
1860 help="Edit the association of a datacenter to the operating tenant")
1861 datacenter_edit_vim_tenant_parser.add_argument("name", help="name or uuid of the datacenter")
1862 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-id', action='store',
1863 help="specify a datacenter tenant to use. A new one is created by default")
1864 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1865 datacenter_edit_vim_tenant_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1866 datacenter_edit_vim_tenant_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1867 datacenter_edit_vim_tenant_parser.add_argument("--config", action="store",
1868 help="aditional configuration in json/yaml format")
1869 datacenter_edit_vim_tenant_parser.set_defaults(func=datacenter_edit_vim_tenant)
1870
tierno7edb6752016-03-21 17:37:52 +01001871 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1872 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1873 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1874 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1875
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001876 #=======================datacenter_sdn_port_mapping_xxx section=======================
1877 #datacenter_sdn_port_mapping_set
1878 datacenter_sdn_port_mapping_set_parser = subparsers.add_parser('datacenter-sdn-port-mapping-set',
1879 parents=[parent_parser],
1880 help="Load a file with the mapping of physical ports "
1881 "and the ports of the dataplaneswitch controlled "
1882 "by a datacenter")
1883 datacenter_sdn_port_mapping_set_parser.add_argument("name", action="store", help="specifies the datacenter")
1884 datacenter_sdn_port_mapping_set_parser.add_argument("file",
1885 help="json/yaml text or file with the port mapping").completer = FilesCompleter
1886 datacenter_sdn_port_mapping_set_parser.add_argument("-f", "--force", action="store_true",
1887 help="forces overwriting without asking")
1888 datacenter_sdn_port_mapping_set_parser.set_defaults(func=datacenter_sdn_port_mapping_set)
1889
1890 #datacenter_sdn_port_mapping_list
1891 datacenter_sdn_port_mapping_list_parser = subparsers.add_parser('datacenter-sdn-port-mapping-list',
1892 parents=[parent_parser],
1893 help="Show the SDN port mapping in a datacenter")
1894 datacenter_sdn_port_mapping_list_parser.add_argument("name", action="store", help="specifies the datacenter")
1895 datacenter_sdn_port_mapping_list_parser.set_defaults(func=datacenter_sdn_port_mapping_list)
1896
1897 # datacenter_sdn_port_mapping_clear
1898 datacenter_sdn_port_mapping_clear_parser = subparsers.add_parser('datacenter-sdn-port-mapping-clear',
1899 parents=[parent_parser],
1900 help="Clean the the SDN port mapping in a datacenter")
1901 datacenter_sdn_port_mapping_clear_parser.add_argument("name", action="store",
1902 help="specifies the datacenter")
1903 datacenter_sdn_port_mapping_clear_parser.add_argument("-f", "--force", action="store_true",
1904 help="forces clearing without asking")
1905 datacenter_sdn_port_mapping_clear_parser.set_defaults(func=datacenter_sdn_port_mapping_clear)
1906 # =======================
1907
1908 # =======================sdn_controller_xxx section=======================
1909 # sdn_controller_create
1910 sdn_controller_create_parser = subparsers.add_parser('sdn-controller-create', parents=[parent_parser],
1911 help="Creates an SDN controller entity within RO")
1912 sdn_controller_create_parser.add_argument("name", help="name of the SDN controller")
1913 sdn_controller_create_parser.add_argument("--description", action="store", help="description of the SDN controller")
1914 sdn_controller_create_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1915 sdn_controller_create_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1916 sdn_controller_create_parser.add_argument("--dpid", action="store",
1917 help="DPID of the dataplane switch controlled by this SDN controller")
1918 sdn_controller_create_parser.add_argument("--type", action="store",
1919 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1920 sdn_controller_create_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1921 sdn_controller_create_parser.add_argument("--passwd", action="store", dest='password',
1922 help="password credentials for the SDN controller")
1923 sdn_controller_create_parser.set_defaults(func=sdn_controller_create)
1924
1925 # sdn_controller_edit
1926 sdn_controller_edit_parser = subparsers.add_parser('sdn-controller-edit', parents=[parent_parser],
1927 help="Update one or more options of a SDN controller")
1928 sdn_controller_edit_parser.add_argument("name", help="name or uuid of the SDN controller", )
1929 sdn_controller_edit_parser.add_argument("--name", action="store", help="Update the name of the SDN controller",
1930 dest='new_name')
1931 sdn_controller_edit_parser.add_argument("--description", action="store", help="description of the SDN controller")
1932 sdn_controller_edit_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1933 sdn_controller_edit_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1934 sdn_controller_edit_parser.add_argument("--dpid", action="store",
1935 help="DPID of the dataplane switch controlled by this SDN controller")
1936 sdn_controller_edit_parser.add_argument("--type", action="store",
1937 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1938 sdn_controller_edit_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1939 sdn_controller_edit_parser.add_argument("--password", action="store",
1940 help="password credentials for the SDN controller", dest='password')
1941 sdn_controller_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1942 #TODO: include option --file
1943 sdn_controller_edit_parser.set_defaults(func=sdn_controller_edit)
1944
1945 #sdn_controller_list
1946 sdn_controller_list_parser = subparsers.add_parser('sdn-controller-list',
1947 parents=[parent_parser],
1948 help="List the SDN controllers")
1949 sdn_controller_list_parser.add_argument("name", nargs='?', help="name or uuid of the SDN controller")
1950 sdn_controller_list_parser.set_defaults(func=sdn_controller_list)
1951
1952 # sdn_controller_delete
1953 sdn_controller_delete_parser = subparsers.add_parser('sdn-controller-delete',
1954 parents=[parent_parser],
1955 help="Delete the the SDN controller")
1956 sdn_controller_delete_parser.add_argument("name", help="name or uuid of the SDN controller")
1957 sdn_controller_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1958 sdn_controller_delete_parser.set_defaults(func=sdn_controller_delete)
1959 # =======================
tierno7edb6752016-03-21 17:37:52 +01001960
1961 action_dict={'net-update': 'retrieves external networks from datacenter',
1962 'net-edit': 'edits an external network',
1963 'net-delete': 'deletes an external network',
1964 'net-list': 'lists external networks from a datacenter'
1965 }
1966 for item in action_dict:
1967 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1968 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1969 if item=='net-edit' or item=='net-delete':
1970 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1971 if item=='net-edit':
1972 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1973 if item!='net-list':
1974 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1975 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1976
1977
tierno5acf7202016-08-29 14:28:13 +02001978 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
tierno7edb6752016-03-21 17:37:52 +01001979 'netmap-create': 'create a new network senario netmap',
1980 'netmap-edit': 'edit name of a network senario netmap',
1981 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1982 'netmap-list': 'list/show network scenario netmaps'
1983 }
1984 for item in action_dict:
1985 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1986 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1987 #if item=='net-add':
1988 # datacenter_action_parser.add_argument("net", help="name of the network")
1989 if item=='netmap-delete':
1990 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1991 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1992 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1993 if item=='netmap-edit':
1994 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1995 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1996 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1997 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1998 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1999 if item=='netmap-list':
2000 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
2001 if item=='netmap-create':
2002 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
2003 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
2004 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
2005 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
tierno5acf7202016-08-29 14:28:13 +02002006 if item=='netmap-import':
tierno7edb6752016-03-21 17:37:52 +01002007 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
2008 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002009
2010 # =======================vim_net_sdn_xxx section=======================
2011 # vim_net_sdn_attach
2012 vim_net_sdn_attach_parser = subparsers.add_parser('vim-net-sdn-attach',
2013 parents=[parent_parser],
2014 help="Specify the port to access to an external network using SDN")
2015 vim_net_sdn_attach_parser.add_argument("vim_net", action="store",
2016 help="Name/id of the network in the vim that will be used to connect to the external network")
2017 vim_net_sdn_attach_parser.add_argument("port", action="store", help="Specifies the port in the dataplane switch to access to the external network")
2018 vim_net_sdn_attach_parser.add_argument("--vlan", action="store", help="Specifies the vlan (if any) to use in the defined port")
2019 vim_net_sdn_attach_parser.add_argument("--mac", action="store", help="Specifies the MAC (if known) of the physical device that will be reachable by this external port")
2020 vim_net_sdn_attach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2021 vim_net_sdn_attach_parser.set_defaults(func=vim_net_sdn_attach)
2022
2023 # vim_net_sdn_detach
2024 vim_net_sdn_detach_parser = subparsers.add_parser('vim-net-sdn-detach',
2025 parents=[parent_parser],
2026 help="Remove the port information to access to an external network using SDN")
2027
2028 vim_net_sdn_detach_parser.add_argument("vim_net", action="store", help="Name/id of the vim network")
2029 vim_net_sdn_detach_parser.add_argument("--id", action="store",help="Specify the uuid of the external ports from this network to be detached")
2030 vim_net_sdn_detach_parser.add_argument("--all", action="store_true", help="Detach all external ports from this network")
2031 vim_net_sdn_detach_parser.add_argument("-f", "--force", action="store_true", help="forces clearing without asking")
2032 vim_net_sdn_detach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2033 vim_net_sdn_detach_parser.set_defaults(func=vim_net_sdn_detach)
2034 # =======================
2035
tierno4540ea52017-01-18 17:44:32 +01002036 for item in ("network", "tenant", "image"):
tierno7edb6752016-03-21 17:37:52 +01002037 if item=="network":
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002038 command_name = 'vim-net'
tierno7edb6752016-03-21 17:37:52 +01002039 else:
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002040 command_name = 'vim-'+item
2041 vim_item_list_parser = subparsers.add_parser(command_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
tierno7edb6752016-03-21 17:37:52 +01002042 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
2043 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2044 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
2045
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002046 vim_item_del_parser = subparsers.add_parser(command_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
tierno7edb6752016-03-21 17:37:52 +01002047 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
2048 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2049 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
2050
tierno4540ea52017-01-18 17:44:32 +01002051 if item == "network" or item == "tenant":
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002052 vim_item_create_parser = subparsers.add_parser(command_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
tierno4540ea52017-01-18 17:44:32 +01002053 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
2054 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
2055 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2056 if item=="network":
2057 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
2058 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
2059 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>'")
2060 else:
2061 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
2062 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
tierno7edb6752016-03-21 17:37:52 +01002063
2064 argcomplete.autocomplete(main_parser)
2065
2066 try:
2067 args = main_parser.parse_args()
2068 #logging info
2069 level = logging.CRITICAL
2070 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
2071 if "debug" in args and args.debug:
2072 level = logging.DEBUG
2073 logging.basicConfig(format=streamformat, level= level)
2074 logger = logging.getLogger('mano')
2075 logger.setLevel(level)
2076 result = args.func(args)
2077 if result == None:
2078 result = 0
2079 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
2080 except (requests.exceptions.ConnectionError):
2081 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
2082 result = -2
2083 except (KeyboardInterrupt):
2084 print 'Exiting openmano'
2085 result = -3
2086 except (SystemExit, ArgumentParserError):
2087 result = -4
2088 except OpenmanoCLIError as e:
2089 print str(e)
2090 result = -5
2091
2092 #print result
2093 exit(result)
2094