blob: 6c546c126156a3232d9d2eae38a1eee259ed939d [file] [log] [blame]
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# PYTHON_ARGCOMPLETE_OK
##
# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
# This file is part of openmano
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# For those usages not covered by the Apache License, Version 2.0 please
# contact with: nfvlabs@tid.es
##
'''
openmano client used to interact with openmano-server (openmanod)
'''
__author__="Alfonso Tierno, Gerardo Garcia"
__date__ ="$09-oct-2014 09:09:48$"
__version__="0.4.7-r511"
version_date="Oct 2016"
from argcomplete.completers import FilesCompleter
import os
import argparse
import argcomplete
import requests
import json
import yaml
import logging
#from jsonschema import validate as js_v, exceptions as js_e
class ArgumentParserError(Exception): pass
class OpenmanoCLIError(Exception): pass
class ThrowingArgumentParser(argparse.ArgumentParser):
def error(self, message):
print "Error: %s" %message
print
self.print_usage()
#self.print_help()
print
print "Type 'openmano -h' for help"
raise ArgumentParserError
def config(args):
print "OPENMANO_HOST: %s" %mano_host
print "OPENMANO_PORT: %s" %mano_port
if args.n:
logger.debug("resolving tenant and datacenter names")
mano_tenant_id = "None"
mano_tenant_name = "None"
mano_datacenter_id = "None"
mano_datacenter_name = "None"
try:
mano_tenant_id = _get_item_uuid("tenants", mano_tenant)
URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, mano_tenant_id)
mano_response = requests.get(URLrequest)
logger.debug("openmano response: %s", mano_response.text )
content = mano_response.json()
mano_tenant_name = content["tenant"]["name"]
URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, mano_tenant_id, mano_datacenter)
mano_response = requests.get(URLrequest)
logger.debug("openmano response: %s", mano_response.text )
content = mano_response.json()
if "error" not in content:
mano_datacenter_id = content["datacenter"]["uuid"]
mano_datacenter_name = content["datacenter"]["name"]
except OpenmanoCLIError:
pass
print "OPENMANO_TENANT: %s" %mano_tenant
print " Id: %s" %mano_tenant_id
print " Name: %s" %mano_tenant_name
print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
print " Id: %s" %mano_datacenter_id
print " Name: %s" %mano_datacenter_name
else:
print "OPENMANO_TENANT: %s" %mano_tenant
print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
def _print_verbose(mano_response, verbose_level=0):
content = mano_response.json()
result = 0 if mano_response.status_code==200 else mano_response.status_code
if type(content)!=dict or len(content)!=1:
#print "Non expected format output"
print str(content)
return result
val=content.values()[0]
if type(val)==str:
print val
return result
elif type(val) == list:
content_list = val
elif type(val)==dict:
content_list = [val]
else:
#print "Non expected dict/list format output"
print str(content)
return result
#print content_list
if verbose_level==None:
verbose_level=0
if verbose_level >= 3:
print yaml.safe_dump(content, indent=4, default_flow_style=False)
return result
if mano_response.status_code == 200:
for content in content_list:
if "uuid" in content:
uuid = content['uuid']
elif "id" in content:
uuid = content['id']
elif "vim_id" in content:
uuid = content['vim_id']
myoutput = "%s %s" %(uuid.ljust(38),content['name'].ljust(20))
if "status" in content:
myoutput += " " + content['status'].ljust(20)
elif "enabled" in content and not content["enabled"]:
myoutput += " enabled=False".ljust(20)
if verbose_level >=1:
if 'created_at' in content:
myoutput += " " + content['created_at'].ljust(20)
if verbose_level >=2:
new_line='\n'
if 'type' in content and content['type']!=None:
myoutput += new_line + " Type: " + content['type'].ljust(29)
new_line=''
if 'description' in content and content['description']!=None:
myoutput += new_line + " Description: " + content['description'].ljust(20)
print myoutput
else:
print content['error']['description']
return result
def parser_json_yaml(file_name):
try:
f = file(file_name, "r")
text = f.read()
f.close()
except Exception as e:
return (False, str(e))
#Read and parse file
if file_name[-5:]=='.yaml' or file_name[-4:]=='.yml' or (file_name[-5:]!='.json' and '\t' not in text):
try:
config = yaml.load(text)
except yaml.YAMLError as exc:
error_pos = ""
if hasattr(exc, 'problem_mark'):
mark = exc.problem_mark
error_pos = " at line:%s column:%s" % (mark.line+1, mark.column+1)
return (False, "Error loading file '"+file_name+"' yaml format error" + error_pos)
else: #json
try:
config = json.loads(text)
except Exception as e:
return (False, "Error loading file '"+file_name+"' json format error " + str(e) )
return True, config
def _load_file_or_yaml(content):
'''
'content' can be or a yaml/json file or a text containing a yaml/json text format
This function autodetect, trying to load and parse the file,
if fails trying to parse the 'content' text
Returns the dictionary once parsed, or print an error and finish the program
'''
#Check config file exists
if os.path.isfile(content):
r,payload = parser_json_yaml(content)
if not r:
print payload
exit(-1)
elif "{" in content or ":" in content:
try:
payload = yaml.load(content)
except yaml.YAMLError as exc:
error_pos = ""
if hasattr(exc, 'problem_mark'):
mark = exc.problem_mark
error_pos = " at position: (%s:%s)" % (mark.line+1, mark.column+1)
print "Error loading yaml/json text"+error_pos
exit (-1)
else:
print "'%s' is neither a valid file nor a yaml/json content" % content
exit(-1)
return payload
def _get_item_uuid(item, item_name_id, tenant=None):
if tenant:
URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, tenant, item)
else:
URLrequest = "http://%s:%s/openmano/%s" %(mano_host, mano_port, item)
mano_response = requests.get(URLrequest)
logger.debug("openmano response: %s", mano_response.text )
content = mano_response.json()
#print content
found = 0
for i in content[item]:
if i["uuid"] == item_name_id:
return item_name_id
if i["name"] == item_name_id:
uuid = i["uuid"]
found += 1
if found == 0:
raise OpenmanoCLIError("No %s found with name/uuid '%s'" %(item[:-1], item_name_id))
elif found > 1:
raise OpenmanoCLIError("%d %s found with name '%s'. uuid must be used" %(found, item, item_name_id))
return uuid
#
# def check_valid_uuid(uuid):
# id_schema = {"type" : "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
# try:
# js_v(uuid, id_schema)
# return True
# except js_e.ValidationError:
# return False
def _get_tenant(tenant_name_id = None):
if not tenant_name_id:
tenant_name_id = mano_tenant
if not mano_tenant:
raise OpenmanoCLIError("'OPENMANO_TENANT' environment variable is not set")
return _get_item_uuid("tenants", tenant_name_id)
def _get_datacenter(datacenter_name_id = None, tenant = "any"):
if not datacenter_name_id:
datacenter_name_id = mano_datacenter
if not datacenter_name_id:
raise OpenmanoCLIError("neither 'OPENMANO_DATACENTER' environment variable is set nor --datacenter option is used")
return _get_item_uuid("datacenters", datacenter_name_id, tenant)
def vnf_create(args):
#print "vnf-create",args
headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
tenant = _get_tenant()
myvnf = _load_file_or_yaml(args.file)
if args.name or args.description or args.image_path:
#print args.name
try:
if args.name:
myvnf['vnf']['name'] = args.name
if args.description:
myvnf['vnf']['description'] = args.description
if args.image_path:
index=0
for image_path_ in args.image_path.split(","):
#print "image-path", image_path_
myvnf['vnf']['VNFC'][index]['VNFC image']=image_path_
index=index+1
except (KeyError, TypeError), e:
if str(e)=='vnf': error_pos= "missing field 'vnf'"
elif str(e)=='name': error_pos= "missing field 'vnf':'name'"
elif str(e)=='description': error_pos= "missing field 'vnf':'description'"
elif str(e)=='VNFC': error_pos= "missing field 'vnf':'VNFC'"
elif str(e)==str(index): error_pos= "field 'vnf':'VNFC' must be an array"
elif str(e)=='VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
else: error_pos="wrong format"
print "Wrong VNF descriptor: " + error_pos
return -1
payload_req = json.dumps(myvnf)
#print payload_req
URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
logger.debug("openmano request: %s", payload_req)
mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
logger.debug("openmano response: %s", mano_response.text )
return _print_verbose(mano_response, args.verbose)
def vnf_list(args):
#print "vnf-list",args
if args.all:
tenant = "any"
else:
tenant = _get_tenant()
if args.name:
toshow = _get_item_uuid("vnfs", args.name, tenant)
URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
else:
URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
mano_response = requests.get(URLrequest)
logger.debug("openmano response: %s", mano_response.text )
content = mano_response.json()
#print json.dumps(content, indent=4)
if args.verbose==None:
args.verbose=0
result = 0 if mano_response.status_code==200 else mano_response.status_code
if mano_response.status_code == 200:
if not args.name:
if args.verbose >= 3:
print yaml.safe_dump(content, indent=4, default_flow_style=False)
return result
if len(content['vnfs']) == 0:
print "No VNFs were found."
return 404 #HTTP_Not_Found
for vnf in content['vnfs']:
myoutput = "%s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20))
if args.verbose >=1:
myoutput = "%s %s" %(myoutput, vnf['created_at'].ljust(20))
print myoutput
if args.verbose >=2:
print " Description: %s" %vnf['description']
print " VNF descriptor file: %s" %vnf['path']
else:
if args.verbose:
print yaml.safe_dump(content, indent=4, default_flow_style=False)
return result
vnf = content['vnf']
print "%s %s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20), vnf['created_at'].ljust(20))
print " Description: %s" %vnf['description']
#print " VNF descriptor file: %s" %vnf['path']
print " VMs:"
for vm in vnf['VNFC']:
#print " %s %s %s" %(vm['name'].ljust(20), vm['uuid'].ljust(38), vm['description'].ljust(30))
print " %s %s" %(vm['name'].ljust(20), vm['description'])
if len(vnf['nets'])>0:
print " Internal nets:"
for net in vnf['nets']:
print " %s %s" %(net['name'].ljust(20), net['description'])
if len(vnf['external-connections'])>0:
print " External interfaces:"
for interface in vnf['external-connections']:
print " %s %s %s %s" %(interface['external_name'].ljust(20), interface['vm_name'].ljust(20), interface['internal_name'].ljust(20), \
interface['vpci'].ljust(14))
else:
print content['error']['description']
if args.verbose:
print yaml.safe_dump(content, indent=4, default_flow_style=False)
return result
def vnf_delete(args):
#print "vnf-delete",args
if args.all:
tenant = "any"
else:
tenant = _get_tenant()
todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
if not args.force:
r = raw_input("Delete VNF %s (y/N)? " %(todelete))
if not (len(r)>0 and r[0].lower()=="y"):
return 0
URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
mano_response = requests.delete(URLrequest)
logger.debug("openmano response: %s", mano_response.text )
result = 0 if mano_response.status_code==200 else mano_response.status_code
content = mano_response.json()
#print json.dumps(content, indent=4)
if mano_response.status_code == 200:
print content['result']
else:
print content['error']['description']
return result
def scenario_create(args):
#print "scenario-create",args
tenant = _get_tenant()
headers_req = {'content-type': 'application/yaml'}
myscenario = _load_file_or_yaml(args.file)
if args.name:
myscenario['name'] = args.name
if args.description:
myscenario['description'] = args.description
payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
#print payload_req
URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
logger.debug("openmano request: %s", payload_req)
mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
logger.debug("openmano response: %s", mano_response.text )
return _print_verbose(mano_response, args.verbose)
def scenario_list(args):
#print "scenario-list",args
if args.all:
tenant = "any"
else:
tenant = _get_tenant()
if args.name:
toshow = _get_item_uuid("scenarios", args.name, tenant)
URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
else:
URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
mano_response = requests.get(URLrequest)
logger.debug("openmano response: %s", mano_response.text )
content = mano_response.json()
#print json.dumps(content, indent=4)
if args.verbose==None:
args.verbose=0
result = 0 if mano_response.status_code==200 else mano_response.status_code
if mano_response.status_code == 200:
if not args.name:
if args.verbose >= 3:
print yaml.safe_dump(content, indent=4, default_flow_style=False)
return result
if len(content['scenarios']) == 0:
print "No scenarios were found."
return 404 #HTTP_Not_Found
for scenario in content['scenarios']:
myoutput = "%s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20))
if args.verbose >=1:
myoutput = "%s %s" %(myoutput, scenario['created_at'].ljust(20))
print myoutput
if args.verbose >=2:
print " Description: %s" %scenario['description']
else:
if args.verbose:
print yaml.safe_dump(content, indent=4, default_flow_style=False)
return result
scenario = content['scenario']
myoutput = "%s %s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20), scenario['created_at'].ljust(20))
print myoutput
print " Description: %s" %scenario['description']
print " VNFs:"
for vnf in scenario['vnfs']:
print " %s %s %s" %(vnf['name'].ljust(20), vnf['vnf_id'].ljust(38), vnf['description'])
if len(scenario['nets'])>0:
print " Internal nets:"
for net in scenario['nets']:
if net['description'] is None: #if description does not exist, description is "-". Valid for external and internal nets.
net['description'] = '-'
if not net['external']:
print " %s %s %s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30))
print " External nets:"
for net in scenario['nets']:
if net['external']:
print " %s %s %s vim-id:%s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30), net['vim_id'])
else:
print content['error']['description']
if args.verbose:
print yaml.safe_dump(content, indent=4, default_flow_style=False)
return result
def scenario_delete(args):
#print "scenario-delete",args
if args.all:
tenant = "any"
else:
tenant = _get_tenant()
todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
if not args.force:
r = raw_input("Delete scenario %s (y/N)? " %(args.name))
if not (len(r)>0 and r[0].lower()=="y"):
return 0
URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
mano_response = requests.delete(URLrequest)
logger.debug("openmano response: %s", mano_response.text )
result = 0 if mano_response.status_code==200 else mano_response.status_code
content = mano_response.json()
#print json.dumps(content, indent=4)
if mano_response.status_code == 200:
print content['result']
else:
print content['error']['description']
return result
def scenario_deploy(args):
print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
print
args.file = None
args.netmap_use = None
args.netmap_create = None
args.keypair = None
args.keypair_auto = None
return instance_create(args)
# #print "scenario-deploy",args
# headers_req = {'content-type': 'application/json'}
# action = {}
# actionCmd="start"
# if args.nostart:
# actionCmd="reserve"
# action[actionCmd] = {}
# action[actionCmd]["instance_name"] = args.name
# if args.datacenter != None:
# action[actionCmd]["datacenter"] = args.datacenter
# elif mano_datacenter != None:
# action[actionCmd]["datacenter"] = mano_datacenter
#
# if args.description:
# action[actionCmd]["description"] = args.description
# payload_req = json.dumps(action, indent=4)
# #print payload_req
#
# URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
# logger.debug("openmano request: %s", payload_req)
# mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
# logger.debug("openmano response: %s", mano_response.text )
# if args.verbose==None:
# args.verbose=0
#
# result = 0 if mano_response.status_code==200 else mano_response.status_code
# content = mano_response.json()
# #print json.dumps(content, indent=4)
# if args.verbose >= 3:
# print yaml.safe_dump(content, indent=4, default_flow_style=False)
# return result
#
# if mano_response.status_code == 200:
# myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
# if args.verbose >=1:
# myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
# if args.verbose >=2:
# myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
# print myoutput
# print ""
# print "To check the status, run the following command:"
# print "openmano instance-scenario-list <instance_id>"
# else:
# print content['error']['description']
# return result
def scenario_verify(args):
#print "scenario-verify",args
headers_req = {'content-type': 'application/json'}
action = {}
action["verify"] = {}
action["verify"]["instance_name"] = "scen-verify-return5"
payload_req = json.dumps(action, indent=4)
#print payload_req
URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
logger.debug("openmano request: %s", payload_req)
mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
logger.debug("openmano response: %s", mano_response.text )
result = 0 if mano_response.status_code==200 else mano_response.status_code
content = mano_response.json()
#print json.dumps(content, indent=4)
if mano_response.status_code == 200:
print content['result']
else:
print content['error']['description']
return result
def instance_create(args):
tenant = _get_tenant()
headers_req = {'content-type': 'application/yaml'}
myInstance={"instance": {}, "schema_version": "0.1"}
if args.file:
instance_dict = _load_file_or_yaml(args.file)
if "instance" not in instance_dict:
myInstance = {"instance": instance_dict, "schema_version": "0.1"}
else:
myInstance = instance_dict
if args.name:
myInstance["instance"]['name'] = args.name
if args.description:
myInstance["instance"]['description'] = args.description
if args.nostart:
myInstance["instance"]['action'] = "reserve"
#datacenter
datacenter = myInstance["instance"].get("datacenter")
if args.datacenter != None:
datacenter = args.datacenter
myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
#scenario
scenario = myInstance["instance"].get("scenario")
if args.scenario != None:
scenario = args.scenario
if not scenario:
print "you must provide an scenario in the file descriptor or with --scenario"
return -1
myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
if args.netmap_use:
if "networks" not in myInstance["instance"]:
myInstance["instance"]["networks"] = {}
for net in args.netmap_use:
net_comma_list = net.split(",")
for net_comma in net_comma_list:
net_tuple = net_comma.split("=")
if len(net_tuple) != 2:
print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
return
net_scenario = net_tuple[0].strip()
net_datacenter = net_tuple[1].strip()
if net_scenario not in myInstance["instance"]["networks"]:
myInstance["instance"]["networks"][net_scenario] = {}
if "sites" not in myInstance["instance"]["networks"][net_scenario]:
myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
if args.netmap_create:
if "networks" not in myInstance["instance"]:
myInstance["instance"]["networks"] = {}
for net in args.netmap_create:
net_comma_list = net.split(",")
for net_comma in net_comma_list:
net_tuple = net_comma.split("=")
if len(net_tuple) == 1:
net_scenario = net_tuple[0].strip()
net_datacenter = None
elif len(net_tuple) == 2:
net_scenario = net_tuple[0].strip()
net_datacenter = net_tuple[1].strip()
else:
print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
return
if net_scenario not in myInstance["instance"]["networks"]:
myInstance["instance"]["networks"][net_scenario] = {}
if "sites" not in myInstance["instance"]["networks"][net_scenario]:
myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
if args.keypair:
if "cloud-config" not in myInstance["instance"]:
myInstance["instance"]["cloud-config"] = {}
cloud_config = myInstance["instance"]["cloud-config"]
for key in args.keypair:
index = key.find(":")
if index<0:
if "key-pairs" not in cloud_config:
cloud_config["key-pairs"] = []
cloud_config["key-pairs"].append(key)
else:
user = key[:index]
key_ = key[index+1:]
key_list = key_.split(",")
if "users" not in cloud_config:
cloud_config["users"] = []
cloud_config["users"].append({"name": user, "key-pairs": key_list })
if args.keypair_auto:
try:
keys=[]
home = os.getenv("HOME")
user = os.getenv("USER")
files = os.listdir(home+'/.ssh')
for file in files:
if file[-4:] == ".pub":
with open(home+'/.ssh/'+file, 'r') as f:
keys.append(f.read())
if not keys:
print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
return 1
except Exception as e:
print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
return 1
if "cloud-config" not in myInstance["instance"]:
myInstance["instance"]["cloud-config"] = {}
cloud_config = myInstance["instance"]["cloud-config"]
if "key-pairs" not in cloud_config:
cloud_config["key-pairs"] = []
if user:
if "users" not in cloud_config:
cloud_config["users"] = []
cloud_config["users"].append({"name": user, "key-pairs": keys })
payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
logger.debug("openmano request: %s", payload_req)
URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
logger.debug("openmano response: %s", mano_response.text )
if args.verbose==None:
args.verbose=0
result = 0 if mano_response.status_code==200 else mano_response.status_code
content = mano_response.json()
#print json.dumps(content, indent=4)
if args.verbose >= 3:
print yaml.safe_dump(content, indent=4, default_flow_style=False)
return result
if mano_response.status_code == 200:
myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
if args.verbose >=1:
myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
if args.verbose >=2:
myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
print myoutput
else:
print content['error']['description']
return result
def instance_scenario_list(args):
#print "instance-scenario-list",args
if args.all:
tenant = "any"
else:
tenant = _get_tenant()
if args.name:
toshow = _get_item_uuid("instances", args.name, tenant)
URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
else:
URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
mano_response = requests.get(URLrequest)
logger.debug("openmano response: %s", mano_response.text )
content = mano_response.json()
#print json.dumps(content, indent=4)
if args.verbose==None:
args.verbose=0
result = 0 if mano_response.status_code==200 else mano_response.status_code
if mano_response.status_code == 200:
if not args.name:
if args.verbose >= 3:
print yaml.safe_dump(content, indent=4, default_flow_style=False)
return result
if len(content['instances']) == 0:
print "No scenario instances were found."
return result
for instance in content['instances']:
myoutput = "%s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20))
if args.verbose >=1:
myoutput = "%s %s" %(myoutput, instance['created_at'].ljust(20))
print myoutput
if args.verbose >=2:
print "Description: %s" %instance['description']
else:
if args.verbose:
print yaml.safe_dump(content, indent=4, default_flow_style=False)
return result
instance = content
print "%s %s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20),instance['created_at'].ljust(20))
print "Description: %s" %instance['description']
print "Template scenario id: %s" %instance['scenario_id']
print "Template scenario name: %s" %instance['scenario_name']
print "---------------------------------------"
print "VNF instances: %d" %len(instance['vnfs'])
for vnf in instance['vnfs']:
#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))
print " %s %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
if len(instance['nets'])>0:
print "---------------------------------------"
print "Internal nets:"
for net in instance['nets']:
if net['created']:
print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
print "---------------------------------------"
print "External nets:"
for net in instance['nets']:
if not net['created']:
print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
print "---------------------------------------"
print "VM instances:"
for vnf in instance['vnfs']:
for vm in vnf['vms']:
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'])
else:
print content['error']['description']
if args.verbose:
print yaml.safe_dump(content, indent=4, default_flow_style=False)
return result
def instance_scenario_status(args):
print "instance-scenario-status"
return 0
def instance_scenario_delete(args):
if args.all:
tenant = "any"
else:
tenant = _get_tenant()
todelete = _get_item_uuid("instances", args.name, tenant=tenant)
#print "instance-scenario-delete",args
if not args.force:
r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
if not (len(r)>0 and r[0].lower()=="y"):
return
URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
mano_response = requests.delete(URLrequest)
logger.debug("openmano response: %s", mano_response.text )
result = 0 if mano_response.status_code==200 else mano_response.status_code
content = mano_response.json()
#print json.dumps(content, indent=4)
if mano_response.status_code == 200:
print content['result']
else:
print content['error']['description']
return result
def instance_scenario_action(args):
#print "instance-scenario-action", args
tenant = _get_tenant()
toact = _get_item_uuid("instances", args.name, tenant=tenant)
action={}
action[ args.action ] = args.param
if args.vnf:
action["vnfs"] = args.vnf
if args.vm:
action["vms"] = args.vm
headers_req = {'content-type': 'application/json'}
payload_req = json.dumps(action, indent=4)
URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
logger.debug("openmano request: %s", payload_req)
mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
logger.debug("openmano response: %s", mano_response.text )
result = 0 if mano_response.status_code==200 else mano_response.status_code
content = mano_response.json()
#print json.dumps(content, indent=4)
if mano_response.status_code == 200:
if args.verbose:
print yaml.safe_dump(content, indent=4, default_flow_style=False)
return result
for uuid,c in content.iteritems():
print "%s %s %s" %(uuid.ljust(38), c['name'].ljust(20),c['description'].ljust(20))
else:
print content['error']['description']
return result
def instance_vnf_list(args):
print "instance-vnf-list"
return 0
def instance_vnf_status(args):
print "instance-vnf-status"
return 0
def tenant_create(args):
headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
tenant_dict={"name": args.name}
if args.description!=None:
tenant_dict["description"] = args.description
payload_req = json.dumps( {"tenant": tenant_dict })
#print payload_req
URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
logger.debug("openmano request: %s", payload_req)
mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
logger.debug("openmano response: %s", mano_response.text )
return _print_verbose(mano_response, args.verbose)
def tenant_list(args):
#print "tenant-list",args
if args.name:
toshow = _get_item_uuid("tenants", args.name)
URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
else:
URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
mano_response = requests.get(URLrequest)
logger.debug("openmano response: %s", mano_response.text )
if args.verbose==None:
args.verbose=0
if args.name!=None:
args.verbose += 1
return _print_verbose(mano_response, args.verbose)
def tenant_delete(args):
#print "tenant-delete",args
todelete = _get_item_uuid("tenants", args.name)
if not args.force:
r = raw_input("Delete tenant %s (y/N)? " %(args.name))
if not (len(r)>0 and r[0].lower()=="y"):
return 0
URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
mano_response = requests.delete(URLrequest)
logger.debug("openmano response: %s", mano_response.text )
result = 0 if mano_response.status_code==200 else mano_response.status_code
content = mano_response.json()
#print json.dumps(content, indent=4)
if mano_response.status_code == 200:
print content['result']
else:
print content['error']['description']
return result
def datacenter_attach(args):
tenant = _get_tenant()
datacenter = _get_datacenter(args.name)
headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
datacenter_dict={}
if args.vim_tenant_id != None:
datacenter_dict['vim_tenant'] = args.vim_tenant_id
if args.vim_tenant_name != None:
datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
if args.user != None:
datacenter_dict['vim_username'] = args.user
if args.password != None:
datacenter_dict['vim_password'] = args.password
if args.config!=None:
datacenter_dict["config"] = _load_file_or_yaml(args.config)
payload_req = json.dumps( {"datacenter": datacenter_dict })
#print payload_req
URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
logger.debug("openmano request: %s", payload_req)
mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
logger.debug("openmano response: %s", mano_response.text )
result = _print_verbose(mano_response, args.verbose)
#provide addional information if error
if mano_response.status_code != 200:
content = mano_response.json()
if "already in use for 'name'" in content['error']['description'] and \
"to database vim_tenants table" in content['error']['description']:
print "Try to specify a different name with --vim-tenant-name"
return result
def datacenter_detach(args):
if args.all:
tenant = "any"
else:
tenant = _get_tenant()
datacenter = _get_datacenter(args.name, tenant)
headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
mano_response = requests.delete(URLrequest, headers=headers_req)
logger.debug("openmano response: %s", mano_response.text )
content = mano_response.json()
#print json.dumps(content, indent=4)
result = 0 if mano_response.status_code==200 else mano_response.status_code
if mano_response.status_code == 200:
print content['result']
else:
print content['error']['description']
return result
def datacenter_create(args):
headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
datacenter_dict={"name": args.name, "vim_url": args.url}
if args.description!=None:
datacenter_dict["description"] = args.description
if args.type!=None:
datacenter_dict["type"] = args.type
if args.url!=None:
datacenter_dict["vim_url_admin"] = args.url_admin
if args.config!=None:
datacenter_dict["config"] = _load_file_or_yaml(args.config)
payload_req = json.dumps( {"datacenter": datacenter_dict })
#print payload_req
URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
logger.debug("openmano request: %s", payload_req)
mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
logger.debug("openmano response: %s", mano_response.text )
return _print_verbose(mano_response, args.verbose)
def datacenter_delete(args):
#print "datacenter-delete",args
todelete = _get_item_uuid("datacenters", args.name, "any")
if not args.force:
r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
if not (len(r)>0 and r[0].lower()=="y"):
return 0
URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
mano_response = requests.delete(URLrequest)
logger.debug("openmano response: %s", mano_response.text )
result = 0 if mano_response.status_code==200 else mano_response.status_code
content = mano_response.json()
#print json.dumps(content, indent=4)
if mano_response.status_code == 200:
print content['result']
else:
print content['error']['description']
return result
def datacenter_list(args):
#print "datacenter-list",args
tenant='any' if args.all else _get_tenant()
if args.name:
toshow = _get_item_uuid("datacenters", args.name, tenant)
URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
else:
URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
mano_response = requests.get(URLrequest)
logger.debug("openmano response: %s", mano_response.text )
if args.verbose==None:
args.verbose=0
if args.name!=None:
args.verbose += 1
return _print_verbose(mano_response, args.verbose)
def vim_action(args):
#print "datacenter-net-action",args
tenant = _get_tenant()
datacenter = _get_datacenter(args.datacenter, tenant)
if args.verbose==None:
args.verbose=0
if args.action=="list":
URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
if args.name!=None:
args.verbose += 1
URLrequest += "/" + args.name
mano_response = requests.get(URLrequest)
logger.debug("openmano response: %s", mano_response.text )
return _print_verbose(mano_response, args.verbose)
elif args.action=="delete":
URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
mano_response = requests.delete(URLrequest)
logger.debug("openmano response: %s", mano_response.text )
result = 0 if mano_response.status_code==200 else mano_response.status_code
content = mano_response.json()
#print json.dumps(content, indent=4)
if mano_response.status_code == 200:
print content['result']
else:
print content['error']['description']
return result
elif args.action=="create":
headers_req = {'content-type': 'application/yaml'}
if args.file:
create_dict = _load_file_or_yaml(args.file)
if args.item not in create_dict:
create_dict = {args.item: create_dict}
else:
create_dict = {args.item:{}}
if args.name:
create_dict[args.item]['name'] = args.name
#if args.description:
# create_dict[args.item]['description'] = args.description
if args.item=="vim-net":
if args.bind_net:
create_dict[args.item]['bind_net'] = args.bind_net
if args.bind_type:
create_dict[args.item]['bind_type'] = args.bind_type
if args.shared:
create_dict[args.item]['shared'] = args.shared
if "name" not in create_dict[args.item]:
print "You must provide a name in the descriptor file or with the --name option"
return
payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
logger.debug("openmano request: %s", payload_req)
URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, mano_tenant, datacenter, args.item)
mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
logger.debug("openmano response: %s", mano_response.text )
if args.verbose==None:
args.verbose=0
return _print_verbose(mano_response, args.verbose)
def datacenter_net_action(args):
if args.action == "net-update":
print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
print
args.action = "netmap-delete"
args.netmap = None
args.all = True
r = datacenter_netmap_action(args)
if r == 0:
args.force = True
args.action = "netmap-import"
r = datacenter_netmap_action(args)
return r
if args.action == "net-edit":
args.netmap = args.net
args.name = None
elif args.action == "net-list":
args.netmap = None
elif args.action == "net-delete":
args.netmap = args.net
args.all = False
args.action = "netmap" + args.action[3:]
args.vim_name=None
args.vim_id=None
print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
print
return datacenter_netmap_action(args)
def datacenter_netmap_action(args):
tenant = _get_tenant()
datacenter = _get_datacenter(args.datacenter, tenant)
#print "datacenter_netmap_action",args
payload_req = None
if args.verbose==None:
args.verbose=0
headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
if args.action=="netmap-list":
if args.netmap:
URLrequest += "/" + args.netmap
args.verbose += 1
mano_response = requests.get(URLrequest)
elif args.action=="netmap-delete":
if args.netmap and args.all:
print "you can not use a netmap name and the option --all at the same time"
return 1
if args.netmap:
force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
URLrequest += "/" + args.netmap
elif args.all:
force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
else:
print "you must specify a netmap name or the option --all"
return 1
if not args.force:
r = raw_input(force_text)
if len(r)>0 and r[0].lower()=="y":
pass
else:
return 0
mano_response = requests.delete(URLrequest, headers=headers_req)
elif args.action=="netmap-import":
if not args.force:
r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
if len(r)>0 and r[0].lower()=="y":
pass
else:
return 0
URLrequest += "/upload"
mano_response = requests.post(URLrequest, headers=headers_req)
elif args.action=="netmap-edit" or args.action=="netmap-create":
if args.file:
payload = _load_file_or_yaml(args.file)
else:
payload = {}
if "netmap" not in payload:
payload = {"netmap": payload}
if args.name:
payload["netmap"]["name"] = args.name
if args.vim_id:
payload["netmap"]["vim_id"] = args.vim_id
if args.action=="netmap-create" and args.vim_name:
payload["netmap"]["vim_name"] = args.vim_name
payload_req = json.dumps(payload)
logger.debug("openmano request: %s", payload_req)
if args.action=="netmap-edit" and not args.force:
if len(payload["netmap"]) == 0:
print "You must supply some parameter to edit"
return 1
r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
if len(r)>0 and r[0].lower()=="y":
pass
else:
return 0
URLrequest += "/" + args.netmap
mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
else: #netmap-create
if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
return 1
mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
logger.debug("openmano response: %s", mano_response.text )
return _print_verbose(mano_response, args.verbose)
def element_edit(args):
element = _get_item_uuid(args.element, args.name)
headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
payload=_load_file_or_yaml(args.file)
if args.element[:-1] not in payload:
payload = {args.element[:-1]: payload }
payload_req = json.dumps(payload)
#print payload_req
if not args.force or (args.name==None and args.filer==None):
r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
if len(r)>0 and r[0].lower()=="y":
pass
else:
return 0
logger.debug("openmano request: %s", payload_req)
mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
logger.debug("openmano response: %s", mano_response.text )
if args.verbose==None:
args.verbose=0
if args.name!=None:
args.verbose += 1
return _print_verbose(mano_response, args.verbose)
global mano_host
global mano_port
global mano_tenant
if __name__=="__main__":
mano_tenant = os.getenv('OPENMANO_TENANT', None)
mano_host = os.getenv('OPENMANO_HOST',"localhost")
mano_port = os.getenv('OPENMANO_PORT',"9090")
mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
main_parser.add_argument('--version', action='version', version='%(prog)s ' + __version__ )
subparsers = main_parser.add_subparsers(help='commands')
parent_parser = argparse.ArgumentParser(add_help=False)
parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
config_parser.set_defaults(func=config)
vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
vnf_create_parser.set_defaults(func=vnf_create)
vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
#vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
vnf_list_parser.set_defaults(func=vnf_list)
vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
vnf_delete_parser.set_defaults(func=vnf_delete)
scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
scenario_create_parser.set_defaults(func=scenario_create)
scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
#scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
scenario_list_parser.set_defaults(func=scenario_list)
scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
scenario_delete_parser.set_defaults(func=scenario_delete)
scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
scenario_deploy_parser.set_defaults(func=scenario_deploy)
scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
scenario_deploy_parser.set_defaults(func=scenario_verify)
instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
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")
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")
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")
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")
instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
instance_scenario_create_parser.set_defaults(func=instance_create)
instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
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)")
instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
instance_scenario_action_parser.add_argument("action", action="store", type=str, \
choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console"],\
help="action to send")
instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
#instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
#instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
#instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
tenant_create_parser.set_defaults(func=tenant_create)
tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
tenant_delete_parser.set_defaults(func=tenant_delete)
tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
tenant_list_parser.set_defaults(func=tenant_list)
item_list=('tenant','datacenter') #put tenant before so that help appear in order
for item in item_list:
element_edit_parser = subparsers.add_parser(item+'-edit', parents=[parent_parser], help="edits one "+item)
element_edit_parser.add_argument("name", help="name or uuid of the "+item)
element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
element_edit_parser.set_defaults(func=element_edit, element=item + 's')
datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
datacenter_create_parser.set_defaults(func=datacenter_create)
datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
datacenter_delete_parser.set_defaults(func=datacenter_delete)
datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
datacenter_list_parser.set_defaults(func=datacenter_list)
datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
datacenter_attach_parser.set_defaults(func=datacenter_attach)
datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
datacenter_detach_parser.set_defaults(func=datacenter_detach)
action_dict={'net-update': 'retrieves external networks from datacenter',
'net-edit': 'edits an external network',
'net-delete': 'deletes an external network',
'net-list': 'lists external networks from a datacenter'
}
for item in action_dict:
datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
if item=='net-edit' or item=='net-delete':
datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
if item=='net-edit':
datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
if item!='net-list':
datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
'netmap-create': 'create a new network senario netmap',
'netmap-edit': 'edit name of a network senario netmap',
'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
'netmap-list': 'list/show network scenario netmaps'
}
for item in action_dict:
datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
#if item=='net-add':
# datacenter_action_parser.add_argument("net", help="name of the network")
if item=='netmap-delete':
datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
if item=='netmap-edit':
datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
if item=='netmap-list':
datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
if item=='netmap-create':
datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
if item=='netmap-import':
datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
for item in ("network", "tenant"):
if item=="network":
commnad_name = 'vim-net'
else:
commnad_name = 'vim-'+item
vim_item_list_parser = subparsers.add_parser(commnad_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
vim_item_del_parser = subparsers.add_parser(commnad_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
vim_item_create_parser = subparsers.add_parser(commnad_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
if item=="network":
vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
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>'")
else:
vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
argcomplete.autocomplete(main_parser)
try:
args = main_parser.parse_args()
#logging info
level = logging.CRITICAL
streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
if "debug" in args and args.debug:
level = logging.DEBUG
logging.basicConfig(format=streamformat, level= level)
logger = logging.getLogger('mano')
logger.setLevel(level)
result = args.func(args)
if result == None:
result = 0
#for some reason it fails if call exit inside try instance. Need to call exit at the end !?
except (requests.exceptions.ConnectionError):
print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
result = -2
except (KeyboardInterrupt):
print 'Exiting openmano'
result = -3
except (SystemExit, ArgumentParserError):
result = -4
except OpenmanoCLIError as e:
print str(e)
result = -5
#print result
exit(result)