blob: 6af5ea58091fa8886a61126e2c1e39f8ef299a7a [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$"
tiernof1ba57e2017-09-07 12:23:19 +020031__version__ = "0.4.20-r530"
32version_date = "Sep 2017"
tierno7edb6752016-03-21 17:37:52 +010033
34from argcomplete.completers import FilesCompleter
35import os
36import argparse
37import argcomplete
38import requests
39import json
40import yaml
41import logging
42#from jsonschema import validate as js_v, exceptions as js_e
43
44class ArgumentParserError(Exception): pass
45
46class OpenmanoCLIError(Exception): pass
47
48class ThrowingArgumentParser(argparse.ArgumentParser):
49 def error(self, message):
50 print "Error: %s" %message
51 print
52 self.print_usage()
53 #self.print_help()
54 print
55 print "Type 'openmano -h' for help"
56 raise ArgumentParserError
57
58
59def config(args):
60 print "OPENMANO_HOST: %s" %mano_host
61 print "OPENMANO_PORT: %s" %mano_port
garciadeblas0e9fd832016-07-08 15:20:18 +020062 if args.n:
63 logger.debug("resolving tenant and datacenter names")
64 mano_tenant_id = "None"
65 mano_tenant_name = "None"
66 mano_datacenter_id = "None"
67 mano_datacenter_name = "None"
68 try:
69 mano_tenant_id = _get_item_uuid("tenants", mano_tenant)
70 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, mano_tenant_id)
71 mano_response = requests.get(URLrequest)
72 logger.debug("openmano response: %s", mano_response.text )
73 content = mano_response.json()
74 mano_tenant_name = content["tenant"]["name"]
75 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, mano_tenant_id, mano_datacenter)
76 mano_response = requests.get(URLrequest)
77 logger.debug("openmano response: %s", mano_response.text )
78 content = mano_response.json()
79 if "error" not in content:
80 mano_datacenter_id = content["datacenter"]["uuid"]
81 mano_datacenter_name = content["datacenter"]["name"]
82 except OpenmanoCLIError:
83 pass
84 print "OPENMANO_TENANT: %s" %mano_tenant
85 print " Id: %s" %mano_tenant_id
86 print " Name: %s" %mano_tenant_name
87 print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
88 print " Id: %s" %mano_datacenter_id
89 print " Name: %s" %mano_datacenter_name
90 else:
91 print "OPENMANO_TENANT: %s" %mano_tenant
92 print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
tierno7edb6752016-03-21 17:37:52 +010093
94def _print_verbose(mano_response, verbose_level=0):
95 content = mano_response.json()
96 result = 0 if mano_response.status_code==200 else mano_response.status_code
97 if type(content)!=dict or len(content)!=1:
98 #print "Non expected format output"
99 print str(content)
100 return result
101
102 val=content.values()[0]
103 if type(val)==str:
104 print val
105 return result
106 elif type(val) == list:
107 content_list = val
108 elif type(val)==dict:
109 content_list = [val]
110 else:
111 #print "Non expected dict/list format output"
112 print str(content)
113 return result
114
115 #print content_list
116 if verbose_level==None:
117 verbose_level=0
118 if verbose_level >= 3:
119 print yaml.safe_dump(content, indent=4, default_flow_style=False)
120 return result
121
122 if mano_response.status_code == 200:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100123 uuid = None
tierno7edb6752016-03-21 17:37:52 +0100124 for content in content_list:
125 if "uuid" in content:
126 uuid = content['uuid']
127 elif "id" in content:
128 uuid = content['id']
129 elif "vim_id" in content:
130 uuid = content['vim_id']
tierno250954a2017-01-31 14:25:57 +0100131 name = content.get('name');
132 if not uuid:
133 uuid = ""
134 if not name:
135 name = ""
136 myoutput = "%s %s" %(uuid.ljust(38),name.ljust(20))
137 if content.get("status"):
tierno7edb6752016-03-21 17:37:52 +0100138 myoutput += " " + content['status'].ljust(20)
139 elif "enabled" in content and not content["enabled"]:
140 myoutput += " enabled=False".ljust(20)
141 if verbose_level >=1:
tierno250954a2017-01-31 14:25:57 +0100142 if content.get('created_at'):
143 myoutput += " " + content['created_at'].ljust(20)
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'):
tierno7edb6752016-03-21 17:37:52 +0100150 myoutput += new_line + " Type: " + content['type'].ljust(29)
151 new_line=''
tierno250954a2017-01-31 14:25:57 +0100152 if content.get('description'):
tierno7edb6752016-03-21 17:37:52 +0100153 myoutput += new_line + " Description: " + content['description'].ljust(20)
154 print myoutput
155 else:
156 print content['error']['description']
157 return result
158
159def parser_json_yaml(file_name):
160 try:
161 f = file(file_name, "r")
162 text = f.read()
163 f.close()
164 except Exception as e:
165 return (False, str(e))
166
167 #Read and parse file
168 if file_name[-5:]=='.yaml' or file_name[-4:]=='.yml' or (file_name[-5:]!='.json' and '\t' not in text):
169 try:
170 config = yaml.load(text)
171 except yaml.YAMLError as exc:
172 error_pos = ""
173 if hasattr(exc, 'problem_mark'):
174 mark = exc.problem_mark
175 error_pos = " at line:%s column:%s" % (mark.line+1, mark.column+1)
176 return (False, "Error loading file '"+file_name+"' yaml format error" + error_pos)
177 else: #json
178 try:
179 config = json.loads(text)
180 except Exception as e:
181 return (False, "Error loading file '"+file_name+"' json format error " + str(e) )
182
183 return True, config
184
185def _load_file_or_yaml(content):
186 '''
187 'content' can be or a yaml/json file or a text containing a yaml/json text format
188 This function autodetect, trying to load and parse the file,
189 if fails trying to parse the 'content' text
190 Returns the dictionary once parsed, or print an error and finish the program
191 '''
192 #Check config file exists
193 if os.path.isfile(content):
194 r,payload = parser_json_yaml(content)
195 if not r:
196 print payload
197 exit(-1)
198 elif "{" in content or ":" in content:
199 try:
200 payload = yaml.load(content)
201 except yaml.YAMLError as exc:
202 error_pos = ""
203 if hasattr(exc, 'problem_mark'):
204 mark = exc.problem_mark
205 error_pos = " at position: (%s:%s)" % (mark.line+1, mark.column+1)
206 print "Error loading yaml/json text"+error_pos
207 exit (-1)
208 else:
209 print "'%s' is neither a valid file nor a yaml/json content" % content
210 exit(-1)
211 return payload
212
213def _get_item_uuid(item, item_name_id, tenant=None):
214 if tenant:
215 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, tenant, item)
216 else:
217 URLrequest = "http://%s:%s/openmano/%s" %(mano_host, mano_port, item)
218 mano_response = requests.get(URLrequest)
219 logger.debug("openmano response: %s", mano_response.text )
220 content = mano_response.json()
221 #print content
222 found = 0
223 for i in content[item]:
224 if i["uuid"] == item_name_id:
225 return item_name_id
226 if i["name"] == item_name_id:
227 uuid = i["uuid"]
228 found += 1
tiernof1ba57e2017-09-07 12:23:19 +0200229 if item_name_id.startswith("osm_id=") and i.get("osm_id") == item_name_id[7:]:
230 uuid = i["uuid"]
231 found += 1
tierno7edb6752016-03-21 17:37:52 +0100232 if found == 0:
233 raise OpenmanoCLIError("No %s found with name/uuid '%s'" %(item[:-1], item_name_id))
234 elif found > 1:
235 raise OpenmanoCLIError("%d %s found with name '%s'. uuid must be used" %(found, item, item_name_id))
236 return uuid
237#
238# def check_valid_uuid(uuid):
239# id_schema = {"type" : "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
240# try:
241# js_v(uuid, id_schema)
242# return True
243# except js_e.ValidationError:
244# return False
245
246def _get_tenant(tenant_name_id = None):
247 if not tenant_name_id:
248 tenant_name_id = mano_tenant
249 if not mano_tenant:
250 raise OpenmanoCLIError("'OPENMANO_TENANT' environment variable is not set")
251 return _get_item_uuid("tenants", tenant_name_id)
252
253def _get_datacenter(datacenter_name_id = None, tenant = "any"):
254 if not datacenter_name_id:
255 datacenter_name_id = mano_datacenter
256 if not datacenter_name_id:
257 raise OpenmanoCLIError("neither 'OPENMANO_DATACENTER' environment variable is set nor --datacenter option is used")
258 return _get_item_uuid("datacenters", datacenter_name_id, tenant)
259
260def vnf_create(args):
261 #print "vnf-create",args
262 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
263 tenant = _get_tenant()
264 myvnf = _load_file_or_yaml(args.file)
tiernof1ba57e2017-09-07 12:23:19 +0200265 api_version = ""
266 if "vnfd:vnfd-catalog" in myvnf or "vnfd-catalog" in myvnf:
267 api_version = "/v3"
268 token = "vnfd"
269 vnfd_catalog = myvnf.get("vnfd:vnfd-catalog")
270 if not vnfd_catalog:
271 vnfd_catalog = myvnf.get("vnfd-catalog")
272 vnfds = vnfd_catalog.get("vnfd:vnfd")
273 if not vnfds:
274 vnfds = vnfd_catalog.get("vnfd")
275 vnfd = vnfds[0]
276 vdu_list = vnfd["vdu"]
277
278 else: # old API
279 api_version = ""
280 token = "vnfs"
281 vnfd = myvnf['vnf']
282 vdu_list = vnfd["VNFC"]
tierno7edb6752016-03-21 17:37:52 +0100283
garciadeblas14480452017-01-10 13:08:07 +0100284 if args.name or args.description or args.image_path or args.image_name or args.image_checksum:
tiernof1ba57e2017-09-07 12:23:19 +0200285 # TODO, change this for API v3
286 # print args.name
tierno7edb6752016-03-21 17:37:52 +0100287 try:
288 if args.name:
tiernof1ba57e2017-09-07 12:23:19 +0200289 vnfd['name'] = args.name
tierno7edb6752016-03-21 17:37:52 +0100290 if args.description:
tiernof1ba57e2017-09-07 12:23:19 +0200291 vnfd['description'] = args.description
tierno7edb6752016-03-21 17:37:52 +0100292 if args.image_path:
tiernof1ba57e2017-09-07 12:23:19 +0200293 index = 0
tierno7edb6752016-03-21 17:37:52 +0100294 for image_path_ in args.image_path.split(","):
tiernof1ba57e2017-09-07 12:23:19 +0200295 # print "image-path", image_path_
296 if api_version == "/v3":
297 if vdu_list[index].get("image"):
298 vdu_list[index]['image'] = image_path_
299 if "image-checksum" in vdu_list[index]:
300 del vdu_list[index]["image-checksum"]
301 else: # image name in volumes
302 vdu_list[index]["volumes"][0]["image"] = image_path_
303 if "image-checksum" in vdu_list[index]["volumes"][0]:
304 del vdu_list[index]["volumes"][0]["image-checksum"]
305 else:
306 vdu_list[index]['VNFC image'] = image_path_
307 if "image name" in vdu_list[index]:
308 del vdu_list[index]["image name"]
309 if "image checksum" in vdu_list[index]:
310 del vdu_list[index]["image checksum"]
311 index += 1
312 if args.image_name: # image name precedes if both are supplied
313 index = 0
garciadeblas14480452017-01-10 13:08:07 +0100314 for image_name_ in args.image_name.split(","):
tiernof1ba57e2017-09-07 12:23:19 +0200315 if api_version == "/v3":
316 if vdu_list[index].get("image"):
317 vdu_list[index]['image'] = image_name_
318 if "image-checksum" in vdu_list[index]:
319 del vdu_list[index]["image-checksum"]
320 else: # image name in volumes
321 vdu_list[index]["volumes"][0]["image"] = image_name_
322 if "image-checksum" in vdu_list[index]["volumes"][0]:
323 del vdu_list[index]["volumes"][0]["image-checksum"]
324 else:
325 vdu_list[index]['image name'] = image_name_
326 if "VNFC image" in vdu_list[index]:
327 del vdu_list[index]["VNFC image"]
328 index += 1
garciadeblas14480452017-01-10 13:08:07 +0100329 if args.image_checksum:
tiernof1ba57e2017-09-07 12:23:19 +0200330 index = 0
garciadeblas14480452017-01-10 13:08:07 +0100331 for image_checksum_ in args.image_checksum.split(","):
tiernof1ba57e2017-09-07 12:23:19 +0200332 if api_version == "/v3":
333 if vdu_list[index].get("image"):
334 vdu_list[index]['image-checksum'] = image_checksum_
335 else: # image name in volumes
336 vdu_list[index]["volumes"][0]["image-checksum"] = image_checksum_
337 else:
338 vdu_list[index]['image checksum'] = image_checksum_
339 index += 1
tierno7edb6752016-03-21 17:37:52 +0100340 except (KeyError, TypeError), e:
tiernof1ba57e2017-09-07 12:23:19 +0200341 if str(e) == 'vnf': error_pos= "missing field 'vnf'"
342 elif str(e) == 'name': error_pos= "missing field 'vnf':'name'"
343 elif str(e) == 'description': error_pos= "missing field 'vnf':'description'"
344 elif str(e) == 'VNFC': error_pos= "missing field 'vnf':'VNFC'"
345 elif str(e) == str(index): error_pos= "field 'vnf':'VNFC' must be an array"
346 elif str(e) == 'VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
347 elif str(e) == 'image name': error_pos= "missing field 'vnf':'VNFC'['image name']"
348 elif str(e) == 'image checksum': error_pos= "missing field 'vnf':'VNFC'['image checksum']"
tierno7edb6752016-03-21 17:37:52 +0100349 else: error_pos="wrong format"
350 print "Wrong VNF descriptor: " + error_pos
351 return -1
352 payload_req = json.dumps(myvnf)
353
354 #print payload_req
355
tiernof1ba57e2017-09-07 12:23:19 +0200356 URLrequest = "http://{}:{}/openmano{}/{}/{token}".format(mano_host, mano_port, api_version, tenant, token=token)
tierno7edb6752016-03-21 17:37:52 +0100357 logger.debug("openmano request: %s", payload_req)
358 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
359 logger.debug("openmano response: %s", mano_response.text )
360
361 return _print_verbose(mano_response, args.verbose)
362
363def vnf_list(args):
364 #print "vnf-list",args
365 if args.all:
366 tenant = "any"
367 else:
368 tenant = _get_tenant()
369 if args.name:
370 toshow = _get_item_uuid("vnfs", args.name, tenant)
371 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
372 else:
373 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
374 mano_response = requests.get(URLrequest)
375 logger.debug("openmano response: %s", mano_response.text )
376 content = mano_response.json()
tiernof1ba57e2017-09-07 12:23:19 +0200377 # print json.dumps(content, indent=4)
tierno7edb6752016-03-21 17:37:52 +0100378 if args.verbose==None:
379 args.verbose=0
380 result = 0 if mano_response.status_code==200 else mano_response.status_code
381 if mano_response.status_code == 200:
382 if not args.name:
383 if args.verbose >= 3:
384 print yaml.safe_dump(content, indent=4, default_flow_style=False)
385 return result
386 if len(content['vnfs']) == 0:
387 print "No VNFs were found."
tiernof1ba57e2017-09-07 12:23:19 +0200388 return 404 # HTTP_Not_Found
tierno7edb6752016-03-21 17:37:52 +0100389 for vnf in content['vnfs']:
tiernof1ba57e2017-09-07 12:23:19 +0200390 myoutput = "{:38} {:20}".format(vnf['uuid'], vnf['name'])
391 if vnf.get('osm_id') or args.verbose >= 1:
392 myoutput += " osm_id={:20}".format(vnf.get('osm_id'))
393 if args.verbose >= 1:
394 myoutput += " {}".format(vnf['created_at'])
395 print (myoutput)
396 if args.verbose >= 2:
397 print (" Description: {}".format(vnf['description']))
398 # print (" VNF descriptor file: {}".format(vnf['path']))
tierno7edb6752016-03-21 17:37:52 +0100399 else:
400 if args.verbose:
401 print yaml.safe_dump(content, indent=4, default_flow_style=False)
402 return result
403 vnf = content['vnf']
tiernof1ba57e2017-09-07 12:23:19 +0200404 print ("{:38} {:20} osm_id={:20} {:20}".format(vnf['uuid'], vnf['name'], vnf.get('osm_id'),
405 vnf['created_at']))
406 print (" Description: {}".format(vnf['description']))
407 # print " VNF descriptor file: %s" %vnf['path']
408 print (" VMs:")
tierno7edb6752016-03-21 17:37:52 +0100409 for vm in vnf['VNFC']:
tiernof1ba57e2017-09-07 12:23:19 +0200410 print (" {:20} osm_id={:20} {}".format(vm['name'], vm.get('osm_id'), vm['description']))
411 if len(vnf['nets']) > 0:
412 print (" Internal nets:")
tierno7edb6752016-03-21 17:37:52 +0100413 for net in vnf['nets']:
tiernof1ba57e2017-09-07 12:23:19 +0200414 print (" {:20} {}".format(net['name'], net['description']))
415 if len(vnf['external-connections']) > 0:
416 print (" External interfaces:")
tierno7edb6752016-03-21 17:37:52 +0100417 for interface in vnf['external-connections']:
tiernof1ba57e2017-09-07 12:23:19 +0200418 print (" {:20} {:20} {:20} {:14}".format(
419 interface['external_name'], interface['vm_name'],
420 interface['internal_name'],
421 interface.get('vpci') if interface.get('vpci') else ""))
tierno7edb6752016-03-21 17:37:52 +0100422 else:
423 print content['error']['description']
424 if args.verbose:
425 print yaml.safe_dump(content, indent=4, default_flow_style=False)
426 return result
427
428def vnf_delete(args):
429 #print "vnf-delete",args
430 if args.all:
431 tenant = "any"
432 else:
433 tenant = _get_tenant()
434 todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
435 if not args.force:
436 r = raw_input("Delete VNF %s (y/N)? " %(todelete))
437 if not (len(r)>0 and r[0].lower()=="y"):
438 return 0
439 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
440 mano_response = requests.delete(URLrequest)
441 logger.debug("openmano response: %s", mano_response.text )
442 result = 0 if mano_response.status_code==200 else mano_response.status_code
443 content = mano_response.json()
444 #print json.dumps(content, indent=4)
445 if mano_response.status_code == 200:
446 print content['result']
447 else:
448 print content['error']['description']
449 return result
450
451def scenario_create(args):
tiernof1ba57e2017-09-07 12:23:19 +0200452 # print "scenario-create",args
tierno7edb6752016-03-21 17:37:52 +0100453 tenant = _get_tenant()
454 headers_req = {'content-type': 'application/yaml'}
455 myscenario = _load_file_or_yaml(args.file)
tiernof1ba57e2017-09-07 12:23:19 +0200456 if "nsd:nsd-catalog" in myscenario or "nsd-catalog" in myscenario:
457 api_version = "/v3"
458 token = "nsd"
459 nsd_catalog = myscenario.get("nsd:nsd-catalog")
460 if not nsd_catalog:
461 nsd_catalog = myscenario.get("nsd-catalog")
462 nsds = nsd_catalog.get("nsd:nsd")
463 if not nsds:
464 nsds = nsd_catalog.get("nsd")
465 nsd = nsds[0]
466 else: # API<v3
467 api_version = ""
468 token = "scenarios"
469 if "scenario" in myscenario:
470 nsd = myscenario["scenario"]
471 else:
472 nsd = myscenario
473 # TODO modify for API v3
tierno7edb6752016-03-21 17:37:52 +0100474 if args.name:
tiernof1ba57e2017-09-07 12:23:19 +0200475 nsd['name'] = args.name
tierno7edb6752016-03-21 17:37:52 +0100476 if args.description:
tiernof1ba57e2017-09-07 12:23:19 +0200477 nsd['description'] = args.description
478 payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False,
479 encoding='utf-8', allow_unicode=True)
tierno7edb6752016-03-21 17:37:52 +0100480
tiernof1ba57e2017-09-07 12:23:19 +0200481 # print payload_req
482 URLrequest = "http://{host}:{port}/openmano{api}/{tenant}/{token}".format(
483 host=mano_host, port=mano_port, api=api_version, tenant=tenant, token=token)
tierno7edb6752016-03-21 17:37:52 +0100484 logger.debug("openmano request: %s", payload_req)
485 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
486 logger.debug("openmano response: %s", mano_response.text )
487 return _print_verbose(mano_response, args.verbose)
488
489def scenario_list(args):
490 #print "scenario-list",args
491 if args.all:
492 tenant = "any"
493 else:
494 tenant = _get_tenant()
495 if args.name:
496 toshow = _get_item_uuid("scenarios", args.name, tenant)
497 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
498 else:
499 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
500 mano_response = requests.get(URLrequest)
501 logger.debug("openmano response: %s", mano_response.text )
502 content = mano_response.json()
503 #print json.dumps(content, indent=4)
504 if args.verbose==None:
505 args.verbose=0
506
507 result = 0 if mano_response.status_code==200 else mano_response.status_code
508 if mano_response.status_code == 200:
509 if not args.name:
510 if args.verbose >= 3:
511 print yaml.safe_dump(content, indent=4, default_flow_style=False)
512 return result
513 if len(content['scenarios']) == 0:
514 print "No scenarios were found."
515 return 404 #HTTP_Not_Found
516 for scenario in content['scenarios']:
tiernof1ba57e2017-09-07 12:23:19 +0200517 myoutput = "{:38} {:20}".format(scenario['uuid'], scenario['name'])
518 if scenario.get('osm_id') or args.verbose >= 1:
519 myoutput += " osm_id={:20}".format(scenario.get('osm_id'))
520 if args.verbose >= 1:
521 myoutput += " {}".format(scenario['created_at'])
522 print (myoutput)
tierno7edb6752016-03-21 17:37:52 +0100523 if args.verbose >=2:
tiernof1ba57e2017-09-07 12:23:19 +0200524 print (" Description: {}".format(scenario['description']))
tierno7edb6752016-03-21 17:37:52 +0100525 else:
526 if args.verbose:
527 print yaml.safe_dump(content, indent=4, default_flow_style=False)
528 return result
529 scenario = content['scenario']
tiernof1ba57e2017-09-07 12:23:19 +0200530 print ("{:38} {:20} osm_id={:20} {:20}".format(scenario['uuid'], scenario['name'], scenario.get('osm_id'),
531 scenario['created_at']))
532 print (" Description: {}".format(scenario['description']))
533 print (" VNFs:")
tierno7edb6752016-03-21 17:37:52 +0100534 for vnf in scenario['vnfs']:
tiernof1ba57e2017-09-07 12:23:19 +0200535 print (" {:38} {:20} vnf_index={} {}".format(vnf['vnf_id'], vnf['name'], vnf.get("member_vnf_index"),
536 vnf['description']))
537 if len(scenario['nets']) > 0:
538 print (" nets:")
tierno7edb6752016-03-21 17:37:52 +0100539 for net in scenario['nets']:
tiernof1ba57e2017-09-07 12:23:19 +0200540 description = net['description']
541 if not description: # if description does not exist, description is "-". Valid for external and internal nets.
542 description = '-'
543 vim_id = ""
544 if net.get('vim_id'):
545 vim_id = " vim_id=" + net["vim_id"]
546 external = ""
547 if net["external"]:
548 external = " external"
549 print (" {:20} {:38} {:30}{}{}".format(net['name'], net['uuid'], description, vim_id, external))
tierno7edb6752016-03-21 17:37:52 +0100550 else:
tiernof1ba57e2017-09-07 12:23:19 +0200551 print (content['error']['description'])
tierno7edb6752016-03-21 17:37:52 +0100552 if args.verbose:
553 print yaml.safe_dump(content, indent=4, default_flow_style=False)
554 return result
555
556def scenario_delete(args):
557 #print "scenario-delete",args
558 if args.all:
559 tenant = "any"
560 else:
561 tenant = _get_tenant()
562 todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
563 if not args.force:
564 r = raw_input("Delete scenario %s (y/N)? " %(args.name))
565 if not (len(r)>0 and r[0].lower()=="y"):
566 return 0
567 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
568 mano_response = requests.delete(URLrequest)
569 logger.debug("openmano response: %s", mano_response.text )
570 result = 0 if mano_response.status_code==200 else mano_response.status_code
571 content = mano_response.json()
572 #print json.dumps(content, indent=4)
573 if mano_response.status_code == 200:
574 print content['result']
575 else:
576 print content['error']['description']
577 return result
578
579def scenario_deploy(args):
580 print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
581 print
582 args.file = None
583 args.netmap_use = None
584 args.netmap_create = None
tiernobe41e222016-09-02 15:16:13 +0200585 args.keypair = None
586 args.keypair_auto = None
tierno7edb6752016-03-21 17:37:52 +0100587 return instance_create(args)
588
589# #print "scenario-deploy",args
590# headers_req = {'content-type': 'application/json'}
591# action = {}
592# actionCmd="start"
593# if args.nostart:
594# actionCmd="reserve"
595# action[actionCmd] = {}
596# action[actionCmd]["instance_name"] = args.name
597# if args.datacenter != None:
598# action[actionCmd]["datacenter"] = args.datacenter
599# elif mano_datacenter != None:
600# action[actionCmd]["datacenter"] = mano_datacenter
601#
602# if args.description:
603# action[actionCmd]["description"] = args.description
604# payload_req = json.dumps(action, indent=4)
605# #print payload_req
606#
607# URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
608# logger.debug("openmano request: %s", payload_req)
609# mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
610# logger.debug("openmano response: %s", mano_response.text )
611# if args.verbose==None:
612# args.verbose=0
613#
614# result = 0 if mano_response.status_code==200 else mano_response.status_code
615# content = mano_response.json()
616# #print json.dumps(content, indent=4)
617# if args.verbose >= 3:
618# print yaml.safe_dump(content, indent=4, default_flow_style=False)
619# return result
620#
621# if mano_response.status_code == 200:
622# myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
623# if args.verbose >=1:
624# myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
625# if args.verbose >=2:
626# myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
627# print myoutput
628# print ""
629# print "To check the status, run the following command:"
630# print "openmano instance-scenario-list <instance_id>"
631# else:
632# print content['error']['description']
633# return result
634
635def scenario_verify(args):
636 #print "scenario-verify",args
tierno72a08d72017-05-25 13:12:30 +0200637 tenant = _get_tenant()
tierno7edb6752016-03-21 17:37:52 +0100638 headers_req = {'content-type': 'application/json'}
639 action = {}
640 action["verify"] = {}
641 action["verify"]["instance_name"] = "scen-verify-return5"
642 payload_req = json.dumps(action, indent=4)
643 #print payload_req
644
tierno72a08d72017-05-25 13:12:30 +0200645 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, tenant, args.scenario)
tierno7edb6752016-03-21 17:37:52 +0100646 logger.debug("openmano request: %s", payload_req)
647 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
648 logger.debug("openmano response: %s", mano_response.text )
649
650 result = 0 if mano_response.status_code==200 else mano_response.status_code
651 content = mano_response.json()
652 #print json.dumps(content, indent=4)
653 if mano_response.status_code == 200:
654 print content['result']
655 else:
656 print content['error']['description']
657 return result
658
659def instance_create(args):
660 tenant = _get_tenant()
661 headers_req = {'content-type': 'application/yaml'}
662 myInstance={"instance": {}, "schema_version": "0.1"}
663 if args.file:
664 instance_dict = _load_file_or_yaml(args.file)
665 if "instance" not in instance_dict:
666 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
667 else:
668 myInstance = instance_dict
669 if args.name:
670 myInstance["instance"]['name'] = args.name
671 if args.description:
672 myInstance["instance"]['description'] = args.description
673 if args.nostart:
674 myInstance["instance"]['action'] = "reserve"
675 #datacenter
676 datacenter = myInstance["instance"].get("datacenter")
677 if args.datacenter != None:
678 datacenter = args.datacenter
679 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
680 #scenario
681 scenario = myInstance["instance"].get("scenario")
682 if args.scenario != None:
683 scenario = args.scenario
684 if not scenario:
garciadeblased746032017-01-05 11:58:41 +0100685 print "you must provide a scenario in the file descriptor or with --scenario"
tierno7edb6752016-03-21 17:37:52 +0100686 return -1
687 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
688 if args.netmap_use:
689 if "networks" not in myInstance["instance"]:
690 myInstance["instance"]["networks"] = {}
691 for net in args.netmap_use:
692 net_comma_list = net.split(",")
693 for net_comma in net_comma_list:
694 net_tuple = net_comma.split("=")
695 if len(net_tuple) != 2:
696 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
697 return
698 net_scenario = net_tuple[0].strip()
699 net_datacenter = net_tuple[1].strip()
700 if net_scenario not in myInstance["instance"]["networks"]:
701 myInstance["instance"]["networks"][net_scenario] = {}
tiernobe41e222016-09-02 15:16:13 +0200702 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
703 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
704 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
tierno7edb6752016-03-21 17:37:52 +0100705 if args.netmap_create:
706 if "networks" not in myInstance["instance"]:
707 myInstance["instance"]["networks"] = {}
708 for net in args.netmap_create:
709 net_comma_list = net.split(",")
710 for net_comma in net_comma_list:
711 net_tuple = net_comma.split("=")
712 if len(net_tuple) == 1:
713 net_scenario = net_tuple[0].strip()
714 net_datacenter = None
715 elif len(net_tuple) == 2:
716 net_scenario = net_tuple[0].strip()
717 net_datacenter = net_tuple[1].strip()
718 else:
719 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
720 return
721 if net_scenario not in myInstance["instance"]["networks"]:
722 myInstance["instance"]["networks"][net_scenario] = {}
tiernobe41e222016-09-02 15:16:13 +0200723 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
724 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
725 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
tiernoa4e1a6e2016-08-31 14:19:40 +0200726 if args.keypair:
727 if "cloud-config" not in myInstance["instance"]:
728 myInstance["instance"]["cloud-config"] = {}
729 cloud_config = myInstance["instance"]["cloud-config"]
730 for key in args.keypair:
731 index = key.find(":")
732 if index<0:
733 if "key-pairs" not in cloud_config:
734 cloud_config["key-pairs"] = []
735 cloud_config["key-pairs"].append(key)
736 else:
737 user = key[:index]
738 key_ = key[index+1:]
739 key_list = key_.split(",")
740 if "users" not in cloud_config:
741 cloud_config["users"] = []
742 cloud_config["users"].append({"name": user, "key-pairs": key_list })
743 if args.keypair_auto:
744 try:
745 keys=[]
746 home = os.getenv("HOME")
747 user = os.getenv("USER")
748 files = os.listdir(home+'/.ssh')
749 for file in files:
750 if file[-4:] == ".pub":
751 with open(home+'/.ssh/'+file, 'r') as f:
752 keys.append(f.read())
753 if not keys:
754 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
755 return 1
756 except Exception as e:
757 print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
758 return 1
759
760 if "cloud-config" not in myInstance["instance"]:
761 myInstance["instance"]["cloud-config"] = {}
762 cloud_config = myInstance["instance"]["cloud-config"]
763 if "key-pairs" not in cloud_config:
764 cloud_config["key-pairs"] = []
765 if user:
766 if "users" not in cloud_config:
767 cloud_config["users"] = []
768 cloud_config["users"].append({"name": user, "key-pairs": keys })
tierno7edb6752016-03-21 17:37:52 +0100769
770 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
771 logger.debug("openmano request: %s", payload_req)
772 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
773 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
774 logger.debug("openmano response: %s", mano_response.text )
775 if args.verbose==None:
776 args.verbose=0
777
778 result = 0 if mano_response.status_code==200 else mano_response.status_code
779 content = mano_response.json()
780 #print json.dumps(content, indent=4)
781 if args.verbose >= 3:
782 print yaml.safe_dump(content, indent=4, default_flow_style=False)
783 return result
784
785 if mano_response.status_code == 200:
786 myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
787 if args.verbose >=1:
788 myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
789 if args.verbose >=2:
790 myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
791 print myoutput
792 else:
793 print content['error']['description']
794 return result
795
796def instance_scenario_list(args):
797 #print "instance-scenario-list",args
798 if args.all:
799 tenant = "any"
800 else:
801 tenant = _get_tenant()
802 if args.name:
803 toshow = _get_item_uuid("instances", args.name, tenant)
804 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
805 else:
806 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
807 mano_response = requests.get(URLrequest)
808 logger.debug("openmano response: %s", mano_response.text )
809 content = mano_response.json()
810 #print json.dumps(content, indent=4)
811 if args.verbose==None:
812 args.verbose=0
813
814 result = 0 if mano_response.status_code==200 else mano_response.status_code
815 if mano_response.status_code == 200:
816 if not args.name:
817 if args.verbose >= 3:
818 print yaml.safe_dump(content, indent=4, default_flow_style=False)
819 return result
820 if len(content['instances']) == 0:
821 print "No scenario instances were found."
822 return result
823 for instance in content['instances']:
824 myoutput = "%s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20))
825 if args.verbose >=1:
826 myoutput = "%s %s" %(myoutput, instance['created_at'].ljust(20))
827 print myoutput
828 if args.verbose >=2:
829 print "Description: %s" %instance['description']
830 else:
831 if args.verbose:
832 print yaml.safe_dump(content, indent=4, default_flow_style=False)
833 return result
834 instance = content
835 print "%s %s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20),instance['created_at'].ljust(20))
836 print "Description: %s" %instance['description']
837 print "Template scenario id: %s" %instance['scenario_id']
838 print "Template scenario name: %s" %instance['scenario_name']
839 print "---------------------------------------"
840 print "VNF instances: %d" %len(instance['vnfs'])
841 for vnf in instance['vnfs']:
842 #print " %s %s Template vnf name: %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['name'].ljust(20), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
843 print " %s %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
844 if len(instance['nets'])>0:
845 print "---------------------------------------"
846 print "Internal nets:"
847 for net in instance['nets']:
tierno5c7c4732016-09-26 13:38:55 +0000848 if net['created']:
tierno7edb6752016-03-21 17:37:52 +0100849 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
850 print "---------------------------------------"
851 print "External nets:"
852 for net in instance['nets']:
tierno5c7c4732016-09-26 13:38:55 +0000853 if not net['created']:
tierno7edb6752016-03-21 17:37:52 +0100854 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
855 print "---------------------------------------"
856 print "VM instances:"
857 for vnf in instance['vnfs']:
858 for vm in vnf['vms']:
859 print " %s %s %s %s VIM ID: %s" %(vm['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vm['name'].ljust(20), vm['status'].ljust(12), vm['vim_vm_id'])
860 else:
861 print content['error']['description']
862 if args.verbose:
863 print yaml.safe_dump(content, indent=4, default_flow_style=False)
864 return result
865
866def instance_scenario_status(args):
867 print "instance-scenario-status"
868 return 0
869
870def instance_scenario_delete(args):
871 if args.all:
872 tenant = "any"
873 else:
874 tenant = _get_tenant()
875 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
876 #print "instance-scenario-delete",args
877 if not args.force:
878 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
879 if not (len(r)>0 and r[0].lower()=="y"):
880 return
881 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
882 mano_response = requests.delete(URLrequest)
883 logger.debug("openmano response: %s", mano_response.text )
884 result = 0 if mano_response.status_code==200 else mano_response.status_code
885 content = mano_response.json()
886 #print json.dumps(content, indent=4)
887 if mano_response.status_code == 200:
888 print content['result']
889 else:
890 print content['error']['description']
891 return result
892
tierno868220c2017-09-26 00:11:05 +0200893def get_action(args):
894 if not args.all:
895 tenant = _get_tenant()
896 else:
897 tenant = "any"
898 if not args.instance:
899 instance_id = "any"
900 else:
901 instance_id =args.instance
902 action_id = ""
903 if args.id:
904 action_id = "/" + args.id
905 URLrequest = "http://{}:{}/openmano/{}/instances/{}/action{}".format(mano_host, mano_port, tenant, instance_id,
906 action_id)
907 mano_response = requests.get(URLrequest)
908 logger.debug("openmano response: %s", mano_response.text )
909 if args.verbose == None:
910 args.verbose = 0
911 if args.id != None:
912 args.verbose += 1
913 return _print_verbose(mano_response, args.verbose)
914
tierno7edb6752016-03-21 17:37:52 +0100915def instance_scenario_action(args):
916 #print "instance-scenario-action", args
917 tenant = _get_tenant()
918 toact = _get_item_uuid("instances", args.name, tenant=tenant)
919 action={}
920 action[ args.action ] = args.param
921 if args.vnf:
922 action["vnfs"] = args.vnf
923 if args.vm:
924 action["vms"] = args.vm
925
926 headers_req = {'content-type': 'application/json'}
927 payload_req = json.dumps(action, indent=4)
928 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
929 logger.debug("openmano request: %s", payload_req)
930 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
931 logger.debug("openmano response: %s", mano_response.text )
932 result = 0 if mano_response.status_code==200 else mano_response.status_code
933 content = mano_response.json()
934 #print json.dumps(content, indent=4)
935 if mano_response.status_code == 200:
936 if args.verbose:
937 print yaml.safe_dump(content, indent=4, default_flow_style=False)
938 return result
939 for uuid,c in content.iteritems():
940 print "%s %s %s" %(uuid.ljust(38), c['name'].ljust(20),c['description'].ljust(20))
941 else:
942 print content['error']['description']
943 return result
944
945
946def instance_vnf_list(args):
947 print "instance-vnf-list"
948 return 0
949
950def instance_vnf_status(args):
951 print "instance-vnf-status"
952 return 0
953
954def tenant_create(args):
955 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
956 tenant_dict={"name": args.name}
957 if args.description!=None:
958 tenant_dict["description"] = args.description
959 payload_req = json.dumps( {"tenant": tenant_dict })
960
961 #print payload_req
962
963 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
964 logger.debug("openmano request: %s", payload_req)
965 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
966 logger.debug("openmano response: %s", mano_response.text )
967 return _print_verbose(mano_response, args.verbose)
968
969def tenant_list(args):
970 #print "tenant-list",args
971 if args.name:
tierno392f2852016-05-13 12:28:55 +0200972 toshow = _get_item_uuid("tenants", args.name)
tierno7edb6752016-03-21 17:37:52 +0100973 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
974 else:
975 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
976 mano_response = requests.get(URLrequest)
977 logger.debug("openmano response: %s", mano_response.text )
978 if args.verbose==None:
979 args.verbose=0
980 if args.name!=None:
981 args.verbose += 1
982 return _print_verbose(mano_response, args.verbose)
983
984def tenant_delete(args):
985 #print "tenant-delete",args
986 todelete = _get_item_uuid("tenants", args.name)
987 if not args.force:
988 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
989 if not (len(r)>0 and r[0].lower()=="y"):
990 return 0
991 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
992 mano_response = requests.delete(URLrequest)
993 logger.debug("openmano response: %s", mano_response.text )
994 result = 0 if mano_response.status_code==200 else mano_response.status_code
995 content = mano_response.json()
996 #print json.dumps(content, indent=4)
997 if mano_response.status_code == 200:
998 print content['result']
999 else:
1000 print content['error']['description']
1001 return result
1002
1003def datacenter_attach(args):
1004 tenant = _get_tenant()
1005 datacenter = _get_datacenter(args.name)
1006 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1007
1008 datacenter_dict={}
1009 if args.vim_tenant_id != None:
1010 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1011 if args.vim_tenant_name != None:
1012 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1013 if args.user != None:
1014 datacenter_dict['vim_username'] = args.user
1015 if args.password != None:
1016 datacenter_dict['vim_password'] = args.password
tierno8008c3a2016-10-13 15:34:28 +00001017 if args.config!=None:
1018 datacenter_dict["config"] = _load_file_or_yaml(args.config)
tierno7edb6752016-03-21 17:37:52 +01001019 payload_req = json.dumps( {"datacenter": datacenter_dict })
1020
1021 #print payload_req
1022
1023 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1024 logger.debug("openmano request: %s", payload_req)
1025 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1026 logger.debug("openmano response: %s", mano_response.text )
1027 result = _print_verbose(mano_response, args.verbose)
1028 #provide addional information if error
1029 if mano_response.status_code != 200:
1030 content = mano_response.json()
1031 if "already in use for 'name'" in content['error']['description'] and \
1032 "to database vim_tenants table" in content['error']['description']:
1033 print "Try to specify a different name with --vim-tenant-name"
1034 return result
1035
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001036
1037def datacenter_edit_vim_tenant(args):
1038 tenant = _get_tenant()
1039 datacenter = _get_datacenter(args.name)
1040 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1041
1042 if not (args.vim_tenant_id or args.vim_tenant_name or args.user or args.password or args.config):
1043 raise OpenmanoCLIError("Error. At least one parameter must be updated.")
1044
1045 datacenter_dict = {}
1046 if args.vim_tenant_id != None:
1047 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1048 if args.vim_tenant_name != None:
1049 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1050 if args.user != None:
1051 datacenter_dict['vim_username'] = args.user
1052 if args.password != None:
1053 datacenter_dict['vim_password'] = args.password
1054 if args.config != None:
1055 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1056 payload_req = json.dumps({"datacenter": datacenter_dict})
1057
1058 # print payload_req
1059
1060 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" % (mano_host, mano_port, tenant, datacenter)
1061 logger.debug("openmano request: %s", payload_req)
1062 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1063 logger.debug("openmano response: %s", mano_response.text)
1064 result = _print_verbose(mano_response, args.verbose)
1065
1066 return result
1067
tierno7edb6752016-03-21 17:37:52 +01001068def datacenter_detach(args):
1069 if args.all:
1070 tenant = "any"
1071 else:
1072 tenant = _get_tenant()
1073 datacenter = _get_datacenter(args.name, tenant)
1074 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1075 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1076 mano_response = requests.delete(URLrequest, headers=headers_req)
1077 logger.debug("openmano response: %s", mano_response.text )
1078 content = mano_response.json()
1079 #print json.dumps(content, indent=4)
1080 result = 0 if mano_response.status_code==200 else mano_response.status_code
1081 if mano_response.status_code == 200:
1082 print content['result']
1083 else:
1084 print content['error']['description']
1085 return result
1086
1087def datacenter_create(args):
1088 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1089 datacenter_dict={"name": args.name, "vim_url": args.url}
1090 if args.description!=None:
1091 datacenter_dict["description"] = args.description
1092 if args.type!=None:
1093 datacenter_dict["type"] = args.type
1094 if args.url!=None:
1095 datacenter_dict["vim_url_admin"] = args.url_admin
1096 if args.config!=None:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001097 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1098 if args.sdn_controller!=None:
1099 tenant = _get_tenant()
1100 sdn_controller = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1101 if not 'config' in datacenter_dict:
1102 datacenter_dict['config'] = {}
1103 datacenter_dict['config']['sdn-controller'] = sdn_controller
tierno7edb6752016-03-21 17:37:52 +01001104 payload_req = json.dumps( {"datacenter": datacenter_dict })
1105
1106 #print payload_req
1107
1108 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
1109 logger.debug("openmano request: %s", payload_req)
1110 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1111 logger.debug("openmano response: %s", mano_response.text )
1112 return _print_verbose(mano_response, args.verbose)
1113
1114def datacenter_delete(args):
1115 #print "datacenter-delete",args
1116 todelete = _get_item_uuid("datacenters", args.name, "any")
1117 if not args.force:
1118 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
1119 if not (len(r)>0 and r[0].lower()=="y"):
1120 return 0
1121 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
1122 mano_response = requests.delete(URLrequest)
1123 logger.debug("openmano response: %s", mano_response.text )
1124 result = 0 if mano_response.status_code==200 else mano_response.status_code
1125 content = mano_response.json()
1126 #print json.dumps(content, indent=4)
1127 if mano_response.status_code == 200:
1128 print content['result']
1129 else:
1130 print content['error']['description']
1131 return result
1132
tierno20df3bb2017-07-07 14:31:00 +02001133
tierno7edb6752016-03-21 17:37:52 +01001134def datacenter_list(args):
1135 #print "datacenter-list",args
1136 tenant='any' if args.all else _get_tenant()
1137
1138 if args.name:
1139 toshow = _get_item_uuid("datacenters", args.name, tenant)
1140 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
1141 else:
1142 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
1143 mano_response = requests.get(URLrequest)
1144 logger.debug("openmano response: %s", mano_response.text )
1145 if args.verbose==None:
1146 args.verbose=0
1147 if args.name!=None:
1148 args.verbose += 1
1149 return _print_verbose(mano_response, args.verbose)
1150
tierno20df3bb2017-07-07 14:31:00 +02001151
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001152def datacenter_sdn_port_mapping_set(args):
1153 tenant = _get_tenant()
1154 datacenter = _get_datacenter(args.name, tenant)
1155 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1156
1157 if not args.file:
1158 raise OpenmanoCLIError(
1159 "No yaml/json has been provided specifying the SDN port mapping")
tierno20df3bb2017-07-07 14:31:00 +02001160 sdn_port_mapping = _load_file_or_yaml(args.file)
1161 payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping})
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001162
tierno20df3bb2017-07-07 14:31:00 +02001163 # read
1164 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1165 mano_response = requests.get(URLrequest)
1166 logger.debug("openmano response: %s", mano_response.text)
1167 port_mapping = mano_response.json()
1168 if mano_response.status_code != 200:
1169 str(mano_response.json())
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001170 raise OpenmanoCLIError("openmano client error: {}".format(port_mapping['error']['description']))
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001171 if len(port_mapping["sdn_port_mapping"]["ports_mapping"]) > 0:
1172 if not args.force:
1173 r = raw_input("Datacenter %s already contains a port mapping. Overwrite? (y/N)? " % (datacenter))
1174 if not (len(r) > 0 and r[0].lower() == "y"):
1175 return 0
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001176
tierno20df3bb2017-07-07 14:31:00 +02001177 # clear
1178 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1179 mano_response = requests.delete(URLrequest)
1180 logger.debug("openmano response: %s", mano_response.text)
1181 if mano_response.status_code != 200:
1182 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001183
tierno20df3bb2017-07-07 14:31:00 +02001184 # set
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001185 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1186 logger.debug("openmano request: %s", payload_req)
1187 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1188 logger.debug("openmano response: %s", mano_response.text)
tierno20df3bb2017-07-07 14:31:00 +02001189 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001190
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001191
1192def datacenter_sdn_port_mapping_list(args):
1193 tenant = _get_tenant()
1194 datacenter = _get_datacenter(args.name, tenant)
1195
1196 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1197 mano_response = requests.get(URLrequest)
1198 logger.debug("openmano response: %s", mano_response.text)
1199
tierno20df3bb2017-07-07 14:31:00 +02001200 return _print_verbose(mano_response, 4)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001201
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001202
1203def datacenter_sdn_port_mapping_clear(args):
1204 tenant = _get_tenant()
1205 datacenter = _get_datacenter(args.name, tenant)
1206
1207 if not args.force:
1208 r = raw_input("Clean SDN port mapping for datacenter %s (y/N)? " %(datacenter))
tierno20df3bb2017-07-07 14:31:00 +02001209 if not (len(r) > 0 and r[0].lower() == "y"):
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001210 return 0
1211
1212 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1213 mano_response = requests.delete(URLrequest)
1214 logger.debug("openmano response: %s", mano_response.text)
1215
tierno20df3bb2017-07-07 14:31:00 +02001216 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001217
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001218
1219def sdn_controller_create(args):
1220 tenant = _get_tenant()
1221 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1222
tierno8fe7a492017-07-11 13:50:04 +02001223 error_msg=[]
1224 if not args.ip: error_msg.append("'ip'")
1225 if not args.port: error_msg.append("'port'")
1226 if not args.dpid: error_msg.append("'dpid'")
1227 if not args.type: error_msg.append("'type'")
1228 if error_msg:
1229 raise OpenmanoCLIError("The following arguments are required: " + ",".join(error_msg))
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001230
1231 controller_dict = {}
1232 controller_dict['name'] = args.name
1233 controller_dict['ip'] = args.ip
1234 controller_dict['port'] = int(args.port)
1235 controller_dict['dpid'] = args.dpid
1236 controller_dict['type'] = args.type
1237 if args.description != None:
1238 controller_dict['description'] = args.description
1239 if args.user != None:
1240 controller_dict['user'] = args.user
1241 if args.password != None:
1242 controller_dict['password'] = args.password
1243
1244 payload_req = json.dumps({"sdn_controller": controller_dict})
1245
1246 # print payload_req
1247
1248 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" % (mano_host, mano_port, tenant)
1249 logger.debug("openmano request: %s", payload_req)
1250 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1251 logger.debug("openmano response: %s", mano_response.text)
1252 result = _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001253 return result
1254
tierno20df3bb2017-07-07 14:31:00 +02001255
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001256def sdn_controller_edit(args):
1257 tenant = _get_tenant()
1258 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1259 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1260
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001261 controller_dict = {}
tierno20df3bb2017-07-07 14:31:00 +02001262 if args.new_name:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001263 controller_dict['name'] = args.new_name
tierno20df3bb2017-07-07 14:31:00 +02001264 if args.ip:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001265 controller_dict['ip'] = args.ip
tierno20df3bb2017-07-07 14:31:00 +02001266 if args.port:
Pablo Montes Morenob12711f2017-04-06 11:54:34 +02001267 controller_dict['port'] = int(args.port)
tierno20df3bb2017-07-07 14:31:00 +02001268 if args.dpid:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001269 controller_dict['dpid'] = args.dpid
tierno20df3bb2017-07-07 14:31:00 +02001270 if args.type:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001271 controller_dict['type'] = args.type
tierno20df3bb2017-07-07 14:31:00 +02001272 if args.description:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001273 controller_dict['description'] = args.description
tierno20df3bb2017-07-07 14:31:00 +02001274 if args.user:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001275 controller_dict['user'] = args.user
tierno20df3bb2017-07-07 14:31:00 +02001276 if args.password:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001277 controller_dict['password'] = args.password
1278
tierno20df3bb2017-07-07 14:31:00 +02001279 if not controller_dict:
1280 raise OpenmanoCLIError("At least one parameter must be edited")
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001281
tierno20df3bb2017-07-07 14:31:00 +02001282 if not args.force:
1283 r = raw_input("Update SDN controller {} (y/N)? ".format(args.name))
1284 if not (len(r) > 0 and r[0].lower() == "y"):
1285 return 0
1286
1287 payload_req = json.dumps({"sdn_controller": controller_dict})
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001288 # print payload_req
1289
1290 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1291 logger.debug("openmano request: %s", payload_req)
1292 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1293 logger.debug("openmano response: %s", mano_response.text)
1294 result = _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001295 return result
1296
tierno20df3bb2017-07-07 14:31:00 +02001297
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001298def sdn_controller_list(args):
1299 tenant = _get_tenant()
1300 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1301
1302 if args.name:
1303 toshow = _get_item_uuid("sdn_controllers", args.name, tenant)
1304 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" %(mano_host, mano_port, tenant, toshow)
1305 else:
1306 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" %(mano_host, mano_port, tenant)
1307 #print URLrequest
1308 mano_response = requests.get(URLrequest)
1309 logger.debug("openmano response: %s", mano_response.text )
1310 if args.verbose==None:
1311 args.verbose=0
1312 if args.name!=None:
1313 args.verbose += 1
1314
tierno20df3bb2017-07-07 14:31:00 +02001315 # json.dumps(mano_response.json(), indent=4)
1316 return _print_verbose(mano_response, args.verbose)
1317
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001318
1319def sdn_controller_delete(args):
1320 tenant = _get_tenant()
1321 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1322
1323 if not args.force:
1324 r = raw_input("Delete SDN controller %s (y/N)? " % (args.name))
1325 if not (len(r) > 0 and r[0].lower() == "y"):
1326 return 0
1327
1328 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1329 mano_response = requests.delete(URLrequest)
1330 logger.debug("openmano response: %s", mano_response.text)
tierno20df3bb2017-07-07 14:31:00 +02001331 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001332
tierno7edb6752016-03-21 17:37:52 +01001333def vim_action(args):
1334 #print "datacenter-net-action",args
1335 tenant = _get_tenant()
1336 datacenter = _get_datacenter(args.datacenter, tenant)
1337 if args.verbose==None:
1338 args.verbose=0
1339 if args.action=="list":
1340 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1341 if args.name!=None:
1342 args.verbose += 1
1343 URLrequest += "/" + args.name
1344 mano_response = requests.get(URLrequest)
1345 logger.debug("openmano response: %s", mano_response.text )
1346 return _print_verbose(mano_response, args.verbose)
1347 elif args.action=="delete":
1348 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1349 mano_response = requests.delete(URLrequest)
1350 logger.debug("openmano response: %s", mano_response.text )
1351 result = 0 if mano_response.status_code==200 else mano_response.status_code
1352 content = mano_response.json()
1353 #print json.dumps(content, indent=4)
1354 if mano_response.status_code == 200:
1355 print content['result']
1356 else:
1357 print content['error']['description']
1358 return result
1359 elif args.action=="create":
1360 headers_req = {'content-type': 'application/yaml'}
1361 if args.file:
1362 create_dict = _load_file_or_yaml(args.file)
1363 if args.item not in create_dict:
1364 create_dict = {args.item: create_dict}
1365 else:
1366 create_dict = {args.item:{}}
1367 if args.name:
1368 create_dict[args.item]['name'] = args.name
1369 #if args.description:
1370 # create_dict[args.item]['description'] = args.description
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001371 if args.item=="network":
tierno7edb6752016-03-21 17:37:52 +01001372 if args.bind_net:
1373 create_dict[args.item]['bind_net'] = args.bind_net
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001374 if args.type:
1375 create_dict[args.item]['type'] = args.type
tierno7edb6752016-03-21 17:37:52 +01001376 if args.shared:
1377 create_dict[args.item]['shared'] = args.shared
1378 if "name" not in create_dict[args.item]:
1379 print "You must provide a name in the descriptor file or with the --name option"
1380 return
1381 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1382 logger.debug("openmano request: %s", payload_req)
tierno72a08d72017-05-25 13:12:30 +02001383 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
tierno7edb6752016-03-21 17:37:52 +01001384 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1385 logger.debug("openmano response: %s", mano_response.text )
1386 if args.verbose==None:
1387 args.verbose=0
1388 return _print_verbose(mano_response, args.verbose)
1389
tierno20df3bb2017-07-07 14:31:00 +02001390
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001391def _get_items(item, item_name_id=None, datacenter=None, tenant=None):
1392 URLrequest = "http://%s:%s/openmano" %(mano_host, mano_port)
1393 if tenant:
1394 URLrequest += "/" + tenant
1395 if datacenter:
1396 URLrequest += "/vim/" + datacenter
1397 if item:
1398 URLrequest += "/" + item +"s"
1399 if item_name_id:
1400 URLrequest += "/" + item_name_id
1401 mano_response = requests.get(URLrequest)
1402 logger.debug("openmano response: %s", mano_response.text )
1403
1404 return mano_response
1405
tierno20df3bb2017-07-07 14:31:00 +02001406
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001407def vim_net_sdn_attach(args):
1408 #Verify the network exists in the vim
1409 tenant = _get_tenant()
1410 datacenter = _get_datacenter(args.datacenter, tenant)
1411 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1412 content = yaml.load(result.content)
1413 if 'networks' in content:
1414 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1415 if 'error' in content:
1416 raise OpenmanoCLIError(yaml.safe_dump(content))
1417 network_uuid = content['network']['id']
1418
1419 #Make call to attach the dataplane port to the SND network associated to the vim network
1420 headers_req = {'content-type': 'application/yaml'}
1421 payload_req = {'port': args.port}
1422 if args.vlan:
1423 payload_req['vlan'] = int(args.vlan)
1424 if args.mac:
1425 payload_req['mac'] = args.mac
1426
1427 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/attach" % (mano_host, mano_port, tenant, datacenter, network_uuid)
1428 logger.debug("openmano request: %s", payload_req)
1429 mano_response = requests.post(URLrequest, headers=headers_req, data=json.dumps(payload_req))
1430 logger.debug("openmano response: %s", mano_response.text)
1431 result = _print_verbose(mano_response, args.verbose)
tierno20df3bb2017-07-07 14:31:00 +02001432 return result
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001433
1434
1435def vim_net_sdn_detach(args):
1436 if not args.all and not args.id:
1437 print "--all or --id must be used"
1438 return 1
1439
1440 # Verify the network exists in the vim
1441 tenant = _get_tenant()
1442 datacenter = _get_datacenter(args.datacenter, tenant)
1443 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1444 content = yaml.load(result.content)
1445 if 'networks' in content:
1446 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1447 if 'error' in content:
1448 raise OpenmanoCLIError(yaml.safe_dump(content))
1449 network_uuid = content['network']['id']
1450
1451 if not args.force:
1452 r = raw_input("Confirm action' (y/N)? ")
1453 if len(r) == 0 or r[0].lower() != "y":
1454 return 0
1455
1456 if args.id:
1457 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach/%s" % (
1458 mano_host, mano_port, tenant, datacenter, network_uuid, args.id)
1459 else:
1460 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach" % (
1461 mano_host, mano_port, tenant, datacenter, network_uuid)
1462 mano_response = requests.delete(URLrequest)
1463 logger.debug("openmano response: %s", mano_response.text)
1464 result = _print_verbose(mano_response, args.verbose)
tierno20df3bb2017-07-07 14:31:00 +02001465 return result
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001466
tierno7edb6752016-03-21 17:37:52 +01001467
1468def datacenter_net_action(args):
1469 if args.action == "net-update":
tierno5acf7202016-08-29 14:28:13 +02001470 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
tierno7edb6752016-03-21 17:37:52 +01001471 print
1472 args.action = "netmap-delete"
1473 args.netmap = None
1474 args.all = True
1475 r = datacenter_netmap_action(args)
1476 if r == 0:
1477 args.force = True
tierno5acf7202016-08-29 14:28:13 +02001478 args.action = "netmap-import"
tierno7edb6752016-03-21 17:37:52 +01001479 r = datacenter_netmap_action(args)
1480 return r
1481
1482 if args.action == "net-edit":
1483 args.netmap = args.net
1484 args.name = None
1485 elif args.action == "net-list":
1486 args.netmap = None
1487 elif args.action == "net-delete":
1488 args.netmap = args.net
1489 args.all = False
1490
1491 args.action = "netmap" + args.action[3:]
1492 args.vim_name=None
1493 args.vim_id=None
1494 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1495 print
1496 return datacenter_netmap_action(args)
1497
1498def datacenter_netmap_action(args):
1499 tenant = _get_tenant()
1500 datacenter = _get_datacenter(args.datacenter, tenant)
1501 #print "datacenter_netmap_action",args
1502 payload_req = None
1503 if args.verbose==None:
1504 args.verbose=0
1505 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1506 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1507
1508 if args.action=="netmap-list":
1509 if args.netmap:
1510 URLrequest += "/" + args.netmap
1511 args.verbose += 1
1512 mano_response = requests.get(URLrequest)
1513
1514 elif args.action=="netmap-delete":
1515 if args.netmap and args.all:
1516 print "you can not use a netmap name and the option --all at the same time"
1517 return 1
1518 if args.netmap:
1519 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1520 URLrequest += "/" + args.netmap
1521 elif args.all:
1522 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1523 else:
tiernoae4a8d12016-07-08 12:30:39 +02001524 print "you must specify a netmap name or the option --all"
tierno7edb6752016-03-21 17:37:52 +01001525 return 1
1526 if not args.force:
1527 r = raw_input(force_text)
1528 if len(r)>0 and r[0].lower()=="y":
1529 pass
1530 else:
1531 return 0
1532 mano_response = requests.delete(URLrequest, headers=headers_req)
tierno5acf7202016-08-29 14:28:13 +02001533 elif args.action=="netmap-import":
tierno7edb6752016-03-21 17:37:52 +01001534 if not args.force:
1535 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1536 if len(r)>0 and r[0].lower()=="y":
1537 pass
1538 else:
1539 return 0
1540 URLrequest += "/upload"
1541 mano_response = requests.post(URLrequest, headers=headers_req)
1542 elif args.action=="netmap-edit" or args.action=="netmap-create":
1543 if args.file:
1544 payload = _load_file_or_yaml(args.file)
1545 else:
1546 payload = {}
1547 if "netmap" not in payload:
1548 payload = {"netmap": payload}
1549 if args.name:
1550 payload["netmap"]["name"] = args.name
1551 if args.vim_id:
1552 payload["netmap"]["vim_id"] = args.vim_id
1553 if args.action=="netmap-create" and args.vim_name:
1554 payload["netmap"]["vim_name"] = args.vim_name
1555 payload_req = json.dumps(payload)
1556 logger.debug("openmano request: %s", payload_req)
1557
1558 if args.action=="netmap-edit" and not args.force:
1559 if len(payload["netmap"]) == 0:
1560 print "You must supply some parameter to edit"
1561 return 1
1562 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1563 if len(r)>0 and r[0].lower()=="y":
1564 pass
1565 else:
1566 return 0
1567 URLrequest += "/" + args.netmap
1568 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1569 else: #netmap-create
1570 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1571 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1572 return 1
1573 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1574
1575 logger.debug("openmano response: %s", mano_response.text )
1576 return _print_verbose(mano_response, args.verbose)
1577
tierno20df3bb2017-07-07 14:31:00 +02001578
tierno7edb6752016-03-21 17:37:52 +01001579def element_edit(args):
1580 element = _get_item_uuid(args.element, args.name)
1581 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1582 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1583 payload=_load_file_or_yaml(args.file)
1584 if args.element[:-1] not in payload:
1585 payload = {args.element[:-1]: payload }
1586 payload_req = json.dumps(payload)
1587
1588 #print payload_req
1589 if not args.force or (args.name==None and args.filer==None):
1590 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1591 if len(r)>0 and r[0].lower()=="y":
1592 pass
1593 else:
1594 return 0
1595 logger.debug("openmano request: %s", payload_req)
1596 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1597 logger.debug("openmano response: %s", mano_response.text )
1598 if args.verbose==None:
1599 args.verbose=0
1600 if args.name!=None:
1601 args.verbose += 1
1602 return _print_verbose(mano_response, args.verbose)
1603
1604
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001605def datacenter_edit(args):
1606 tenant = _get_tenant()
1607 element = _get_item_uuid('datacenters', args.name, tenant)
1608 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1609 URLrequest = "http://%s:%s/openmano/datacenters/%s" % (mano_host, mano_port, element)
1610
1611 has_arguments = False
1612 if args.file != None:
1613 has_arguments = True
1614 payload = _load_file_or_yaml(args.file)
1615 else:
1616 payload = {}
1617
1618 if args.sdn_controller != None:
1619 has_arguments = True
1620 if not 'config' in payload:
1621 payload['config'] = {}
1622 if not 'sdn-controller' in payload['config']:
1623 payload['config']['sdn-controller'] = {}
1624 if args.sdn_controller == 'null':
1625 payload['config']['sdn-controller'] = None
1626 else:
1627 payload['config']['sdn-controller'] = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1628
1629 if not has_arguments:
1630 raise OpenmanoCLIError("At least one argument must be provided to modify the datacenter")
1631
1632 if 'datacenter' not in payload:
1633 payload = {'datacenter': payload}
1634 payload_req = json.dumps(payload)
1635
1636 # print payload_req
1637 if not args.force or (args.name == None and args.filer == None):
1638 r = raw_input(" Edit datacenter " + args.name + " (y/N)? ")
1639 if len(r) > 0 and r[0].lower() == "y":
1640 pass
1641 else:
1642 return 0
1643 logger.debug("openmano request: %s", payload_req)
1644 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1645 logger.debug("openmano response: %s", mano_response.text)
1646 if args.verbose == None:
1647 args.verbose = 0
1648 if args.name != None:
1649 args.verbose += 1
1650 return _print_verbose(mano_response, args.verbose)
1651
tierno20df3bb2017-07-07 14:31:00 +02001652
tierno6ddeded2017-05-16 15:40:26 +02001653def version(args):
1654 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1655 URLrequest = "http://%s:%s/openmano/version" % (mano_host, mano_port)
1656
1657 mano_response = requests.get(URLrequest, headers=headers_req)
1658 logger.debug("openmano response: %s", mano_response.text)
1659 print mano_response.text
1660
1661
tierno7edb6752016-03-21 17:37:52 +01001662global mano_host
1663global mano_port
1664global mano_tenant
1665
1666if __name__=="__main__":
1667
1668 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1669 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1670 mano_port = os.getenv('OPENMANO_PORT',"9090")
1671 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1672
1673 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
tierno6ddeded2017-05-16 15:40:26 +02001674 main_parser.add_argument('--version', action='version', help="get version of this client",
1675 version='%(prog)s client version ' + __version__ +
1676 " (Note: use '%(prog)s version' to get server version)")
1677
tierno7edb6752016-03-21 17:37:52 +01001678 subparsers = main_parser.add_subparsers(help='commands')
1679
tierno7edb6752016-03-21 17:37:52 +01001680 parent_parser = argparse.ArgumentParser(add_help=False)
1681 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1682 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1683
garciadeblas0e9fd832016-07-08 15:20:18 +02001684 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1685 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1686 config_parser.set_defaults(func=config)
1687
tierno6ddeded2017-05-16 15:40:26 +02001688 version_parser = subparsers.add_parser('version', parents=[parent_parser], help="get server version")
1689 version_parser.set_defaults(func=version)
1690
tierno7edb6752016-03-21 17:37:52 +01001691 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1692 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1693 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1694 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1695 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
garciadeblas14480452017-01-10 13:08:07 +01001696 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1697 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
tierno7edb6752016-03-21 17:37:52 +01001698 vnf_create_parser.set_defaults(func=vnf_create)
1699
1700 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1701 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1702 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1703 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1704 vnf_list_parser.set_defaults(func=vnf_list)
1705
1706 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1707 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1708 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1709 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1710 vnf_delete_parser.set_defaults(func=vnf_delete)
1711
1712 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1713 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1714 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1715 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1716 scenario_create_parser.set_defaults(func=scenario_create)
1717
1718 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1719 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1720 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1721 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1722 scenario_list_parser.set_defaults(func=scenario_list)
1723
1724 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1725 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1726 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1727 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1728 scenario_delete_parser.set_defaults(func=scenario_delete)
1729
1730 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1731 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1732 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1733 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1734 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1735 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1736 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1737
1738 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1739 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1740 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1741 scenario_deploy_parser.set_defaults(func=scenario_verify)
1742
1743 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1744 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1745 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1746 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1747 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1748 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1749 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")
1750 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 +02001751 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")
1752 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 +01001753 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1754 instance_scenario_create_parser.set_defaults(func=instance_create)
1755
1756 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1757 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1758 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1759 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1760
1761 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)")
1762 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1763 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1764 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1765 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1766
1767 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1768 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1769 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
gcalvinoe580c7d2017-09-22 14:09:51 +02001770 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console", "add_public_key"],\
tierno7edb6752016-03-21 17:37:52 +01001771 help="action to send")
1772 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1773 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1774 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1775 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1776
tierno868220c2017-09-26 00:11:05 +02001777 action_parser = subparsers.add_parser('action-list', parents=[parent_parser], help="get action over an instance status")
1778 action_parser.add_argument("id", nargs='?', action="store", help="action id")
1779 action_parser.add_argument("--instance", action="store", help="fitler by this instance_id")
1780 action_parser.add_argument("--all", action="store", help="Not filter by tenant")
1781 action_parser.set_defaults(func=get_action)
1782
tierno7edb6752016-03-21 17:37:52 +01001783 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1784 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1785 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1786
1787 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1788 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1789 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1790 tenant_create_parser.set_defaults(func=tenant_create)
1791
1792 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1793 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1794 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1795 tenant_delete_parser.set_defaults(func=tenant_delete)
1796
1797 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1798 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1799 tenant_list_parser.set_defaults(func=tenant_list)
1800
tierno161c24b2017-05-16 15:45:56 +02001801 element_edit_parser = subparsers.add_parser('tenant-edit', parents=[parent_parser], help="edits one tenant")
1802 element_edit_parser.add_argument("name", help="name or uuid of the tenant")
1803 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1804 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1805 element_edit_parser.set_defaults(func=element_edit, element='tenants')
tierno7edb6752016-03-21 17:37:52 +01001806
1807 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1808 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1809 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1810 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1811 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1812 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1813 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001814 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 +01001815 datacenter_create_parser.set_defaults(func=datacenter_create)
1816
1817 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1818 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1819 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1820 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1821
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001822 datacenter_edit_parser = subparsers.add_parser('datacenter-edit', parents=[parent_parser], help="Edit datacenter")
1823 datacenter_edit_parser.add_argument("name", help="name or uuid of the datacenter")
1824 datacenter_edit_parser.add_argument("--file", help="json/yaml text or file with the changes").completer = FilesCompleter
1825 datacenter_edit_parser.add_argument("--sdn-controller", action="store",
1826 help="Name or uuid of the SDN controller to be used. Specify 'null' to clear entry", dest='sdn_controller')
1827 datacenter_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1828 datacenter_edit_parser.set_defaults(func=datacenter_edit)
1829
tierno7edb6752016-03-21 17:37:52 +01001830 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1831 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1832 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1833 datacenter_list_parser.set_defaults(func=datacenter_list)
1834
1835 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1836 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1837 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1838 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1839 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1840 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
tierno8008c3a2016-10-13 15:34:28 +00001841 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
tierno7edb6752016-03-21 17:37:52 +01001842 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1843
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001844 datacenter_edit_vim_tenant_parser = subparsers.add_parser('datacenter-edit-vim-tenant', parents=[parent_parser],
1845 help="Edit the association of a datacenter to the operating tenant")
1846 datacenter_edit_vim_tenant_parser.add_argument("name", help="name or uuid of the datacenter")
1847 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-id', action='store',
1848 help="specify a datacenter tenant to use. A new one is created by default")
1849 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1850 datacenter_edit_vim_tenant_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1851 datacenter_edit_vim_tenant_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1852 datacenter_edit_vim_tenant_parser.add_argument("--config", action="store",
1853 help="aditional configuration in json/yaml format")
1854 datacenter_edit_vim_tenant_parser.set_defaults(func=datacenter_edit_vim_tenant)
1855
tierno7edb6752016-03-21 17:37:52 +01001856 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1857 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1858 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1859 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1860
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001861 #=======================datacenter_sdn_port_mapping_xxx section=======================
1862 #datacenter_sdn_port_mapping_set
1863 datacenter_sdn_port_mapping_set_parser = subparsers.add_parser('datacenter-sdn-port-mapping-set',
1864 parents=[parent_parser],
1865 help="Load a file with the mapping of physical ports "
1866 "and the ports of the dataplaneswitch controlled "
1867 "by a datacenter")
1868 datacenter_sdn_port_mapping_set_parser.add_argument("name", action="store", help="specifies the datacenter")
1869 datacenter_sdn_port_mapping_set_parser.add_argument("file",
1870 help="json/yaml text or file with the port mapping").completer = FilesCompleter
1871 datacenter_sdn_port_mapping_set_parser.add_argument("-f", "--force", action="store_true",
1872 help="forces overwriting without asking")
1873 datacenter_sdn_port_mapping_set_parser.set_defaults(func=datacenter_sdn_port_mapping_set)
1874
1875 #datacenter_sdn_port_mapping_list
1876 datacenter_sdn_port_mapping_list_parser = subparsers.add_parser('datacenter-sdn-port-mapping-list',
1877 parents=[parent_parser],
1878 help="Show the SDN port mapping in a datacenter")
1879 datacenter_sdn_port_mapping_list_parser.add_argument("name", action="store", help="specifies the datacenter")
1880 datacenter_sdn_port_mapping_list_parser.set_defaults(func=datacenter_sdn_port_mapping_list)
1881
1882 # datacenter_sdn_port_mapping_clear
1883 datacenter_sdn_port_mapping_clear_parser = subparsers.add_parser('datacenter-sdn-port-mapping-clear',
1884 parents=[parent_parser],
1885 help="Clean the the SDN port mapping in a datacenter")
1886 datacenter_sdn_port_mapping_clear_parser.add_argument("name", action="store",
1887 help="specifies the datacenter")
1888 datacenter_sdn_port_mapping_clear_parser.add_argument("-f", "--force", action="store_true",
1889 help="forces clearing without asking")
1890 datacenter_sdn_port_mapping_clear_parser.set_defaults(func=datacenter_sdn_port_mapping_clear)
1891 # =======================
1892
1893 # =======================sdn_controller_xxx section=======================
1894 # sdn_controller_create
1895 sdn_controller_create_parser = subparsers.add_parser('sdn-controller-create', parents=[parent_parser],
1896 help="Creates an SDN controller entity within RO")
1897 sdn_controller_create_parser.add_argument("name", help="name of the SDN controller")
1898 sdn_controller_create_parser.add_argument("--description", action="store", help="description of the SDN controller")
1899 sdn_controller_create_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1900 sdn_controller_create_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1901 sdn_controller_create_parser.add_argument("--dpid", action="store",
1902 help="DPID of the dataplane switch controlled by this SDN controller")
1903 sdn_controller_create_parser.add_argument("--type", action="store",
1904 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1905 sdn_controller_create_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1906 sdn_controller_create_parser.add_argument("--passwd", action="store", dest='password',
1907 help="password credentials for the SDN controller")
1908 sdn_controller_create_parser.set_defaults(func=sdn_controller_create)
1909
1910 # sdn_controller_edit
1911 sdn_controller_edit_parser = subparsers.add_parser('sdn-controller-edit', parents=[parent_parser],
1912 help="Update one or more options of a SDN controller")
1913 sdn_controller_edit_parser.add_argument("name", help="name or uuid of the SDN controller", )
1914 sdn_controller_edit_parser.add_argument("--name", action="store", help="Update the name of the SDN controller",
1915 dest='new_name')
1916 sdn_controller_edit_parser.add_argument("--description", action="store", help="description of the SDN controller")
1917 sdn_controller_edit_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1918 sdn_controller_edit_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1919 sdn_controller_edit_parser.add_argument("--dpid", action="store",
1920 help="DPID of the dataplane switch controlled by this SDN controller")
1921 sdn_controller_edit_parser.add_argument("--type", action="store",
1922 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1923 sdn_controller_edit_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1924 sdn_controller_edit_parser.add_argument("--password", action="store",
1925 help="password credentials for the SDN controller", dest='password')
1926 sdn_controller_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1927 #TODO: include option --file
1928 sdn_controller_edit_parser.set_defaults(func=sdn_controller_edit)
1929
1930 #sdn_controller_list
1931 sdn_controller_list_parser = subparsers.add_parser('sdn-controller-list',
1932 parents=[parent_parser],
1933 help="List the SDN controllers")
1934 sdn_controller_list_parser.add_argument("name", nargs='?', help="name or uuid of the SDN controller")
1935 sdn_controller_list_parser.set_defaults(func=sdn_controller_list)
1936
1937 # sdn_controller_delete
1938 sdn_controller_delete_parser = subparsers.add_parser('sdn-controller-delete',
1939 parents=[parent_parser],
1940 help="Delete the the SDN controller")
1941 sdn_controller_delete_parser.add_argument("name", help="name or uuid of the SDN controller")
1942 sdn_controller_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1943 sdn_controller_delete_parser.set_defaults(func=sdn_controller_delete)
1944 # =======================
tierno7edb6752016-03-21 17:37:52 +01001945
1946 action_dict={'net-update': 'retrieves external networks from datacenter',
1947 'net-edit': 'edits an external network',
1948 'net-delete': 'deletes an external network',
1949 'net-list': 'lists external networks from a datacenter'
1950 }
1951 for item in action_dict:
1952 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1953 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1954 if item=='net-edit' or item=='net-delete':
1955 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1956 if item=='net-edit':
1957 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1958 if item!='net-list':
1959 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1960 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1961
1962
tierno5acf7202016-08-29 14:28:13 +02001963 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
tierno7edb6752016-03-21 17:37:52 +01001964 'netmap-create': 'create a new network senario netmap',
1965 'netmap-edit': 'edit name of a network senario netmap',
1966 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1967 'netmap-list': 'list/show network scenario netmaps'
1968 }
1969 for item in action_dict:
1970 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1971 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1972 #if item=='net-add':
1973 # datacenter_action_parser.add_argument("net", help="name of the network")
1974 if item=='netmap-delete':
1975 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1976 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1977 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1978 if item=='netmap-edit':
1979 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1980 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1981 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1982 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1983 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1984 if item=='netmap-list':
1985 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1986 if item=='netmap-create':
1987 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1988 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1989 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1990 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
tierno5acf7202016-08-29 14:28:13 +02001991 if item=='netmap-import':
tierno7edb6752016-03-21 17:37:52 +01001992 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1993 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001994
1995 # =======================vim_net_sdn_xxx section=======================
1996 # vim_net_sdn_attach
1997 vim_net_sdn_attach_parser = subparsers.add_parser('vim-net-sdn-attach',
1998 parents=[parent_parser],
1999 help="Specify the port to access to an external network using SDN")
2000 vim_net_sdn_attach_parser.add_argument("vim_net", action="store",
2001 help="Name/id of the network in the vim that will be used to connect to the external network")
2002 vim_net_sdn_attach_parser.add_argument("port", action="store", help="Specifies the port in the dataplane switch to access to the external network")
2003 vim_net_sdn_attach_parser.add_argument("--vlan", action="store", help="Specifies the vlan (if any) to use in the defined port")
2004 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")
2005 vim_net_sdn_attach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2006 vim_net_sdn_attach_parser.set_defaults(func=vim_net_sdn_attach)
2007
2008 # vim_net_sdn_detach
2009 vim_net_sdn_detach_parser = subparsers.add_parser('vim-net-sdn-detach',
2010 parents=[parent_parser],
2011 help="Remove the port information to access to an external network using SDN")
2012
2013 vim_net_sdn_detach_parser.add_argument("vim_net", action="store", help="Name/id of the vim network")
2014 vim_net_sdn_detach_parser.add_argument("--id", action="store",help="Specify the uuid of the external ports from this network to be detached")
2015 vim_net_sdn_detach_parser.add_argument("--all", action="store_true", help="Detach all external ports from this network")
2016 vim_net_sdn_detach_parser.add_argument("-f", "--force", action="store_true", help="forces clearing without asking")
2017 vim_net_sdn_detach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2018 vim_net_sdn_detach_parser.set_defaults(func=vim_net_sdn_detach)
2019 # =======================
2020
tierno4540ea52017-01-18 17:44:32 +01002021 for item in ("network", "tenant", "image"):
tierno7edb6752016-03-21 17:37:52 +01002022 if item=="network":
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002023 command_name = 'vim-net'
tierno7edb6752016-03-21 17:37:52 +01002024 else:
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002025 command_name = 'vim-'+item
2026 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 +01002027 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
2028 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2029 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
2030
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002031 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 +01002032 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
2033 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2034 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
2035
tierno4540ea52017-01-18 17:44:32 +01002036 if item == "network" or item == "tenant":
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002037 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 +01002038 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
2039 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
2040 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2041 if item=="network":
2042 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
2043 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
2044 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>'")
2045 else:
2046 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
2047 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
tierno7edb6752016-03-21 17:37:52 +01002048
2049 argcomplete.autocomplete(main_parser)
2050
2051 try:
2052 args = main_parser.parse_args()
2053 #logging info
2054 level = logging.CRITICAL
2055 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
2056 if "debug" in args and args.debug:
2057 level = logging.DEBUG
2058 logging.basicConfig(format=streamformat, level= level)
2059 logger = logging.getLogger('mano')
2060 logger.setLevel(level)
2061 result = args.func(args)
2062 if result == None:
2063 result = 0
2064 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
2065 except (requests.exceptions.ConnectionError):
2066 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
2067 result = -2
2068 except (KeyboardInterrupt):
2069 print 'Exiting openmano'
2070 result = -3
2071 except (SystemExit, ArgumentParserError):
2072 result = -4
2073 except OpenmanoCLIError as e:
2074 print str(e)
2075 result = -5
2076
2077 #print result
2078 exit(result)
2079