| tierno | f7aa8c4 | 2016-09-06 16:43:04 +0200 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | # -*- coding: utf-8 -*- |
| 3 | |
| 4 | |
| 5 | ## |
| 6 | # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. |
| tierno | 9a61c6b | 2016-09-08 10:57:02 +0200 | [diff] [blame^] | 7 | # This file is part of openvim |
| tierno | f7aa8c4 | 2016-09-06 16:43:04 +0200 | [diff] [blame] | 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 | |
| 26 | ''' |
| 27 | This is a client tester for openvim. |
| 28 | It is almost DEPRECATED by the openvim client |
| 29 | |
| 30 | The reason for keeping is because it is used for some scripts |
| 31 | and it contain the -r option (delete recursive) |
| 32 | that it is very useful for deleting content of database. |
| 33 | Another difference from openvim is that it is more verbose |
| 34 | and so more suitable for the developers |
| 35 | ''' |
| 36 | |
| 37 | __author__="Alfonso Tierno" |
| 38 | __date__ ="$5-oct-2014 11:09:29$" |
| 39 | |
| 40 | import requests |
| 41 | import json |
| 42 | import yaml |
| 43 | import sys |
| 44 | import getopt |
| 45 | from jsonschema import validate as js_v, exceptions as js_e |
| 46 | |
| 47 | version="0.0.2" |
| 48 | global global_config |
| 49 | |
| 50 | |
| 51 | def get_elements(url): |
| 52 | headers_req = {'content-type': 'application/json'} |
| 53 | try: |
| 54 | vim_response = requests.get(url, headers = headers_req) |
| 55 | #print vim_response |
| 56 | #print vim_response.status_code |
| 57 | if vim_response.status_code == 200: |
| 58 | #print vim_response.json() |
| 59 | #print json.dumps(vim_response.json(), indent=4) |
| 60 | content = vim_response.json() |
| 61 | return 1, content |
| 62 | #print http_content |
| 63 | else: |
| 64 | text = " Error. VIM response '%s': not possible to GET %s" % (vim_response.status_code, url) |
| 65 | text += "\n " + vim_response.text |
| 66 | #print text |
| 67 | return -vim_response.status_code,text |
| 68 | except requests.exceptions.RequestException, e: |
| 69 | return -1, " Exception "+ str(e.message) |
| 70 | |
| 71 | def delete_elements(url): |
| 72 | headers_req = {'content-type': 'application/json'} |
| 73 | |
| 74 | try: |
| 75 | vim_response = requests.delete(url, headers = headers_req) |
| 76 | #print vim_response |
| 77 | #print vim_response.status_code |
| 78 | if vim_response.status_code == 200: |
| 79 | pass |
| 80 | #print vim_response.json() |
| 81 | #print json.dumps(vim_response.json(), indent=4) |
| 82 | else: |
| 83 | #print vim_response.text |
| 84 | text = " Error. VIM response '%s': not possible to DELETE %s" % (vim_response.status_code, url) |
| 85 | text += "\n " + vim_response.text |
| 86 | #print text |
| 87 | return -vim_response.status_code,text |
| 88 | except requests.exceptions.RequestException, e: |
| 89 | return -1, " Exception "+ str(e.message) |
| 90 | return 1, None |
| 91 | |
| 92 | |
| 93 | def new_elements(url, payload): |
| 94 | headers_req = {'Accept': 'application/json', 'content-type': 'application/json'} |
| 95 | #print str(payload) |
| 96 | try: |
| 97 | vim_response = requests.post(url, data=json.dumps(payload), headers=headers_req) |
| 98 | #print vim_response |
| 99 | #print vim_response.status_code |
| 100 | if vim_response.status_code == 200: |
| 101 | #print vim_response.json() |
| 102 | #print json.dumps(vim_response.json(), indent=4) |
| 103 | return 1, vim_response.text |
| 104 | else: |
| 105 | #print vim_response.text |
| 106 | text = "Error. VIM response '%s': not possible to ADD %s" % (vim_response.status_code, url) |
| 107 | text += "\n" + vim_response.text |
| 108 | #print text |
| 109 | return -vim_response.status_code,text |
| 110 | except requests.exceptions.RequestException, e: |
| 111 | return -1, " Exception "+ str(e.message) |
| 112 | |
| 113 | |
| 114 | def get_details(url, what, c): |
| 115 | item_list = [] |
| 116 | return_dict = {what+'s': []} |
| 117 | |
| 118 | item = c.get(what,None) |
| 119 | if item is None: item = c.get(what+'s',None) |
| 120 | if item is None: |
| 121 | error_text= " Internal error, not found '" + what +"[s]' in content" |
| 122 | print 'get_details()', error_text, c |
| 123 | return -1, error_text |
| 124 | if type(item) is list: |
| 125 | item_list = item |
| 126 | else: |
| 127 | item_list.append(item) |
| 128 | if len(item_list)==0: |
| 129 | print what, "not found" |
| 130 | return 1 |
| 131 | for item in item_list: |
| 132 | uuid = item.get('id',None) |
| 133 | if uuid is None: uuid = item.get('uuid',None) |
| 134 | if uuid is None: |
| 135 | error_text= " Internal error, not found 'id/uuid' in item" |
| 136 | print 'get_details()', error_text, item |
| 137 | return -1, error_text |
| 138 | #print " get", what, uuid, " >>>>>>>> ", |
| 139 | r,c = get_elements(url + "/" + uuid) |
| 140 | if r<0: |
| 141 | # print "fail" |
| 142 | print " get", what, uuid, "fail", c |
| 143 | return -1, c |
| 144 | #else: |
| 145 | # print 'ok' |
| 146 | return_dict[what+'s'].append(c[what]) |
| 147 | return 1, return_dict |
| 148 | |
| 149 | |
| 150 | def action_details(url, what, c, force, payload): |
| 151 | item_list = [] |
| 152 | return_dict = {what+'s': []} |
| 153 | headers_req = {'Accept': 'application/json', 'content-type': 'application/json'} |
| 154 | fail=0 |
| 155 | ok=0 |
| 156 | |
| 157 | #Allows for payload both keypairs inside a 'server','port' ... or directly. In later case, put keypairs inside what |
| 158 | |
| 159 | item = c.get(what,None) |
| 160 | if item is None: item = c.get(what+'s',None) |
| 161 | if item is None: |
| 162 | error_text= " Internal error, not found '" + what +"[s]' in content" |
| 163 | print 'get_details()', error_text, c |
| 164 | return -1, error_text |
| 165 | if type(item) is list: |
| 166 | item_list = item |
| 167 | else: |
| 168 | item_list.append(item) |
| 169 | if len(item_list)==0: |
| 170 | print what, "not found" |
| 171 | return 1 |
| 172 | for item in item_list: |
| 173 | name = item.get('name',None) |
| 174 | uuid = item.get('id',None) |
| 175 | if uuid is None: uuid = item.get('uuid',None) |
| 176 | if uuid is None: |
| 177 | error_text= " Internal error, not found 'id/uuid' in item" |
| 178 | print 'get_details()', error_text, item |
| 179 | return -1, error_text |
| 180 | if not force: |
| 181 | r = raw_input("Action on " + what + " " + uuid + " " + name + " (y/N)? ") |
| 182 | if len(r)>0 and r[0].lower()=="y": |
| 183 | print " put", what, uuid, " >>>>>>>> ", |
| 184 | else: |
| 185 | continue |
| 186 | |
| 187 | #print str(payload) |
| 188 | try: |
| 189 | vim_response = requests.post(url + "/" + uuid + "/action", data=json.dumps(payload), headers=headers_req) |
| 190 | if vim_response.status_code == 200: |
| 191 | print 'ok' |
| 192 | ok += 1 |
| 193 | return_dict[what+'s'].append(vim_response.json()) |
| 194 | return_dict[what+'s'][-1]['uuid'] = uuid |
| 195 | return_dict[what+'s'][-1]['name'] = name |
| 196 | else: |
| 197 | fail += 1 |
| 198 | print "fail" |
| 199 | #print vim_response.text |
| 200 | #text = "Error. VIM response '%s': not possible to PUT %s" % (vim_response.status_code, url) |
| 201 | #text += "\n" + vim_response.text |
| 202 | #print text |
| 203 | error_dict = vim_response.json() |
| 204 | error_dict['error']['uuid']=uuid |
| 205 | error_dict['error']['name']=name |
| 206 | return_dict[what+'s'].append(error_dict) |
| 207 | except requests.exceptions.RequestException, e: |
| 208 | return -1, " Exception "+ str(e.message) |
| 209 | if ok>0 and fail>0: return 0, return_dict |
| 210 | elif fail==0 : return 1, return_dict |
| 211 | else: return -1, return_dict |
| 212 | |
| 213 | |
| 214 | |
| 215 | def edit_details(url, what, c, force, payload): |
| 216 | item_list = [] |
| 217 | return_dict = {what+'s': []} |
| 218 | headers_req = {'Accept': 'application/json', 'content-type': 'application/json'} |
| 219 | fail=0 |
| 220 | ok=0 |
| 221 | |
| 222 | #Allows for payload both keypairs inside a 'server','port' ... or directly. In later case, put keypairs inside what |
| 223 | if what not in payload: |
| 224 | payload = {what:payload} |
| 225 | |
| 226 | item = c.get(what,None) |
| 227 | if item is None: item = c.get(what+'s',None) |
| 228 | if item is None: |
| 229 | error_text= " Internal error, not found '" + what +"[s]' in content" |
| 230 | print 'get_details()', error_text, c |
| 231 | return -1, error_text |
| 232 | if type(item) is list: |
| 233 | item_list = item |
| 234 | else: |
| 235 | item_list.append(item) |
| 236 | if len(item_list)==0: |
| 237 | print what, "not found" |
| 238 | return 1 |
| 239 | for item in item_list: |
| 240 | name = item.get('name',None) |
| 241 | uuid = item.get('id',None) |
| 242 | if uuid is None: uuid = item.get('uuid',None) |
| 243 | if uuid is None: |
| 244 | error_text= " Internal error, not found 'id/uuid' in item" |
| 245 | print 'get_details()', error_text, item |
| 246 | return -1, error_text |
| 247 | if not force: |
| 248 | r = raw_input("Edit " + what + " " + uuid + " " + name + " (y/N)? ") |
| 249 | if len(r)>0 and r[0].lower()=="y": |
| 250 | print " put", what, uuid, " >>>>>>>> ", |
| 251 | else: |
| 252 | continue |
| 253 | |
| 254 | #print str(payload) |
| 255 | try: |
| 256 | vim_response = requests.put(url + "/" + uuid, data=json.dumps(payload), headers=headers_req) |
| 257 | if vim_response.status_code == 200: |
| 258 | print 'ok' |
| 259 | ok += 1 |
| 260 | return_dict[what+'s'].append( vim_response.json()[what] ) |
| 261 | else: |
| 262 | fail += 1 |
| 263 | print "fail" |
| 264 | #print vim_response.text |
| 265 | #text = "Error. VIM response '%s': not possible to PUT %s" % (vim_response.status_code, url) |
| 266 | #text += "\n" + vim_response.text |
| 267 | #print text |
| 268 | error_dict = vim_response.json() |
| 269 | error_dict['error']['uuid']=uuid |
| 270 | error_dict['error']['name']=name |
| 271 | return_dict[what+'s'].append(error_dict) |
| 272 | except requests.exceptions.RequestException, e: |
| 273 | return -1, " Exception "+ str(e.message) |
| 274 | if ok>0 and fail>0: return 0, return_dict |
| 275 | elif fail==0 : return 1, return_dict |
| 276 | else: return -1, return_dict |
| 277 | |
| 278 | def get_del_recursive(url, what, url_suffix, force=False, recursive=False): |
| 279 | #print |
| 280 | #print " get", what, a, " >>>>>>>> ", |
| 281 | r,c = get_elements(url + what + 's' + url_suffix) |
| 282 | if r<0: |
| 283 | print c, "when getting", what, url_suffix |
| 284 | return -1 |
| 285 | # print "ok" |
| 286 | |
| 287 | list_todelete = c.get(what, None) |
| 288 | if list_todelete is None: list_todelete = c.get(what+'s', None) |
| 289 | if list_todelete is None: |
| 290 | print " Internal error, not found '" + what +"[s]' in", c |
| 291 | return -3, " Internal error, not found a valid dictionary" |
| 292 | if type(list_todelete) == dict: |
| 293 | list_todelete = (list_todelete, ) |
| 294 | |
| 295 | if len(list_todelete)==0: |
| 296 | print what, url_suffix, "not found" |
| 297 | return 1 |
| 298 | for c in list_todelete: |
| 299 | uuid=c.get('id', None) |
| 300 | if uuid is None: |
| 301 | uuid=c.get('uuid', None) |
| 302 | if uuid is None: |
| 303 | print "Id not found" |
| 304 | continue |
| 305 | name = c.get("name","") |
| 306 | if recursive: |
| 307 | if what=='tenant' : |
| 308 | get_del_recursive(url + uuid + "/", 'server', "", force, recursive) |
| 309 | get_del_recursive(url + uuid + "/", 'flavor', "", force, recursive) |
| 310 | get_del_recursive(url + uuid + "/", 'image', "", force, recursive) |
| 311 | get_del_recursive(url, 'network', "?tenant_id="+uuid, force, recursive) |
| 312 | elif what=='flavors' : |
| 313 | #get_del_recursive(url, 'servers', "?flavorRef="+uuid, force, recursive) |
| 314 | pass |
| 315 | elif what=='image' : |
| 316 | get_del_recursive(url, 'server', "?imageRef="+uuid, force, recursive) |
| 317 | elif what=='hosts' : |
| 318 | get_del_recursive(url, 'server', "?hostId="+uuid, force, recursive) |
| 319 | |
| 320 | if not force: |
| 321 | r = raw_input("Delete " + what + " " + uuid + " " + name + " (y/N)? ") |
| 322 | if len(r)>0 and r[0].lower()=="y": |
| 323 | pass |
| 324 | else: |
| 325 | continue |
| 326 | r,c = delete_elements(url + what + "s/" + uuid) |
| 327 | if r<0: |
| 328 | #print "Error deleting", vimURI, -r |
| 329 | print c |
| 330 | else: |
| 331 | print what, uuid, name, "deleted" |
| 332 | return 1 |
| 333 | |
| 334 | def check_valid_uuid(uuid): |
| 335 | id_schema = {"type" : "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"} |
| 336 | try: |
| 337 | js_v(uuid, id_schema) |
| 338 | return True |
| 339 | except js_e.ValidationError: |
| 340 | return False |
| 341 | |
| 342 | def change_string(text, var_list): |
| 343 | end=0 |
| 344 | type_=None |
| 345 | while True: |
| 346 | ini = text.find("${", end) |
| 347 | if ini<0: return text |
| 348 | end = text.find("}", ini) |
| 349 | if end<0: return text |
| 350 | end+=1 |
| 351 | |
| 352 | var = text[ini:end] |
| 353 | if ' ' in var: |
| 354 | kk=var.split(" ") |
| 355 | var=kk[0]+"}" |
| 356 | type_=kk[-1][:-1] |
| 357 | var = var_list.get(var, None) |
| 358 | if var==None: return text |
| 359 | |
| 360 | text = text[:ini] + var + text[end:] |
| 361 | if type_ != None: |
| 362 | if 'null' in type_ and text=="null": |
| 363 | return None |
| 364 | if 'int' in type_ : #and text.isnumeric(): |
| 365 | return int(text) |
| 366 | return text |
| 367 | |
| 368 | def chage_var_recursively(data, var_list): |
| 369 | '''Check recursively the conent of data, and look for "*${*}*" variables and changes |
| 370 | It assumes that this variables are not in the key of dictionary, |
| 371 | Attributes: |
| 372 | 'data': dictionary, or list. None or empty is consideted valid |
| 373 | 'var_list': dictionary (name:change) pairs |
| 374 | Return: |
| 375 | None, data is modified |
| 376 | ''' |
| 377 | |
| 378 | if type(data) is dict: |
| 379 | for k in data.keys(): |
| 380 | if type(data[k]) is dict or type(data[k]) is tuple or type(data[k]) is list: |
| 381 | chage_var_recursively(data[k], var_list) |
| 382 | elif type(data[k]) is str: |
| 383 | data[k] = change_string(data[k], var_list) |
| 384 | if type(data) is list: |
| 385 | for k in range(0,len(data)): |
| 386 | if type(data[k]) is dict or type(data[k]) is list: |
| 387 | chage_var_recursively(data[k], var_list) |
| 388 | elif type(data[k]) is str: |
| 389 | data[k] = change_string(data[k], var_list) |
| 390 | |
| 391 | def change_var(data): |
| 392 | if type(data) is not dict: |
| 393 | return -1, "Format error, not a object (dictionary)" |
| 394 | if "${}" not in data: |
| 395 | return 0, data |
| 396 | |
| 397 | var_list={} |
| 398 | for var in data["${}"]: |
| 399 | r = var.find("}",) + 1 |
| 400 | if r<=2 or var[:2] != '${': |
| 401 | return -1, "Format error at '${}':" + var |
| 402 | #change variables inside description text |
| 403 | if "${" in var[r:]: |
| 404 | var = var[:r] + change_string(var[r:], var_list) |
| 405 | d_start = var.rfind("(",) + 1 |
| 406 | d_end = var.rfind(")",) |
| 407 | if d_start>0 and d_end>=d_start: |
| 408 | default = var[d_start:d_end] |
| 409 | else: default=None |
| 410 | v = raw_input(var[r:] + "? ") |
| 411 | if v=="": |
| 412 | if default != None: |
| 413 | v = default |
| 414 | else: |
| 415 | v = raw_input(" empty string? try again: ") |
| 416 | var_list[ var[:r] ] = str(v) |
| 417 | |
| 418 | del data["${}"] |
| 419 | chage_var_recursively(data, var_list) |
| 420 | return 0, data |
| 421 | |
| 422 | def parse_yaml_json(text): |
| 423 | try: |
| 424 | data = yaml.load(text) |
| 425 | return 0, data |
| 426 | except yaml.YAMLError, exc: |
| 427 | error_pos = "" |
| 428 | if hasattr(exc, 'problem_mark'): |
| 429 | mark = exc.problem_mark |
| 430 | error_pos = " at position: (%s:%s)" % (mark.line+1, mark.column+1) |
| 431 | return -1, " Error yaml/json format error at " + error_pos |
| 432 | |
| 433 | def load_file(file_, parse=False): |
| 434 | try: |
| 435 | f = open(file_, 'r') |
| 436 | read_data = f.read() |
| 437 | f.close() |
| 438 | if not parse: |
| 439 | return 0, read_data |
| 440 | except IOError, e: |
| 441 | return -1, " Error opening file '" + file_ + "': " + e.args[1] |
| 442 | |
| 443 | try: |
| 444 | data = yaml.load(read_data) |
| 445 | return change_var(data) |
| 446 | except yaml.YAMLError, exc: |
| 447 | error_pos = "" |
| 448 | if hasattr(exc, 'problem_mark'): |
| 449 | mark = exc.problem_mark |
| 450 | error_pos = " at position: (%s:%s)" % (mark.line+1, mark.column+1) |
| 451 | return -2, " Error yaml/json format error at '"+ file_ +"'"+error_pos |
| 452 | |
| 453 | def load_configuration(configuration_file): |
| 454 | default_tokens ={'http_port':8080, 'http_host':'localhost', 'test_mode':False, 'of_controller_nets_with_same_vlan':True} |
| 455 | |
| 456 | r, config = load_file(configuration_file, parse=True) |
| 457 | if r < 0: |
| 458 | return False, config |
| 459 | |
| 460 | #Check default values tokens |
| 461 | for k,v in default_tokens.items(): |
| 462 | if k not in config: config[k]=v |
| 463 | |
| 464 | return (True, config) |
| 465 | |
| 466 | items_list = ('server','host','tenant','image','flavor','network','port') |
| 467 | action_list = ('list','get','new','del','edit','action') |
| 468 | |
| 469 | |
| 470 | def usage(complete=False): |
| 471 | global items_list |
| 472 | global action_list |
| 473 | print "Usage: ", sys.argv[0], "[options]", " [" + ",".join(action_list) +"] ", "<item> [<other>] " |
| 474 | print " Perform an test action over openvim" |
| 475 | print " "+",".join(action_list)+": List (by default), GET detais, Creates, Deletes, Edit" |
| 476 | print " <item>: can be one of " + ",".join(items_list) |
| 477 | print " <other>: list of uuid|name for 'get|del'; list of json/yaml files for 'new' or 'edit'" |
| 478 | if not complete: |
| 479 | print " Type -h or --help for a complete list of options" |
| 480 | return |
| 481 | print " Options:" |
| 482 | print " -v|--version: prints current version" |
| 483 | print " -c|--config [configuration_file]: loads the configuration file (default: openvimd.cfg)" |
| 484 | print " -h|--help: shows this help" |
| 485 | print " -u|--url [URL]: url to use instead of the one loaded from configuration file" |
| 486 | print " -t|--tenant [tenant uuid]: tenant to be used for some comands. IF mising it will use the default obtained in configuration file" |
| 487 | print " -F|--filter [A=B[&C=D...]: URL query string used for 'get' or 'del' commands" |
| 488 | print " -f|--force : Do not ask for confirmation when deleting. Also remove dependent objects." |
| 489 | print " -r|--recursive : Delete also dependency elements, (from tenants: images, flavors,server; from hosts: instances; ..." |
| 490 | print " Examples:" |
| 491 | print " ",sys.argv[0]," tenant #list tenants " |
| 492 | print " ",sys.argv[0]," -F'device_owner=external' get port #get details of all external ports" |
| 493 | print " ",sys.argv[0]," del server ses pan #delete server names 'ses' and 'pan'. Do not ask for confirmation" |
| 494 | print " ",sys.argv[0]," -r -f del host #delete all host and all the dependencies " |
| 495 | print " ",sys.argv[0]," new host ./Host/nfv100.json #add a host which information is in this file" |
| 496 | print " ",sys.argv[0]," edit network f348faf8-59ef-11e4-b4c7-52540030594e '{\"network\":{\"admin_state_up\":false}}'" |
| 497 | print " #change the admin status of this network" |
| 498 | return |
| 499 | |
| 500 | |
| 501 | if __name__=="__main__": |
| 502 | global vimURI |
| 503 | global vimURI_admin |
| 504 | |
| 505 | global what |
| 506 | global query_string |
| 507 | #init variables |
| 508 | action="list" |
| 509 | what=None |
| 510 | url=None |
| 511 | query_string = "" |
| 512 | force = False |
| 513 | recursive = False |
| 514 | tenant = None |
| 515 | additional = [] |
| 516 | #look for parent dir |
| 517 | config_file = '../openvimd.cfg' |
| 518 | pos = sys.argv[0].rfind("/") |
| 519 | if pos<0: |
| 520 | base_dir="./" |
| 521 | else: |
| 522 | base_dir = sys.argv[0] [:pos+1] |
| 523 | if pos>=0: |
| 524 | config_file = base_dir + config_file |
| 525 | |
| 526 | #get params |
| 527 | try: |
| 528 | opts, args = getopt.getopt(sys.argv[1:], "hvrfc:u:t:F:", |
| 529 | ["config", "help", "version", "force", "filter","tenant","url","recursive"]) |
| 530 | except getopt.GetoptError, err: |
| 531 | print " Error:", err # will print something like "option -a not recognized" |
| 532 | usage() |
| 533 | sys.exit(-2) |
| 534 | |
| 535 | for o, a in opts: |
| 536 | if o in ("-v", "--version"): |
| 537 | print "test_openvim version", version, "Oct 2014" |
| 538 | print "(c) Copyright Telefonica" |
| 539 | sys.exit(0) |
| 540 | elif o in ("-h", "--help"): |
| 541 | usage(True) |
| 542 | sys.exit(0) |
| 543 | elif o in ("-c", "--config"): config_file = a |
| 544 | elif o in ("-f", "--force"): force = True |
| 545 | elif o in ("-r", "--recursive"): recursive = True |
| 546 | elif o in ("-F", "--filter"): query_string = "?"+a |
| 547 | elif o in ("-u", "--url"): url = a |
| 548 | elif o in ("-t", "--tenant"): tenant = a |
| 549 | else: |
| 550 | assert False, "Unhandled option" |
| 551 | |
| 552 | for a in args: |
| 553 | if len(a) == 0: |
| 554 | print " Warning!!! Found an empty parameter?" |
| 555 | elif a[0]=="-": |
| 556 | print " Error!!! Put options parameter at the beginning" |
| 557 | sys.exit(-2) |
| 558 | elif what is not None: |
| 559 | additional.append(a) |
| 560 | elif a in items_list: |
| 561 | what=a |
| 562 | elif a[:-1] in items_list and a[-1]=='s': |
| 563 | what=a[:-1] |
| 564 | elif a in action_list: |
| 565 | action=a |
| 566 | else: |
| 567 | print " Missing <item>", ",".join(items_list) |
| 568 | sys.exit(-2) |
| 569 | if what is None: |
| 570 | usage() |
| 571 | sys.exit(-1) |
| 572 | #Load configuration file |
| 573 | r, config_dic = load_configuration(config_file) |
| 574 | #print config_dic |
| 575 | if not r: |
| 576 | print config_dic |
| 577 | config_dic={} |
| 578 | #exit(-1) |
| 579 | |
| 580 | #override parameters obtained by command line |
| 581 | try: |
| 582 | if url is not None: |
| 583 | vimURI = vimURI_admin = url |
| 584 | else: |
| 585 | vimURI = "http://" + config_dic['http_host'] +":"+ str(config_dic['http_port']) + "/openvim/" |
| 586 | if 'http_admin_port' in config_dic: |
| 587 | vimURI_admin = "http://" + config_dic['http_host'] +":"+ str(config_dic['http_admin_port']) + "/openvim/" |
| 588 | except: #key error |
| 589 | print " Error: can not get URL; neither option --u,-url, nor reading configuration file" |
| 590 | exit(-1) |
| 591 | if tenant is None: |
| 592 | tenant = config_dic.get('tenant_id', None) |
| 593 | |
| 594 | #check enough parameters |
| 595 | URI=vimURI |
| 596 | if (what in ('host','port') and action in ('del','new')) or (what=='host' and action=='edit' ): |
| 597 | if vimURI_admin is None: |
| 598 | print " Error: Can not get admin URL; neither option -t,--tenant, nor reading configuration file" |
| 599 | exit(-1) |
| 600 | else: |
| 601 | URI=vimURI_admin |
| 602 | if URI[-1] != "/": URI+="/" |
| 603 | if what in ('server','image','flavor'): |
| 604 | if tenant is None: |
| 605 | print " Error: Can not get tenant; neither option -t,--tenant, nor reading configuration file" |
| 606 | exit(-1) |
| 607 | URI += tenant + "/" |
| 608 | |
| 609 | |
| 610 | exit_code=0 |
| 611 | try: |
| 612 | #load file for new/edit |
| 613 | payload_list=[] |
| 614 | if action=='new' or action=='edit' or action=='action': |
| 615 | if len(additional)==0: |
| 616 | if action=='new' : |
| 617 | additional.append(base_dir+what+"s/new_"+what+".yaml") |
| 618 | #print " New what? Missing additional parameters to complete action" |
| 619 | else: |
| 620 | print " What must be edited? Missing additional parameters to complete action" |
| 621 | exit(-1) |
| 622 | if action=='edit'or action=='action': |
| 623 | #obtain only last element |
| 624 | additional_temp = additional[:-1] |
| 625 | additional = additional[-1:] |
| 626 | |
| 627 | for a in additional: |
| 628 | r,payload = load_file(a, parse=True) |
| 629 | if r<0: |
| 630 | if r==-1 and "{" in a or ":" in a: |
| 631 | #try to parse directly |
| 632 | r,payload = parse_yaml_json(a) |
| 633 | if r<0: |
| 634 | print payload |
| 635 | exit (-1) |
| 636 | else: |
| 637 | print payload |
| 638 | exit (-1) |
| 639 | payload_list.append(payload) |
| 640 | if action=='edit'or action=='action': |
| 641 | additional = additional_temp |
| 642 | |
| 643 | |
| 644 | #perform actions NEW |
| 645 | if action=='new': |
| 646 | for payload in payload_list: |
| 647 | print "\n new", what, a, " >>>>>>>> ", |
| 648 | r,c = new_elements(URI+what+'s', payload) |
| 649 | if r>0: |
| 650 | print "ok" |
| 651 | else: |
| 652 | print "fail" |
| 653 | exit_code = -1 |
| 654 | print c |
| 655 | #try to decode |
| 656 | exit(exit_code) |
| 657 | |
| 658 | #perform actions GET LIST EDIT DEL |
| 659 | if len(additional)==0: |
| 660 | additional=[""] |
| 661 | for a in additional: |
| 662 | filter_qs = query_string |
| 663 | if a != "" : |
| 664 | if check_valid_uuid(a): |
| 665 | if len(filter_qs) > 0: filter_qs += "&" + "id=" + str(a) |
| 666 | else: filter_qs += "?" + "id=" + str(a) |
| 667 | else: |
| 668 | if len(filter_qs) > 0: filter_qs += "&" + "name=" + str(a) |
| 669 | else: filter_qs += "?" + "name=" + str(a) |
| 670 | |
| 671 | if action=='list' or action=='get' or action=='edit'or action=='action': |
| 672 | url = URI + what+'s' |
| 673 | print url + filter_qs |
| 674 | #print " get", what, a, " >>>>>>>> ", |
| 675 | r,c = get_elements(url + filter_qs) |
| 676 | if r<0: |
| 677 | #print "fail" |
| 678 | exit_code = -1 |
| 679 | print c |
| 680 | else: |
| 681 | #print "ok" |
| 682 | if action=='list': |
| 683 | print json.dumps(c, indent=4) |
| 684 | continue |
| 685 | |
| 686 | if action=='get': |
| 687 | r1,c1 = get_details(url, what, c) |
| 688 | elif action=='action': |
| 689 | r1,c1 = action_details(url, what, c, force, payload_list[0]) |
| 690 | else: # action=='edit': |
| 691 | r1,c1 = edit_details(url, what, c, force, payload_list[0]) |
| 692 | if r1<0: |
| 693 | exit_code = -1 |
| 694 | else: |
| 695 | if r>0: print "ok" |
| 696 | else: print "ok with some fails" |
| 697 | print json.dumps(c1, indent=4) |
| 698 | |
| 699 | elif action=='del': |
| 700 | r = get_del_recursive(URI, what, filter_qs, force, recursive) |
| 701 | if r<0: |
| 702 | exit_code = -1 |
| 703 | exit(exit_code) |
| 704 | |
| 705 | except KeyboardInterrupt: |
| 706 | print " Canceled" |
| 707 | |
| 708 | |