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