add osimages, add ViNS management
This commit is contained in:
@@ -1247,26 +1247,25 @@ class DecortController(object):
|
||||
def image_find(self, image_id, image_name, account_id, rg_id=0, sepid=0, pool=""):
|
||||
"""Locates image specified by name and returns its facts as dictionary.
|
||||
Primary use of this function is to obtain the ID of the image identified by its name and,
|
||||
optionally SEP ID and/or pool name. Also note that only images in status CREATED are
|
||||
optionally SEP ID and/or pool name. Also note that only images in status CREATED are
|
||||
returned.
|
||||
|
||||
@param (string) image_id: ID of the OS image to find. If non-zero ID is specified, then
|
||||
image_name is ignored.
|
||||
@param (string) image_name: name of the OS image to find. This argument is ignored if non-zero
|
||||
image ID is passed.
|
||||
@param (int) account_id: ID of the account for which the image will be looked up. If set to 0,
|
||||
@param (int) account_id: ID of the account for which the image will be looked up. If set to 0,
|
||||
the account ID will be obtained from the specified RG ID.
|
||||
@param (int) rg_id: ID of the RG to use as a reference when listing OS images. This argument is
|
||||
ignored if non-zero image id and/or non-zero account_id are specified.
|
||||
@param (int) sepid: ID of the SEP where the image should be present. If set to 0, there will be no
|
||||
@param (int) sepid: ID of the SEP where the image should be present. If set to 0, there will be no
|
||||
filtering by SEP ID and the first matching image will be returned.
|
||||
@param (string) pool: name of the pool where the image should be present. If set to empty string, there
|
||||
@param (string) pool: name of the pool where the image should be present. If set to empty string, there
|
||||
will be no filtering by pool name and first matching image will be returned.
|
||||
|
||||
@return: image ID and dictionary with image specs. If no matching image found, 0 for ID and None for
|
||||
@return: image ID and dictionary with image specs. If no matching image found, 0 for ID and None for
|
||||
dictionary are returned, and self.result['failed']=True.
|
||||
"""
|
||||
|
||||
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "image_find")
|
||||
|
||||
if image_id > 0:
|
||||
@@ -1292,7 +1291,7 @@ class DecortController(object):
|
||||
for image_record in images_list:
|
||||
if image_record['name'] == image_name and image_record['status'] == "CREATED":
|
||||
if sepid == 0 and pool == "":
|
||||
# if no filtering by SEP ID or pool name is requested, return the first match
|
||||
# if no filtering by SEP ID or pool name is requested, return the first match
|
||||
return image_record['id'], image_record
|
||||
# if positive SEP ID and/or non-emtpy pool name are passed, match by them
|
||||
full_match = True
|
||||
@@ -1302,6 +1301,7 @@ class DecortController(object):
|
||||
full_match = False
|
||||
if full_match:
|
||||
return image_record['id'], image_record
|
||||
self.result['failed'] = False
|
||||
|
||||
self.result['failed'] = True
|
||||
self.result['msg'] = ("Failed to find OS image by name '{}', SEP ID {}, pool '{}' for "
|
||||
@@ -1310,6 +1310,136 @@ class DecortController(object):
|
||||
account_id)
|
||||
return 0, None
|
||||
|
||||
def virt_image_find(self, image_id, virt_name, account_id, rg_id=0, sepid=0, pool=""):
|
||||
"""Locates virtual image specified by name and returns its facts as dictionary.
|
||||
Primary use of this function is to obtain the ID of the image identified by its name and,
|
||||
optionally SEP ID and/or pool name. Also note that only virtual images in status CREATED are
|
||||
returned.
|
||||
|
||||
@param (string) image_id: ID of the OS image to find. If non-zero ID is specified, then
|
||||
virt_name is ignored.
|
||||
@param (string) virt_name: name of the OS image to find. This argument is ignored if non-zero
|
||||
image ID is passed.
|
||||
@param (int) account_id: ID of the account for which the image will be looked up. If set to 0,
|
||||
the account ID will be obtained from the specified RG ID.
|
||||
@param (int) rg_id: ID of the RG to use as a reference when listing OS images. This argument is
|
||||
ignored if non-zero image id and/or non-zero account_id are specified.
|
||||
@param (int) sepid: ID of the SEP where the image should be present. If set to 0, there will be no
|
||||
filtering by SEP ID and the first matching image will be returned.
|
||||
@param (string) pool: name of the pool where the image should be present. If set to empty string, there
|
||||
will be no filtering by pool name and first matching image will be returned.
|
||||
|
||||
@return: image ID and dictionary with image specs. If no matching image found, 0 for ID and None for
|
||||
dictionary are returned, and self.result['failed']=True.
|
||||
"""
|
||||
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "virt_image_find")
|
||||
|
||||
|
||||
|
||||
if image_id > 0:
|
||||
ret_image_id, ret_image_dict = self._image_get_by_id(image_id)
|
||||
if (ret_image_id and
|
||||
(sepid == 0 or sepid == ret_image_dict['sepId']) and
|
||||
(pool == "" or pool == ret_image_dict['pool'])):
|
||||
return ret_image_id, ret_image_dict
|
||||
else:
|
||||
validated_acc_id = account_id
|
||||
if account_id == 0:
|
||||
validated_rg_id, rg_facts = self._rg_get_by_id(rg_id)
|
||||
if not validated_rg_id:
|
||||
self.result['failed'] = True
|
||||
self.result['msg'] = ("Failed to find RG ID {}, and account ID is zero.").format(rg_id)
|
||||
return 0, None
|
||||
validated_acc_id = rg_facts['accountId']
|
||||
|
||||
api_params = dict(accountId=validated_acc_id)
|
||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/image/list", api_params)
|
||||
# On success the above call will return here. On error it will abort execution by calling fail_json.
|
||||
images_list = json.loads(api_resp.content.decode('utf8'))
|
||||
for image_record in images_list:
|
||||
if image_record['name'] == virt_name and image_record['status'] == "CREATED" and image_record['type'] == "virtual":
|
||||
if sepid == 0 and pool == "":
|
||||
# if no filtering by SEP ID or pool name is requested, return the first match
|
||||
return image_record['id'], image_record
|
||||
full_match = True
|
||||
if full_match:
|
||||
return image_record['id'], image_record
|
||||
|
||||
self.result['failed'] = True
|
||||
self.result['msg'] = ("Failed to find virtual OS image by name '{}', SEP ID {}, pool '{}' for "
|
||||
"account ID '{}'.").format(virt_name,
|
||||
sepid, pool,
|
||||
account_id)
|
||||
|
||||
return 0, None
|
||||
|
||||
def virt_image_create(self, name, targetId):
|
||||
|
||||
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "virt_image_create")
|
||||
|
||||
api_params = dict(name=name, targetId=targetId,)
|
||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/image/createVirtual", api_params)
|
||||
# On success the above call will return here. On error it will abort execution by calling fail_json.
|
||||
virt_image_dict = json.loads(api_resp.content.decode('utf8'))
|
||||
|
||||
self.result['failed'] = False
|
||||
self.result['changed'] = True
|
||||
return 0, None
|
||||
|
||||
def image_delete(self, imageId, permanently):
|
||||
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "image_delete")
|
||||
|
||||
api_params = dict(imageId=imageId, permanently=permanently,)
|
||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/image/delete", api_params)
|
||||
# On success the above call will return here. On error it will abort execution by calling fail_json.
|
||||
image_dict = json.loads(api_resp.content.decode('utf8'))
|
||||
|
||||
self.result['changed'] = True
|
||||
return 0, None
|
||||
|
||||
|
||||
def image_create(self,img_name,url,gid,boottype,imagetype,architecture,drivers,hotresize,username,password,account_Id,usernameDL,passwordDL,sepId,poolName):
|
||||
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "image_create")
|
||||
|
||||
api_params = dict(name=img_name, url=url,
|
||||
gid=gid, boottype=boottype,
|
||||
imagetype=imagetype, architecture=architecture,
|
||||
drivers=drivers, accountId=account_Id,
|
||||
hotresize=hotresize, username=username,
|
||||
password=password, usernameDL=usernameDL,
|
||||
passwordDL=passwordDL, sepId=sepId,
|
||||
poolName=poolName,
|
||||
)
|
||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/image/create", api_params)
|
||||
# On success the above call will return here. On error it will abort execution by calling fail_json.
|
||||
virt_image_dict = json.loads(api_resp.content.decode('utf8'))
|
||||
self.result['failed'] = False
|
||||
self.result['changed'] = True
|
||||
return 0, None
|
||||
|
||||
def virt_image_link(self, imageId, targetId):
|
||||
|
||||
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "virt_image_link")
|
||||
|
||||
api_params = dict(imageId=imageId, targetId=targetId,)
|
||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/image/link", api_params)
|
||||
# On success the above call will return here. On error it will abort execution by calling fail_json.
|
||||
link_image_dict = json.loads(api_resp.content.decode('utf8'))
|
||||
self.result['failed'] = False
|
||||
self.result['changed'] = True
|
||||
|
||||
|
||||
return 0, None
|
||||
|
||||
def image_rename(self, imageId, name):
|
||||
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "image_rename")
|
||||
api_params = dict(imageId=imageId, name=name,)
|
||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/image/rename", api_params)
|
||||
# On success the above call will return here. On error it will abort execution by calling fail_json.
|
||||
link_image_dict = json.loads(api_resp.content.decode('utf8'))
|
||||
self.result['failed'] = False
|
||||
self.result['changed'] = True
|
||||
|
||||
###################################
|
||||
# Resource Group (RG) manipulation methods
|
||||
###################################
|
||||
@@ -2166,7 +2296,7 @@ class DecortController(object):
|
||||
desired_state)
|
||||
return
|
||||
|
||||
def vins_update(self, vins_dict, ext_net_id, ext_ip_addr="", mgmtaddr=""):
|
||||
def vins_update(self, vins_dict, ext_net_id, ext_ip_addr=""):
|
||||
"""Update ViNS. Currently only updates to the external network connection settings and
|
||||
external IP address assignment are implemented.
|
||||
Note that as ViNS created at account level cannot have external connections, attempt
|
||||
@@ -2191,11 +2321,6 @@ class DecortController(object):
|
||||
self.result['msg'] = ("vins_update() in check mode: updating ViNS ID {}, name '{}' "
|
||||
"was requested.").format(vins_dict['id'], vins_dict['name'])
|
||||
return
|
||||
if self.amodule.params['config_save'] and vins_dict['VNFDev']['customPrecfg']:
|
||||
# only save config,no other modifictaion
|
||||
self.result['changed'] = True
|
||||
self._vins_vnf_config_save(vins_dict['VNFDev']['id'])
|
||||
return
|
||||
|
||||
if not vins_dict['rgId']:
|
||||
# this ViNS exists at account level - no updates are possible
|
||||
@@ -2246,24 +2371,117 @@ class DecortController(object):
|
||||
self.result['warning'] = ("vins_update(): ViNS ID {} is already connected to ext net ID {}, "
|
||||
"no reconnection to default network will be done.").format(vins_dict['id'],
|
||||
gw_config[
|
||||
'ext_net_id'])
|
||||
'ext_net_id'])
|
||||
return
|
||||
def vins_update_mgmt(self, vins_dict, mgmtaddr=""):
|
||||
|
||||
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "vins_update_mgmt")
|
||||
|
||||
if self.amodule.params['config_save'] and vins_dict['VNFDev']['customPrecfg']:
|
||||
# only save config,no other modifictaion
|
||||
self.result['changed'] = True
|
||||
self._vins_vnf_config_save(vins_dict['VNFDev']['id'])
|
||||
self.result['changed'] = True
|
||||
self.result['failed'] = False
|
||||
return
|
||||
|
||||
for iface in vins_dict['VNFDev']['interfaces']:
|
||||
if iface['ipAddress'] == mgmtaddr:
|
||||
if not iface['listenSsh']:
|
||||
self._vins_vnf_addmgmtaddr(vins_dict['VNFDev']['id'],mgmtaddr)
|
||||
self.result['changed'] = True
|
||||
self.result['failed'] = False
|
||||
elif mgmtaddr =="":
|
||||
if iface['listenSsh'] and iface['name'] != "ens9":
|
||||
self._vins_vnf_delmgmtaddr(vins_dict['VNFDev']['id'],iface['ipAddress'])
|
||||
|
||||
self.result['changed'] = True
|
||||
self.result['failed'] = False
|
||||
if self.amodule.params['custom_config']:
|
||||
if not vins_dict['VNFDev']['customPrecfg']:
|
||||
self._vins_vnf_config_save(vins_dict['VNFDev']['id'])
|
||||
self._vins_vnf_customconfig_set(vins_dict['VNFDev']['id'])
|
||||
self.result['changed'] = True
|
||||
self.result['failed'] = False
|
||||
else:
|
||||
if vins_dict['VNFDev']['customPrecfg']:
|
||||
self._vins_vnf_customconfig_set(vins_dict['VNFDev']['id'],False)
|
||||
|
||||
self.result['changed'] = True
|
||||
self.result['failed'] = False
|
||||
return
|
||||
|
||||
def vins_update_ifaces(self,vins_dict,vinses=""):
|
||||
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "vins_update_ifaces")
|
||||
existed_conn_ip = []
|
||||
#vnf_dict = self._get_vnf_by_id(vins_dict['VNFDev']['id'])
|
||||
list_account_vins = self._get_all_account_vinses(vins_dict['VNFDev']['accountId'])
|
||||
list_account_vinsid = [rec['id'] for rec in list_account_vins]
|
||||
list_ifaces_ip = [rec['ipaddr'] for rec in vinses]
|
||||
vins_inner = [rec['id'] for rec in vinses]
|
||||
vins_outer = [rec['id'] for rec in list_account_vins]
|
||||
for iface in vins_dict['VNFDev']['interfaces']:
|
||||
if iface['connType'] == "VXLAN" and iface['type'] == "CUSTOM":
|
||||
if iface['ipAddress'] not in list_ifaces_ip:
|
||||
self._vnf_iface_remove(vins_dict['VNFDev']['id'],iface['name'])
|
||||
self.result['changed'] = True
|
||||
self.result['failed'] = False
|
||||
else:
|
||||
existed_conn_ip.append(iface['ipAddress'])
|
||||
|
||||
for vins in vinses:
|
||||
if vins['id'] in list_account_vinsid:
|
||||
_,v_dict = self._vins_get_by_id(vins['id'])
|
||||
if vins['ipaddr'] not in existed_conn_ip:
|
||||
self._vnf_iface_add(vins_dict['VNFDev']['id'],v_dict['vxlanId'],vins['ipaddr'],vins['netmask'])
|
||||
self.result['changed'] = True
|
||||
self.result['failed'] = False
|
||||
return
|
||||
|
||||
def _vnf_iface_add(self,arg_devid,arg_vxlanid,arg_ipaddr,arg_netmask="24",arg_defgw=""):
|
||||
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "_vnf_iface_add")
|
||||
api_params = dict(
|
||||
devId=arg_devid,
|
||||
ifType="CUSTOM",
|
||||
connType="VXLAN",
|
||||
connId=arg_vxlanid,
|
||||
ipAddr=arg_ipaddr,
|
||||
netMask=arg_netmask,
|
||||
defGw=arg_defgw
|
||||
)
|
||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudbroker/vnfdev/ifaceAdd", api_params)
|
||||
conn_dict = json.loads(api_resp.content.decode('utf8'))
|
||||
return
|
||||
|
||||
def _vnf_iface_remove(self,arg_devid,arg_iface_name):
|
||||
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "_vnf_iface_add")
|
||||
api_params = dict(
|
||||
devId=arg_devid,
|
||||
name=arg_iface_name,
|
||||
|
||||
)
|
||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudbroker/vnfdev/ifaceRemove", api_params)
|
||||
return
|
||||
|
||||
def _get_vnf_by_id(self,vnf_id):
|
||||
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "get_vnf_by_id")
|
||||
api_params = dict(devId=vnf_id)
|
||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudbroker/vnfdev/get", api_params)
|
||||
if api_resp.status_code == 200:
|
||||
ret_vnf_dict = json.loads(api_resp.content.decode('utf8'))
|
||||
else:
|
||||
self.result['warning'] = ("get_all_account_vinses(): failed to configuration of the specified VNF device ID{}. HTTP code {}, "
|
||||
"response {}.").format(vnf_id, api_resp.status_code, api_resp.reason)
|
||||
return ret_vnf_dict
|
||||
|
||||
def _get_all_account_vinses(self,acc_id):
|
||||
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "get_all_account_vinses")
|
||||
api_params = dict(accountId=acc_id)
|
||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/account/listVins", api_params)
|
||||
if api_resp.status_code == 200:
|
||||
ret_listvins_dict = json.loads(api_resp.content.decode('utf8'))
|
||||
else:
|
||||
self.result['warning'] = ("get_all_account_vinses(): failed to get list VINS in Account ID {}. HTTP code {}, "
|
||||
"response {}.").format(acc_id, api_resp.status_code, api_resp.reason)
|
||||
return ret_listvins_dict
|
||||
|
||||
def _vins_vnf_addmgmtaddr(self,dev_id,mgmtip):
|
||||
|
||||
@@ -2649,8 +2867,8 @@ class DecortController(object):
|
||||
iface_ipaddr = iface['ipAddress']
|
||||
break
|
||||
else:
|
||||
decon.result['failed'] = True
|
||||
decon.result['msg'] = "Compute ID {} is not connected to ViNS ID {}.".format(comp_facts['id'],
|
||||
self.result['failed'] = True
|
||||
self.result['msg'] = "Compute ID {} is not connected to ViNS ID {}.".format(comp_facts['id'],
|
||||
vins_facts['id'])
|
||||
return ret_rules
|
||||
|
||||
|
||||
Reference in New Issue
Block a user