blob: d3b4feb6a0503984e9d93eaa9e85c65a5ee44f96 [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$"
tiernofc5f80b2018-05-29 16:00:43 +020031__version__ = "0.4.23-r533"
32version_date = "May 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]
276 vdu_list = vnfd["vdu"]
277
278 else: # old API
279 api_version = ""
280 token = "vnfs"
281 vnfd = myvnf['vnf']
282 vdu_list = vnfd["VNFC"]
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
tierno7edb6752016-03-21 17:37:52 +0100292 if args.image_path:
tiernof1ba57e2017-09-07 12:23:19 +0200293 index = 0
tierno7edb6752016-03-21 17:37:52 +0100294 for image_path_ in args.image_path.split(","):
tiernof1ba57e2017-09-07 12:23:19 +0200295 # print "image-path", image_path_
296 if api_version == "/v3":
297 if vdu_list[index].get("image"):
298 vdu_list[index]['image'] = image_path_
299 if "image-checksum" in vdu_list[index]:
300 del vdu_list[index]["image-checksum"]
301 else: # image name in volumes
302 vdu_list[index]["volumes"][0]["image"] = image_path_
303 if "image-checksum" in vdu_list[index]["volumes"][0]:
304 del vdu_list[index]["volumes"][0]["image-checksum"]
305 else:
306 vdu_list[index]['VNFC image'] = image_path_
307 if "image name" in vdu_list[index]:
308 del vdu_list[index]["image name"]
309 if "image checksum" in vdu_list[index]:
310 del vdu_list[index]["image checksum"]
311 index += 1
312 if args.image_name: # image name precedes if both are supplied
313 index = 0
garciadeblas14480452017-01-10 13:08:07 +0100314 for image_name_ in args.image_name.split(","):
tiernof1ba57e2017-09-07 12:23:19 +0200315 if api_version == "/v3":
316 if vdu_list[index].get("image"):
317 vdu_list[index]['image'] = image_name_
318 if "image-checksum" in vdu_list[index]:
319 del vdu_list[index]["image-checksum"]
tierno16e3dd42018-04-24 12:52:40 +0200320 if vdu_list[index].get("alternative-images"):
321 for a_image in vdu_list[index]["alternative-images"]:
322 a_image['image'] = image_name_
323 if "image-checksum" in a_image:
324 del a_image["image-checksum"]
tiernof1ba57e2017-09-07 12:23:19 +0200325 else: # image name in volumes
326 vdu_list[index]["volumes"][0]["image"] = image_name_
327 if "image-checksum" in vdu_list[index]["volumes"][0]:
328 del vdu_list[index]["volumes"][0]["image-checksum"]
329 else:
330 vdu_list[index]['image name'] = image_name_
331 if "VNFC image" in vdu_list[index]:
332 del vdu_list[index]["VNFC image"]
333 index += 1
garciadeblas14480452017-01-10 13:08:07 +0100334 if args.image_checksum:
tiernof1ba57e2017-09-07 12:23:19 +0200335 index = 0
garciadeblas14480452017-01-10 13:08:07 +0100336 for image_checksum_ in args.image_checksum.split(","):
tiernof1ba57e2017-09-07 12:23:19 +0200337 if api_version == "/v3":
338 if vdu_list[index].get("image"):
339 vdu_list[index]['image-checksum'] = image_checksum_
tierno16e3dd42018-04-24 12:52:40 +0200340 if vdu_list[index].get("alternative-images"):
341 for a_image in vdu_list[index]["alternative-images"]:
342 a_image['image-checksum'] = image_checksum_
tiernof1ba57e2017-09-07 12:23:19 +0200343 else: # image name in volumes
344 vdu_list[index]["volumes"][0]["image-checksum"] = image_checksum_
345 else:
346 vdu_list[index]['image checksum'] = image_checksum_
347 index += 1
tierno7edb6752016-03-21 17:37:52 +0100348 except (KeyError, TypeError), e:
tiernof1ba57e2017-09-07 12:23:19 +0200349 if str(e) == 'vnf': error_pos= "missing field 'vnf'"
350 elif str(e) == 'name': error_pos= "missing field 'vnf':'name'"
351 elif str(e) == 'description': error_pos= "missing field 'vnf':'description'"
352 elif str(e) == 'VNFC': error_pos= "missing field 'vnf':'VNFC'"
353 elif str(e) == str(index): error_pos= "field 'vnf':'VNFC' must be an array"
354 elif str(e) == 'VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
355 elif str(e) == 'image name': error_pos= "missing field 'vnf':'VNFC'['image name']"
356 elif str(e) == 'image checksum': error_pos= "missing field 'vnf':'VNFC'['image checksum']"
tierno7edb6752016-03-21 17:37:52 +0100357 else: error_pos="wrong format"
358 print "Wrong VNF descriptor: " + error_pos
359 return -1
360 payload_req = json.dumps(myvnf)
361
362 #print payload_req
363
tiernof1ba57e2017-09-07 12:23:19 +0200364 URLrequest = "http://{}:{}/openmano{}/{}/{token}".format(mano_host, mano_port, api_version, tenant, token=token)
tierno7edb6752016-03-21 17:37:52 +0100365 logger.debug("openmano request: %s", payload_req)
366 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
367 logger.debug("openmano response: %s", mano_response.text )
368
369 return _print_verbose(mano_response, args.verbose)
370
371def vnf_list(args):
372 #print "vnf-list",args
373 if args.all:
374 tenant = "any"
375 else:
376 tenant = _get_tenant()
377 if args.name:
378 toshow = _get_item_uuid("vnfs", args.name, tenant)
379 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
380 else:
381 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
382 mano_response = requests.get(URLrequest)
383 logger.debug("openmano response: %s", mano_response.text )
384 content = mano_response.json()
tiernof1ba57e2017-09-07 12:23:19 +0200385 # print json.dumps(content, indent=4)
tierno7edb6752016-03-21 17:37:52 +0100386 if args.verbose==None:
387 args.verbose=0
388 result = 0 if mano_response.status_code==200 else mano_response.status_code
389 if mano_response.status_code == 200:
390 if not args.name:
391 if args.verbose >= 3:
392 print yaml.safe_dump(content, indent=4, default_flow_style=False)
393 return result
394 if len(content['vnfs']) == 0:
395 print "No VNFs were found."
tiernof1ba57e2017-09-07 12:23:19 +0200396 return 404 # HTTP_Not_Found
tierno7edb6752016-03-21 17:37:52 +0100397 for vnf in content['vnfs']:
tiernof1ba57e2017-09-07 12:23:19 +0200398 myoutput = "{:38} {:20}".format(vnf['uuid'], vnf['name'])
399 if vnf.get('osm_id') or args.verbose >= 1:
400 myoutput += " osm_id={:20}".format(vnf.get('osm_id'))
401 if args.verbose >= 1:
402 myoutput += " {}".format(vnf['created_at'])
403 print (myoutput)
404 if args.verbose >= 2:
405 print (" Description: {}".format(vnf['description']))
406 # print (" VNF descriptor file: {}".format(vnf['path']))
tierno7edb6752016-03-21 17:37:52 +0100407 else:
408 if args.verbose:
409 print yaml.safe_dump(content, indent=4, default_flow_style=False)
410 return result
411 vnf = content['vnf']
tiernof1ba57e2017-09-07 12:23:19 +0200412 print ("{:38} {:20} osm_id={:20} {:20}".format(vnf['uuid'], vnf['name'], vnf.get('osm_id'),
413 vnf['created_at']))
414 print (" Description: {}".format(vnf['description']))
415 # print " VNF descriptor file: %s" %vnf['path']
416 print (" VMs:")
tierno7edb6752016-03-21 17:37:52 +0100417 for vm in vnf['VNFC']:
tiernof1ba57e2017-09-07 12:23:19 +0200418 print (" {:20} osm_id={:20} {}".format(vm['name'], vm.get('osm_id'), vm['description']))
419 if len(vnf['nets']) > 0:
420 print (" Internal nets:")
tierno7edb6752016-03-21 17:37:52 +0100421 for net in vnf['nets']:
tiernof1ba57e2017-09-07 12:23:19 +0200422 print (" {:20} {}".format(net['name'], net['description']))
423 if len(vnf['external-connections']) > 0:
424 print (" External interfaces:")
tierno7edb6752016-03-21 17:37:52 +0100425 for interface in vnf['external-connections']:
tiernof1ba57e2017-09-07 12:23:19 +0200426 print (" {:20} {:20} {:20} {:14}".format(
427 interface['external_name'], interface['vm_name'],
428 interface['internal_name'],
429 interface.get('vpci') if interface.get('vpci') else ""))
tierno7edb6752016-03-21 17:37:52 +0100430 else:
431 print content['error']['description']
432 if args.verbose:
433 print yaml.safe_dump(content, indent=4, default_flow_style=False)
434 return result
435
436def vnf_delete(args):
437 #print "vnf-delete",args
438 if args.all:
439 tenant = "any"
440 else:
441 tenant = _get_tenant()
442 todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
443 if not args.force:
444 r = raw_input("Delete VNF %s (y/N)? " %(todelete))
445 if not (len(r)>0 and r[0].lower()=="y"):
446 return 0
447 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
448 mano_response = requests.delete(URLrequest)
449 logger.debug("openmano response: %s", mano_response.text )
450 result = 0 if mano_response.status_code==200 else mano_response.status_code
451 content = mano_response.json()
452 #print json.dumps(content, indent=4)
453 if mano_response.status_code == 200:
454 print content['result']
455 else:
456 print content['error']['description']
457 return result
458
459def scenario_create(args):
tiernof1ba57e2017-09-07 12:23:19 +0200460 # print "scenario-create",args
tierno7edb6752016-03-21 17:37:52 +0100461 tenant = _get_tenant()
462 headers_req = {'content-type': 'application/yaml'}
463 myscenario = _load_file_or_yaml(args.file)
tiernof1ba57e2017-09-07 12:23:19 +0200464 if "nsd:nsd-catalog" in myscenario or "nsd-catalog" in myscenario:
465 api_version = "/v3"
466 token = "nsd"
467 nsd_catalog = myscenario.get("nsd:nsd-catalog")
468 if not nsd_catalog:
469 nsd_catalog = myscenario.get("nsd-catalog")
470 nsds = nsd_catalog.get("nsd:nsd")
471 if not nsds:
472 nsds = nsd_catalog.get("nsd")
473 nsd = nsds[0]
474 else: # API<v3
475 api_version = ""
476 token = "scenarios"
477 if "scenario" in myscenario:
478 nsd = myscenario["scenario"]
479 else:
480 nsd = myscenario
481 # TODO modify for API v3
tierno7edb6752016-03-21 17:37:52 +0100482 if args.name:
tiernof1ba57e2017-09-07 12:23:19 +0200483 nsd['name'] = args.name
tierno7edb6752016-03-21 17:37:52 +0100484 if args.description:
tiernof1ba57e2017-09-07 12:23:19 +0200485 nsd['description'] = args.description
486 payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False,
487 encoding='utf-8', allow_unicode=True)
tierno7edb6752016-03-21 17:37:52 +0100488
tiernof1ba57e2017-09-07 12:23:19 +0200489 # print payload_req
490 URLrequest = "http://{host}:{port}/openmano{api}/{tenant}/{token}".format(
491 host=mano_host, port=mano_port, api=api_version, tenant=tenant, token=token)
tierno7edb6752016-03-21 17:37:52 +0100492 logger.debug("openmano request: %s", payload_req)
493 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
494 logger.debug("openmano response: %s", mano_response.text )
495 return _print_verbose(mano_response, args.verbose)
496
497def scenario_list(args):
498 #print "scenario-list",args
499 if args.all:
500 tenant = "any"
501 else:
502 tenant = _get_tenant()
503 if args.name:
504 toshow = _get_item_uuid("scenarios", args.name, tenant)
505 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
506 else:
507 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
508 mano_response = requests.get(URLrequest)
509 logger.debug("openmano response: %s", mano_response.text )
510 content = mano_response.json()
511 #print json.dumps(content, indent=4)
512 if args.verbose==None:
513 args.verbose=0
514
515 result = 0 if mano_response.status_code==200 else mano_response.status_code
516 if mano_response.status_code == 200:
517 if not args.name:
518 if args.verbose >= 3:
519 print yaml.safe_dump(content, indent=4, default_flow_style=False)
520 return result
521 if len(content['scenarios']) == 0:
522 print "No scenarios were found."
523 return 404 #HTTP_Not_Found
524 for scenario in content['scenarios']:
tiernof1ba57e2017-09-07 12:23:19 +0200525 myoutput = "{:38} {:20}".format(scenario['uuid'], scenario['name'])
526 if scenario.get('osm_id') or args.verbose >= 1:
527 myoutput += " osm_id={:20}".format(scenario.get('osm_id'))
528 if args.verbose >= 1:
529 myoutput += " {}".format(scenario['created_at'])
530 print (myoutput)
tierno7edb6752016-03-21 17:37:52 +0100531 if args.verbose >=2:
tiernof1ba57e2017-09-07 12:23:19 +0200532 print (" Description: {}".format(scenario['description']))
tierno7edb6752016-03-21 17:37:52 +0100533 else:
534 if args.verbose:
535 print yaml.safe_dump(content, indent=4, default_flow_style=False)
536 return result
537 scenario = content['scenario']
tiernof1ba57e2017-09-07 12:23:19 +0200538 print ("{:38} {:20} osm_id={:20} {:20}".format(scenario['uuid'], scenario['name'], scenario.get('osm_id'),
539 scenario['created_at']))
540 print (" Description: {}".format(scenario['description']))
541 print (" VNFs:")
tierno7edb6752016-03-21 17:37:52 +0100542 for vnf in scenario['vnfs']:
tiernof1ba57e2017-09-07 12:23:19 +0200543 print (" {:38} {:20} vnf_index={} {}".format(vnf['vnf_id'], vnf['name'], vnf.get("member_vnf_index"),
544 vnf['description']))
545 if len(scenario['nets']) > 0:
546 print (" nets:")
tierno7edb6752016-03-21 17:37:52 +0100547 for net in scenario['nets']:
tiernof1ba57e2017-09-07 12:23:19 +0200548 description = net['description']
549 if not description: # if description does not exist, description is "-". Valid for external and internal nets.
550 description = '-'
551 vim_id = ""
552 if net.get('vim_id'):
553 vim_id = " vim_id=" + net["vim_id"]
554 external = ""
555 if net["external"]:
556 external = " external"
557 print (" {:20} {:38} {:30}{}{}".format(net['name'], net['uuid'], description, vim_id, external))
tierno7edb6752016-03-21 17:37:52 +0100558 else:
tiernof1ba57e2017-09-07 12:23:19 +0200559 print (content['error']['description'])
tierno7edb6752016-03-21 17:37:52 +0100560 if args.verbose:
561 print yaml.safe_dump(content, indent=4, default_flow_style=False)
562 return result
563
564def scenario_delete(args):
565 #print "scenario-delete",args
566 if args.all:
567 tenant = "any"
568 else:
569 tenant = _get_tenant()
570 todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
571 if not args.force:
572 r = raw_input("Delete scenario %s (y/N)? " %(args.name))
573 if not (len(r)>0 and r[0].lower()=="y"):
574 return 0
575 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
576 mano_response = requests.delete(URLrequest)
577 logger.debug("openmano response: %s", mano_response.text )
578 result = 0 if mano_response.status_code==200 else mano_response.status_code
579 content = mano_response.json()
580 #print json.dumps(content, indent=4)
581 if mano_response.status_code == 200:
582 print content['result']
583 else:
584 print content['error']['description']
585 return result
586
587def scenario_deploy(args):
588 print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
589 print
590 args.file = None
591 args.netmap_use = None
592 args.netmap_create = None
tiernobe41e222016-09-02 15:16:13 +0200593 args.keypair = None
594 args.keypair_auto = None
tierno7edb6752016-03-21 17:37:52 +0100595 return instance_create(args)
596
597# #print "scenario-deploy",args
598# headers_req = {'content-type': 'application/json'}
599# action = {}
600# actionCmd="start"
601# if args.nostart:
602# actionCmd="reserve"
603# action[actionCmd] = {}
604# action[actionCmd]["instance_name"] = args.name
605# if args.datacenter != None:
606# action[actionCmd]["datacenter"] = args.datacenter
607# elif mano_datacenter != None:
608# action[actionCmd]["datacenter"] = mano_datacenter
609#
610# if args.description:
611# action[actionCmd]["description"] = args.description
612# payload_req = json.dumps(action, indent=4)
613# #print payload_req
614#
615# URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
616# logger.debug("openmano request: %s", payload_req)
617# mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
618# logger.debug("openmano response: %s", mano_response.text )
619# if args.verbose==None:
620# args.verbose=0
621#
622# result = 0 if mano_response.status_code==200 else mano_response.status_code
623# content = mano_response.json()
624# #print json.dumps(content, indent=4)
625# if args.verbose >= 3:
626# print yaml.safe_dump(content, indent=4, default_flow_style=False)
627# return result
628#
629# if mano_response.status_code == 200:
630# myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
631# if args.verbose >=1:
632# myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
633# if args.verbose >=2:
634# myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
635# print myoutput
636# print ""
637# print "To check the status, run the following command:"
638# print "openmano instance-scenario-list <instance_id>"
639# else:
640# print content['error']['description']
641# return result
642
643def scenario_verify(args):
644 #print "scenario-verify",args
tierno72a08d72017-05-25 13:12:30 +0200645 tenant = _get_tenant()
tierno7edb6752016-03-21 17:37:52 +0100646 headers_req = {'content-type': 'application/json'}
647 action = {}
648 action["verify"] = {}
649 action["verify"]["instance_name"] = "scen-verify-return5"
650 payload_req = json.dumps(action, indent=4)
651 #print payload_req
652
tierno72a08d72017-05-25 13:12:30 +0200653 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, tenant, args.scenario)
tierno7edb6752016-03-21 17:37:52 +0100654 logger.debug("openmano request: %s", payload_req)
655 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
656 logger.debug("openmano response: %s", mano_response.text )
657
658 result = 0 if mano_response.status_code==200 else mano_response.status_code
659 content = mano_response.json()
660 #print json.dumps(content, indent=4)
661 if mano_response.status_code == 200:
662 print content['result']
663 else:
664 print content['error']['description']
665 return result
666
667def instance_create(args):
668 tenant = _get_tenant()
669 headers_req = {'content-type': 'application/yaml'}
670 myInstance={"instance": {}, "schema_version": "0.1"}
671 if args.file:
672 instance_dict = _load_file_or_yaml(args.file)
673 if "instance" not in instance_dict:
674 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
675 else:
676 myInstance = instance_dict
677 if args.name:
678 myInstance["instance"]['name'] = args.name
679 if args.description:
680 myInstance["instance"]['description'] = args.description
681 if args.nostart:
682 myInstance["instance"]['action'] = "reserve"
683 #datacenter
684 datacenter = myInstance["instance"].get("datacenter")
685 if args.datacenter != None:
686 datacenter = args.datacenter
687 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
688 #scenario
689 scenario = myInstance["instance"].get("scenario")
690 if args.scenario != None:
691 scenario = args.scenario
692 if not scenario:
garciadeblased746032017-01-05 11:58:41 +0100693 print "you must provide a scenario in the file descriptor or with --scenario"
tierno7edb6752016-03-21 17:37:52 +0100694 return -1
695 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
696 if args.netmap_use:
697 if "networks" not in myInstance["instance"]:
698 myInstance["instance"]["networks"] = {}
699 for net in args.netmap_use:
700 net_comma_list = net.split(",")
701 for net_comma in net_comma_list:
702 net_tuple = net_comma.split("=")
703 if len(net_tuple) != 2:
704 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
705 return
706 net_scenario = net_tuple[0].strip()
707 net_datacenter = net_tuple[1].strip()
708 if net_scenario not in myInstance["instance"]["networks"]:
709 myInstance["instance"]["networks"][net_scenario] = {}
tiernobe41e222016-09-02 15:16:13 +0200710 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
711 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
712 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
tierno7edb6752016-03-21 17:37:52 +0100713 if args.netmap_create:
714 if "networks" not in myInstance["instance"]:
715 myInstance["instance"]["networks"] = {}
716 for net in args.netmap_create:
717 net_comma_list = net.split(",")
718 for net_comma in net_comma_list:
719 net_tuple = net_comma.split("=")
720 if len(net_tuple) == 1:
721 net_scenario = net_tuple[0].strip()
722 net_datacenter = None
723 elif len(net_tuple) == 2:
724 net_scenario = net_tuple[0].strip()
725 net_datacenter = net_tuple[1].strip()
726 else:
727 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
728 return
729 if net_scenario not in myInstance["instance"]["networks"]:
730 myInstance["instance"]["networks"][net_scenario] = {}
tiernobe41e222016-09-02 15:16:13 +0200731 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
732 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
733 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
tiernoa4e1a6e2016-08-31 14:19:40 +0200734 if args.keypair:
735 if "cloud-config" not in myInstance["instance"]:
736 myInstance["instance"]["cloud-config"] = {}
737 cloud_config = myInstance["instance"]["cloud-config"]
738 for key in args.keypair:
739 index = key.find(":")
740 if index<0:
741 if "key-pairs" not in cloud_config:
742 cloud_config["key-pairs"] = []
743 cloud_config["key-pairs"].append(key)
744 else:
745 user = key[:index]
746 key_ = key[index+1:]
747 key_list = key_.split(",")
748 if "users" not in cloud_config:
749 cloud_config["users"] = []
750 cloud_config["users"].append({"name": user, "key-pairs": key_list })
751 if args.keypair_auto:
752 try:
753 keys=[]
754 home = os.getenv("HOME")
755 user = os.getenv("USER")
756 files = os.listdir(home+'/.ssh')
757 for file in files:
758 if file[-4:] == ".pub":
759 with open(home+'/.ssh/'+file, 'r') as f:
760 keys.append(f.read())
761 if not keys:
762 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
763 return 1
764 except Exception as e:
765 print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
766 return 1
767
768 if "cloud-config" not in myInstance["instance"]:
769 myInstance["instance"]["cloud-config"] = {}
770 cloud_config = myInstance["instance"]["cloud-config"]
771 if "key-pairs" not in cloud_config:
772 cloud_config["key-pairs"] = []
773 if user:
774 if "users" not in cloud_config:
775 cloud_config["users"] = []
776 cloud_config["users"].append({"name": user, "key-pairs": keys })
tierno7edb6752016-03-21 17:37:52 +0100777
778 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
779 logger.debug("openmano request: %s", payload_req)
780 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
781 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
782 logger.debug("openmano response: %s", mano_response.text )
783 if args.verbose==None:
784 args.verbose=0
785
786 result = 0 if mano_response.status_code==200 else mano_response.status_code
787 content = mano_response.json()
788 #print json.dumps(content, indent=4)
789 if args.verbose >= 3:
790 print yaml.safe_dump(content, indent=4, default_flow_style=False)
791 return result
792
793 if mano_response.status_code == 200:
tiernoa15c4b92017-10-05 12:41:44 +0200794 myoutput = "{:38} {:20}".format(content['uuid'], content['name'])
tierno7edb6752016-03-21 17:37:52 +0100795 if args.verbose >=1:
tiernoa15c4b92017-10-05 12:41:44 +0200796 myoutput = "{} {:20}".format(myoutput, content['created_at'])
tierno7edb6752016-03-21 17:37:52 +0100797 if args.verbose >=2:
tiernoa15c4b92017-10-05 12:41:44 +0200798 myoutput = "{} {:30}".format(myoutput, content['description'])
tierno7edb6752016-03-21 17:37:52 +0100799 print myoutput
800 else:
801 print content['error']['description']
802 return result
803
804def instance_scenario_list(args):
805 #print "instance-scenario-list",args
806 if args.all:
807 tenant = "any"
808 else:
809 tenant = _get_tenant()
810 if args.name:
811 toshow = _get_item_uuid("instances", args.name, tenant)
812 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
813 else:
814 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
815 mano_response = requests.get(URLrequest)
816 logger.debug("openmano response: %s", mano_response.text )
817 content = mano_response.json()
818 #print json.dumps(content, indent=4)
819 if args.verbose==None:
820 args.verbose=0
821
822 result = 0 if mano_response.status_code==200 else mano_response.status_code
823 if mano_response.status_code == 200:
824 if not args.name:
825 if args.verbose >= 3:
826 print yaml.safe_dump(content, indent=4, default_flow_style=False)
827 return result
828 if len(content['instances']) == 0:
829 print "No scenario instances were found."
830 return result
831 for instance in content['instances']:
tiernoa15c4b92017-10-05 12:41:44 +0200832 myoutput = "{:38} {:20}".format(instance['uuid'], instance['name'])
tierno7edb6752016-03-21 17:37:52 +0100833 if args.verbose >=1:
tiernoa15c4b92017-10-05 12:41:44 +0200834 myoutput = "{} {:20}".format(myoutput, instance['created_at'])
tierno7edb6752016-03-21 17:37:52 +0100835 print myoutput
836 if args.verbose >=2:
837 print "Description: %s" %instance['description']
838 else:
839 if args.verbose:
840 print yaml.safe_dump(content, indent=4, default_flow_style=False)
841 return result
842 instance = content
tiernoa15c4b92017-10-05 12:41:44 +0200843 print ("{:38} {:20} {:20}".format(instance['uuid'],instance['name'],instance['created_at']))
844 print ("Description: %s" %instance['description'])
845 print ("Template scenario id: {}".format(instance['scenario_id']))
846 print ("Template scenario name: {}".format(instance['scenario_name']))
847 print ("---------------------------------------")
848 print ("VNF instances: {}".format(len(instance['vnfs'])))
tierno7edb6752016-03-21 17:37:52 +0100849 for vnf in instance['vnfs']:
850 #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 +0200851 print (" {:38} {:20} Template vnf id: {:38}".format(vnf['uuid'], vnf['vnf_name'], vnf['vnf_id']))
tierno7edb6752016-03-21 17:37:52 +0100852 if len(instance['nets'])>0:
853 print "---------------------------------------"
854 print "Internal nets:"
855 for net in instance['nets']:
tierno5c7c4732016-09-26 13:38:55 +0000856 if net['created']:
tiernoa15c4b92017-10-05 12:41:44 +0200857 print (" {:38} {:12} VIM ID: {}".format(net['uuid'], net['status'], net['vim_net_id']))
tierno7edb6752016-03-21 17:37:52 +0100858 print "---------------------------------------"
859 print "External nets:"
860 for net in instance['nets']:
tierno5c7c4732016-09-26 13:38:55 +0000861 if not net['created']:
tiernoa15c4b92017-10-05 12:41:44 +0200862 print (" {:38} {:12} VIM ID: {}".format(net['uuid'], net['status'], net['vim_net_id']))
863 print ("---------------------------------------")
864 print ("VM instances:")
tierno7edb6752016-03-21 17:37:52 +0100865 for vnf in instance['vnfs']:
866 for vm in vnf['vms']:
tiernoa15c4b92017-10-05 12:41:44 +0200867 print (" {:38} {:20} {:20} {:12} VIM ID: {}".format(vm['uuid'], vnf['vnf_name'], vm['name'],
868 vm['status'], vm['vim_vm_id']))
tierno7edb6752016-03-21 17:37:52 +0100869 else:
870 print content['error']['description']
871 if args.verbose:
872 print yaml.safe_dump(content, indent=4, default_flow_style=False)
873 return result
874
875def instance_scenario_status(args):
876 print "instance-scenario-status"
877 return 0
878
879def instance_scenario_delete(args):
880 if args.all:
881 tenant = "any"
882 else:
883 tenant = _get_tenant()
884 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
885 #print "instance-scenario-delete",args
886 if not args.force:
887 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
888 if not (len(r)>0 and r[0].lower()=="y"):
889 return
890 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
891 mano_response = requests.delete(URLrequest)
892 logger.debug("openmano response: %s", mano_response.text )
893 result = 0 if mano_response.status_code==200 else mano_response.status_code
894 content = mano_response.json()
895 #print json.dumps(content, indent=4)
896 if mano_response.status_code == 200:
897 print content['result']
898 else:
899 print content['error']['description']
900 return result
901
tierno868220c2017-09-26 00:11:05 +0200902def get_action(args):
903 if not args.all:
904 tenant = _get_tenant()
905 else:
906 tenant = "any"
907 if not args.instance:
908 instance_id = "any"
909 else:
910 instance_id =args.instance
911 action_id = ""
912 if args.id:
913 action_id = "/" + args.id
914 URLrequest = "http://{}:{}/openmano/{}/instances/{}/action{}".format(mano_host, mano_port, tenant, instance_id,
915 action_id)
916 mano_response = requests.get(URLrequest)
917 logger.debug("openmano response: %s", mano_response.text )
918 if args.verbose == None:
919 args.verbose = 0
920 if args.id != None:
921 args.verbose += 1
922 return _print_verbose(mano_response, args.verbose)
923
tierno7edb6752016-03-21 17:37:52 +0100924def instance_scenario_action(args):
925 #print "instance-scenario-action", args
926 tenant = _get_tenant()
927 toact = _get_item_uuid("instances", args.name, tenant=tenant)
928 action={}
tiernofc5f80b2018-05-29 16:00:43 +0200929 action[ args.action ] = yaml.safe_load(args.param)
tierno7edb6752016-03-21 17:37:52 +0100930 if args.vnf:
931 action["vnfs"] = args.vnf
932 if args.vm:
933 action["vms"] = args.vm
934
935 headers_req = {'content-type': 'application/json'}
936 payload_req = json.dumps(action, indent=4)
937 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
938 logger.debug("openmano request: %s", payload_req)
939 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
940 logger.debug("openmano response: %s", mano_response.text )
941 result = 0 if mano_response.status_code==200 else mano_response.status_code
942 content = mano_response.json()
tiernofc5f80b2018-05-29 16:00:43 +0200943 # print json.dumps(content, indent=4)
tierno7edb6752016-03-21 17:37:52 +0100944 if mano_response.status_code == 200:
945 if args.verbose:
946 print yaml.safe_dump(content, indent=4, default_flow_style=False)
947 return result
tiernofc5f80b2018-05-29 16:00:43 +0200948 if "instance_action_id" in content:
949 print("instance_action_id={}".format(content["instance_action_id"]))
950 else:
951 for uuid,c in content.iteritems():
952 print ("{:38} {:20} {:20}".format(uuid, c.get('name'), c.get('description')))
tierno7edb6752016-03-21 17:37:52 +0100953 else:
954 print content['error']['description']
955 return result
956
957
958def instance_vnf_list(args):
959 print "instance-vnf-list"
960 return 0
961
962def instance_vnf_status(args):
963 print "instance-vnf-status"
964 return 0
965
966def tenant_create(args):
967 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
968 tenant_dict={"name": args.name}
969 if args.description!=None:
970 tenant_dict["description"] = args.description
971 payload_req = json.dumps( {"tenant": tenant_dict })
972
973 #print payload_req
974
975 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
976 logger.debug("openmano request: %s", payload_req)
977 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
978 logger.debug("openmano response: %s", mano_response.text )
979 return _print_verbose(mano_response, args.verbose)
980
981def tenant_list(args):
982 #print "tenant-list",args
983 if args.name:
tierno392f2852016-05-13 12:28:55 +0200984 toshow = _get_item_uuid("tenants", args.name)
tierno7edb6752016-03-21 17:37:52 +0100985 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
986 else:
987 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
988 mano_response = requests.get(URLrequest)
989 logger.debug("openmano response: %s", mano_response.text )
990 if args.verbose==None:
991 args.verbose=0
992 if args.name!=None:
993 args.verbose += 1
994 return _print_verbose(mano_response, args.verbose)
995
996def tenant_delete(args):
997 #print "tenant-delete",args
998 todelete = _get_item_uuid("tenants", args.name)
999 if not args.force:
1000 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
1001 if not (len(r)>0 and r[0].lower()=="y"):
1002 return 0
1003 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
1004 mano_response = requests.delete(URLrequest)
1005 logger.debug("openmano response: %s", mano_response.text )
1006 result = 0 if mano_response.status_code==200 else mano_response.status_code
1007 content = mano_response.json()
1008 #print json.dumps(content, indent=4)
1009 if mano_response.status_code == 200:
1010 print content['result']
1011 else:
1012 print content['error']['description']
1013 return result
1014
1015def datacenter_attach(args):
1016 tenant = _get_tenant()
1017 datacenter = _get_datacenter(args.name)
1018 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1019
1020 datacenter_dict={}
1021 if args.vim_tenant_id != None:
1022 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1023 if args.vim_tenant_name != None:
1024 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1025 if args.user != None:
1026 datacenter_dict['vim_username'] = args.user
1027 if args.password != None:
1028 datacenter_dict['vim_password'] = args.password
tierno8008c3a2016-10-13 15:34:28 +00001029 if args.config!=None:
1030 datacenter_dict["config"] = _load_file_or_yaml(args.config)
gcalvinoc62cfa52017-10-05 18:21:25 +02001031
tierno7edb6752016-03-21 17:37:52 +01001032 payload_req = json.dumps( {"datacenter": datacenter_dict })
gcalvinoc62cfa52017-10-05 18:21:25 +02001033
tierno7edb6752016-03-21 17:37:52 +01001034 #print payload_req
1035
1036 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1037 logger.debug("openmano request: %s", payload_req)
1038 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1039 logger.debug("openmano response: %s", mano_response.text )
1040 result = _print_verbose(mano_response, args.verbose)
1041 #provide addional information if error
1042 if mano_response.status_code != 200:
1043 content = mano_response.json()
1044 if "already in use for 'name'" in content['error']['description'] and \
1045 "to database vim_tenants table" in content['error']['description']:
1046 print "Try to specify a different name with --vim-tenant-name"
1047 return result
1048
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001049
1050def datacenter_edit_vim_tenant(args):
1051 tenant = _get_tenant()
1052 datacenter = _get_datacenter(args.name)
1053 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1054
1055 if not (args.vim_tenant_id or args.vim_tenant_name or args.user or args.password or args.config):
1056 raise OpenmanoCLIError("Error. At least one parameter must be updated.")
1057
1058 datacenter_dict = {}
1059 if args.vim_tenant_id != None:
1060 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1061 if args.vim_tenant_name != None:
1062 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1063 if args.user != None:
1064 datacenter_dict['vim_username'] = args.user
1065 if args.password != None:
1066 datacenter_dict['vim_password'] = args.password
1067 if args.config != None:
1068 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1069 payload_req = json.dumps({"datacenter": datacenter_dict})
1070
1071 # print payload_req
1072
1073 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" % (mano_host, mano_port, tenant, datacenter)
1074 logger.debug("openmano request: %s", payload_req)
1075 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1076 logger.debug("openmano response: %s", mano_response.text)
1077 result = _print_verbose(mano_response, args.verbose)
1078
1079 return result
1080
tierno7edb6752016-03-21 17:37:52 +01001081def datacenter_detach(args):
1082 if args.all:
1083 tenant = "any"
1084 else:
1085 tenant = _get_tenant()
1086 datacenter = _get_datacenter(args.name, tenant)
1087 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1088 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1089 mano_response = requests.delete(URLrequest, headers=headers_req)
1090 logger.debug("openmano response: %s", mano_response.text )
1091 content = mano_response.json()
1092 #print json.dumps(content, indent=4)
1093 result = 0 if mano_response.status_code==200 else mano_response.status_code
1094 if mano_response.status_code == 200:
1095 print content['result']
1096 else:
1097 print content['error']['description']
1098 return result
1099
1100def datacenter_create(args):
1101 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1102 datacenter_dict={"name": args.name, "vim_url": args.url}
1103 if args.description!=None:
1104 datacenter_dict["description"] = args.description
1105 if args.type!=None:
1106 datacenter_dict["type"] = args.type
1107 if args.url!=None:
1108 datacenter_dict["vim_url_admin"] = args.url_admin
1109 if args.config!=None:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001110 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1111 if args.sdn_controller!=None:
1112 tenant = _get_tenant()
1113 sdn_controller = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1114 if not 'config' in datacenter_dict:
1115 datacenter_dict['config'] = {}
1116 datacenter_dict['config']['sdn-controller'] = sdn_controller
tierno7edb6752016-03-21 17:37:52 +01001117 payload_req = json.dumps( {"datacenter": datacenter_dict })
1118
1119 #print payload_req
1120
1121 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
1122 logger.debug("openmano request: %s", payload_req)
1123 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1124 logger.debug("openmano response: %s", mano_response.text )
1125 return _print_verbose(mano_response, args.verbose)
1126
1127def datacenter_delete(args):
1128 #print "datacenter-delete",args
1129 todelete = _get_item_uuid("datacenters", args.name, "any")
1130 if not args.force:
1131 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
1132 if not (len(r)>0 and r[0].lower()=="y"):
1133 return 0
1134 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
1135 mano_response = requests.delete(URLrequest)
1136 logger.debug("openmano response: %s", mano_response.text )
1137 result = 0 if mano_response.status_code==200 else mano_response.status_code
1138 content = mano_response.json()
1139 #print json.dumps(content, indent=4)
1140 if mano_response.status_code == 200:
1141 print content['result']
1142 else:
1143 print content['error']['description']
1144 return result
1145
tierno20df3bb2017-07-07 14:31:00 +02001146
tierno7edb6752016-03-21 17:37:52 +01001147def datacenter_list(args):
1148 #print "datacenter-list",args
1149 tenant='any' if args.all else _get_tenant()
1150
1151 if args.name:
1152 toshow = _get_item_uuid("datacenters", args.name, tenant)
1153 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
1154 else:
1155 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
1156 mano_response = requests.get(URLrequest)
1157 logger.debug("openmano response: %s", mano_response.text )
1158 if args.verbose==None:
1159 args.verbose=0
1160 if args.name!=None:
1161 args.verbose += 1
1162 return _print_verbose(mano_response, args.verbose)
1163
tierno20df3bb2017-07-07 14:31:00 +02001164
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001165def datacenter_sdn_port_mapping_set(args):
1166 tenant = _get_tenant()
1167 datacenter = _get_datacenter(args.name, tenant)
1168 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1169
1170 if not args.file:
1171 raise OpenmanoCLIError(
1172 "No yaml/json has been provided specifying the SDN port mapping")
tierno20df3bb2017-07-07 14:31:00 +02001173 sdn_port_mapping = _load_file_or_yaml(args.file)
1174 payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping})
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001175
tierno20df3bb2017-07-07 14:31:00 +02001176 # read
1177 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1178 mano_response = requests.get(URLrequest)
1179 logger.debug("openmano response: %s", mano_response.text)
1180 port_mapping = mano_response.json()
1181 if mano_response.status_code != 200:
1182 str(mano_response.json())
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001183 raise OpenmanoCLIError("openmano client error: {}".format(port_mapping['error']['description']))
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001184 if len(port_mapping["sdn_port_mapping"]["ports_mapping"]) > 0:
1185 if not args.force:
1186 r = raw_input("Datacenter %s already contains a port mapping. Overwrite? (y/N)? " % (datacenter))
1187 if not (len(r) > 0 and r[0].lower() == "y"):
1188 return 0
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001189
tierno20df3bb2017-07-07 14:31:00 +02001190 # clear
1191 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1192 mano_response = requests.delete(URLrequest)
1193 logger.debug("openmano response: %s", mano_response.text)
1194 if mano_response.status_code != 200:
1195 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001196
tierno20df3bb2017-07-07 14:31:00 +02001197 # set
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001198 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1199 logger.debug("openmano request: %s", payload_req)
1200 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1201 logger.debug("openmano response: %s", mano_response.text)
tierno20df3bb2017-07-07 14:31:00 +02001202 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001203
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001204
1205def datacenter_sdn_port_mapping_list(args):
1206 tenant = _get_tenant()
1207 datacenter = _get_datacenter(args.name, tenant)
1208
1209 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1210 mano_response = requests.get(URLrequest)
1211 logger.debug("openmano response: %s", mano_response.text)
1212
tierno20df3bb2017-07-07 14:31:00 +02001213 return _print_verbose(mano_response, 4)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001214
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001215
1216def datacenter_sdn_port_mapping_clear(args):
1217 tenant = _get_tenant()
1218 datacenter = _get_datacenter(args.name, tenant)
1219
1220 if not args.force:
1221 r = raw_input("Clean SDN port mapping for datacenter %s (y/N)? " %(datacenter))
tierno20df3bb2017-07-07 14:31:00 +02001222 if not (len(r) > 0 and r[0].lower() == "y"):
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001223 return 0
1224
1225 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1226 mano_response = requests.delete(URLrequest)
1227 logger.debug("openmano response: %s", mano_response.text)
1228
tierno20df3bb2017-07-07 14:31:00 +02001229 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001230
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001231
1232def sdn_controller_create(args):
1233 tenant = _get_tenant()
1234 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1235
tierno8fe7a492017-07-11 13:50:04 +02001236 error_msg=[]
1237 if not args.ip: error_msg.append("'ip'")
1238 if not args.port: error_msg.append("'port'")
1239 if not args.dpid: error_msg.append("'dpid'")
1240 if not args.type: error_msg.append("'type'")
1241 if error_msg:
1242 raise OpenmanoCLIError("The following arguments are required: " + ",".join(error_msg))
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001243
1244 controller_dict = {}
1245 controller_dict['name'] = args.name
1246 controller_dict['ip'] = args.ip
1247 controller_dict['port'] = int(args.port)
1248 controller_dict['dpid'] = args.dpid
1249 controller_dict['type'] = args.type
1250 if args.description != None:
1251 controller_dict['description'] = args.description
1252 if args.user != None:
1253 controller_dict['user'] = args.user
1254 if args.password != None:
1255 controller_dict['password'] = args.password
1256
1257 payload_req = json.dumps({"sdn_controller": controller_dict})
1258
1259 # print payload_req
1260
1261 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" % (mano_host, mano_port, tenant)
1262 logger.debug("openmano request: %s", payload_req)
1263 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1264 logger.debug("openmano response: %s", mano_response.text)
1265 result = _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001266 return result
1267
tierno20df3bb2017-07-07 14:31:00 +02001268
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001269def sdn_controller_edit(args):
1270 tenant = _get_tenant()
1271 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1272 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1273
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001274 controller_dict = {}
tierno20df3bb2017-07-07 14:31:00 +02001275 if args.new_name:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001276 controller_dict['name'] = args.new_name
tierno20df3bb2017-07-07 14:31:00 +02001277 if args.ip:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001278 controller_dict['ip'] = args.ip
tierno20df3bb2017-07-07 14:31:00 +02001279 if args.port:
Pablo Montes Morenob12711f2017-04-06 11:54:34 +02001280 controller_dict['port'] = int(args.port)
tierno20df3bb2017-07-07 14:31:00 +02001281 if args.dpid:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001282 controller_dict['dpid'] = args.dpid
tierno20df3bb2017-07-07 14:31:00 +02001283 if args.type:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001284 controller_dict['type'] = args.type
tierno20df3bb2017-07-07 14:31:00 +02001285 if args.description:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001286 controller_dict['description'] = args.description
tierno20df3bb2017-07-07 14:31:00 +02001287 if args.user:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001288 controller_dict['user'] = args.user
tierno20df3bb2017-07-07 14:31:00 +02001289 if args.password:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001290 controller_dict['password'] = args.password
1291
tierno20df3bb2017-07-07 14:31:00 +02001292 if not controller_dict:
1293 raise OpenmanoCLIError("At least one parameter must be edited")
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001294
tierno20df3bb2017-07-07 14:31:00 +02001295 if not args.force:
1296 r = raw_input("Update SDN controller {} (y/N)? ".format(args.name))
1297 if not (len(r) > 0 and r[0].lower() == "y"):
1298 return 0
1299
1300 payload_req = json.dumps({"sdn_controller": controller_dict})
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001301 # print payload_req
1302
1303 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1304 logger.debug("openmano request: %s", payload_req)
1305 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1306 logger.debug("openmano response: %s", mano_response.text)
1307 result = _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001308 return result
1309
tierno20df3bb2017-07-07 14:31:00 +02001310
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001311def sdn_controller_list(args):
1312 tenant = _get_tenant()
1313 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1314
1315 if args.name:
1316 toshow = _get_item_uuid("sdn_controllers", args.name, tenant)
1317 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" %(mano_host, mano_port, tenant, toshow)
1318 else:
1319 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" %(mano_host, mano_port, tenant)
1320 #print URLrequest
1321 mano_response = requests.get(URLrequest)
1322 logger.debug("openmano response: %s", mano_response.text )
1323 if args.verbose==None:
1324 args.verbose=0
1325 if args.name!=None:
1326 args.verbose += 1
1327
tierno20df3bb2017-07-07 14:31:00 +02001328 # json.dumps(mano_response.json(), indent=4)
1329 return _print_verbose(mano_response, args.verbose)
1330
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001331
1332def sdn_controller_delete(args):
1333 tenant = _get_tenant()
1334 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1335
1336 if not args.force:
1337 r = raw_input("Delete SDN controller %s (y/N)? " % (args.name))
1338 if not (len(r) > 0 and r[0].lower() == "y"):
1339 return 0
1340
1341 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1342 mano_response = requests.delete(URLrequest)
1343 logger.debug("openmano response: %s", mano_response.text)
tierno20df3bb2017-07-07 14:31:00 +02001344 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001345
tierno7edb6752016-03-21 17:37:52 +01001346def vim_action(args):
1347 #print "datacenter-net-action",args
1348 tenant = _get_tenant()
1349 datacenter = _get_datacenter(args.datacenter, tenant)
1350 if args.verbose==None:
1351 args.verbose=0
1352 if args.action=="list":
1353 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1354 if args.name!=None:
1355 args.verbose += 1
1356 URLrequest += "/" + args.name
1357 mano_response = requests.get(URLrequest)
1358 logger.debug("openmano response: %s", mano_response.text )
1359 return _print_verbose(mano_response, args.verbose)
1360 elif args.action=="delete":
1361 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1362 mano_response = requests.delete(URLrequest)
1363 logger.debug("openmano response: %s", mano_response.text )
1364 result = 0 if mano_response.status_code==200 else mano_response.status_code
1365 content = mano_response.json()
1366 #print json.dumps(content, indent=4)
1367 if mano_response.status_code == 200:
1368 print content['result']
1369 else:
1370 print content['error']['description']
1371 return result
1372 elif args.action=="create":
1373 headers_req = {'content-type': 'application/yaml'}
1374 if args.file:
1375 create_dict = _load_file_or_yaml(args.file)
1376 if args.item not in create_dict:
1377 create_dict = {args.item: create_dict}
1378 else:
1379 create_dict = {args.item:{}}
1380 if args.name:
1381 create_dict[args.item]['name'] = args.name
1382 #if args.description:
1383 # create_dict[args.item]['description'] = args.description
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001384 if args.item=="network":
tierno7edb6752016-03-21 17:37:52 +01001385 if args.bind_net:
1386 create_dict[args.item]['bind_net'] = args.bind_net
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001387 if args.type:
1388 create_dict[args.item]['type'] = args.type
tierno7edb6752016-03-21 17:37:52 +01001389 if args.shared:
1390 create_dict[args.item]['shared'] = args.shared
1391 if "name" not in create_dict[args.item]:
1392 print "You must provide a name in the descriptor file or with the --name option"
1393 return
1394 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1395 logger.debug("openmano request: %s", payload_req)
tierno72a08d72017-05-25 13:12:30 +02001396 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
tierno7edb6752016-03-21 17:37:52 +01001397 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1398 logger.debug("openmano response: %s", mano_response.text )
1399 if args.verbose==None:
1400 args.verbose=0
1401 return _print_verbose(mano_response, args.verbose)
1402
tierno20df3bb2017-07-07 14:31:00 +02001403
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001404def _get_items(item, item_name_id=None, datacenter=None, tenant=None):
1405 URLrequest = "http://%s:%s/openmano" %(mano_host, mano_port)
1406 if tenant:
1407 URLrequest += "/" + tenant
1408 if datacenter:
1409 URLrequest += "/vim/" + datacenter
1410 if item:
1411 URLrequest += "/" + item +"s"
1412 if item_name_id:
1413 URLrequest += "/" + item_name_id
1414 mano_response = requests.get(URLrequest)
1415 logger.debug("openmano response: %s", mano_response.text )
1416
1417 return mano_response
1418
tierno20df3bb2017-07-07 14:31:00 +02001419
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001420def vim_net_sdn_attach(args):
1421 #Verify the network exists in the vim
1422 tenant = _get_tenant()
1423 datacenter = _get_datacenter(args.datacenter, tenant)
1424 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1425 content = yaml.load(result.content)
1426 if 'networks' in content:
1427 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1428 if 'error' in content:
1429 raise OpenmanoCLIError(yaml.safe_dump(content))
1430 network_uuid = content['network']['id']
1431
1432 #Make call to attach the dataplane port to the SND network associated to the vim network
1433 headers_req = {'content-type': 'application/yaml'}
1434 payload_req = {'port': args.port}
1435 if args.vlan:
1436 payload_req['vlan'] = int(args.vlan)
1437 if args.mac:
1438 payload_req['mac'] = args.mac
1439
1440 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/attach" % (mano_host, mano_port, tenant, datacenter, network_uuid)
1441 logger.debug("openmano request: %s", payload_req)
1442 mano_response = requests.post(URLrequest, headers=headers_req, data=json.dumps(payload_req))
1443 logger.debug("openmano response: %s", mano_response.text)
1444 result = _print_verbose(mano_response, args.verbose)
tierno20df3bb2017-07-07 14:31:00 +02001445 return result
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001446
1447
1448def vim_net_sdn_detach(args):
1449 if not args.all and not args.id:
1450 print "--all or --id must be used"
1451 return 1
1452
1453 # Verify the network exists in the vim
1454 tenant = _get_tenant()
1455 datacenter = _get_datacenter(args.datacenter, tenant)
1456 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1457 content = yaml.load(result.content)
1458 if 'networks' in content:
1459 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1460 if 'error' in content:
1461 raise OpenmanoCLIError(yaml.safe_dump(content))
1462 network_uuid = content['network']['id']
1463
1464 if not args.force:
1465 r = raw_input("Confirm action' (y/N)? ")
1466 if len(r) == 0 or r[0].lower() != "y":
1467 return 0
1468
1469 if args.id:
1470 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach/%s" % (
1471 mano_host, mano_port, tenant, datacenter, network_uuid, args.id)
1472 else:
1473 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach" % (
1474 mano_host, mano_port, tenant, datacenter, network_uuid)
1475 mano_response = requests.delete(URLrequest)
1476 logger.debug("openmano response: %s", mano_response.text)
1477 result = _print_verbose(mano_response, args.verbose)
tierno20df3bb2017-07-07 14:31:00 +02001478 return result
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001479
tierno7edb6752016-03-21 17:37:52 +01001480
1481def datacenter_net_action(args):
1482 if args.action == "net-update":
tierno5acf7202016-08-29 14:28:13 +02001483 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
tierno7edb6752016-03-21 17:37:52 +01001484 print
1485 args.action = "netmap-delete"
1486 args.netmap = None
1487 args.all = True
1488 r = datacenter_netmap_action(args)
1489 if r == 0:
1490 args.force = True
tierno5acf7202016-08-29 14:28:13 +02001491 args.action = "netmap-import"
tierno7edb6752016-03-21 17:37:52 +01001492 r = datacenter_netmap_action(args)
1493 return r
1494
1495 if args.action == "net-edit":
1496 args.netmap = args.net
1497 args.name = None
1498 elif args.action == "net-list":
1499 args.netmap = None
1500 elif args.action == "net-delete":
1501 args.netmap = args.net
1502 args.all = False
1503
1504 args.action = "netmap" + args.action[3:]
1505 args.vim_name=None
1506 args.vim_id=None
1507 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1508 print
1509 return datacenter_netmap_action(args)
1510
1511def datacenter_netmap_action(args):
1512 tenant = _get_tenant()
1513 datacenter = _get_datacenter(args.datacenter, tenant)
1514 #print "datacenter_netmap_action",args
1515 payload_req = None
1516 if args.verbose==None:
1517 args.verbose=0
1518 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1519 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1520
1521 if args.action=="netmap-list":
1522 if args.netmap:
1523 URLrequest += "/" + args.netmap
1524 args.verbose += 1
1525 mano_response = requests.get(URLrequest)
1526
1527 elif args.action=="netmap-delete":
1528 if args.netmap and args.all:
1529 print "you can not use a netmap name and the option --all at the same time"
1530 return 1
1531 if args.netmap:
1532 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1533 URLrequest += "/" + args.netmap
1534 elif args.all:
1535 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1536 else:
tiernoae4a8d12016-07-08 12:30:39 +02001537 print "you must specify a netmap name or the option --all"
tierno7edb6752016-03-21 17:37:52 +01001538 return 1
1539 if not args.force:
1540 r = raw_input(force_text)
1541 if len(r)>0 and r[0].lower()=="y":
1542 pass
1543 else:
1544 return 0
1545 mano_response = requests.delete(URLrequest, headers=headers_req)
tierno5acf7202016-08-29 14:28:13 +02001546 elif args.action=="netmap-import":
tierno7edb6752016-03-21 17:37:52 +01001547 if not args.force:
1548 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1549 if len(r)>0 and r[0].lower()=="y":
1550 pass
1551 else:
1552 return 0
1553 URLrequest += "/upload"
1554 mano_response = requests.post(URLrequest, headers=headers_req)
1555 elif args.action=="netmap-edit" or args.action=="netmap-create":
1556 if args.file:
1557 payload = _load_file_or_yaml(args.file)
1558 else:
1559 payload = {}
1560 if "netmap" not in payload:
1561 payload = {"netmap": payload}
1562 if args.name:
1563 payload["netmap"]["name"] = args.name
1564 if args.vim_id:
1565 payload["netmap"]["vim_id"] = args.vim_id
1566 if args.action=="netmap-create" and args.vim_name:
1567 payload["netmap"]["vim_name"] = args.vim_name
1568 payload_req = json.dumps(payload)
1569 logger.debug("openmano request: %s", payload_req)
1570
1571 if args.action=="netmap-edit" and not args.force:
1572 if len(payload["netmap"]) == 0:
1573 print "You must supply some parameter to edit"
1574 return 1
1575 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1576 if len(r)>0 and r[0].lower()=="y":
1577 pass
1578 else:
1579 return 0
1580 URLrequest += "/" + args.netmap
1581 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1582 else: #netmap-create
1583 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1584 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1585 return 1
1586 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1587
1588 logger.debug("openmano response: %s", mano_response.text )
1589 return _print_verbose(mano_response, args.verbose)
1590
tierno20df3bb2017-07-07 14:31:00 +02001591
tierno7edb6752016-03-21 17:37:52 +01001592def element_edit(args):
1593 element = _get_item_uuid(args.element, args.name)
1594 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1595 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1596 payload=_load_file_or_yaml(args.file)
1597 if args.element[:-1] not in payload:
1598 payload = {args.element[:-1]: payload }
1599 payload_req = json.dumps(payload)
1600
1601 #print payload_req
1602 if not args.force or (args.name==None and args.filer==None):
1603 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1604 if len(r)>0 and r[0].lower()=="y":
1605 pass
1606 else:
1607 return 0
1608 logger.debug("openmano request: %s", payload_req)
1609 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1610 logger.debug("openmano response: %s", mano_response.text )
1611 if args.verbose==None:
1612 args.verbose=0
1613 if args.name!=None:
1614 args.verbose += 1
1615 return _print_verbose(mano_response, args.verbose)
1616
1617
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001618def datacenter_edit(args):
1619 tenant = _get_tenant()
1620 element = _get_item_uuid('datacenters', args.name, tenant)
1621 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1622 URLrequest = "http://%s:%s/openmano/datacenters/%s" % (mano_host, mano_port, element)
1623
1624 has_arguments = False
1625 if args.file != None:
1626 has_arguments = True
1627 payload = _load_file_or_yaml(args.file)
1628 else:
1629 payload = {}
1630
1631 if args.sdn_controller != None:
1632 has_arguments = True
1633 if not 'config' in payload:
1634 payload['config'] = {}
1635 if not 'sdn-controller' in payload['config']:
1636 payload['config']['sdn-controller'] = {}
1637 if args.sdn_controller == 'null':
1638 payload['config']['sdn-controller'] = None
1639 else:
1640 payload['config']['sdn-controller'] = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1641
1642 if not has_arguments:
1643 raise OpenmanoCLIError("At least one argument must be provided to modify the datacenter")
1644
1645 if 'datacenter' not in payload:
1646 payload = {'datacenter': payload}
1647 payload_req = json.dumps(payload)
1648
1649 # print payload_req
1650 if not args.force or (args.name == None and args.filer == None):
1651 r = raw_input(" Edit datacenter " + args.name + " (y/N)? ")
1652 if len(r) > 0 and r[0].lower() == "y":
1653 pass
1654 else:
1655 return 0
1656 logger.debug("openmano request: %s", payload_req)
1657 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1658 logger.debug("openmano response: %s", mano_response.text)
1659 if args.verbose == None:
1660 args.verbose = 0
1661 if args.name != None:
1662 args.verbose += 1
1663 return _print_verbose(mano_response, args.verbose)
1664
tierno20df3bb2017-07-07 14:31:00 +02001665
tierno6ddeded2017-05-16 15:40:26 +02001666def version(args):
1667 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1668 URLrequest = "http://%s:%s/openmano/version" % (mano_host, mano_port)
1669
1670 mano_response = requests.get(URLrequest, headers=headers_req)
1671 logger.debug("openmano response: %s", mano_response.text)
1672 print mano_response.text
1673
1674
tierno7edb6752016-03-21 17:37:52 +01001675global mano_host
1676global mano_port
1677global mano_tenant
1678
1679if __name__=="__main__":
1680
1681 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1682 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1683 mano_port = os.getenv('OPENMANO_PORT',"9090")
1684 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1685
1686 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
tierno6ddeded2017-05-16 15:40:26 +02001687 main_parser.add_argument('--version', action='version', help="get version of this client",
1688 version='%(prog)s client version ' + __version__ +
1689 " (Note: use '%(prog)s version' to get server version)")
1690
tierno7edb6752016-03-21 17:37:52 +01001691 subparsers = main_parser.add_subparsers(help='commands')
1692
tierno7edb6752016-03-21 17:37:52 +01001693 parent_parser = argparse.ArgumentParser(add_help=False)
1694 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1695 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1696
garciadeblas0e9fd832016-07-08 15:20:18 +02001697 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1698 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1699 config_parser.set_defaults(func=config)
1700
tierno6ddeded2017-05-16 15:40:26 +02001701 version_parser = subparsers.add_parser('version', parents=[parent_parser], help="get server version")
1702 version_parser.set_defaults(func=version)
1703
tierno7edb6752016-03-21 17:37:52 +01001704 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1705 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1706 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1707 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1708 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
garciadeblas14480452017-01-10 13:08:07 +01001709 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1710 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
tierno7edb6752016-03-21 17:37:52 +01001711 vnf_create_parser.set_defaults(func=vnf_create)
1712
1713 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1714 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1715 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1716 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1717 vnf_list_parser.set_defaults(func=vnf_list)
1718
1719 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1720 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1721 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1722 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1723 vnf_delete_parser.set_defaults(func=vnf_delete)
1724
1725 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1726 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1727 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1728 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1729 scenario_create_parser.set_defaults(func=scenario_create)
1730
1731 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1732 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1733 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1734 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1735 scenario_list_parser.set_defaults(func=scenario_list)
1736
1737 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1738 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1739 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1740 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1741 scenario_delete_parser.set_defaults(func=scenario_delete)
1742
1743 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1744 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1745 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1746 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1747 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1748 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1749 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1750
1751 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1752 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1753 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1754 scenario_deploy_parser.set_defaults(func=scenario_verify)
1755
1756 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1757 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1758 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1759 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1760 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1761 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1762 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")
1763 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 +02001764 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")
1765 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 +01001766 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1767 instance_scenario_create_parser.set_defaults(func=instance_create)
1768
1769 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1770 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1771 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1772 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1773
1774 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)")
1775 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1776 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1777 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1778 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1779
1780 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1781 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1782 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
tiernofc5f80b2018-05-29 16:00:43 +02001783 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console", "add_public_key","vdu-scaling"],\
tierno7edb6752016-03-21 17:37:52 +01001784 help="action to send")
tiernofc5f80b2018-05-29 16:00:43 +02001785 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 +01001786 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1787 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1788 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1789
tierno868220c2017-09-26 00:11:05 +02001790 action_parser = subparsers.add_parser('action-list', parents=[parent_parser], help="get action over an instance status")
1791 action_parser.add_argument("id", nargs='?', action="store", help="action id")
1792 action_parser.add_argument("--instance", action="store", help="fitler by this instance_id")
1793 action_parser.add_argument("--all", action="store", help="Not filter by tenant")
1794 action_parser.set_defaults(func=get_action)
1795
tierno7edb6752016-03-21 17:37:52 +01001796 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1797 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1798 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1799
1800 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1801 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1802 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1803 tenant_create_parser.set_defaults(func=tenant_create)
1804
1805 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1806 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1807 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1808 tenant_delete_parser.set_defaults(func=tenant_delete)
1809
1810 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1811 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1812 tenant_list_parser.set_defaults(func=tenant_list)
1813
tierno161c24b2017-05-16 15:45:56 +02001814 element_edit_parser = subparsers.add_parser('tenant-edit', parents=[parent_parser], help="edits one tenant")
1815 element_edit_parser.add_argument("name", help="name or uuid of the tenant")
1816 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1817 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1818 element_edit_parser.set_defaults(func=element_edit, element='tenants')
tierno7edb6752016-03-21 17:37:52 +01001819
1820 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1821 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1822 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1823 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1824 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1825 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1826 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001827 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 +01001828 datacenter_create_parser.set_defaults(func=datacenter_create)
1829
1830 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1831 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1832 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1833 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1834
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001835 datacenter_edit_parser = subparsers.add_parser('datacenter-edit', parents=[parent_parser], help="Edit datacenter")
1836 datacenter_edit_parser.add_argument("name", help="name or uuid of the datacenter")
1837 datacenter_edit_parser.add_argument("--file", help="json/yaml text or file with the changes").completer = FilesCompleter
1838 datacenter_edit_parser.add_argument("--sdn-controller", action="store",
1839 help="Name or uuid of the SDN controller to be used. Specify 'null' to clear entry", dest='sdn_controller')
1840 datacenter_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1841 datacenter_edit_parser.set_defaults(func=datacenter_edit)
1842
tierno7edb6752016-03-21 17:37:52 +01001843 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1844 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1845 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1846 datacenter_list_parser.set_defaults(func=datacenter_list)
1847
1848 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1849 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1850 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1851 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1852 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1853 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
tierno8008c3a2016-10-13 15:34:28 +00001854 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
tierno7edb6752016-03-21 17:37:52 +01001855 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1856
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001857 datacenter_edit_vim_tenant_parser = subparsers.add_parser('datacenter-edit-vim-tenant', parents=[parent_parser],
1858 help="Edit the association of a datacenter to the operating tenant")
1859 datacenter_edit_vim_tenant_parser.add_argument("name", help="name or uuid of the datacenter")
1860 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-id', action='store',
1861 help="specify a datacenter tenant to use. A new one is created by default")
1862 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1863 datacenter_edit_vim_tenant_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1864 datacenter_edit_vim_tenant_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1865 datacenter_edit_vim_tenant_parser.add_argument("--config", action="store",
1866 help="aditional configuration in json/yaml format")
1867 datacenter_edit_vim_tenant_parser.set_defaults(func=datacenter_edit_vim_tenant)
1868
tierno7edb6752016-03-21 17:37:52 +01001869 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1870 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1871 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1872 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1873
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001874 #=======================datacenter_sdn_port_mapping_xxx section=======================
1875 #datacenter_sdn_port_mapping_set
1876 datacenter_sdn_port_mapping_set_parser = subparsers.add_parser('datacenter-sdn-port-mapping-set',
1877 parents=[parent_parser],
1878 help="Load a file with the mapping of physical ports "
1879 "and the ports of the dataplaneswitch controlled "
1880 "by a datacenter")
1881 datacenter_sdn_port_mapping_set_parser.add_argument("name", action="store", help="specifies the datacenter")
1882 datacenter_sdn_port_mapping_set_parser.add_argument("file",
1883 help="json/yaml text or file with the port mapping").completer = FilesCompleter
1884 datacenter_sdn_port_mapping_set_parser.add_argument("-f", "--force", action="store_true",
1885 help="forces overwriting without asking")
1886 datacenter_sdn_port_mapping_set_parser.set_defaults(func=datacenter_sdn_port_mapping_set)
1887
1888 #datacenter_sdn_port_mapping_list
1889 datacenter_sdn_port_mapping_list_parser = subparsers.add_parser('datacenter-sdn-port-mapping-list',
1890 parents=[parent_parser],
1891 help="Show the SDN port mapping in a datacenter")
1892 datacenter_sdn_port_mapping_list_parser.add_argument("name", action="store", help="specifies the datacenter")
1893 datacenter_sdn_port_mapping_list_parser.set_defaults(func=datacenter_sdn_port_mapping_list)
1894
1895 # datacenter_sdn_port_mapping_clear
1896 datacenter_sdn_port_mapping_clear_parser = subparsers.add_parser('datacenter-sdn-port-mapping-clear',
1897 parents=[parent_parser],
1898 help="Clean the the SDN port mapping in a datacenter")
1899 datacenter_sdn_port_mapping_clear_parser.add_argument("name", action="store",
1900 help="specifies the datacenter")
1901 datacenter_sdn_port_mapping_clear_parser.add_argument("-f", "--force", action="store_true",
1902 help="forces clearing without asking")
1903 datacenter_sdn_port_mapping_clear_parser.set_defaults(func=datacenter_sdn_port_mapping_clear)
1904 # =======================
1905
1906 # =======================sdn_controller_xxx section=======================
1907 # sdn_controller_create
1908 sdn_controller_create_parser = subparsers.add_parser('sdn-controller-create', parents=[parent_parser],
1909 help="Creates an SDN controller entity within RO")
1910 sdn_controller_create_parser.add_argument("name", help="name of the SDN controller")
1911 sdn_controller_create_parser.add_argument("--description", action="store", help="description of the SDN controller")
1912 sdn_controller_create_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1913 sdn_controller_create_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1914 sdn_controller_create_parser.add_argument("--dpid", action="store",
1915 help="DPID of the dataplane switch controlled by this SDN controller")
1916 sdn_controller_create_parser.add_argument("--type", action="store",
1917 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1918 sdn_controller_create_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1919 sdn_controller_create_parser.add_argument("--passwd", action="store", dest='password',
1920 help="password credentials for the SDN controller")
1921 sdn_controller_create_parser.set_defaults(func=sdn_controller_create)
1922
1923 # sdn_controller_edit
1924 sdn_controller_edit_parser = subparsers.add_parser('sdn-controller-edit', parents=[parent_parser],
1925 help="Update one or more options of a SDN controller")
1926 sdn_controller_edit_parser.add_argument("name", help="name or uuid of the SDN controller", )
1927 sdn_controller_edit_parser.add_argument("--name", action="store", help="Update the name of the SDN controller",
1928 dest='new_name')
1929 sdn_controller_edit_parser.add_argument("--description", action="store", help="description of the SDN controller")
1930 sdn_controller_edit_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1931 sdn_controller_edit_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1932 sdn_controller_edit_parser.add_argument("--dpid", action="store",
1933 help="DPID of the dataplane switch controlled by this SDN controller")
1934 sdn_controller_edit_parser.add_argument("--type", action="store",
1935 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1936 sdn_controller_edit_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1937 sdn_controller_edit_parser.add_argument("--password", action="store",
1938 help="password credentials for the SDN controller", dest='password')
1939 sdn_controller_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1940 #TODO: include option --file
1941 sdn_controller_edit_parser.set_defaults(func=sdn_controller_edit)
1942
1943 #sdn_controller_list
1944 sdn_controller_list_parser = subparsers.add_parser('sdn-controller-list',
1945 parents=[parent_parser],
1946 help="List the SDN controllers")
1947 sdn_controller_list_parser.add_argument("name", nargs='?', help="name or uuid of the SDN controller")
1948 sdn_controller_list_parser.set_defaults(func=sdn_controller_list)
1949
1950 # sdn_controller_delete
1951 sdn_controller_delete_parser = subparsers.add_parser('sdn-controller-delete',
1952 parents=[parent_parser],
1953 help="Delete the the SDN controller")
1954 sdn_controller_delete_parser.add_argument("name", help="name or uuid of the SDN controller")
1955 sdn_controller_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1956 sdn_controller_delete_parser.set_defaults(func=sdn_controller_delete)
1957 # =======================
tierno7edb6752016-03-21 17:37:52 +01001958
1959 action_dict={'net-update': 'retrieves external networks from datacenter',
1960 'net-edit': 'edits an external network',
1961 'net-delete': 'deletes an external network',
1962 'net-list': 'lists external networks from a datacenter'
1963 }
1964 for item in action_dict:
1965 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1966 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1967 if item=='net-edit' or item=='net-delete':
1968 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1969 if item=='net-edit':
1970 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1971 if item!='net-list':
1972 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1973 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1974
1975
tierno5acf7202016-08-29 14:28:13 +02001976 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
tierno7edb6752016-03-21 17:37:52 +01001977 'netmap-create': 'create a new network senario netmap',
1978 'netmap-edit': 'edit name of a network senario netmap',
1979 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1980 'netmap-list': 'list/show network scenario netmaps'
1981 }
1982 for item in action_dict:
1983 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1984 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1985 #if item=='net-add':
1986 # datacenter_action_parser.add_argument("net", help="name of the network")
1987 if item=='netmap-delete':
1988 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1989 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1990 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1991 if item=='netmap-edit':
1992 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1993 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1994 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1995 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1996 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1997 if item=='netmap-list':
1998 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1999 if item=='netmap-create':
2000 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
2001 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
2002 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
2003 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
tierno5acf7202016-08-29 14:28:13 +02002004 if item=='netmap-import':
tierno7edb6752016-03-21 17:37:52 +01002005 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
2006 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002007
2008 # =======================vim_net_sdn_xxx section=======================
2009 # vim_net_sdn_attach
2010 vim_net_sdn_attach_parser = subparsers.add_parser('vim-net-sdn-attach',
2011 parents=[parent_parser],
2012 help="Specify the port to access to an external network using SDN")
2013 vim_net_sdn_attach_parser.add_argument("vim_net", action="store",
2014 help="Name/id of the network in the vim that will be used to connect to the external network")
2015 vim_net_sdn_attach_parser.add_argument("port", action="store", help="Specifies the port in the dataplane switch to access to the external network")
2016 vim_net_sdn_attach_parser.add_argument("--vlan", action="store", help="Specifies the vlan (if any) to use in the defined port")
2017 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")
2018 vim_net_sdn_attach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2019 vim_net_sdn_attach_parser.set_defaults(func=vim_net_sdn_attach)
2020
2021 # vim_net_sdn_detach
2022 vim_net_sdn_detach_parser = subparsers.add_parser('vim-net-sdn-detach',
2023 parents=[parent_parser],
2024 help="Remove the port information to access to an external network using SDN")
2025
2026 vim_net_sdn_detach_parser.add_argument("vim_net", action="store", help="Name/id of the vim network")
2027 vim_net_sdn_detach_parser.add_argument("--id", action="store",help="Specify the uuid of the external ports from this network to be detached")
2028 vim_net_sdn_detach_parser.add_argument("--all", action="store_true", help="Detach all external ports from this network")
2029 vim_net_sdn_detach_parser.add_argument("-f", "--force", action="store_true", help="forces clearing without asking")
2030 vim_net_sdn_detach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2031 vim_net_sdn_detach_parser.set_defaults(func=vim_net_sdn_detach)
2032 # =======================
2033
tierno4540ea52017-01-18 17:44:32 +01002034 for item in ("network", "tenant", "image"):
tierno7edb6752016-03-21 17:37:52 +01002035 if item=="network":
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002036 command_name = 'vim-net'
tierno7edb6752016-03-21 17:37:52 +01002037 else:
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002038 command_name = 'vim-'+item
2039 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 +01002040 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
2041 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2042 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
2043
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002044 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 +01002045 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
2046 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2047 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
2048
tierno4540ea52017-01-18 17:44:32 +01002049 if item == "network" or item == "tenant":
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002050 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 +01002051 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
2052 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
2053 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2054 if item=="network":
2055 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
2056 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
2057 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>'")
2058 else:
2059 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
2060 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
tierno7edb6752016-03-21 17:37:52 +01002061
2062 argcomplete.autocomplete(main_parser)
2063
2064 try:
2065 args = main_parser.parse_args()
2066 #logging info
2067 level = logging.CRITICAL
2068 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
2069 if "debug" in args and args.debug:
2070 level = logging.DEBUG
2071 logging.basicConfig(format=streamformat, level= level)
2072 logger = logging.getLogger('mano')
2073 logger.setLevel(level)
2074 result = args.func(args)
2075 if result == None:
2076 result = 0
2077 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
2078 except (requests.exceptions.ConnectionError):
2079 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
2080 result = -2
2081 except (KeyboardInterrupt):
2082 print 'Exiting openmano'
2083 result = -3
2084 except (SystemExit, ArgumentParserError):
2085 result = -4
2086 except OpenmanoCLIError as e:
2087 print str(e)
2088 result = -5
2089
2090 #print result
2091 exit(result)
2092