Fixing Jinja templating quirks for compute_networks method
This commit is contained in:
@@ -464,12 +464,12 @@ class DecortController(object):
|
|||||||
break
|
break
|
||||||
return
|
return
|
||||||
|
|
||||||
def compute_data_disks(self, comp_dict, data_disks):
|
def compute_data_disks(self, comp_dict, new_data_disks):
|
||||||
"""Manage attachment of data disks to the Compute instance.
|
"""Manage attachment of data disks to the Compute instance.
|
||||||
|
|
||||||
@param (dict) comp_dict: dictionary with Compute facts, that identifies the Compute instance
|
@param (dict) comp_dict: dictionary with Compute facts, that identifies the Compute instance
|
||||||
to manage data disks for.
|
to manage data disks for.
|
||||||
@param (list of int) data_disks: list of interger IDs for the disks that must be attached to
|
@param (list of int) new_data_disks: list of integer IDs for the disks that must be attached to
|
||||||
this Compute instance. If some disk IDs appear in this list, but are not present in comp_dict,
|
this Compute instance. If some disk IDs appear in this list, but are not present in comp_dict,
|
||||||
these disks will be attached. Vice versa, if some disks appear in comp_dict but are not present
|
these disks will be attached. Vice versa, if some disks appear in comp_dict but are not present
|
||||||
in data_disks, such disks will be detached.
|
in data_disks, such disks will be detached.
|
||||||
@@ -496,19 +496,30 @@ class DecortController(object):
|
|||||||
detach_list = []
|
detach_list = []
|
||||||
attach_list = []
|
attach_list = []
|
||||||
|
|
||||||
|
# 'data_disks' argument for decort_kvmvm module expects list of integer disk IDs.
|
||||||
|
# However, if the value for disk ID comes via Jinja templating like this:
|
||||||
|
# data_disks:
|
||||||
|
# - "{{ my_disk.facts.id }}" <= will come as string, which is WRONG!!!
|
||||||
|
# - 4571 <= no Jinja templae, will come as int - OK
|
||||||
|
#
|
||||||
|
# then all values when entering this method will be of type string. We need to
|
||||||
|
# explicitly cast int type on all of them.
|
||||||
|
for repair in new_data_disks:
|
||||||
|
repair = int(repair)
|
||||||
|
|
||||||
for disk in comp_dict['disks']:
|
for disk in comp_dict['disks']:
|
||||||
if disk['type'] == 'B':
|
if disk['type'] == 'B':
|
||||||
bdisk_id = disk['id']
|
bdisk_id = disk['id']
|
||||||
if bdisk_id in data_disks:
|
if bdisk_id in new_data_disks:
|
||||||
# If boot disk ID is listed in data_disks - remove it
|
# If boot disk ID is listed in data_disks - remove it
|
||||||
data_disks.remove(bdisk_id)
|
new_data_disks.remove(bdisk_id)
|
||||||
elif disk['type'] == 'D':
|
elif disk['type'] == 'D':
|
||||||
# build manipulation sets for 'D' type disks only
|
# build manipulation sets for 'D' type disks only
|
||||||
current_list.append(disk['id'])
|
current_list.append(disk['id'])
|
||||||
if disk['id'] not in data_disks:
|
if disk['id'] not in new_data_disks:
|
||||||
detach_list.append(disk['id'])
|
detach_list.append(disk['id'])
|
||||||
|
|
||||||
attach_list = [ did for did in data_disks if did not in current_list ]
|
attach_list = [ did for did in new_data_disks if did not in current_list ]
|
||||||
|
|
||||||
for did in detach_list:
|
for did in detach_list:
|
||||||
api_params = dict(computeId = comp_dict['id'], diskId=did)
|
api_params = dict(computeId = comp_dict['id'], diskId=did)
|
||||||
@@ -812,6 +823,20 @@ class DecortController(object):
|
|||||||
"ID {} was requested.").format(comp_dict['id'])
|
"ID {} was requested.").format(comp_dict['id'])
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# 'networks' dictionary for decort_kvmvm module has 'id' parameter, which is expected
|
||||||
|
# to be interger.
|
||||||
|
# However, if the value for 'id' comes via Jinja templating like this:
|
||||||
|
# networks:
|
||||||
|
# - type: VINS <= will come as string, which is OK.
|
||||||
|
# id: "{{ my_vins.facts.id }}" <= will come as string, which is WRONG!!!
|
||||||
|
# - type: VINS <= will come as string, which is OK
|
||||||
|
# id: 37 <= no Jinja templae, will come as int - OK
|
||||||
|
#
|
||||||
|
# then all values (including those for 'id' key) when entering this method will be of
|
||||||
|
# type string. We need to explicitly cast int type on all of them.
|
||||||
|
for repair in new_networks:
|
||||||
|
repair['id'] = int(repair['id'])
|
||||||
|
|
||||||
api_params = dict(accountId = comp_dict['accountId'])
|
api_params = dict(accountId = comp_dict['accountId'])
|
||||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/vins/search", api_params)
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/vins/search", api_params)
|
||||||
vins_list = json.loads(api_resp.content.decode('utf8'))
|
vins_list = json.loads(api_resp.content.decode('utf8'))
|
||||||
@@ -829,6 +854,7 @@ class DecortController(object):
|
|||||||
"Compute ID {}.").format(comp_dict['accountId'], comp_dict['id'])
|
"Compute ID {}.").format(comp_dict['accountId'], comp_dict['id'])
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Prepare the lists of network interfaces for the compute instance:
|
||||||
vins_iface_list = [] # will contain dict(id=<int>, ipAddress=<str>, mac=<str>) for ifaces connected to ViNS(es)
|
vins_iface_list = [] # will contain dict(id=<int>, ipAddress=<str>, mac=<str>) for ifaces connected to ViNS(es)
|
||||||
enet_iface_list = [] # will contain dict(id=<int>, ipAddress=<str>, mac=<str>) for ifaces connected to Ext net(s)
|
enet_iface_list = [] # will contain dict(id=<int>, ipAddress=<str>, mac=<str>) for ifaces connected to Ext net(s)
|
||||||
for iface in comp_dict['interfaces']:
|
for iface in comp_dict['interfaces']:
|
||||||
@@ -856,27 +882,32 @@ class DecortController(object):
|
|||||||
enet_iface_list.append(iface_data)
|
enet_iface_list.append(iface_data)
|
||||||
|
|
||||||
vins_id_list = [ rec['id'] for rec in vins_iface_list ]
|
vins_id_list = [ rec['id'] for rec in vins_iface_list ]
|
||||||
|
|
||||||
enet_id_list = [ rec['id'] for rec in enet_iface_list ]
|
enet_id_list = [ rec['id'] for rec in enet_iface_list ]
|
||||||
|
|
||||||
# Build attach list by looking for ViNS/Ext net IDs that appear in new_networks, but do not appear in current lists
|
# Build attach list by looking for ViNS/Ext net IDs that appear in new_networks, but do not appear in current lists
|
||||||
attach_list = [] # attach list holds both ViNS and Ext Net attachment specs, as these do not differ from API perspective
|
attach_list = [] # attach list holds both ViNS and Ext Net attachment specs, as API handles them the same way
|
||||||
for netrunner in new_networks:
|
for netrunner in new_networks:
|
||||||
if netrunner['type'] == 'VINS' and netrunner['id'] not in vins_id_list:
|
if netrunner['type'] == 'VINS' and ( netrunner['id'] not in vins_id_list ):
|
||||||
net2attach = dict(computeId=comp_dict['id'],
|
net2attach = dict(computeId=comp_dict['id'],
|
||||||
netType='VINS',
|
netType='VINS',
|
||||||
netId=netrunner['id'],
|
netId=netrunner['id'],
|
||||||
ipAddr=netrunner.get('ip_addr', ""))
|
ipAddr=netrunner.get('ip_addr', ""))
|
||||||
attach_list.append(net2attach)
|
attach_list.append(net2attach)
|
||||||
elif netrunner['type'] == 'EXTNET' and netrunner['id'] not in enet_id_list:
|
elif netrunner['type'] == 'EXTNET' and ( netrunner['id'] not in enet_id_list ):
|
||||||
net2attach = dict(computeId=comp_dict['id'],
|
net2attach = dict(computeId=comp_dict['id'],
|
||||||
netType='EXTNET',
|
netType='EXTNET',
|
||||||
netId=netrunner['id'],
|
netId=netrunner['id'],
|
||||||
ipAddr=netrunner.get('ip_addr', ""))
|
ipAddr=netrunner.get('ip_addr', ""))
|
||||||
attach_list.append(net2attach)
|
attach_list.append(net2attach)
|
||||||
|
|
||||||
|
# detach is meaningful only if compute's interfaces list was not empty
|
||||||
|
if vins_id_list or enet_id_list:
|
||||||
# Build detach list by looking for ViNS/Ext net IDs that appear in current lists, but do not appear in new_networks
|
# Build detach list by looking for ViNS/Ext net IDs that appear in current lists, but do not appear in new_networks
|
||||||
detach_list = [] # detach list holds both ViNS and Ext Net detachment specs, as these do not differ from API perspective
|
detach_list = [] # detach list holds both ViNS and Ext Net detachment specs, as API handles them the same way
|
||||||
|
|
||||||
target_list = [ rec['id'] for rec in new_networks if rec['type'] == 'VINS' ]
|
target_list = [ rec['id'] for rec in new_networks if rec['type'] == 'VINS' ]
|
||||||
|
|
||||||
for netrunner in vins_iface_list:
|
for netrunner in vins_iface_list:
|
||||||
if netrunner['id'] not in target_list:
|
if netrunner['id'] not in target_list:
|
||||||
net2detach = dict(computeId=comp_dict['id'],
|
net2detach = dict(computeId=comp_dict['id'],
|
||||||
@@ -885,6 +916,7 @@ class DecortController(object):
|
|||||||
detach_list.append(net2detach)
|
detach_list.append(net2detach)
|
||||||
|
|
||||||
target_list = [ rec['id'] for rec in new_networks if rec['type'] == 'EXTNET' ]
|
target_list = [ rec['id'] for rec in new_networks if rec['type'] == 'EXTNET' ]
|
||||||
|
|
||||||
for netrunner in enet_iface_list:
|
for netrunner in enet_iface_list:
|
||||||
if netrunner['id'] not in target_list:
|
if netrunner['id'] not in target_list:
|
||||||
net2detach = dict(computeId=comp_dict['id'],
|
net2detach = dict(computeId=comp_dict['id'],
|
||||||
@@ -892,7 +924,6 @@ class DecortController(object):
|
|||||||
mac=netrunner['mac'])
|
mac=netrunner['mac'])
|
||||||
detach_list.append(net2detach)
|
detach_list.append(net2detach)
|
||||||
|
|
||||||
|
|
||||||
for api_params in detach_list:
|
for api_params in detach_list:
|
||||||
self.decort_api_call(requests.post, "/restmachine/cloudapi/compute/netDetach", api_params)
|
self.decort_api_call(requests.post, "/restmachine/cloudapi/compute/netDetach", api_params)
|
||||||
# On success the above call will return here. On error it will abort execution by calling fail_json.
|
# On success the above call will return here. On error it will abort execution by calling fail_json.
|
||||||
|
|||||||
Reference in New Issue
Block a user