# contact with: nfvlabs@tid.es
##
-'''
+"""
openmano client used to interact with openmano-server (openmanod)
-'''
-__author__="Alfonso Tierno, Gerardo Garcia, Pablo Montes"
-__date__ ="$09-oct-2014 09:09:48$"
-__version__="0.4.13-r519"
-version_date="Mar 2017"
+"""
+__author__ = "Alfonso Tierno, Gerardo Garcia, Pablo Montes"
+__date__ = "$09-oct-2014 09:09:48$"
+__version__ = "0.4.15-r525"
+version_date = "Jul 2017"
from argcomplete.completers import FilesCompleter
import os
if verbose_level >=1:
if content.get('created_at'):
myoutput += " " + content['created_at'].ljust(20)
+ if content.get('sdn_attached_ports'):
+ #myoutput += " " + str(content['sdn_attached_ports']).ljust(20)
+ myoutput += "\nsdn_attached_ports:\n" + yaml.safe_dump(content['sdn_attached_ports'], indent=4, default_flow_style=False)
if verbose_level >=2:
new_line='\n'
if content.get('type'):
def scenario_verify(args):
#print "scenario-verify",args
+ tenant = _get_tenant()
headers_req = {'content-type': 'application/json'}
action = {}
action["verify"] = {}
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)
+ URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, 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 )
print content['error']['description']
return result
+
def datacenter_list(args):
#print "datacenter-list",args
tenant='any' if args.all else _get_tenant()
args.verbose += 1
return _print_verbose(mano_response, args.verbose)
+
def datacenter_sdn_port_mapping_set(args):
tenant = _get_tenant()
datacenter = _get_datacenter(args.name, tenant)
if not args.file:
raise OpenmanoCLIError(
"No yaml/json has been provided specifying the SDN port mapping")
+ sdn_port_mapping = _load_file_or_yaml(args.file)
+ payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping})
- port_mapping = yaml.load(datacenter_sdn_port_mapping_list(args))
+ # read
+ URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
+ mano_response = requests.get(URLrequest)
+ logger.debug("openmano response: %s", mano_response.text)
+ port_mapping = mano_response.json()
+ if mano_response.status_code != 200:
+ str(mano_response.json())
+ raise OpenmanoCLIError("openmano client error: {}".format(port_mapping['error']['description']))
if len(port_mapping["sdn_port_mapping"]["ports_mapping"]) > 0:
if not args.force:
r = raw_input("Datacenter %s already contains a port mapping. Overwrite? (y/N)? " % (datacenter))
if not (len(r) > 0 and r[0].lower() == "y"):
return 0
- args.force = True
- print datacenter_sdn_port_mapping_clear(args)
- sdn_port_mapping = _load_file_or_yaml(args.file)
- payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping})
+ # clear
+ URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
+ mano_response = requests.delete(URLrequest)
+ logger.debug("openmano response: %s", mano_response.text)
+ if mano_response.status_code != 200:
+ return _print_verbose(mano_response, args.verbose)
+ # set
URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (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)
+ return _print_verbose(mano_response, args.verbose)
- if mano_response.status_code == 200:
- return yaml.safe_dump(mano_response.json())
- else:
- return mano_response.content
def datacenter_sdn_port_mapping_list(args):
tenant = _get_tenant()
mano_response = requests.get(URLrequest)
logger.debug("openmano response: %s", mano_response.text)
- if mano_response.status_code != 200:
- return mano_response.content
+ return _print_verbose(mano_response, 4)
- return yaml.safe_dump(mano_response.json())
def datacenter_sdn_port_mapping_clear(args):
tenant = _get_tenant()
if not args.force:
r = raw_input("Clean SDN port mapping for datacenter %s (y/N)? " %(datacenter))
- if not (len(r)>0 and r[0].lower()=="y"):
+ if not (len(r) > 0 and r[0].lower() == "y"):
return 0
URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
mano_response = requests.delete(URLrequest)
logger.debug("openmano response: %s", mano_response.text)
- if mano_response.status_code != 200:
- if "No port mapping for datacenter" in mano_response.content:
- return "No port mapping for datacenter " + datacenter + " has been found"
- return mano_response.content
+ return _print_verbose(mano_response, args.verbose)
- return yaml.safe_dump(mano_response.json())
def sdn_controller_create(args):
tenant = _get_tenant()
headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
- if not (args.ip and args.port and args.dpid and args.type):
- raise OpenmanoCLIError("The following arguments are required: ip, port, dpid, type")
+ error_msg=[]
+ if not args.ip: error_msg.append("'ip'")
+ if not args.port: error_msg.append("'port'")
+ if not args.dpid: error_msg.append("'dpid'")
+ if not args.type: error_msg.append("'type'")
+ if error_msg:
+ raise OpenmanoCLIError("The following arguments are required: " + ",".join(error_msg))
controller_dict = {}
controller_dict['name'] = args.name
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)
-
return result
+
def sdn_controller_edit(args):
tenant = _get_tenant()
controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
- if not (args.new_name or args.ip or args.port or args.dpid or args.type):
- raise OpenmanoCLIError("At least one parameter must be editd")
-
- if not args.force:
- r = raw_input("Update SDN controller %s (y/N)? " %(args.name))
- if not (len(r)>0 and r[0].lower()=="y"):
- return 0
-
controller_dict = {}
- if args.new_name != None:
+ if args.new_name:
controller_dict['name'] = args.new_name
- if args.ip != None:
+ if args.ip:
controller_dict['ip'] = args.ip
- if args.port != None:
+ if args.port:
controller_dict['port'] = int(args.port)
- if args.dpid != None:
+ if args.dpid:
controller_dict['dpid'] = args.dpid
- if args.type != None:
+ if args.type:
controller_dict['type'] = args.type
- if args.description != None:
+ if args.description:
controller_dict['description'] = args.description
- if args.user != None:
+ if args.user:
controller_dict['user'] = args.user
- if args.password != None:
+ if args.password:
controller_dict['password'] = args.password
- payload_req = json.dumps({"sdn_controller": controller_dict})
+ if not controller_dict:
+ raise OpenmanoCLIError("At least one parameter must be edited")
+ if not args.force:
+ r = raw_input("Update SDN controller {} (y/N)? ".format(args.name))
+ if not (len(r) > 0 and r[0].lower() == "y"):
+ return 0
+
+ payload_req = json.dumps({"sdn_controller": controller_dict})
# print payload_req
URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
logger.debug("openmano response: %s", mano_response.text)
result = _print_verbose(mano_response, args.verbose)
-
return result
+
def sdn_controller_list(args):
tenant = _get_tenant()
headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
if args.name!=None:
args.verbose += 1
- result = json.dumps(mano_response.json(), indent=4)
- return result
+ # json.dumps(mano_response.json(), indent=4)
+ return _print_verbose(mano_response, args.verbose)
+
def sdn_controller_delete(args):
tenant = _get_tenant()
URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
mano_response = requests.delete(URLrequest)
logger.debug("openmano response: %s", mano_response.text)
- result = _print_verbose(mano_response, args.verbose)
-
- return result
+ return _print_verbose(mano_response, args.verbose)
def vim_action(args):
#print "datacenter-net-action",args
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)
+ URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, 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:
return _print_verbose(mano_response, args.verbose)
+def _get_items(item, item_name_id=None, datacenter=None, tenant=None):
+ URLrequest = "http://%s:%s/openmano" %(mano_host, mano_port)
+ if tenant:
+ URLrequest += "/" + tenant
+ if datacenter:
+ URLrequest += "/vim/" + datacenter
+ if item:
+ URLrequest += "/" + item +"s"
+ if item_name_id:
+ URLrequest += "/" + item_name_id
+ mano_response = requests.get(URLrequest)
+ logger.debug("openmano response: %s", mano_response.text )
+
+ return mano_response
+
+
+def vim_net_sdn_attach(args):
+ #Verify the network exists in the vim
+ tenant = _get_tenant()
+ datacenter = _get_datacenter(args.datacenter, tenant)
+ result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
+ content = yaml.load(result.content)
+ if 'networks' in content:
+ raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
+ if 'error' in content:
+ raise OpenmanoCLIError(yaml.safe_dump(content))
+ network_uuid = content['network']['id']
+
+ #Make call to attach the dataplane port to the SND network associated to the vim network
+ headers_req = {'content-type': 'application/yaml'}
+ payload_req = {'port': args.port}
+ if args.vlan:
+ payload_req['vlan'] = int(args.vlan)
+ if args.mac:
+ payload_req['mac'] = args.mac
+
+ URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/attach" % (mano_host, mano_port, tenant, datacenter, network_uuid)
+ logger.debug("openmano request: %s", payload_req)
+ mano_response = requests.post(URLrequest, headers=headers_req, data=json.dumps(payload_req))
+ logger.debug("openmano response: %s", mano_response.text)
+ result = _print_verbose(mano_response, args.verbose)
+ return result
+
+
+def vim_net_sdn_detach(args):
+ if not args.all and not args.id:
+ print "--all or --id must be used"
+ return 1
+
+ # Verify the network exists in the vim
+ tenant = _get_tenant()
+ datacenter = _get_datacenter(args.datacenter, tenant)
+ result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
+ content = yaml.load(result.content)
+ if 'networks' in content:
+ raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
+ if 'error' in content:
+ raise OpenmanoCLIError(yaml.safe_dump(content))
+ network_uuid = content['network']['id']
+
+ if not args.force:
+ r = raw_input("Confirm action' (y/N)? ")
+ if len(r) == 0 or r[0].lower() != "y":
+ return 0
+
+ if args.id:
+ URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach/%s" % (
+ mano_host, mano_port, tenant, datacenter, network_uuid, args.id)
+ else:
+ URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach" % (
+ mano_host, mano_port, tenant, datacenter, network_uuid)
+ mano_response = requests.delete(URLrequest)
+ logger.debug("openmano response: %s", mano_response.text)
+ result = _print_verbose(mano_response, args.verbose)
+ return result
+
+
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!!!"
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'}
args.verbose += 1
return _print_verbose(mano_response, args.verbose)
+
def version(args):
headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
URLrequest = "http://%s:%s/openmano/version" % (mano_host, mano_port)
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)
-
+
+ # =======================vim_net_sdn_xxx section=======================
+ # vim_net_sdn_attach
+ vim_net_sdn_attach_parser = subparsers.add_parser('vim-net-sdn-attach',
+ parents=[parent_parser],
+ help="Specify the port to access to an external network using SDN")
+ vim_net_sdn_attach_parser.add_argument("vim_net", action="store",
+ help="Name/id of the network in the vim that will be used to connect to the external network")
+ vim_net_sdn_attach_parser.add_argument("port", action="store", help="Specifies the port in the dataplane switch to access to the external network")
+ vim_net_sdn_attach_parser.add_argument("--vlan", action="store", help="Specifies the vlan (if any) to use in the defined port")
+ 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")
+ vim_net_sdn_attach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
+ vim_net_sdn_attach_parser.set_defaults(func=vim_net_sdn_attach)
+
+ # vim_net_sdn_detach
+ vim_net_sdn_detach_parser = subparsers.add_parser('vim-net-sdn-detach',
+ parents=[parent_parser],
+ help="Remove the port information to access to an external network using SDN")
+
+ vim_net_sdn_detach_parser.add_argument("vim_net", action="store", help="Name/id of the vim network")
+ vim_net_sdn_detach_parser.add_argument("--id", action="store",help="Specify the uuid of the external ports from this network to be detached")
+ vim_net_sdn_detach_parser.add_argument("--all", action="store_true", help="Detach all external ports from this network")
+ vim_net_sdn_detach_parser.add_argument("-f", "--force", action="store_true", help="forces clearing without asking")
+ vim_net_sdn_detach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
+ vim_net_sdn_detach_parser.set_defaults(func=vim_net_sdn_detach)
+ # =======================
+
for item in ("network", "tenant", "image"):
if item=="network":
- commnad_name = 'vim-net'
+ command_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")
+ command_name = 'vim-'+item
+ vim_item_list_parser = subparsers.add_parser(command_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 = subparsers.add_parser(command_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")
if item == "network" or item == "tenant":
- vim_item_create_parser = subparsers.add_parser(commnad_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
+ vim_item_create_parser = subparsers.add_parser(command_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")