blob: 8f5d7cc4534b6eb5acc06f2b70380cc4a7b9b2c0 [file] [log] [blame]
tierno7edb6752016-03-21 17:37:52 +01001#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# PYTHON_ARGCOMPLETE_OK
4
5##
6# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
7# This file is part of openmano
8# All Rights Reserved.
9#
10# Licensed under the Apache License, Version 2.0 (the "License"); you may
11# not use this file except in compliance with the License. You may obtain
12# a copy of the License at
13#
14# http://www.apache.org/licenses/LICENSE-2.0
15#
16# Unless required by applicable law or agreed to in writing, software
17# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
18# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
19# License for the specific language governing permissions and limitations
20# under the License.
21#
22# For those usages not covered by the Apache License, Version 2.0 please
23# contact with: nfvlabs@tid.es
24##
25
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$"
tiernoa15c4b92017-10-05 12:41:44 +020031__version__ = "0.4.21-r531"
32version_date = "Oct 2017"
tierno7edb6752016-03-21 17:37:52 +010033
34from argcomplete.completers import FilesCompleter
35import os
36import argparse
37import argcomplete
38import requests
39import json
40import yaml
41import logging
42#from jsonschema import validate as js_v, exceptions as js_e
43
44class ArgumentParserError(Exception): pass
45
46class OpenmanoCLIError(Exception): pass
47
48class ThrowingArgumentParser(argparse.ArgumentParser):
49 def error(self, message):
50 print "Error: %s" %message
51 print
52 self.print_usage()
53 #self.print_help()
54 print
55 print "Type 'openmano -h' for help"
56 raise ArgumentParserError
57
58
59def config(args):
60 print "OPENMANO_HOST: %s" %mano_host
61 print "OPENMANO_PORT: %s" %mano_port
garciadeblas0e9fd832016-07-08 15:20:18 +020062 if args.n:
63 logger.debug("resolving tenant and datacenter names")
64 mano_tenant_id = "None"
65 mano_tenant_name = "None"
66 mano_datacenter_id = "None"
67 mano_datacenter_name = "None"
68 try:
69 mano_tenant_id = _get_item_uuid("tenants", mano_tenant)
70 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, mano_tenant_id)
71 mano_response = requests.get(URLrequest)
72 logger.debug("openmano response: %s", mano_response.text )
73 content = mano_response.json()
74 mano_tenant_name = content["tenant"]["name"]
75 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, mano_tenant_id, mano_datacenter)
76 mano_response = requests.get(URLrequest)
77 logger.debug("openmano response: %s", mano_response.text )
78 content = mano_response.json()
79 if "error" not in content:
80 mano_datacenter_id = content["datacenter"]["uuid"]
81 mano_datacenter_name = content["datacenter"]["name"]
82 except OpenmanoCLIError:
83 pass
84 print "OPENMANO_TENANT: %s" %mano_tenant
85 print " Id: %s" %mano_tenant_id
86 print " Name: %s" %mano_tenant_name
87 print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
88 print " Id: %s" %mano_datacenter_id
89 print " Name: %s" %mano_datacenter_name
90 else:
91 print "OPENMANO_TENANT: %s" %mano_tenant
92 print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
tierno7edb6752016-03-21 17:37:52 +010093
94def _print_verbose(mano_response, verbose_level=0):
95 content = mano_response.json()
96 result = 0 if mano_response.status_code==200 else mano_response.status_code
97 if type(content)!=dict or len(content)!=1:
98 #print "Non expected format output"
99 print str(content)
100 return result
101
102 val=content.values()[0]
103 if type(val)==str:
104 print val
105 return result
106 elif type(val) == list:
107 content_list = val
108 elif type(val)==dict:
109 content_list = [val]
110 else:
111 #print "Non expected dict/list format output"
112 print str(content)
113 return result
114
115 #print content_list
116 if verbose_level==None:
117 verbose_level=0
118 if verbose_level >= 3:
119 print yaml.safe_dump(content, indent=4, default_flow_style=False)
120 return result
121
122 if mano_response.status_code == 200:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100123 uuid = None
tierno7edb6752016-03-21 17:37:52 +0100124 for content in content_list:
125 if "uuid" in content:
126 uuid = content['uuid']
127 elif "id" in content:
128 uuid = content['id']
129 elif "vim_id" in content:
130 uuid = content['vim_id']
tierno250954a2017-01-31 14:25:57 +0100131 name = content.get('name');
132 if not uuid:
133 uuid = ""
134 if not name:
135 name = ""
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"]
320 else: # image name in volumes
321 vdu_list[index]["volumes"][0]["image"] = image_name_
322 if "image-checksum" in vdu_list[index]["volumes"][0]:
323 del vdu_list[index]["volumes"][0]["image-checksum"]
324 else:
325 vdu_list[index]['image name'] = image_name_
326 if "VNFC image" in vdu_list[index]:
327 del vdu_list[index]["VNFC image"]
328 index += 1
garciadeblas14480452017-01-10 13:08:07 +0100329 if args.image_checksum:
tiernof1ba57e2017-09-07 12:23:19 +0200330 index = 0
garciadeblas14480452017-01-10 13:08:07 +0100331 for image_checksum_ in args.image_checksum.split(","):
tiernof1ba57e2017-09-07 12:23:19 +0200332 if api_version == "/v3":
333 if vdu_list[index].get("image"):
334 vdu_list[index]['image-checksum'] = image_checksum_
335 else: # image name in volumes
336 vdu_list[index]["volumes"][0]["image-checksum"] = image_checksum_
337 else:
338 vdu_list[index]['image checksum'] = image_checksum_
339 index += 1
tierno7edb6752016-03-21 17:37:52 +0100340 except (KeyError, TypeError), e:
tiernof1ba57e2017-09-07 12:23:19 +0200341 if str(e) == 'vnf': error_pos= "missing field 'vnf'"
342 elif str(e) == 'name': error_pos= "missing field 'vnf':'name'"
343 elif str(e) == 'description': error_pos= "missing field 'vnf':'description'"
344 elif str(e) == 'VNFC': error_pos= "missing field 'vnf':'VNFC'"
345 elif str(e) == str(index): error_pos= "field 'vnf':'VNFC' must be an array"
346 elif str(e) == 'VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
347 elif str(e) == 'image name': error_pos= "missing field 'vnf':'VNFC'['image name']"
348 elif str(e) == 'image checksum': error_pos= "missing field 'vnf':'VNFC'['image checksum']"
tierno7edb6752016-03-21 17:37:52 +0100349 else: error_pos="wrong format"
350 print "Wrong VNF descriptor: " + error_pos
351 return -1
352 payload_req = json.dumps(myvnf)
353
354 #print payload_req
355
tiernof1ba57e2017-09-07 12:23:19 +0200356 URLrequest = "http://{}:{}/openmano{}/{}/{token}".format(mano_host, mano_port, api_version, tenant, token=token)
tierno7edb6752016-03-21 17:37:52 +0100357 logger.debug("openmano request: %s", payload_req)
358 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
359 logger.debug("openmano response: %s", mano_response.text )
360
361 return _print_verbose(mano_response, args.verbose)
362
363def vnf_list(args):
364 #print "vnf-list",args
365 if args.all:
366 tenant = "any"
367 else:
368 tenant = _get_tenant()
369 if args.name:
370 toshow = _get_item_uuid("vnfs", args.name, tenant)
371 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
372 else:
373 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
374 mano_response = requests.get(URLrequest)
375 logger.debug("openmano response: %s", mano_response.text )
376 content = mano_response.json()
tiernof1ba57e2017-09-07 12:23:19 +0200377 # print json.dumps(content, indent=4)
tierno7edb6752016-03-21 17:37:52 +0100378 if args.verbose==None:
379 args.verbose=0
380 result = 0 if mano_response.status_code==200 else mano_response.status_code
381 if mano_response.status_code == 200:
382 if not args.name:
383 if args.verbose >= 3:
384 print yaml.safe_dump(content, indent=4, default_flow_style=False)
385 return result
386 if len(content['vnfs']) == 0:
387 print "No VNFs were found."
tiernof1ba57e2017-09-07 12:23:19 +0200388 return 404 # HTTP_Not_Found
tierno7edb6752016-03-21 17:37:52 +0100389 for vnf in content['vnfs']:
tiernof1ba57e2017-09-07 12:23:19 +0200390 myoutput = "{:38} {:20}".format(vnf['uuid'], vnf['name'])
391 if vnf.get('osm_id') or args.verbose >= 1:
392 myoutput += " osm_id={:20}".format(vnf.get('osm_id'))
393 if args.verbose >= 1:
394 myoutput += " {}".format(vnf['created_at'])
395 print (myoutput)
396 if args.verbose >= 2:
397 print (" Description: {}".format(vnf['description']))
398 # print (" VNF descriptor file: {}".format(vnf['path']))
tierno7edb6752016-03-21 17:37:52 +0100399 else:
400 if args.verbose:
401 print yaml.safe_dump(content, indent=4, default_flow_style=False)
402 return result
403 vnf = content['vnf']
tiernof1ba57e2017-09-07 12:23:19 +0200404 print ("{:38} {:20} osm_id={:20} {:20}".format(vnf['uuid'], vnf['name'], vnf.get('osm_id'),
405 vnf['created_at']))
406 print (" Description: {}".format(vnf['description']))
407 # print " VNF descriptor file: %s" %vnf['path']
408 print (" VMs:")
tierno7edb6752016-03-21 17:37:52 +0100409 for vm in vnf['VNFC']:
tiernof1ba57e2017-09-07 12:23:19 +0200410 print (" {:20} osm_id={:20} {}".format(vm['name'], vm.get('osm_id'), vm['description']))
411 if len(vnf['nets']) > 0:
412 print (" Internal nets:")
tierno7edb6752016-03-21 17:37:52 +0100413 for net in vnf['nets']:
tiernof1ba57e2017-09-07 12:23:19 +0200414 print (" {:20} {}".format(net['name'], net['description']))
415 if len(vnf['external-connections']) > 0:
416 print (" External interfaces:")
tierno7edb6752016-03-21 17:37:52 +0100417 for interface in vnf['external-connections']:
tiernof1ba57e2017-09-07 12:23:19 +0200418 print (" {:20} {:20} {:20} {:14}".format(
419 interface['external_name'], interface['vm_name'],
420 interface['internal_name'],
421 interface.get('vpci') if interface.get('vpci') else ""))
tierno7edb6752016-03-21 17:37:52 +0100422 else:
423 print content['error']['description']
424 if args.verbose:
425 print yaml.safe_dump(content, indent=4, default_flow_style=False)
426 return result
427
428def vnf_delete(args):
429 #print "vnf-delete",args
430 if args.all:
431 tenant = "any"
432 else:
433 tenant = _get_tenant()
434 todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
435 if not args.force:
436 r = raw_input("Delete VNF %s (y/N)? " %(todelete))
437 if not (len(r)>0 and r[0].lower()=="y"):
438 return 0
439 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
440 mano_response = requests.delete(URLrequest)
441 logger.debug("openmano response: %s", mano_response.text )
442 result = 0 if mano_response.status_code==200 else mano_response.status_code
443 content = mano_response.json()
444 #print json.dumps(content, indent=4)
445 if mano_response.status_code == 200:
446 print content['result']
447 else:
448 print content['error']['description']
449 return result
450
451def scenario_create(args):
tiernof1ba57e2017-09-07 12:23:19 +0200452 # print "scenario-create",args
tierno7edb6752016-03-21 17:37:52 +0100453 tenant = _get_tenant()
454 headers_req = {'content-type': 'application/yaml'}
455 myscenario = _load_file_or_yaml(args.file)
tiernof1ba57e2017-09-07 12:23:19 +0200456 if "nsd:nsd-catalog" in myscenario or "nsd-catalog" in myscenario:
457 api_version = "/v3"
458 token = "nsd"
459 nsd_catalog = myscenario.get("nsd:nsd-catalog")
460 if not nsd_catalog:
461 nsd_catalog = myscenario.get("nsd-catalog")
462 nsds = nsd_catalog.get("nsd:nsd")
463 if not nsds:
464 nsds = nsd_catalog.get("nsd")
465 nsd = nsds[0]
466 else: # API<v3
467 api_version = ""
468 token = "scenarios"
469 if "scenario" in myscenario:
470 nsd = myscenario["scenario"]
471 else:
472 nsd = myscenario
473 # TODO modify for API v3
tierno7edb6752016-03-21 17:37:52 +0100474 if args.name:
tiernof1ba57e2017-09-07 12:23:19 +0200475 nsd['name'] = args.name
tierno7edb6752016-03-21 17:37:52 +0100476 if args.description:
tiernof1ba57e2017-09-07 12:23:19 +0200477 nsd['description'] = args.description
478 payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False,
479 encoding='utf-8', allow_unicode=True)
tierno7edb6752016-03-21 17:37:52 +0100480
tiernof1ba57e2017-09-07 12:23:19 +0200481 # print payload_req
482 URLrequest = "http://{host}:{port}/openmano{api}/{tenant}/{token}".format(
483 host=mano_host, port=mano_port, api=api_version, tenant=tenant, token=token)
tierno7edb6752016-03-21 17:37:52 +0100484 logger.debug("openmano request: %s", payload_req)
485 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
486 logger.debug("openmano response: %s", mano_response.text )
487 return _print_verbose(mano_response, args.verbose)
488
489def scenario_list(args):
490 #print "scenario-list",args
491 if args.all:
492 tenant = "any"
493 else:
494 tenant = _get_tenant()
495 if args.name:
496 toshow = _get_item_uuid("scenarios", args.name, tenant)
497 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
498 else:
499 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
500 mano_response = requests.get(URLrequest)
501 logger.debug("openmano response: %s", mano_response.text )
502 content = mano_response.json()
503 #print json.dumps(content, indent=4)
504 if args.verbose==None:
505 args.verbose=0
506
507 result = 0 if mano_response.status_code==200 else mano_response.status_code
508 if mano_response.status_code == 200:
509 if not args.name:
510 if args.verbose >= 3:
511 print yaml.safe_dump(content, indent=4, default_flow_style=False)
512 return result
513 if len(content['scenarios']) == 0:
514 print "No scenarios were found."
515 return 404 #HTTP_Not_Found
516 for scenario in content['scenarios']:
tiernof1ba57e2017-09-07 12:23:19 +0200517 myoutput = "{:38} {:20}".format(scenario['uuid'], scenario['name'])
518 if scenario.get('osm_id') or args.verbose >= 1:
519 myoutput += " osm_id={:20}".format(scenario.get('osm_id'))
520 if args.verbose >= 1:
521 myoutput += " {}".format(scenario['created_at'])
522 print (myoutput)
tierno7edb6752016-03-21 17:37:52 +0100523 if args.verbose >=2:
tiernof1ba57e2017-09-07 12:23:19 +0200524 print (" Description: {}".format(scenario['description']))
tierno7edb6752016-03-21 17:37:52 +0100525 else:
526 if args.verbose:
527 print yaml.safe_dump(content, indent=4, default_flow_style=False)
528 return result
529 scenario = content['scenario']
tiernof1ba57e2017-09-07 12:23:19 +0200530 print ("{:38} {:20} osm_id={:20} {:20}".format(scenario['uuid'], scenario['name'], scenario.get('osm_id'),
531 scenario['created_at']))
532 print (" Description: {}".format(scenario['description']))
533 print (" VNFs:")
tierno7edb6752016-03-21 17:37:52 +0100534 for vnf in scenario['vnfs']:
tiernof1ba57e2017-09-07 12:23:19 +0200535 print (" {:38} {:20} vnf_index={} {}".format(vnf['vnf_id'], vnf['name'], vnf.get("member_vnf_index"),
536 vnf['description']))
537 if len(scenario['nets']) > 0:
538 print (" nets:")
tierno7edb6752016-03-21 17:37:52 +0100539 for net in scenario['nets']:
tiernof1ba57e2017-09-07 12:23:19 +0200540 description = net['description']
541 if not description: # if description does not exist, description is "-". Valid for external and internal nets.
542 description = '-'
543 vim_id = ""
544 if net.get('vim_id'):
545 vim_id = " vim_id=" + net["vim_id"]
546 external = ""
547 if net["external"]:
548 external = " external"
549 print (" {:20} {:38} {:30}{}{}".format(net['name'], net['uuid'], description, vim_id, external))
tierno7edb6752016-03-21 17:37:52 +0100550 else:
tiernof1ba57e2017-09-07 12:23:19 +0200551 print (content['error']['description'])
tierno7edb6752016-03-21 17:37:52 +0100552 if args.verbose:
553 print yaml.safe_dump(content, indent=4, default_flow_style=False)
554 return result
555
556def scenario_delete(args):
557 #print "scenario-delete",args
558 if args.all:
559 tenant = "any"
560 else:
561 tenant = _get_tenant()
562 todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
563 if not args.force:
564 r = raw_input("Delete scenario %s (y/N)? " %(args.name))
565 if not (len(r)>0 and r[0].lower()=="y"):
566 return 0
567 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
568 mano_response = requests.delete(URLrequest)
569 logger.debug("openmano response: %s", mano_response.text )
570 result = 0 if mano_response.status_code==200 else mano_response.status_code
571 content = mano_response.json()
572 #print json.dumps(content, indent=4)
573 if mano_response.status_code == 200:
574 print content['result']
575 else:
576 print content['error']['description']
577 return result
578
579def scenario_deploy(args):
580 print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
581 print
582 args.file = None
583 args.netmap_use = None
584 args.netmap_create = None
tiernobe41e222016-09-02 15:16:13 +0200585 args.keypair = None
586 args.keypair_auto = None
tierno7edb6752016-03-21 17:37:52 +0100587 return instance_create(args)
588
589# #print "scenario-deploy",args
590# headers_req = {'content-type': 'application/json'}
591# action = {}
592# actionCmd="start"
593# if args.nostart:
594# actionCmd="reserve"
595# action[actionCmd] = {}
596# action[actionCmd]["instance_name"] = args.name
597# if args.datacenter != None:
598# action[actionCmd]["datacenter"] = args.datacenter
599# elif mano_datacenter != None:
600# action[actionCmd]["datacenter"] = mano_datacenter
601#
602# if args.description:
603# action[actionCmd]["description"] = args.description
604# payload_req = json.dumps(action, indent=4)
605# #print payload_req
606#
607# URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
608# logger.debug("openmano request: %s", payload_req)
609# mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
610# logger.debug("openmano response: %s", mano_response.text )
611# if args.verbose==None:
612# args.verbose=0
613#
614# result = 0 if mano_response.status_code==200 else mano_response.status_code
615# content = mano_response.json()
616# #print json.dumps(content, indent=4)
617# if args.verbose >= 3:
618# print yaml.safe_dump(content, indent=4, default_flow_style=False)
619# return result
620#
621# if mano_response.status_code == 200:
622# myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
623# if args.verbose >=1:
624# myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
625# if args.verbose >=2:
626# myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
627# print myoutput
628# print ""
629# print "To check the status, run the following command:"
630# print "openmano instance-scenario-list <instance_id>"
631# else:
632# print content['error']['description']
633# return result
634
635def scenario_verify(args):
636 #print "scenario-verify",args
tierno72a08d72017-05-25 13:12:30 +0200637 tenant = _get_tenant()
tierno7edb6752016-03-21 17:37:52 +0100638 headers_req = {'content-type': 'application/json'}
639 action = {}
640 action["verify"] = {}
641 action["verify"]["instance_name"] = "scen-verify-return5"
642 payload_req = json.dumps(action, indent=4)
643 #print payload_req
644
tierno72a08d72017-05-25 13:12:30 +0200645 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, tenant, args.scenario)
tierno7edb6752016-03-21 17:37:52 +0100646 logger.debug("openmano request: %s", payload_req)
647 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
648 logger.debug("openmano response: %s", mano_response.text )
649
650 result = 0 if mano_response.status_code==200 else mano_response.status_code
651 content = mano_response.json()
652 #print json.dumps(content, indent=4)
653 if mano_response.status_code == 200:
654 print content['result']
655 else:
656 print content['error']['description']
657 return result
658
659def instance_create(args):
660 tenant = _get_tenant()
661 headers_req = {'content-type': 'application/yaml'}
662 myInstance={"instance": {}, "schema_version": "0.1"}
663 if args.file:
664 instance_dict = _load_file_or_yaml(args.file)
665 if "instance" not in instance_dict:
666 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
667 else:
668 myInstance = instance_dict
669 if args.name:
670 myInstance["instance"]['name'] = args.name
671 if args.description:
672 myInstance["instance"]['description'] = args.description
673 if args.nostart:
674 myInstance["instance"]['action'] = "reserve"
675 #datacenter
676 datacenter = myInstance["instance"].get("datacenter")
677 if args.datacenter != None:
678 datacenter = args.datacenter
679 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
680 #scenario
681 scenario = myInstance["instance"].get("scenario")
682 if args.scenario != None:
683 scenario = args.scenario
684 if not scenario:
garciadeblased746032017-01-05 11:58:41 +0100685 print "you must provide a scenario in the file descriptor or with --scenario"
tierno7edb6752016-03-21 17:37:52 +0100686 return -1
687 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
688 if args.netmap_use:
689 if "networks" not in myInstance["instance"]:
690 myInstance["instance"]["networks"] = {}
691 for net in args.netmap_use:
692 net_comma_list = net.split(",")
693 for net_comma in net_comma_list:
694 net_tuple = net_comma.split("=")
695 if len(net_tuple) != 2:
696 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
697 return
698 net_scenario = net_tuple[0].strip()
699 net_datacenter = net_tuple[1].strip()
700 if net_scenario not in myInstance["instance"]["networks"]:
701 myInstance["instance"]["networks"][net_scenario] = {}
tiernobe41e222016-09-02 15:16:13 +0200702 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
703 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
704 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
tierno7edb6752016-03-21 17:37:52 +0100705 if args.netmap_create:
706 if "networks" not in myInstance["instance"]:
707 myInstance["instance"]["networks"] = {}
708 for net in args.netmap_create:
709 net_comma_list = net.split(",")
710 for net_comma in net_comma_list:
711 net_tuple = net_comma.split("=")
712 if len(net_tuple) == 1:
713 net_scenario = net_tuple[0].strip()
714 net_datacenter = None
715 elif len(net_tuple) == 2:
716 net_scenario = net_tuple[0].strip()
717 net_datacenter = net_tuple[1].strip()
718 else:
719 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
720 return
721 if net_scenario not in myInstance["instance"]["networks"]:
722 myInstance["instance"]["networks"][net_scenario] = {}
tiernobe41e222016-09-02 15:16:13 +0200723 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
724 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
725 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
tiernoa4e1a6e2016-08-31 14:19:40 +0200726 if args.keypair:
727 if "cloud-config" not in myInstance["instance"]:
728 myInstance["instance"]["cloud-config"] = {}
729 cloud_config = myInstance["instance"]["cloud-config"]
730 for key in args.keypair:
731 index = key.find(":")
732 if index<0:
733 if "key-pairs" not in cloud_config:
734 cloud_config["key-pairs"] = []
735 cloud_config["key-pairs"].append(key)
736 else:
737 user = key[:index]
738 key_ = key[index+1:]
739 key_list = key_.split(",")
740 if "users" not in cloud_config:
741 cloud_config["users"] = []
742 cloud_config["users"].append({"name": user, "key-pairs": key_list })
743 if args.keypair_auto:
744 try:
745 keys=[]
746 home = os.getenv("HOME")
747 user = os.getenv("USER")
748 files = os.listdir(home+'/.ssh')
749 for file in files:
750 if file[-4:] == ".pub":
751 with open(home+'/.ssh/'+file, 'r') as f:
752 keys.append(f.read())
753 if not keys:
754 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
755 return 1
756 except Exception as e:
757 print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
758 return 1
759
760 if "cloud-config" not in myInstance["instance"]:
761 myInstance["instance"]["cloud-config"] = {}
762 cloud_config = myInstance["instance"]["cloud-config"]
763 if "key-pairs" not in cloud_config:
764 cloud_config["key-pairs"] = []
765 if user:
766 if "users" not in cloud_config:
767 cloud_config["users"] = []
768 cloud_config["users"].append({"name": user, "key-pairs": keys })
tierno7edb6752016-03-21 17:37:52 +0100769
770 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
771 logger.debug("openmano request: %s", payload_req)
772 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
773 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
774 logger.debug("openmano response: %s", mano_response.text )
775 if args.verbose==None:
776 args.verbose=0
777
778 result = 0 if mano_response.status_code==200 else mano_response.status_code
779 content = mano_response.json()
780 #print json.dumps(content, indent=4)
781 if args.verbose >= 3:
782 print yaml.safe_dump(content, indent=4, default_flow_style=False)
783 return result
784
785 if mano_response.status_code == 200:
tiernoa15c4b92017-10-05 12:41:44 +0200786 myoutput = "{:38} {:20}".format(content['uuid'], content['name'])
tierno7edb6752016-03-21 17:37:52 +0100787 if args.verbose >=1:
tiernoa15c4b92017-10-05 12:41:44 +0200788 myoutput = "{} {:20}".format(myoutput, content['created_at'])
tierno7edb6752016-03-21 17:37:52 +0100789 if args.verbose >=2:
tiernoa15c4b92017-10-05 12:41:44 +0200790 myoutput = "{} {:30}".format(myoutput, content['description'])
tierno7edb6752016-03-21 17:37:52 +0100791 print myoutput
792 else:
793 print content['error']['description']
794 return result
795
796def instance_scenario_list(args):
797 #print "instance-scenario-list",args
798 if args.all:
799 tenant = "any"
800 else:
801 tenant = _get_tenant()
802 if args.name:
803 toshow = _get_item_uuid("instances", args.name, tenant)
804 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
805 else:
806 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
807 mano_response = requests.get(URLrequest)
808 logger.debug("openmano response: %s", mano_response.text )
809 content = mano_response.json()
810 #print json.dumps(content, indent=4)
811 if args.verbose==None:
812 args.verbose=0
813
814 result = 0 if mano_response.status_code==200 else mano_response.status_code
815 if mano_response.status_code == 200:
816 if not args.name:
817 if args.verbose >= 3:
818 print yaml.safe_dump(content, indent=4, default_flow_style=False)
819 return result
820 if len(content['instances']) == 0:
821 print "No scenario instances were found."
822 return result
823 for instance in content['instances']:
tiernoa15c4b92017-10-05 12:41:44 +0200824 myoutput = "{:38} {:20}".format(instance['uuid'], instance['name'])
tierno7edb6752016-03-21 17:37:52 +0100825 if args.verbose >=1:
tiernoa15c4b92017-10-05 12:41:44 +0200826 myoutput = "{} {:20}".format(myoutput, instance['created_at'])
tierno7edb6752016-03-21 17:37:52 +0100827 print myoutput
828 if args.verbose >=2:
829 print "Description: %s" %instance['description']
830 else:
831 if args.verbose:
832 print yaml.safe_dump(content, indent=4, default_flow_style=False)
833 return result
834 instance = content
tiernoa15c4b92017-10-05 12:41:44 +0200835 print ("{:38} {:20} {:20}".format(instance['uuid'],instance['name'],instance['created_at']))
836 print ("Description: %s" %instance['description'])
837 print ("Template scenario id: {}".format(instance['scenario_id']))
838 print ("Template scenario name: {}".format(instance['scenario_name']))
839 print ("---------------------------------------")
840 print ("VNF instances: {}".format(len(instance['vnfs'])))
tierno7edb6752016-03-21 17:37:52 +0100841 for vnf in instance['vnfs']:
842 #print " %s %s Template vnf name: %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['name'].ljust(20), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
tiernoa15c4b92017-10-05 12:41:44 +0200843 print (" {:38} {:20} Template vnf id: {:38}".format(vnf['uuid'], vnf['vnf_name'], vnf['vnf_id']))
tierno7edb6752016-03-21 17:37:52 +0100844 if len(instance['nets'])>0:
845 print "---------------------------------------"
846 print "Internal nets:"
847 for net in instance['nets']:
tierno5c7c4732016-09-26 13:38:55 +0000848 if net['created']:
tiernoa15c4b92017-10-05 12:41:44 +0200849 print (" {:38} {:12} VIM ID: {}".format(net['uuid'], net['status'], net['vim_net_id']))
tierno7edb6752016-03-21 17:37:52 +0100850 print "---------------------------------------"
851 print "External nets:"
852 for net in instance['nets']:
tierno5c7c4732016-09-26 13:38:55 +0000853 if not net['created']:
tiernoa15c4b92017-10-05 12:41:44 +0200854 print (" {:38} {:12} VIM ID: {}".format(net['uuid'], net['status'], net['vim_net_id']))
855 print ("---------------------------------------")
856 print ("VM instances:")
tierno7edb6752016-03-21 17:37:52 +0100857 for vnf in instance['vnfs']:
858 for vm in vnf['vms']:
tiernoa15c4b92017-10-05 12:41:44 +0200859 print (" {:38} {:20} {:20} {:12} VIM ID: {}".format(vm['uuid'], vnf['vnf_name'], vm['name'],
860 vm['status'], vm['vim_vm_id']))
tierno7edb6752016-03-21 17:37:52 +0100861 else:
862 print content['error']['description']
863 if args.verbose:
864 print yaml.safe_dump(content, indent=4, default_flow_style=False)
865 return result
866
867def instance_scenario_status(args):
868 print "instance-scenario-status"
869 return 0
870
871def instance_scenario_delete(args):
872 if args.all:
873 tenant = "any"
874 else:
875 tenant = _get_tenant()
876 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
877 #print "instance-scenario-delete",args
878 if not args.force:
879 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
880 if not (len(r)>0 and r[0].lower()=="y"):
881 return
882 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
883 mano_response = requests.delete(URLrequest)
884 logger.debug("openmano response: %s", mano_response.text )
885 result = 0 if mano_response.status_code==200 else mano_response.status_code
886 content = mano_response.json()
887 #print json.dumps(content, indent=4)
888 if mano_response.status_code == 200:
889 print content['result']
890 else:
891 print content['error']['description']
892 return result
893
tierno868220c2017-09-26 00:11:05 +0200894def get_action(args):
895 if not args.all:
896 tenant = _get_tenant()
897 else:
898 tenant = "any"
899 if not args.instance:
900 instance_id = "any"
901 else:
902 instance_id =args.instance
903 action_id = ""
904 if args.id:
905 action_id = "/" + args.id
906 URLrequest = "http://{}:{}/openmano/{}/instances/{}/action{}".format(mano_host, mano_port, tenant, instance_id,
907 action_id)
908 mano_response = requests.get(URLrequest)
909 logger.debug("openmano response: %s", mano_response.text )
910 if args.verbose == None:
911 args.verbose = 0
912 if args.id != None:
913 args.verbose += 1
914 return _print_verbose(mano_response, args.verbose)
915
tierno7edb6752016-03-21 17:37:52 +0100916def instance_scenario_action(args):
917 #print "instance-scenario-action", args
918 tenant = _get_tenant()
919 toact = _get_item_uuid("instances", args.name, tenant=tenant)
920 action={}
921 action[ args.action ] = args.param
922 if args.vnf:
923 action["vnfs"] = args.vnf
924 if args.vm:
925 action["vms"] = args.vm
926
927 headers_req = {'content-type': 'application/json'}
928 payload_req = json.dumps(action, indent=4)
929 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
930 logger.debug("openmano request: %s", payload_req)
931 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
932 logger.debug("openmano response: %s", mano_response.text )
933 result = 0 if mano_response.status_code==200 else mano_response.status_code
934 content = mano_response.json()
935 #print json.dumps(content, indent=4)
936 if mano_response.status_code == 200:
937 if args.verbose:
938 print yaml.safe_dump(content, indent=4, default_flow_style=False)
939 return result
940 for uuid,c in content.iteritems():
tiernoa15c4b92017-10-05 12:41:44 +0200941 print ("{:38} {:20} {:20}".format(uuid, c['name'], c['description']))
tierno7edb6752016-03-21 17:37:52 +0100942 else:
943 print content['error']['description']
944 return result
945
946
947def instance_vnf_list(args):
948 print "instance-vnf-list"
949 return 0
950
951def instance_vnf_status(args):
952 print "instance-vnf-status"
953 return 0
954
955def tenant_create(args):
956 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
957 tenant_dict={"name": args.name}
958 if args.description!=None:
959 tenant_dict["description"] = args.description
960 payload_req = json.dumps( {"tenant": tenant_dict })
961
962 #print payload_req
963
964 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
965 logger.debug("openmano request: %s", payload_req)
966 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
967 logger.debug("openmano response: %s", mano_response.text )
968 return _print_verbose(mano_response, args.verbose)
969
970def tenant_list(args):
971 #print "tenant-list",args
972 if args.name:
tierno392f2852016-05-13 12:28:55 +0200973 toshow = _get_item_uuid("tenants", args.name)
tierno7edb6752016-03-21 17:37:52 +0100974 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
975 else:
976 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
977 mano_response = requests.get(URLrequest)
978 logger.debug("openmano response: %s", mano_response.text )
979 if args.verbose==None:
980 args.verbose=0
981 if args.name!=None:
982 args.verbose += 1
983 return _print_verbose(mano_response, args.verbose)
984
985def tenant_delete(args):
986 #print "tenant-delete",args
987 todelete = _get_item_uuid("tenants", args.name)
988 if not args.force:
989 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
990 if not (len(r)>0 and r[0].lower()=="y"):
991 return 0
992 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
993 mano_response = requests.delete(URLrequest)
994 logger.debug("openmano response: %s", mano_response.text )
995 result = 0 if mano_response.status_code==200 else mano_response.status_code
996 content = mano_response.json()
997 #print json.dumps(content, indent=4)
998 if mano_response.status_code == 200:
999 print content['result']
1000 else:
1001 print content['error']['description']
1002 return result
1003
1004def datacenter_attach(args):
1005 tenant = _get_tenant()
1006 datacenter = _get_datacenter(args.name)
1007 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1008
1009 datacenter_dict={}
1010 if args.vim_tenant_id != None:
1011 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1012 if args.vim_tenant_name != None:
1013 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1014 if args.user != None:
1015 datacenter_dict['vim_username'] = args.user
1016 if args.password != None:
1017 datacenter_dict['vim_password'] = args.password
tierno8008c3a2016-10-13 15:34:28 +00001018 if args.config!=None:
1019 datacenter_dict["config"] = _load_file_or_yaml(args.config)
tierno7edb6752016-03-21 17:37:52 +01001020 payload_req = json.dumps( {"datacenter": datacenter_dict })
1021
1022 #print payload_req
1023
1024 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1025 logger.debug("openmano request: %s", payload_req)
1026 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1027 logger.debug("openmano response: %s", mano_response.text )
1028 result = _print_verbose(mano_response, args.verbose)
1029 #provide addional information if error
1030 if mano_response.status_code != 200:
1031 content = mano_response.json()
1032 if "already in use for 'name'" in content['error']['description'] and \
1033 "to database vim_tenants table" in content['error']['description']:
1034 print "Try to specify a different name with --vim-tenant-name"
1035 return result
1036
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001037
1038def datacenter_edit_vim_tenant(args):
1039 tenant = _get_tenant()
1040 datacenter = _get_datacenter(args.name)
1041 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1042
1043 if not (args.vim_tenant_id or args.vim_tenant_name or args.user or args.password or args.config):
1044 raise OpenmanoCLIError("Error. At least one parameter must be updated.")
1045
1046 datacenter_dict = {}
1047 if args.vim_tenant_id != None:
1048 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1049 if args.vim_tenant_name != None:
1050 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1051 if args.user != None:
1052 datacenter_dict['vim_username'] = args.user
1053 if args.password != None:
1054 datacenter_dict['vim_password'] = args.password
1055 if args.config != None:
1056 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1057 payload_req = json.dumps({"datacenter": datacenter_dict})
1058
1059 # print payload_req
1060
1061 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" % (mano_host, mano_port, tenant, datacenter)
1062 logger.debug("openmano request: %s", payload_req)
1063 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1064 logger.debug("openmano response: %s", mano_response.text)
1065 result = _print_verbose(mano_response, args.verbose)
1066
1067 return result
1068
tierno7edb6752016-03-21 17:37:52 +01001069def datacenter_detach(args):
1070 if args.all:
1071 tenant = "any"
1072 else:
1073 tenant = _get_tenant()
1074 datacenter = _get_datacenter(args.name, tenant)
1075 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1076 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1077 mano_response = requests.delete(URLrequest, headers=headers_req)
1078 logger.debug("openmano response: %s", mano_response.text )
1079 content = mano_response.json()
1080 #print json.dumps(content, indent=4)
1081 result = 0 if mano_response.status_code==200 else mano_response.status_code
1082 if mano_response.status_code == 200:
1083 print content['result']
1084 else:
1085 print content['error']['description']
1086 return result
1087
1088def datacenter_create(args):
1089 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1090 datacenter_dict={"name": args.name, "vim_url": args.url}
1091 if args.description!=None:
1092 datacenter_dict["description"] = args.description
1093 if args.type!=None:
1094 datacenter_dict["type"] = args.type
1095 if args.url!=None:
1096 datacenter_dict["vim_url_admin"] = args.url_admin
1097 if args.config!=None:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001098 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1099 if args.sdn_controller!=None:
1100 tenant = _get_tenant()
1101 sdn_controller = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1102 if not 'config' in datacenter_dict:
1103 datacenter_dict['config'] = {}
1104 datacenter_dict['config']['sdn-controller'] = sdn_controller
tierno7edb6752016-03-21 17:37:52 +01001105 payload_req = json.dumps( {"datacenter": datacenter_dict })
1106
1107 #print payload_req
1108
1109 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
1110 logger.debug("openmano request: %s", payload_req)
1111 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1112 logger.debug("openmano response: %s", mano_response.text )
1113 return _print_verbose(mano_response, args.verbose)
1114
1115def datacenter_delete(args):
1116 #print "datacenter-delete",args
1117 todelete = _get_item_uuid("datacenters", args.name, "any")
1118 if not args.force:
1119 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
1120 if not (len(r)>0 and r[0].lower()=="y"):
1121 return 0
1122 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
1123 mano_response = requests.delete(URLrequest)
1124 logger.debug("openmano response: %s", mano_response.text )
1125 result = 0 if mano_response.status_code==200 else mano_response.status_code
1126 content = mano_response.json()
1127 #print json.dumps(content, indent=4)
1128 if mano_response.status_code == 200:
1129 print content['result']
1130 else:
1131 print content['error']['description']
1132 return result
1133
tierno20df3bb2017-07-07 14:31:00 +02001134
tierno7edb6752016-03-21 17:37:52 +01001135def datacenter_list(args):
1136 #print "datacenter-list",args
1137 tenant='any' if args.all else _get_tenant()
1138
1139 if args.name:
1140 toshow = _get_item_uuid("datacenters", args.name, tenant)
1141 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
1142 else:
1143 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
1144 mano_response = requests.get(URLrequest)
1145 logger.debug("openmano response: %s", mano_response.text )
1146 if args.verbose==None:
1147 args.verbose=0
1148 if args.name!=None:
1149 args.verbose += 1
1150 return _print_verbose(mano_response, args.verbose)
1151
tierno20df3bb2017-07-07 14:31:00 +02001152
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001153def datacenter_sdn_port_mapping_set(args):
1154 tenant = _get_tenant()
1155 datacenter = _get_datacenter(args.name, tenant)
1156 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1157
1158 if not args.file:
1159 raise OpenmanoCLIError(
1160 "No yaml/json has been provided specifying the SDN port mapping")
tierno20df3bb2017-07-07 14:31:00 +02001161 sdn_port_mapping = _load_file_or_yaml(args.file)
1162 payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping})
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001163
tierno20df3bb2017-07-07 14:31:00 +02001164 # read
1165 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1166 mano_response = requests.get(URLrequest)
1167 logger.debug("openmano response: %s", mano_response.text)
1168 port_mapping = mano_response.json()
1169 if mano_response.status_code != 200:
1170 str(mano_response.json())
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001171 raise OpenmanoCLIError("openmano client error: {}".format(port_mapping['error']['description']))
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001172 if len(port_mapping["sdn_port_mapping"]["ports_mapping"]) > 0:
1173 if not args.force:
1174 r = raw_input("Datacenter %s already contains a port mapping. Overwrite? (y/N)? " % (datacenter))
1175 if not (len(r) > 0 and r[0].lower() == "y"):
1176 return 0
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001177
tierno20df3bb2017-07-07 14:31:00 +02001178 # clear
1179 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1180 mano_response = requests.delete(URLrequest)
1181 logger.debug("openmano response: %s", mano_response.text)
1182 if mano_response.status_code != 200:
1183 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001184
tierno20df3bb2017-07-07 14:31:00 +02001185 # set
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001186 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1187 logger.debug("openmano request: %s", payload_req)
1188 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1189 logger.debug("openmano response: %s", mano_response.text)
tierno20df3bb2017-07-07 14:31:00 +02001190 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001191
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001192
1193def datacenter_sdn_port_mapping_list(args):
1194 tenant = _get_tenant()
1195 datacenter = _get_datacenter(args.name, tenant)
1196
1197 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1198 mano_response = requests.get(URLrequest)
1199 logger.debug("openmano response: %s", mano_response.text)
1200
tierno20df3bb2017-07-07 14:31:00 +02001201 return _print_verbose(mano_response, 4)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001202
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001203
1204def datacenter_sdn_port_mapping_clear(args):
1205 tenant = _get_tenant()
1206 datacenter = _get_datacenter(args.name, tenant)
1207
1208 if not args.force:
1209 r = raw_input("Clean SDN port mapping for datacenter %s (y/N)? " %(datacenter))
tierno20df3bb2017-07-07 14:31:00 +02001210 if not (len(r) > 0 and r[0].lower() == "y"):
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001211 return 0
1212
1213 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1214 mano_response = requests.delete(URLrequest)
1215 logger.debug("openmano response: %s", mano_response.text)
1216
tierno20df3bb2017-07-07 14:31:00 +02001217 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001218
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001219
1220def sdn_controller_create(args):
1221 tenant = _get_tenant()
1222 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1223
tierno8fe7a492017-07-11 13:50:04 +02001224 error_msg=[]
1225 if not args.ip: error_msg.append("'ip'")
1226 if not args.port: error_msg.append("'port'")
1227 if not args.dpid: error_msg.append("'dpid'")
1228 if not args.type: error_msg.append("'type'")
1229 if error_msg:
1230 raise OpenmanoCLIError("The following arguments are required: " + ",".join(error_msg))
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001231
1232 controller_dict = {}
1233 controller_dict['name'] = args.name
1234 controller_dict['ip'] = args.ip
1235 controller_dict['port'] = int(args.port)
1236 controller_dict['dpid'] = args.dpid
1237 controller_dict['type'] = args.type
1238 if args.description != None:
1239 controller_dict['description'] = args.description
1240 if args.user != None:
1241 controller_dict['user'] = args.user
1242 if args.password != None:
1243 controller_dict['password'] = args.password
1244
1245 payload_req = json.dumps({"sdn_controller": controller_dict})
1246
1247 # print payload_req
1248
1249 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" % (mano_host, mano_port, tenant)
1250 logger.debug("openmano request: %s", payload_req)
1251 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1252 logger.debug("openmano response: %s", mano_response.text)
1253 result = _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001254 return result
1255
tierno20df3bb2017-07-07 14:31:00 +02001256
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001257def sdn_controller_edit(args):
1258 tenant = _get_tenant()
1259 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1260 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1261
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001262 controller_dict = {}
tierno20df3bb2017-07-07 14:31:00 +02001263 if args.new_name:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001264 controller_dict['name'] = args.new_name
tierno20df3bb2017-07-07 14:31:00 +02001265 if args.ip:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001266 controller_dict['ip'] = args.ip
tierno20df3bb2017-07-07 14:31:00 +02001267 if args.port:
Pablo Montes Morenob12711f2017-04-06 11:54:34 +02001268 controller_dict['port'] = int(args.port)
tierno20df3bb2017-07-07 14:31:00 +02001269 if args.dpid:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001270 controller_dict['dpid'] = args.dpid
tierno20df3bb2017-07-07 14:31:00 +02001271 if args.type:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001272 controller_dict['type'] = args.type
tierno20df3bb2017-07-07 14:31:00 +02001273 if args.description:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001274 controller_dict['description'] = args.description
tierno20df3bb2017-07-07 14:31:00 +02001275 if args.user:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001276 controller_dict['user'] = args.user
tierno20df3bb2017-07-07 14:31:00 +02001277 if args.password:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001278 controller_dict['password'] = args.password
1279
tierno20df3bb2017-07-07 14:31:00 +02001280 if not controller_dict:
1281 raise OpenmanoCLIError("At least one parameter must be edited")
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001282
tierno20df3bb2017-07-07 14:31:00 +02001283 if not args.force:
1284 r = raw_input("Update SDN controller {} (y/N)? ".format(args.name))
1285 if not (len(r) > 0 and r[0].lower() == "y"):
1286 return 0
1287
1288 payload_req = json.dumps({"sdn_controller": controller_dict})
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001289 # print payload_req
1290
1291 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1292 logger.debug("openmano request: %s", payload_req)
1293 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1294 logger.debug("openmano response: %s", mano_response.text)
1295 result = _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001296 return result
1297
tierno20df3bb2017-07-07 14:31:00 +02001298
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001299def sdn_controller_list(args):
1300 tenant = _get_tenant()
1301 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1302
1303 if args.name:
1304 toshow = _get_item_uuid("sdn_controllers", args.name, tenant)
1305 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" %(mano_host, mano_port, tenant, toshow)
1306 else:
1307 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" %(mano_host, mano_port, tenant)
1308 #print URLrequest
1309 mano_response = requests.get(URLrequest)
1310 logger.debug("openmano response: %s", mano_response.text )
1311 if args.verbose==None:
1312 args.verbose=0
1313 if args.name!=None:
1314 args.verbose += 1
1315
tierno20df3bb2017-07-07 14:31:00 +02001316 # json.dumps(mano_response.json(), indent=4)
1317 return _print_verbose(mano_response, args.verbose)
1318
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001319
1320def sdn_controller_delete(args):
1321 tenant = _get_tenant()
1322 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1323
1324 if not args.force:
1325 r = raw_input("Delete SDN controller %s (y/N)? " % (args.name))
1326 if not (len(r) > 0 and r[0].lower() == "y"):
1327 return 0
1328
1329 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1330 mano_response = requests.delete(URLrequest)
1331 logger.debug("openmano response: %s", mano_response.text)
tierno20df3bb2017-07-07 14:31:00 +02001332 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001333
tierno7edb6752016-03-21 17:37:52 +01001334def vim_action(args):
1335 #print "datacenter-net-action",args
1336 tenant = _get_tenant()
1337 datacenter = _get_datacenter(args.datacenter, tenant)
1338 if args.verbose==None:
1339 args.verbose=0
1340 if args.action=="list":
1341 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1342 if args.name!=None:
1343 args.verbose += 1
1344 URLrequest += "/" + args.name
1345 mano_response = requests.get(URLrequest)
1346 logger.debug("openmano response: %s", mano_response.text )
1347 return _print_verbose(mano_response, args.verbose)
1348 elif args.action=="delete":
1349 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1350 mano_response = requests.delete(URLrequest)
1351 logger.debug("openmano response: %s", mano_response.text )
1352 result = 0 if mano_response.status_code==200 else mano_response.status_code
1353 content = mano_response.json()
1354 #print json.dumps(content, indent=4)
1355 if mano_response.status_code == 200:
1356 print content['result']
1357 else:
1358 print content['error']['description']
1359 return result
1360 elif args.action=="create":
1361 headers_req = {'content-type': 'application/yaml'}
1362 if args.file:
1363 create_dict = _load_file_or_yaml(args.file)
1364 if args.item not in create_dict:
1365 create_dict = {args.item: create_dict}
1366 else:
1367 create_dict = {args.item:{}}
1368 if args.name:
1369 create_dict[args.item]['name'] = args.name
1370 #if args.description:
1371 # create_dict[args.item]['description'] = args.description
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001372 if args.item=="network":
tierno7edb6752016-03-21 17:37:52 +01001373 if args.bind_net:
1374 create_dict[args.item]['bind_net'] = args.bind_net
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001375 if args.type:
1376 create_dict[args.item]['type'] = args.type
tierno7edb6752016-03-21 17:37:52 +01001377 if args.shared:
1378 create_dict[args.item]['shared'] = args.shared
1379 if "name" not in create_dict[args.item]:
1380 print "You must provide a name in the descriptor file or with the --name option"
1381 return
1382 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1383 logger.debug("openmano request: %s", payload_req)
tierno72a08d72017-05-25 13:12:30 +02001384 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
tierno7edb6752016-03-21 17:37:52 +01001385 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1386 logger.debug("openmano response: %s", mano_response.text )
1387 if args.verbose==None:
1388 args.verbose=0
1389 return _print_verbose(mano_response, args.verbose)
1390
tierno20df3bb2017-07-07 14:31:00 +02001391
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001392def _get_items(item, item_name_id=None, datacenter=None, tenant=None):
1393 URLrequest = "http://%s:%s/openmano" %(mano_host, mano_port)
1394 if tenant:
1395 URLrequest += "/" + tenant
1396 if datacenter:
1397 URLrequest += "/vim/" + datacenter
1398 if item:
1399 URLrequest += "/" + item +"s"
1400 if item_name_id:
1401 URLrequest += "/" + item_name_id
1402 mano_response = requests.get(URLrequest)
1403 logger.debug("openmano response: %s", mano_response.text )
1404
1405 return mano_response
1406
tierno20df3bb2017-07-07 14:31:00 +02001407
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001408def vim_net_sdn_attach(args):
1409 #Verify the network exists in the vim
1410 tenant = _get_tenant()
1411 datacenter = _get_datacenter(args.datacenter, tenant)
1412 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1413 content = yaml.load(result.content)
1414 if 'networks' in content:
1415 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1416 if 'error' in content:
1417 raise OpenmanoCLIError(yaml.safe_dump(content))
1418 network_uuid = content['network']['id']
1419
1420 #Make call to attach the dataplane port to the SND network associated to the vim network
1421 headers_req = {'content-type': 'application/yaml'}
1422 payload_req = {'port': args.port}
1423 if args.vlan:
1424 payload_req['vlan'] = int(args.vlan)
1425 if args.mac:
1426 payload_req['mac'] = args.mac
1427
1428 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/attach" % (mano_host, mano_port, tenant, datacenter, network_uuid)
1429 logger.debug("openmano request: %s", payload_req)
1430 mano_response = requests.post(URLrequest, headers=headers_req, data=json.dumps(payload_req))
1431 logger.debug("openmano response: %s", mano_response.text)
1432 result = _print_verbose(mano_response, args.verbose)
tierno20df3bb2017-07-07 14:31:00 +02001433 return result
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001434
1435
1436def vim_net_sdn_detach(args):
1437 if not args.all and not args.id:
1438 print "--all or --id must be used"
1439 return 1
1440
1441 # Verify the network exists in the vim
1442 tenant = _get_tenant()
1443 datacenter = _get_datacenter(args.datacenter, tenant)
1444 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1445 content = yaml.load(result.content)
1446 if 'networks' in content:
1447 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1448 if 'error' in content:
1449 raise OpenmanoCLIError(yaml.safe_dump(content))
1450 network_uuid = content['network']['id']
1451
1452 if not args.force:
1453 r = raw_input("Confirm action' (y/N)? ")
1454 if len(r) == 0 or r[0].lower() != "y":
1455 return 0
1456
1457 if args.id:
1458 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach/%s" % (
1459 mano_host, mano_port, tenant, datacenter, network_uuid, args.id)
1460 else:
1461 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach" % (
1462 mano_host, mano_port, tenant, datacenter, network_uuid)
1463 mano_response = requests.delete(URLrequest)
1464 logger.debug("openmano response: %s", mano_response.text)
1465 result = _print_verbose(mano_response, args.verbose)
tierno20df3bb2017-07-07 14:31:00 +02001466 return result
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001467
tierno7edb6752016-03-21 17:37:52 +01001468
1469def datacenter_net_action(args):
1470 if args.action == "net-update":
tierno5acf7202016-08-29 14:28:13 +02001471 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
tierno7edb6752016-03-21 17:37:52 +01001472 print
1473 args.action = "netmap-delete"
1474 args.netmap = None
1475 args.all = True
1476 r = datacenter_netmap_action(args)
1477 if r == 0:
1478 args.force = True
tierno5acf7202016-08-29 14:28:13 +02001479 args.action = "netmap-import"
tierno7edb6752016-03-21 17:37:52 +01001480 r = datacenter_netmap_action(args)
1481 return r
1482
1483 if args.action == "net-edit":
1484 args.netmap = args.net
1485 args.name = None
1486 elif args.action == "net-list":
1487 args.netmap = None
1488 elif args.action == "net-delete":
1489 args.netmap = args.net
1490 args.all = False
1491
1492 args.action = "netmap" + args.action[3:]
1493 args.vim_name=None
1494 args.vim_id=None
1495 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1496 print
1497 return datacenter_netmap_action(args)
1498
1499def datacenter_netmap_action(args):
1500 tenant = _get_tenant()
1501 datacenter = _get_datacenter(args.datacenter, tenant)
1502 #print "datacenter_netmap_action",args
1503 payload_req = None
1504 if args.verbose==None:
1505 args.verbose=0
1506 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1507 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1508
1509 if args.action=="netmap-list":
1510 if args.netmap:
1511 URLrequest += "/" + args.netmap
1512 args.verbose += 1
1513 mano_response = requests.get(URLrequest)
1514
1515 elif args.action=="netmap-delete":
1516 if args.netmap and args.all:
1517 print "you can not use a netmap name and the option --all at the same time"
1518 return 1
1519 if args.netmap:
1520 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1521 URLrequest += "/" + args.netmap
1522 elif args.all:
1523 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1524 else:
tiernoae4a8d12016-07-08 12:30:39 +02001525 print "you must specify a netmap name or the option --all"
tierno7edb6752016-03-21 17:37:52 +01001526 return 1
1527 if not args.force:
1528 r = raw_input(force_text)
1529 if len(r)>0 and r[0].lower()=="y":
1530 pass
1531 else:
1532 return 0
1533 mano_response = requests.delete(URLrequest, headers=headers_req)
tierno5acf7202016-08-29 14:28:13 +02001534 elif args.action=="netmap-import":
tierno7edb6752016-03-21 17:37:52 +01001535 if not args.force:
1536 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1537 if len(r)>0 and r[0].lower()=="y":
1538 pass
1539 else:
1540 return 0
1541 URLrequest += "/upload"
1542 mano_response = requests.post(URLrequest, headers=headers_req)
1543 elif args.action=="netmap-edit" or args.action=="netmap-create":
1544 if args.file:
1545 payload = _load_file_or_yaml(args.file)
1546 else:
1547 payload = {}
1548 if "netmap" not in payload:
1549 payload = {"netmap": payload}
1550 if args.name:
1551 payload["netmap"]["name"] = args.name
1552 if args.vim_id:
1553 payload["netmap"]["vim_id"] = args.vim_id
1554 if args.action=="netmap-create" and args.vim_name:
1555 payload["netmap"]["vim_name"] = args.vim_name
1556 payload_req = json.dumps(payload)
1557 logger.debug("openmano request: %s", payload_req)
1558
1559 if args.action=="netmap-edit" and not args.force:
1560 if len(payload["netmap"]) == 0:
1561 print "You must supply some parameter to edit"
1562 return 1
1563 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1564 if len(r)>0 and r[0].lower()=="y":
1565 pass
1566 else:
1567 return 0
1568 URLrequest += "/" + args.netmap
1569 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1570 else: #netmap-create
1571 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1572 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1573 return 1
1574 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1575
1576 logger.debug("openmano response: %s", mano_response.text )
1577 return _print_verbose(mano_response, args.verbose)
1578
tierno20df3bb2017-07-07 14:31:00 +02001579
tierno7edb6752016-03-21 17:37:52 +01001580def element_edit(args):
1581 element = _get_item_uuid(args.element, args.name)
1582 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1583 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1584 payload=_load_file_or_yaml(args.file)
1585 if args.element[:-1] not in payload:
1586 payload = {args.element[:-1]: payload }
1587 payload_req = json.dumps(payload)
1588
1589 #print payload_req
1590 if not args.force or (args.name==None and args.filer==None):
1591 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1592 if len(r)>0 and r[0].lower()=="y":
1593 pass
1594 else:
1595 return 0
1596 logger.debug("openmano request: %s", payload_req)
1597 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1598 logger.debug("openmano response: %s", mano_response.text )
1599 if args.verbose==None:
1600 args.verbose=0
1601 if args.name!=None:
1602 args.verbose += 1
1603 return _print_verbose(mano_response, args.verbose)
1604
1605
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001606def datacenter_edit(args):
1607 tenant = _get_tenant()
1608 element = _get_item_uuid('datacenters', args.name, tenant)
1609 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1610 URLrequest = "http://%s:%s/openmano/datacenters/%s" % (mano_host, mano_port, element)
1611
1612 has_arguments = False
1613 if args.file != None:
1614 has_arguments = True
1615 payload = _load_file_or_yaml(args.file)
1616 else:
1617 payload = {}
1618
1619 if args.sdn_controller != None:
1620 has_arguments = True
1621 if not 'config' in payload:
1622 payload['config'] = {}
1623 if not 'sdn-controller' in payload['config']:
1624 payload['config']['sdn-controller'] = {}
1625 if args.sdn_controller == 'null':
1626 payload['config']['sdn-controller'] = None
1627 else:
1628 payload['config']['sdn-controller'] = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1629
1630 if not has_arguments:
1631 raise OpenmanoCLIError("At least one argument must be provided to modify the datacenter")
1632
1633 if 'datacenter' not in payload:
1634 payload = {'datacenter': payload}
1635 payload_req = json.dumps(payload)
1636
1637 # print payload_req
1638 if not args.force or (args.name == None and args.filer == None):
1639 r = raw_input(" Edit datacenter " + args.name + " (y/N)? ")
1640 if len(r) > 0 and r[0].lower() == "y":
1641 pass
1642 else:
1643 return 0
1644 logger.debug("openmano request: %s", payload_req)
1645 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1646 logger.debug("openmano response: %s", mano_response.text)
1647 if args.verbose == None:
1648 args.verbose = 0
1649 if args.name != None:
1650 args.verbose += 1
1651 return _print_verbose(mano_response, args.verbose)
1652
tierno20df3bb2017-07-07 14:31:00 +02001653
tierno6ddeded2017-05-16 15:40:26 +02001654def version(args):
1655 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1656 URLrequest = "http://%s:%s/openmano/version" % (mano_host, mano_port)
1657
1658 mano_response = requests.get(URLrequest, headers=headers_req)
1659 logger.debug("openmano response: %s", mano_response.text)
1660 print mano_response.text
1661
1662
tierno7edb6752016-03-21 17:37:52 +01001663global mano_host
1664global mano_port
1665global mano_tenant
1666
1667if __name__=="__main__":
1668
1669 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1670 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1671 mano_port = os.getenv('OPENMANO_PORT',"9090")
1672 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1673
1674 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
tierno6ddeded2017-05-16 15:40:26 +02001675 main_parser.add_argument('--version', action='version', help="get version of this client",
1676 version='%(prog)s client version ' + __version__ +
1677 " (Note: use '%(prog)s version' to get server version)")
1678
tierno7edb6752016-03-21 17:37:52 +01001679 subparsers = main_parser.add_subparsers(help='commands')
1680
tierno7edb6752016-03-21 17:37:52 +01001681 parent_parser = argparse.ArgumentParser(add_help=False)
1682 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1683 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1684
garciadeblas0e9fd832016-07-08 15:20:18 +02001685 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1686 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1687 config_parser.set_defaults(func=config)
1688
tierno6ddeded2017-05-16 15:40:26 +02001689 version_parser = subparsers.add_parser('version', parents=[parent_parser], help="get server version")
1690 version_parser.set_defaults(func=version)
1691
tierno7edb6752016-03-21 17:37:52 +01001692 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1693 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1694 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1695 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1696 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
garciadeblas14480452017-01-10 13:08:07 +01001697 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1698 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
tierno7edb6752016-03-21 17:37:52 +01001699 vnf_create_parser.set_defaults(func=vnf_create)
1700
1701 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1702 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1703 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1704 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1705 vnf_list_parser.set_defaults(func=vnf_list)
1706
1707 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1708 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1709 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1710 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1711 vnf_delete_parser.set_defaults(func=vnf_delete)
1712
1713 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1714 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1715 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1716 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1717 scenario_create_parser.set_defaults(func=scenario_create)
1718
1719 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1720 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1721 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1722 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1723 scenario_list_parser.set_defaults(func=scenario_list)
1724
1725 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1726 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1727 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1728 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1729 scenario_delete_parser.set_defaults(func=scenario_delete)
1730
1731 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1732 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1733 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1734 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1735 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1736 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1737 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1738
1739 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1740 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1741 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1742 scenario_deploy_parser.set_defaults(func=scenario_verify)
1743
1744 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1745 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1746 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1747 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1748 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1749 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1750 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")
1751 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 +02001752 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")
1753 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 +01001754 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1755 instance_scenario_create_parser.set_defaults(func=instance_create)
1756
1757 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1758 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1759 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1760 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1761
1762 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)")
1763 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1764 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1765 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1766 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1767
1768 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1769 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1770 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
gcalvinoe580c7d2017-09-22 14:09:51 +02001771 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console", "add_public_key"],\
tierno7edb6752016-03-21 17:37:52 +01001772 help="action to send")
1773 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1774 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1775 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1776 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1777
tierno868220c2017-09-26 00:11:05 +02001778 action_parser = subparsers.add_parser('action-list', parents=[parent_parser], help="get action over an instance status")
1779 action_parser.add_argument("id", nargs='?', action="store", help="action id")
1780 action_parser.add_argument("--instance", action="store", help="fitler by this instance_id")
1781 action_parser.add_argument("--all", action="store", help="Not filter by tenant")
1782 action_parser.set_defaults(func=get_action)
1783
tierno7edb6752016-03-21 17:37:52 +01001784 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1785 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1786 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1787
1788 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1789 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1790 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1791 tenant_create_parser.set_defaults(func=tenant_create)
1792
1793 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1794 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1795 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1796 tenant_delete_parser.set_defaults(func=tenant_delete)
1797
1798 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1799 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1800 tenant_list_parser.set_defaults(func=tenant_list)
1801
tierno161c24b2017-05-16 15:45:56 +02001802 element_edit_parser = subparsers.add_parser('tenant-edit', parents=[parent_parser], help="edits one tenant")
1803 element_edit_parser.add_argument("name", help="name or uuid of the tenant")
1804 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1805 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1806 element_edit_parser.set_defaults(func=element_edit, element='tenants')
tierno7edb6752016-03-21 17:37:52 +01001807
1808 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1809 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1810 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1811 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1812 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1813 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1814 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001815 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 +01001816 datacenter_create_parser.set_defaults(func=datacenter_create)
1817
1818 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1819 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1820 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1821 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1822
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001823 datacenter_edit_parser = subparsers.add_parser('datacenter-edit', parents=[parent_parser], help="Edit datacenter")
1824 datacenter_edit_parser.add_argument("name", help="name or uuid of the datacenter")
1825 datacenter_edit_parser.add_argument("--file", help="json/yaml text or file with the changes").completer = FilesCompleter
1826 datacenter_edit_parser.add_argument("--sdn-controller", action="store",
1827 help="Name or uuid of the SDN controller to be used. Specify 'null' to clear entry", dest='sdn_controller')
1828 datacenter_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1829 datacenter_edit_parser.set_defaults(func=datacenter_edit)
1830
tierno7edb6752016-03-21 17:37:52 +01001831 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1832 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1833 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1834 datacenter_list_parser.set_defaults(func=datacenter_list)
1835
1836 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1837 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1838 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1839 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1840 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1841 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
tierno8008c3a2016-10-13 15:34:28 +00001842 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
tierno7edb6752016-03-21 17:37:52 +01001843 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1844
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001845 datacenter_edit_vim_tenant_parser = subparsers.add_parser('datacenter-edit-vim-tenant', parents=[parent_parser],
1846 help="Edit the association of a datacenter to the operating tenant")
1847 datacenter_edit_vim_tenant_parser.add_argument("name", help="name or uuid of the datacenter")
1848 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-id', action='store',
1849 help="specify a datacenter tenant to use. A new one is created by default")
1850 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1851 datacenter_edit_vim_tenant_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1852 datacenter_edit_vim_tenant_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1853 datacenter_edit_vim_tenant_parser.add_argument("--config", action="store",
1854 help="aditional configuration in json/yaml format")
1855 datacenter_edit_vim_tenant_parser.set_defaults(func=datacenter_edit_vim_tenant)
1856
tierno7edb6752016-03-21 17:37:52 +01001857 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1858 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1859 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1860 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1861
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001862 #=======================datacenter_sdn_port_mapping_xxx section=======================
1863 #datacenter_sdn_port_mapping_set
1864 datacenter_sdn_port_mapping_set_parser = subparsers.add_parser('datacenter-sdn-port-mapping-set',
1865 parents=[parent_parser],
1866 help="Load a file with the mapping of physical ports "
1867 "and the ports of the dataplaneswitch controlled "
1868 "by a datacenter")
1869 datacenter_sdn_port_mapping_set_parser.add_argument("name", action="store", help="specifies the datacenter")
1870 datacenter_sdn_port_mapping_set_parser.add_argument("file",
1871 help="json/yaml text or file with the port mapping").completer = FilesCompleter
1872 datacenter_sdn_port_mapping_set_parser.add_argument("-f", "--force", action="store_true",
1873 help="forces overwriting without asking")
1874 datacenter_sdn_port_mapping_set_parser.set_defaults(func=datacenter_sdn_port_mapping_set)
1875
1876 #datacenter_sdn_port_mapping_list
1877 datacenter_sdn_port_mapping_list_parser = subparsers.add_parser('datacenter-sdn-port-mapping-list',
1878 parents=[parent_parser],
1879 help="Show the SDN port mapping in a datacenter")
1880 datacenter_sdn_port_mapping_list_parser.add_argument("name", action="store", help="specifies the datacenter")
1881 datacenter_sdn_port_mapping_list_parser.set_defaults(func=datacenter_sdn_port_mapping_list)
1882
1883 # datacenter_sdn_port_mapping_clear
1884 datacenter_sdn_port_mapping_clear_parser = subparsers.add_parser('datacenter-sdn-port-mapping-clear',
1885 parents=[parent_parser],
1886 help="Clean the the SDN port mapping in a datacenter")
1887 datacenter_sdn_port_mapping_clear_parser.add_argument("name", action="store",
1888 help="specifies the datacenter")
1889 datacenter_sdn_port_mapping_clear_parser.add_argument("-f", "--force", action="store_true",
1890 help="forces clearing without asking")
1891 datacenter_sdn_port_mapping_clear_parser.set_defaults(func=datacenter_sdn_port_mapping_clear)
1892 # =======================
1893
1894 # =======================sdn_controller_xxx section=======================
1895 # sdn_controller_create
1896 sdn_controller_create_parser = subparsers.add_parser('sdn-controller-create', parents=[parent_parser],
1897 help="Creates an SDN controller entity within RO")
1898 sdn_controller_create_parser.add_argument("name", help="name of the SDN controller")
1899 sdn_controller_create_parser.add_argument("--description", action="store", help="description of the SDN controller")
1900 sdn_controller_create_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1901 sdn_controller_create_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1902 sdn_controller_create_parser.add_argument("--dpid", action="store",
1903 help="DPID of the dataplane switch controlled by this SDN controller")
1904 sdn_controller_create_parser.add_argument("--type", action="store",
1905 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1906 sdn_controller_create_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1907 sdn_controller_create_parser.add_argument("--passwd", action="store", dest='password',
1908 help="password credentials for the SDN controller")
1909 sdn_controller_create_parser.set_defaults(func=sdn_controller_create)
1910
1911 # sdn_controller_edit
1912 sdn_controller_edit_parser = subparsers.add_parser('sdn-controller-edit', parents=[parent_parser],
1913 help="Update one or more options of a SDN controller")
1914 sdn_controller_edit_parser.add_argument("name", help="name or uuid of the SDN controller", )
1915 sdn_controller_edit_parser.add_argument("--name", action="store", help="Update the name of the SDN controller",
1916 dest='new_name')
1917 sdn_controller_edit_parser.add_argument("--description", action="store", help="description of the SDN controller")
1918 sdn_controller_edit_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1919 sdn_controller_edit_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1920 sdn_controller_edit_parser.add_argument("--dpid", action="store",
1921 help="DPID of the dataplane switch controlled by this SDN controller")
1922 sdn_controller_edit_parser.add_argument("--type", action="store",
1923 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1924 sdn_controller_edit_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1925 sdn_controller_edit_parser.add_argument("--password", action="store",
1926 help="password credentials for the SDN controller", dest='password')
1927 sdn_controller_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1928 #TODO: include option --file
1929 sdn_controller_edit_parser.set_defaults(func=sdn_controller_edit)
1930
1931 #sdn_controller_list
1932 sdn_controller_list_parser = subparsers.add_parser('sdn-controller-list',
1933 parents=[parent_parser],
1934 help="List the SDN controllers")
1935 sdn_controller_list_parser.add_argument("name", nargs='?', help="name or uuid of the SDN controller")
1936 sdn_controller_list_parser.set_defaults(func=sdn_controller_list)
1937
1938 # sdn_controller_delete
1939 sdn_controller_delete_parser = subparsers.add_parser('sdn-controller-delete',
1940 parents=[parent_parser],
1941 help="Delete the the SDN controller")
1942 sdn_controller_delete_parser.add_argument("name", help="name or uuid of the SDN controller")
1943 sdn_controller_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1944 sdn_controller_delete_parser.set_defaults(func=sdn_controller_delete)
1945 # =======================
tierno7edb6752016-03-21 17:37:52 +01001946
1947 action_dict={'net-update': 'retrieves external networks from datacenter',
1948 'net-edit': 'edits an external network',
1949 'net-delete': 'deletes an external network',
1950 'net-list': 'lists external networks from a datacenter'
1951 }
1952 for item in action_dict:
1953 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1954 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1955 if item=='net-edit' or item=='net-delete':
1956 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1957 if item=='net-edit':
1958 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1959 if item!='net-list':
1960 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1961 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1962
1963
tierno5acf7202016-08-29 14:28:13 +02001964 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
tierno7edb6752016-03-21 17:37:52 +01001965 'netmap-create': 'create a new network senario netmap',
1966 'netmap-edit': 'edit name of a network senario netmap',
1967 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1968 'netmap-list': 'list/show network scenario netmaps'
1969 }
1970 for item in action_dict:
1971 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1972 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1973 #if item=='net-add':
1974 # datacenter_action_parser.add_argument("net", help="name of the network")
1975 if item=='netmap-delete':
1976 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1977 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1978 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1979 if item=='netmap-edit':
1980 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1981 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1982 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1983 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1984 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1985 if item=='netmap-list':
1986 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1987 if item=='netmap-create':
1988 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1989 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1990 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1991 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
tierno5acf7202016-08-29 14:28:13 +02001992 if item=='netmap-import':
tierno7edb6752016-03-21 17:37:52 +01001993 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1994 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001995
1996 # =======================vim_net_sdn_xxx section=======================
1997 # vim_net_sdn_attach
1998 vim_net_sdn_attach_parser = subparsers.add_parser('vim-net-sdn-attach',
1999 parents=[parent_parser],
2000 help="Specify the port to access to an external network using SDN")
2001 vim_net_sdn_attach_parser.add_argument("vim_net", action="store",
2002 help="Name/id of the network in the vim that will be used to connect to the external network")
2003 vim_net_sdn_attach_parser.add_argument("port", action="store", help="Specifies the port in the dataplane switch to access to the external network")
2004 vim_net_sdn_attach_parser.add_argument("--vlan", action="store", help="Specifies the vlan (if any) to use in the defined port")
2005 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")
2006 vim_net_sdn_attach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2007 vim_net_sdn_attach_parser.set_defaults(func=vim_net_sdn_attach)
2008
2009 # vim_net_sdn_detach
2010 vim_net_sdn_detach_parser = subparsers.add_parser('vim-net-sdn-detach',
2011 parents=[parent_parser],
2012 help="Remove the port information to access to an external network using SDN")
2013
2014 vim_net_sdn_detach_parser.add_argument("vim_net", action="store", help="Name/id of the vim network")
2015 vim_net_sdn_detach_parser.add_argument("--id", action="store",help="Specify the uuid of the external ports from this network to be detached")
2016 vim_net_sdn_detach_parser.add_argument("--all", action="store_true", help="Detach all external ports from this network")
2017 vim_net_sdn_detach_parser.add_argument("-f", "--force", action="store_true", help="forces clearing without asking")
2018 vim_net_sdn_detach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2019 vim_net_sdn_detach_parser.set_defaults(func=vim_net_sdn_detach)
2020 # =======================
2021
tierno4540ea52017-01-18 17:44:32 +01002022 for item in ("network", "tenant", "image"):
tierno7edb6752016-03-21 17:37:52 +01002023 if item=="network":
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002024 command_name = 'vim-net'
tierno7edb6752016-03-21 17:37:52 +01002025 else:
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002026 command_name = 'vim-'+item
2027 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 +01002028 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
2029 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2030 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
2031
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002032 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 +01002033 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
2034 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2035 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
2036
tierno4540ea52017-01-18 17:44:32 +01002037 if item == "network" or item == "tenant":
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002038 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 +01002039 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
2040 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
2041 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2042 if item=="network":
2043 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
2044 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
2045 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>'")
2046 else:
2047 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
2048 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
tierno7edb6752016-03-21 17:37:52 +01002049
2050 argcomplete.autocomplete(main_parser)
2051
2052 try:
2053 args = main_parser.parse_args()
2054 #logging info
2055 level = logging.CRITICAL
2056 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
2057 if "debug" in args and args.debug:
2058 level = logging.DEBUG
2059 logging.basicConfig(format=streamformat, level= level)
2060 logger = logging.getLogger('mano')
2061 logger.setLevel(level)
2062 result = args.func(args)
2063 if result == None:
2064 result = 0
2065 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
2066 except (requests.exceptions.ConnectionError):
2067 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
2068 result = -2
2069 except (KeyboardInterrupt):
2070 print 'Exiting openmano'
2071 result = -3
2072 except (SystemExit, ArgumentParserError):
2073 result = -4
2074 except OpenmanoCLIError as e:
2075 print str(e)
2076 result = -5
2077
2078 #print result
2079 exit(result)
2080