blob: 26ef9b9317d2c214ad718e5f819f9d23e6bae3ce [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
893def instance_scenario_action(args):
894 #print "instance-scenario-action", args
895 tenant = _get_tenant()
896 toact = _get_item_uuid("instances", args.name, tenant=tenant)
897 action={}
898 action[ args.action ] = args.param
899 if args.vnf:
900 action["vnfs"] = args.vnf
901 if args.vm:
902 action["vms"] = args.vm
903
904 headers_req = {'content-type': 'application/json'}
905 payload_req = json.dumps(action, indent=4)
906 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
907 logger.debug("openmano request: %s", payload_req)
908 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
909 logger.debug("openmano response: %s", mano_response.text )
910 result = 0 if mano_response.status_code==200 else mano_response.status_code
911 content = mano_response.json()
912 #print json.dumps(content, indent=4)
913 if mano_response.status_code == 200:
914 if args.verbose:
915 print yaml.safe_dump(content, indent=4, default_flow_style=False)
916 return result
917 for uuid,c in content.iteritems():
918 print "%s %s %s" %(uuid.ljust(38), c['name'].ljust(20),c['description'].ljust(20))
919 else:
920 print content['error']['description']
921 return result
922
923
924def instance_vnf_list(args):
925 print "instance-vnf-list"
926 return 0
927
928def instance_vnf_status(args):
929 print "instance-vnf-status"
930 return 0
931
932def tenant_create(args):
933 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
934 tenant_dict={"name": args.name}
935 if args.description!=None:
936 tenant_dict["description"] = args.description
937 payload_req = json.dumps( {"tenant": tenant_dict })
938
939 #print payload_req
940
941 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
942 logger.debug("openmano request: %s", payload_req)
943 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
944 logger.debug("openmano response: %s", mano_response.text )
945 return _print_verbose(mano_response, args.verbose)
946
947def tenant_list(args):
948 #print "tenant-list",args
949 if args.name:
tierno392f2852016-05-13 12:28:55 +0200950 toshow = _get_item_uuid("tenants", args.name)
tierno7edb6752016-03-21 17:37:52 +0100951 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
952 else:
953 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
954 mano_response = requests.get(URLrequest)
955 logger.debug("openmano response: %s", mano_response.text )
956 if args.verbose==None:
957 args.verbose=0
958 if args.name!=None:
959 args.verbose += 1
960 return _print_verbose(mano_response, args.verbose)
961
962def tenant_delete(args):
963 #print "tenant-delete",args
964 todelete = _get_item_uuid("tenants", args.name)
965 if not args.force:
966 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
967 if not (len(r)>0 and r[0].lower()=="y"):
968 return 0
969 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
970 mano_response = requests.delete(URLrequest)
971 logger.debug("openmano response: %s", mano_response.text )
972 result = 0 if mano_response.status_code==200 else mano_response.status_code
973 content = mano_response.json()
974 #print json.dumps(content, indent=4)
975 if mano_response.status_code == 200:
976 print content['result']
977 else:
978 print content['error']['description']
979 return result
980
981def datacenter_attach(args):
982 tenant = _get_tenant()
983 datacenter = _get_datacenter(args.name)
984 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
985
986 datacenter_dict={}
987 if args.vim_tenant_id != None:
988 datacenter_dict['vim_tenant'] = args.vim_tenant_id
989 if args.vim_tenant_name != None:
990 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
991 if args.user != None:
992 datacenter_dict['vim_username'] = args.user
993 if args.password != None:
994 datacenter_dict['vim_password'] = args.password
tierno8008c3a2016-10-13 15:34:28 +0000995 if args.config!=None:
996 datacenter_dict["config"] = _load_file_or_yaml(args.config)
tierno7edb6752016-03-21 17:37:52 +0100997 payload_req = json.dumps( {"datacenter": datacenter_dict })
998
999 #print payload_req
1000
1001 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1002 logger.debug("openmano request: %s", payload_req)
1003 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1004 logger.debug("openmano response: %s", mano_response.text )
1005 result = _print_verbose(mano_response, args.verbose)
1006 #provide addional information if error
1007 if mano_response.status_code != 200:
1008 content = mano_response.json()
1009 if "already in use for 'name'" in content['error']['description'] and \
1010 "to database vim_tenants table" in content['error']['description']:
1011 print "Try to specify a different name with --vim-tenant-name"
1012 return result
1013
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001014
1015def datacenter_edit_vim_tenant(args):
1016 tenant = _get_tenant()
1017 datacenter = _get_datacenter(args.name)
1018 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1019
1020 if not (args.vim_tenant_id or args.vim_tenant_name or args.user or args.password or args.config):
1021 raise OpenmanoCLIError("Error. At least one parameter must be updated.")
1022
1023 datacenter_dict = {}
1024 if args.vim_tenant_id != None:
1025 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1026 if args.vim_tenant_name != None:
1027 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1028 if args.user != None:
1029 datacenter_dict['vim_username'] = args.user
1030 if args.password != None:
1031 datacenter_dict['vim_password'] = args.password
1032 if args.config != None:
1033 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1034 payload_req = json.dumps({"datacenter": datacenter_dict})
1035
1036 # print payload_req
1037
1038 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" % (mano_host, mano_port, tenant, datacenter)
1039 logger.debug("openmano request: %s", payload_req)
1040 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1041 logger.debug("openmano response: %s", mano_response.text)
1042 result = _print_verbose(mano_response, args.verbose)
1043
1044 return result
1045
tierno7edb6752016-03-21 17:37:52 +01001046def datacenter_detach(args):
1047 if args.all:
1048 tenant = "any"
1049 else:
1050 tenant = _get_tenant()
1051 datacenter = _get_datacenter(args.name, tenant)
1052 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1053 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1054 mano_response = requests.delete(URLrequest, headers=headers_req)
1055 logger.debug("openmano response: %s", mano_response.text )
1056 content = mano_response.json()
1057 #print json.dumps(content, indent=4)
1058 result = 0 if mano_response.status_code==200 else mano_response.status_code
1059 if mano_response.status_code == 200:
1060 print content['result']
1061 else:
1062 print content['error']['description']
1063 return result
1064
1065def datacenter_create(args):
1066 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1067 datacenter_dict={"name": args.name, "vim_url": args.url}
1068 if args.description!=None:
1069 datacenter_dict["description"] = args.description
1070 if args.type!=None:
1071 datacenter_dict["type"] = args.type
1072 if args.url!=None:
1073 datacenter_dict["vim_url_admin"] = args.url_admin
1074 if args.config!=None:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001075 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1076 if args.sdn_controller!=None:
1077 tenant = _get_tenant()
1078 sdn_controller = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1079 if not 'config' in datacenter_dict:
1080 datacenter_dict['config'] = {}
1081 datacenter_dict['config']['sdn-controller'] = sdn_controller
tierno7edb6752016-03-21 17:37:52 +01001082 payload_req = json.dumps( {"datacenter": datacenter_dict })
1083
1084 #print payload_req
1085
1086 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
1087 logger.debug("openmano request: %s", payload_req)
1088 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1089 logger.debug("openmano response: %s", mano_response.text )
1090 return _print_verbose(mano_response, args.verbose)
1091
1092def datacenter_delete(args):
1093 #print "datacenter-delete",args
1094 todelete = _get_item_uuid("datacenters", args.name, "any")
1095 if not args.force:
1096 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
1097 if not (len(r)>0 and r[0].lower()=="y"):
1098 return 0
1099 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
1100 mano_response = requests.delete(URLrequest)
1101 logger.debug("openmano response: %s", mano_response.text )
1102 result = 0 if mano_response.status_code==200 else mano_response.status_code
1103 content = mano_response.json()
1104 #print json.dumps(content, indent=4)
1105 if mano_response.status_code == 200:
1106 print content['result']
1107 else:
1108 print content['error']['description']
1109 return result
1110
tierno20df3bb2017-07-07 14:31:00 +02001111
tierno7edb6752016-03-21 17:37:52 +01001112def datacenter_list(args):
1113 #print "datacenter-list",args
1114 tenant='any' if args.all else _get_tenant()
1115
1116 if args.name:
1117 toshow = _get_item_uuid("datacenters", args.name, tenant)
1118 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
1119 else:
1120 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
1121 mano_response = requests.get(URLrequest)
1122 logger.debug("openmano response: %s", mano_response.text )
1123 if args.verbose==None:
1124 args.verbose=0
1125 if args.name!=None:
1126 args.verbose += 1
1127 return _print_verbose(mano_response, args.verbose)
1128
tierno20df3bb2017-07-07 14:31:00 +02001129
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001130def datacenter_sdn_port_mapping_set(args):
1131 tenant = _get_tenant()
1132 datacenter = _get_datacenter(args.name, tenant)
1133 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1134
1135 if not args.file:
1136 raise OpenmanoCLIError(
1137 "No yaml/json has been provided specifying the SDN port mapping")
tierno20df3bb2017-07-07 14:31:00 +02001138 sdn_port_mapping = _load_file_or_yaml(args.file)
1139 payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping})
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001140
tierno20df3bb2017-07-07 14:31:00 +02001141 # read
1142 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1143 mano_response = requests.get(URLrequest)
1144 logger.debug("openmano response: %s", mano_response.text)
1145 port_mapping = mano_response.json()
1146 if mano_response.status_code != 200:
1147 str(mano_response.json())
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001148 raise OpenmanoCLIError("openmano client error: {}".format(port_mapping['error']['description']))
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001149 if len(port_mapping["sdn_port_mapping"]["ports_mapping"]) > 0:
1150 if not args.force:
1151 r = raw_input("Datacenter %s already contains a port mapping. Overwrite? (y/N)? " % (datacenter))
1152 if not (len(r) > 0 and r[0].lower() == "y"):
1153 return 0
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001154
tierno20df3bb2017-07-07 14:31:00 +02001155 # clear
1156 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1157 mano_response = requests.delete(URLrequest)
1158 logger.debug("openmano response: %s", mano_response.text)
1159 if mano_response.status_code != 200:
1160 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001161
tierno20df3bb2017-07-07 14:31:00 +02001162 # set
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001163 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1164 logger.debug("openmano request: %s", payload_req)
1165 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1166 logger.debug("openmano response: %s", mano_response.text)
tierno20df3bb2017-07-07 14:31:00 +02001167 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001168
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001169
1170def datacenter_sdn_port_mapping_list(args):
1171 tenant = _get_tenant()
1172 datacenter = _get_datacenter(args.name, tenant)
1173
1174 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1175 mano_response = requests.get(URLrequest)
1176 logger.debug("openmano response: %s", mano_response.text)
1177
tierno20df3bb2017-07-07 14:31:00 +02001178 return _print_verbose(mano_response, 4)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001179
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001180
1181def datacenter_sdn_port_mapping_clear(args):
1182 tenant = _get_tenant()
1183 datacenter = _get_datacenter(args.name, tenant)
1184
1185 if not args.force:
1186 r = raw_input("Clean SDN port mapping for datacenter %s (y/N)? " %(datacenter))
tierno20df3bb2017-07-07 14:31:00 +02001187 if not (len(r) > 0 and r[0].lower() == "y"):
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001188 return 0
1189
1190 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1191 mano_response = requests.delete(URLrequest)
1192 logger.debug("openmano response: %s", mano_response.text)
1193
tierno20df3bb2017-07-07 14:31:00 +02001194 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001195
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001196
1197def sdn_controller_create(args):
1198 tenant = _get_tenant()
1199 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1200
tierno8fe7a492017-07-11 13:50:04 +02001201 error_msg=[]
1202 if not args.ip: error_msg.append("'ip'")
1203 if not args.port: error_msg.append("'port'")
1204 if not args.dpid: error_msg.append("'dpid'")
1205 if not args.type: error_msg.append("'type'")
1206 if error_msg:
1207 raise OpenmanoCLIError("The following arguments are required: " + ",".join(error_msg))
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001208
1209 controller_dict = {}
1210 controller_dict['name'] = args.name
1211 controller_dict['ip'] = args.ip
1212 controller_dict['port'] = int(args.port)
1213 controller_dict['dpid'] = args.dpid
1214 controller_dict['type'] = args.type
1215 if args.description != None:
1216 controller_dict['description'] = args.description
1217 if args.user != None:
1218 controller_dict['user'] = args.user
1219 if args.password != None:
1220 controller_dict['password'] = args.password
1221
1222 payload_req = json.dumps({"sdn_controller": controller_dict})
1223
1224 # print payload_req
1225
1226 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" % (mano_host, mano_port, tenant)
1227 logger.debug("openmano request: %s", payload_req)
1228 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1229 logger.debug("openmano response: %s", mano_response.text)
1230 result = _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001231 return result
1232
tierno20df3bb2017-07-07 14:31:00 +02001233
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001234def sdn_controller_edit(args):
1235 tenant = _get_tenant()
1236 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1237 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1238
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001239 controller_dict = {}
tierno20df3bb2017-07-07 14:31:00 +02001240 if args.new_name:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001241 controller_dict['name'] = args.new_name
tierno20df3bb2017-07-07 14:31:00 +02001242 if args.ip:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001243 controller_dict['ip'] = args.ip
tierno20df3bb2017-07-07 14:31:00 +02001244 if args.port:
Pablo Montes Morenob12711f2017-04-06 11:54:34 +02001245 controller_dict['port'] = int(args.port)
tierno20df3bb2017-07-07 14:31:00 +02001246 if args.dpid:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001247 controller_dict['dpid'] = args.dpid
tierno20df3bb2017-07-07 14:31:00 +02001248 if args.type:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001249 controller_dict['type'] = args.type
tierno20df3bb2017-07-07 14:31:00 +02001250 if args.description:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001251 controller_dict['description'] = args.description
tierno20df3bb2017-07-07 14:31:00 +02001252 if args.user:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001253 controller_dict['user'] = args.user
tierno20df3bb2017-07-07 14:31:00 +02001254 if args.password:
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001255 controller_dict['password'] = args.password
1256
tierno20df3bb2017-07-07 14:31:00 +02001257 if not controller_dict:
1258 raise OpenmanoCLIError("At least one parameter must be edited")
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001259
tierno20df3bb2017-07-07 14:31:00 +02001260 if not args.force:
1261 r = raw_input("Update SDN controller {} (y/N)? ".format(args.name))
1262 if not (len(r) > 0 and r[0].lower() == "y"):
1263 return 0
1264
1265 payload_req = json.dumps({"sdn_controller": controller_dict})
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001266 # print payload_req
1267
1268 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1269 logger.debug("openmano request: %s", payload_req)
1270 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1271 logger.debug("openmano response: %s", mano_response.text)
1272 result = _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001273 return result
1274
tierno20df3bb2017-07-07 14:31:00 +02001275
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001276def sdn_controller_list(args):
1277 tenant = _get_tenant()
1278 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1279
1280 if args.name:
1281 toshow = _get_item_uuid("sdn_controllers", args.name, tenant)
1282 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" %(mano_host, mano_port, tenant, toshow)
1283 else:
1284 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" %(mano_host, mano_port, tenant)
1285 #print URLrequest
1286 mano_response = requests.get(URLrequest)
1287 logger.debug("openmano response: %s", mano_response.text )
1288 if args.verbose==None:
1289 args.verbose=0
1290 if args.name!=None:
1291 args.verbose += 1
1292
tierno20df3bb2017-07-07 14:31:00 +02001293 # json.dumps(mano_response.json(), indent=4)
1294 return _print_verbose(mano_response, args.verbose)
1295
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001296
1297def sdn_controller_delete(args):
1298 tenant = _get_tenant()
1299 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1300
1301 if not args.force:
1302 r = raw_input("Delete SDN controller %s (y/N)? " % (args.name))
1303 if not (len(r) > 0 and r[0].lower() == "y"):
1304 return 0
1305
1306 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1307 mano_response = requests.delete(URLrequest)
1308 logger.debug("openmano response: %s", mano_response.text)
tierno20df3bb2017-07-07 14:31:00 +02001309 return _print_verbose(mano_response, args.verbose)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001310
tierno7edb6752016-03-21 17:37:52 +01001311def vim_action(args):
1312 #print "datacenter-net-action",args
1313 tenant = _get_tenant()
1314 datacenter = _get_datacenter(args.datacenter, tenant)
1315 if args.verbose==None:
1316 args.verbose=0
1317 if args.action=="list":
1318 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1319 if args.name!=None:
1320 args.verbose += 1
1321 URLrequest += "/" + args.name
1322 mano_response = requests.get(URLrequest)
1323 logger.debug("openmano response: %s", mano_response.text )
1324 return _print_verbose(mano_response, args.verbose)
1325 elif args.action=="delete":
1326 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1327 mano_response = requests.delete(URLrequest)
1328 logger.debug("openmano response: %s", mano_response.text )
1329 result = 0 if mano_response.status_code==200 else mano_response.status_code
1330 content = mano_response.json()
1331 #print json.dumps(content, indent=4)
1332 if mano_response.status_code == 200:
1333 print content['result']
1334 else:
1335 print content['error']['description']
1336 return result
1337 elif args.action=="create":
1338 headers_req = {'content-type': 'application/yaml'}
1339 if args.file:
1340 create_dict = _load_file_or_yaml(args.file)
1341 if args.item not in create_dict:
1342 create_dict = {args.item: create_dict}
1343 else:
1344 create_dict = {args.item:{}}
1345 if args.name:
1346 create_dict[args.item]['name'] = args.name
1347 #if args.description:
1348 # create_dict[args.item]['description'] = args.description
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001349 if args.item=="network":
tierno7edb6752016-03-21 17:37:52 +01001350 if args.bind_net:
1351 create_dict[args.item]['bind_net'] = args.bind_net
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001352 if args.type:
1353 create_dict[args.item]['type'] = args.type
tierno7edb6752016-03-21 17:37:52 +01001354 if args.shared:
1355 create_dict[args.item]['shared'] = args.shared
1356 if "name" not in create_dict[args.item]:
1357 print "You must provide a name in the descriptor file or with the --name option"
1358 return
1359 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1360 logger.debug("openmano request: %s", payload_req)
tierno72a08d72017-05-25 13:12:30 +02001361 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
tierno7edb6752016-03-21 17:37:52 +01001362 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1363 logger.debug("openmano response: %s", mano_response.text )
1364 if args.verbose==None:
1365 args.verbose=0
1366 return _print_verbose(mano_response, args.verbose)
1367
tierno20df3bb2017-07-07 14:31:00 +02001368
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001369def _get_items(item, item_name_id=None, datacenter=None, tenant=None):
1370 URLrequest = "http://%s:%s/openmano" %(mano_host, mano_port)
1371 if tenant:
1372 URLrequest += "/" + tenant
1373 if datacenter:
1374 URLrequest += "/vim/" + datacenter
1375 if item:
1376 URLrequest += "/" + item +"s"
1377 if item_name_id:
1378 URLrequest += "/" + item_name_id
1379 mano_response = requests.get(URLrequest)
1380 logger.debug("openmano response: %s", mano_response.text )
1381
1382 return mano_response
1383
tierno20df3bb2017-07-07 14:31:00 +02001384
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001385def vim_net_sdn_attach(args):
1386 #Verify the network exists in the vim
1387 tenant = _get_tenant()
1388 datacenter = _get_datacenter(args.datacenter, tenant)
1389 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1390 content = yaml.load(result.content)
1391 if 'networks' in content:
1392 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1393 if 'error' in content:
1394 raise OpenmanoCLIError(yaml.safe_dump(content))
1395 network_uuid = content['network']['id']
1396
1397 #Make call to attach the dataplane port to the SND network associated to the vim network
1398 headers_req = {'content-type': 'application/yaml'}
1399 payload_req = {'port': args.port}
1400 if args.vlan:
1401 payload_req['vlan'] = int(args.vlan)
1402 if args.mac:
1403 payload_req['mac'] = args.mac
1404
1405 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/attach" % (mano_host, mano_port, tenant, datacenter, network_uuid)
1406 logger.debug("openmano request: %s", payload_req)
1407 mano_response = requests.post(URLrequest, headers=headers_req, data=json.dumps(payload_req))
1408 logger.debug("openmano response: %s", mano_response.text)
1409 result = _print_verbose(mano_response, args.verbose)
tierno20df3bb2017-07-07 14:31:00 +02001410 return result
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001411
1412
1413def vim_net_sdn_detach(args):
1414 if not args.all and not args.id:
1415 print "--all or --id must be used"
1416 return 1
1417
1418 # Verify the network exists in the vim
1419 tenant = _get_tenant()
1420 datacenter = _get_datacenter(args.datacenter, tenant)
1421 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1422 content = yaml.load(result.content)
1423 if 'networks' in content:
1424 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1425 if 'error' in content:
1426 raise OpenmanoCLIError(yaml.safe_dump(content))
1427 network_uuid = content['network']['id']
1428
1429 if not args.force:
1430 r = raw_input("Confirm action' (y/N)? ")
1431 if len(r) == 0 or r[0].lower() != "y":
1432 return 0
1433
1434 if args.id:
1435 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach/%s" % (
1436 mano_host, mano_port, tenant, datacenter, network_uuid, args.id)
1437 else:
1438 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach" % (
1439 mano_host, mano_port, tenant, datacenter, network_uuid)
1440 mano_response = requests.delete(URLrequest)
1441 logger.debug("openmano response: %s", mano_response.text)
1442 result = _print_verbose(mano_response, args.verbose)
tierno20df3bb2017-07-07 14:31:00 +02001443 return result
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001444
tierno7edb6752016-03-21 17:37:52 +01001445
1446def datacenter_net_action(args):
1447 if args.action == "net-update":
tierno5acf7202016-08-29 14:28:13 +02001448 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
tierno7edb6752016-03-21 17:37:52 +01001449 print
1450 args.action = "netmap-delete"
1451 args.netmap = None
1452 args.all = True
1453 r = datacenter_netmap_action(args)
1454 if r == 0:
1455 args.force = True
tierno5acf7202016-08-29 14:28:13 +02001456 args.action = "netmap-import"
tierno7edb6752016-03-21 17:37:52 +01001457 r = datacenter_netmap_action(args)
1458 return r
1459
1460 if args.action == "net-edit":
1461 args.netmap = args.net
1462 args.name = None
1463 elif args.action == "net-list":
1464 args.netmap = None
1465 elif args.action == "net-delete":
1466 args.netmap = args.net
1467 args.all = False
1468
1469 args.action = "netmap" + args.action[3:]
1470 args.vim_name=None
1471 args.vim_id=None
1472 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1473 print
1474 return datacenter_netmap_action(args)
1475
1476def datacenter_netmap_action(args):
1477 tenant = _get_tenant()
1478 datacenter = _get_datacenter(args.datacenter, tenant)
1479 #print "datacenter_netmap_action",args
1480 payload_req = None
1481 if args.verbose==None:
1482 args.verbose=0
1483 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1484 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1485
1486 if args.action=="netmap-list":
1487 if args.netmap:
1488 URLrequest += "/" + args.netmap
1489 args.verbose += 1
1490 mano_response = requests.get(URLrequest)
1491
1492 elif args.action=="netmap-delete":
1493 if args.netmap and args.all:
1494 print "you can not use a netmap name and the option --all at the same time"
1495 return 1
1496 if args.netmap:
1497 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1498 URLrequest += "/" + args.netmap
1499 elif args.all:
1500 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1501 else:
tiernoae4a8d12016-07-08 12:30:39 +02001502 print "you must specify a netmap name or the option --all"
tierno7edb6752016-03-21 17:37:52 +01001503 return 1
1504 if not args.force:
1505 r = raw_input(force_text)
1506 if len(r)>0 and r[0].lower()=="y":
1507 pass
1508 else:
1509 return 0
1510 mano_response = requests.delete(URLrequest, headers=headers_req)
tierno5acf7202016-08-29 14:28:13 +02001511 elif args.action=="netmap-import":
tierno7edb6752016-03-21 17:37:52 +01001512 if not args.force:
1513 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1514 if len(r)>0 and r[0].lower()=="y":
1515 pass
1516 else:
1517 return 0
1518 URLrequest += "/upload"
1519 mano_response = requests.post(URLrequest, headers=headers_req)
1520 elif args.action=="netmap-edit" or args.action=="netmap-create":
1521 if args.file:
1522 payload = _load_file_or_yaml(args.file)
1523 else:
1524 payload = {}
1525 if "netmap" not in payload:
1526 payload = {"netmap": payload}
1527 if args.name:
1528 payload["netmap"]["name"] = args.name
1529 if args.vim_id:
1530 payload["netmap"]["vim_id"] = args.vim_id
1531 if args.action=="netmap-create" and args.vim_name:
1532 payload["netmap"]["vim_name"] = args.vim_name
1533 payload_req = json.dumps(payload)
1534 logger.debug("openmano request: %s", payload_req)
1535
1536 if args.action=="netmap-edit" and not args.force:
1537 if len(payload["netmap"]) == 0:
1538 print "You must supply some parameter to edit"
1539 return 1
1540 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1541 if len(r)>0 and r[0].lower()=="y":
1542 pass
1543 else:
1544 return 0
1545 URLrequest += "/" + args.netmap
1546 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1547 else: #netmap-create
1548 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1549 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1550 return 1
1551 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1552
1553 logger.debug("openmano response: %s", mano_response.text )
1554 return _print_verbose(mano_response, args.verbose)
1555
tierno20df3bb2017-07-07 14:31:00 +02001556
tierno7edb6752016-03-21 17:37:52 +01001557def element_edit(args):
1558 element = _get_item_uuid(args.element, args.name)
1559 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1560 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1561 payload=_load_file_or_yaml(args.file)
1562 if args.element[:-1] not in payload:
1563 payload = {args.element[:-1]: payload }
1564 payload_req = json.dumps(payload)
1565
1566 #print payload_req
1567 if not args.force or (args.name==None and args.filer==None):
1568 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1569 if len(r)>0 and r[0].lower()=="y":
1570 pass
1571 else:
1572 return 0
1573 logger.debug("openmano request: %s", payload_req)
1574 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1575 logger.debug("openmano response: %s", mano_response.text )
1576 if args.verbose==None:
1577 args.verbose=0
1578 if args.name!=None:
1579 args.verbose += 1
1580 return _print_verbose(mano_response, args.verbose)
1581
1582
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001583def datacenter_edit(args):
1584 tenant = _get_tenant()
1585 element = _get_item_uuid('datacenters', args.name, tenant)
1586 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1587 URLrequest = "http://%s:%s/openmano/datacenters/%s" % (mano_host, mano_port, element)
1588
1589 has_arguments = False
1590 if args.file != None:
1591 has_arguments = True
1592 payload = _load_file_or_yaml(args.file)
1593 else:
1594 payload = {}
1595
1596 if args.sdn_controller != None:
1597 has_arguments = True
1598 if not 'config' in payload:
1599 payload['config'] = {}
1600 if not 'sdn-controller' in payload['config']:
1601 payload['config']['sdn-controller'] = {}
1602 if args.sdn_controller == 'null':
1603 payload['config']['sdn-controller'] = None
1604 else:
1605 payload['config']['sdn-controller'] = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1606
1607 if not has_arguments:
1608 raise OpenmanoCLIError("At least one argument must be provided to modify the datacenter")
1609
1610 if 'datacenter' not in payload:
1611 payload = {'datacenter': payload}
1612 payload_req = json.dumps(payload)
1613
1614 # print payload_req
1615 if not args.force or (args.name == None and args.filer == None):
1616 r = raw_input(" Edit datacenter " + args.name + " (y/N)? ")
1617 if len(r) > 0 and r[0].lower() == "y":
1618 pass
1619 else:
1620 return 0
1621 logger.debug("openmano request: %s", payload_req)
1622 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1623 logger.debug("openmano response: %s", mano_response.text)
1624 if args.verbose == None:
1625 args.verbose = 0
1626 if args.name != None:
1627 args.verbose += 1
1628 return _print_verbose(mano_response, args.verbose)
1629
tierno20df3bb2017-07-07 14:31:00 +02001630
tierno6ddeded2017-05-16 15:40:26 +02001631def version(args):
1632 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1633 URLrequest = "http://%s:%s/openmano/version" % (mano_host, mano_port)
1634
1635 mano_response = requests.get(URLrequest, headers=headers_req)
1636 logger.debug("openmano response: %s", mano_response.text)
1637 print mano_response.text
1638
1639
tierno7edb6752016-03-21 17:37:52 +01001640global mano_host
1641global mano_port
1642global mano_tenant
1643
1644if __name__=="__main__":
1645
1646 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1647 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1648 mano_port = os.getenv('OPENMANO_PORT',"9090")
1649 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1650
1651 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
tierno6ddeded2017-05-16 15:40:26 +02001652 main_parser.add_argument('--version', action='version', help="get version of this client",
1653 version='%(prog)s client version ' + __version__ +
1654 " (Note: use '%(prog)s version' to get server version)")
1655
tierno7edb6752016-03-21 17:37:52 +01001656 subparsers = main_parser.add_subparsers(help='commands')
1657
tierno7edb6752016-03-21 17:37:52 +01001658 parent_parser = argparse.ArgumentParser(add_help=False)
1659 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1660 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1661
garciadeblas0e9fd832016-07-08 15:20:18 +02001662 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1663 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1664 config_parser.set_defaults(func=config)
1665
tierno6ddeded2017-05-16 15:40:26 +02001666 version_parser = subparsers.add_parser('version', parents=[parent_parser], help="get server version")
1667 version_parser.set_defaults(func=version)
1668
tierno7edb6752016-03-21 17:37:52 +01001669 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1670 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1671 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1672 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1673 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
garciadeblas14480452017-01-10 13:08:07 +01001674 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1675 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
tierno7edb6752016-03-21 17:37:52 +01001676 vnf_create_parser.set_defaults(func=vnf_create)
1677
1678 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1679 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1680 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1681 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1682 vnf_list_parser.set_defaults(func=vnf_list)
1683
1684 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1685 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1686 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1687 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1688 vnf_delete_parser.set_defaults(func=vnf_delete)
1689
1690 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1691 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1692 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1693 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1694 scenario_create_parser.set_defaults(func=scenario_create)
1695
1696 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1697 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1698 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1699 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1700 scenario_list_parser.set_defaults(func=scenario_list)
1701
1702 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1703 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1704 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1705 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1706 scenario_delete_parser.set_defaults(func=scenario_delete)
1707
1708 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1709 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1710 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1711 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1712 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1713 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1714 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1715
1716 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1717 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1718 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1719 scenario_deploy_parser.set_defaults(func=scenario_verify)
1720
1721 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1722 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1723 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1724 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1725 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1726 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1727 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")
1728 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 +02001729 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")
1730 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 +01001731 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1732 instance_scenario_create_parser.set_defaults(func=instance_create)
1733
1734 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1735 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1736 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1737 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1738
1739 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)")
1740 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1741 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1742 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1743 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1744
1745 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1746 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1747 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1748 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console"],\
1749 help="action to send")
1750 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1751 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1752 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1753 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1754
1755 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1756 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1757 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1758
1759 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1760 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1761 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1762 tenant_create_parser.set_defaults(func=tenant_create)
1763
1764 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1765 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1766 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1767 tenant_delete_parser.set_defaults(func=tenant_delete)
1768
1769 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1770 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1771 tenant_list_parser.set_defaults(func=tenant_list)
1772
tierno161c24b2017-05-16 15:45:56 +02001773 element_edit_parser = subparsers.add_parser('tenant-edit', parents=[parent_parser], help="edits one tenant")
1774 element_edit_parser.add_argument("name", help="name or uuid of the tenant")
1775 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1776 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1777 element_edit_parser.set_defaults(func=element_edit, element='tenants')
tierno7edb6752016-03-21 17:37:52 +01001778
1779 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1780 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1781 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1782 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1783 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1784 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1785 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001786 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 +01001787 datacenter_create_parser.set_defaults(func=datacenter_create)
1788
1789 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1790 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1791 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1792 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1793
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001794 datacenter_edit_parser = subparsers.add_parser('datacenter-edit', parents=[parent_parser], help="Edit datacenter")
1795 datacenter_edit_parser.add_argument("name", help="name or uuid of the datacenter")
1796 datacenter_edit_parser.add_argument("--file", help="json/yaml text or file with the changes").completer = FilesCompleter
1797 datacenter_edit_parser.add_argument("--sdn-controller", action="store",
1798 help="Name or uuid of the SDN controller to be used. Specify 'null' to clear entry", dest='sdn_controller')
1799 datacenter_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1800 datacenter_edit_parser.set_defaults(func=datacenter_edit)
1801
tierno7edb6752016-03-21 17:37:52 +01001802 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1803 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1804 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1805 datacenter_list_parser.set_defaults(func=datacenter_list)
1806
1807 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1808 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1809 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1810 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1811 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1812 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
tierno8008c3a2016-10-13 15:34:28 +00001813 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
tierno7edb6752016-03-21 17:37:52 +01001814 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1815
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001816 datacenter_edit_vim_tenant_parser = subparsers.add_parser('datacenter-edit-vim-tenant', parents=[parent_parser],
1817 help="Edit the association of a datacenter to the operating tenant")
1818 datacenter_edit_vim_tenant_parser.add_argument("name", help="name or uuid of the datacenter")
1819 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-id', action='store',
1820 help="specify a datacenter tenant to use. A new one is created by default")
1821 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1822 datacenter_edit_vim_tenant_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1823 datacenter_edit_vim_tenant_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1824 datacenter_edit_vim_tenant_parser.add_argument("--config", action="store",
1825 help="aditional configuration in json/yaml format")
1826 datacenter_edit_vim_tenant_parser.set_defaults(func=datacenter_edit_vim_tenant)
1827
tierno7edb6752016-03-21 17:37:52 +01001828 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1829 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1830 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1831 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1832
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +01001833 #=======================datacenter_sdn_port_mapping_xxx section=======================
1834 #datacenter_sdn_port_mapping_set
1835 datacenter_sdn_port_mapping_set_parser = subparsers.add_parser('datacenter-sdn-port-mapping-set',
1836 parents=[parent_parser],
1837 help="Load a file with the mapping of physical ports "
1838 "and the ports of the dataplaneswitch controlled "
1839 "by a datacenter")
1840 datacenter_sdn_port_mapping_set_parser.add_argument("name", action="store", help="specifies the datacenter")
1841 datacenter_sdn_port_mapping_set_parser.add_argument("file",
1842 help="json/yaml text or file with the port mapping").completer = FilesCompleter
1843 datacenter_sdn_port_mapping_set_parser.add_argument("-f", "--force", action="store_true",
1844 help="forces overwriting without asking")
1845 datacenter_sdn_port_mapping_set_parser.set_defaults(func=datacenter_sdn_port_mapping_set)
1846
1847 #datacenter_sdn_port_mapping_list
1848 datacenter_sdn_port_mapping_list_parser = subparsers.add_parser('datacenter-sdn-port-mapping-list',
1849 parents=[parent_parser],
1850 help="Show the SDN port mapping in a datacenter")
1851 datacenter_sdn_port_mapping_list_parser.add_argument("name", action="store", help="specifies the datacenter")
1852 datacenter_sdn_port_mapping_list_parser.set_defaults(func=datacenter_sdn_port_mapping_list)
1853
1854 # datacenter_sdn_port_mapping_clear
1855 datacenter_sdn_port_mapping_clear_parser = subparsers.add_parser('datacenter-sdn-port-mapping-clear',
1856 parents=[parent_parser],
1857 help="Clean the the SDN port mapping in a datacenter")
1858 datacenter_sdn_port_mapping_clear_parser.add_argument("name", action="store",
1859 help="specifies the datacenter")
1860 datacenter_sdn_port_mapping_clear_parser.add_argument("-f", "--force", action="store_true",
1861 help="forces clearing without asking")
1862 datacenter_sdn_port_mapping_clear_parser.set_defaults(func=datacenter_sdn_port_mapping_clear)
1863 # =======================
1864
1865 # =======================sdn_controller_xxx section=======================
1866 # sdn_controller_create
1867 sdn_controller_create_parser = subparsers.add_parser('sdn-controller-create', parents=[parent_parser],
1868 help="Creates an SDN controller entity within RO")
1869 sdn_controller_create_parser.add_argument("name", help="name of the SDN controller")
1870 sdn_controller_create_parser.add_argument("--description", action="store", help="description of the SDN controller")
1871 sdn_controller_create_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1872 sdn_controller_create_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1873 sdn_controller_create_parser.add_argument("--dpid", action="store",
1874 help="DPID of the dataplane switch controlled by this SDN controller")
1875 sdn_controller_create_parser.add_argument("--type", action="store",
1876 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1877 sdn_controller_create_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1878 sdn_controller_create_parser.add_argument("--passwd", action="store", dest='password',
1879 help="password credentials for the SDN controller")
1880 sdn_controller_create_parser.set_defaults(func=sdn_controller_create)
1881
1882 # sdn_controller_edit
1883 sdn_controller_edit_parser = subparsers.add_parser('sdn-controller-edit', parents=[parent_parser],
1884 help="Update one or more options of a SDN controller")
1885 sdn_controller_edit_parser.add_argument("name", help="name or uuid of the SDN controller", )
1886 sdn_controller_edit_parser.add_argument("--name", action="store", help="Update the name of the SDN controller",
1887 dest='new_name')
1888 sdn_controller_edit_parser.add_argument("--description", action="store", help="description of the SDN controller")
1889 sdn_controller_edit_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1890 sdn_controller_edit_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1891 sdn_controller_edit_parser.add_argument("--dpid", action="store",
1892 help="DPID of the dataplane switch controlled by this SDN controller")
1893 sdn_controller_edit_parser.add_argument("--type", action="store",
1894 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1895 sdn_controller_edit_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1896 sdn_controller_edit_parser.add_argument("--password", action="store",
1897 help="password credentials for the SDN controller", dest='password')
1898 sdn_controller_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1899 #TODO: include option --file
1900 sdn_controller_edit_parser.set_defaults(func=sdn_controller_edit)
1901
1902 #sdn_controller_list
1903 sdn_controller_list_parser = subparsers.add_parser('sdn-controller-list',
1904 parents=[parent_parser],
1905 help="List the SDN controllers")
1906 sdn_controller_list_parser.add_argument("name", nargs='?', help="name or uuid of the SDN controller")
1907 sdn_controller_list_parser.set_defaults(func=sdn_controller_list)
1908
1909 # sdn_controller_delete
1910 sdn_controller_delete_parser = subparsers.add_parser('sdn-controller-delete',
1911 parents=[parent_parser],
1912 help="Delete the the SDN controller")
1913 sdn_controller_delete_parser.add_argument("name", help="name or uuid of the SDN controller")
1914 sdn_controller_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1915 sdn_controller_delete_parser.set_defaults(func=sdn_controller_delete)
1916 # =======================
tierno7edb6752016-03-21 17:37:52 +01001917
1918 action_dict={'net-update': 'retrieves external networks from datacenter',
1919 'net-edit': 'edits an external network',
1920 'net-delete': 'deletes an external network',
1921 'net-list': 'lists external networks from a datacenter'
1922 }
1923 for item in action_dict:
1924 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1925 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1926 if item=='net-edit' or item=='net-delete':
1927 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1928 if item=='net-edit':
1929 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1930 if item!='net-list':
1931 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1932 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1933
1934
tierno5acf7202016-08-29 14:28:13 +02001935 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
tierno7edb6752016-03-21 17:37:52 +01001936 'netmap-create': 'create a new network senario netmap',
1937 'netmap-edit': 'edit name of a network senario netmap',
1938 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1939 'netmap-list': 'list/show network scenario netmaps'
1940 }
1941 for item in action_dict:
1942 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1943 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1944 #if item=='net-add':
1945 # datacenter_action_parser.add_argument("net", help="name of the network")
1946 if item=='netmap-delete':
1947 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1948 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1949 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1950 if item=='netmap-edit':
1951 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1952 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1953 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1954 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1955 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1956 if item=='netmap-list':
1957 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1958 if item=='netmap-create':
1959 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1960 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1961 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1962 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
tierno5acf7202016-08-29 14:28:13 +02001963 if item=='netmap-import':
tierno7edb6752016-03-21 17:37:52 +01001964 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1965 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001966
1967 # =======================vim_net_sdn_xxx section=======================
1968 # vim_net_sdn_attach
1969 vim_net_sdn_attach_parser = subparsers.add_parser('vim-net-sdn-attach',
1970 parents=[parent_parser],
1971 help="Specify the port to access to an external network using SDN")
1972 vim_net_sdn_attach_parser.add_argument("vim_net", action="store",
1973 help="Name/id of the network in the vim that will be used to connect to the external network")
1974 vim_net_sdn_attach_parser.add_argument("port", action="store", help="Specifies the port in the dataplane switch to access to the external network")
1975 vim_net_sdn_attach_parser.add_argument("--vlan", action="store", help="Specifies the vlan (if any) to use in the defined port")
1976 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")
1977 vim_net_sdn_attach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1978 vim_net_sdn_attach_parser.set_defaults(func=vim_net_sdn_attach)
1979
1980 # vim_net_sdn_detach
1981 vim_net_sdn_detach_parser = subparsers.add_parser('vim-net-sdn-detach',
1982 parents=[parent_parser],
1983 help="Remove the port information to access to an external network using SDN")
1984
1985 vim_net_sdn_detach_parser.add_argument("vim_net", action="store", help="Name/id of the vim network")
1986 vim_net_sdn_detach_parser.add_argument("--id", action="store",help="Specify the uuid of the external ports from this network to be detached")
1987 vim_net_sdn_detach_parser.add_argument("--all", action="store_true", help="Detach all external ports from this network")
1988 vim_net_sdn_detach_parser.add_argument("-f", "--force", action="store_true", help="forces clearing without asking")
1989 vim_net_sdn_detach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1990 vim_net_sdn_detach_parser.set_defaults(func=vim_net_sdn_detach)
1991 # =======================
1992
tierno4540ea52017-01-18 17:44:32 +01001993 for item in ("network", "tenant", "image"):
tierno7edb6752016-03-21 17:37:52 +01001994 if item=="network":
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001995 command_name = 'vim-net'
tierno7edb6752016-03-21 17:37:52 +01001996 else:
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02001997 command_name = 'vim-'+item
1998 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 +01001999 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
2000 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2001 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
2002
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002003 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 +01002004 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
2005 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2006 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
2007
tierno4540ea52017-01-18 17:44:32 +01002008 if item == "network" or item == "tenant":
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +02002009 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 +01002010 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
2011 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
2012 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2013 if item=="network":
2014 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
2015 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
2016 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>'")
2017 else:
2018 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
2019 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
tierno7edb6752016-03-21 17:37:52 +01002020
2021 argcomplete.autocomplete(main_parser)
2022
2023 try:
2024 args = main_parser.parse_args()
2025 #logging info
2026 level = logging.CRITICAL
2027 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
2028 if "debug" in args and args.debug:
2029 level = logging.DEBUG
2030 logging.basicConfig(format=streamformat, level= level)
2031 logger = logging.getLogger('mano')
2032 logger.setLevel(level)
2033 result = args.func(args)
2034 if result == None:
2035 result = 0
2036 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
2037 except (requests.exceptions.ConnectionError):
2038 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
2039 result = -2
2040 except (KeyboardInterrupt):
2041 print 'Exiting openmano'
2042 result = -3
2043 except (SystemExit, ArgumentParserError):
2044 result = -4
2045 except OpenmanoCLIError as e:
2046 print str(e)
2047 result = -5
2048
2049 #print result
2050 exit(result)
2051