Merge branch 'feature/decort_lb'
This commit is contained in:
@@ -114,10 +114,10 @@ class decort_k8s(DecortController):
|
|||||||
return ret_dict
|
return ret_dict
|
||||||
|
|
||||||
def nop(self):
|
def nop(self):
|
||||||
"""No operation (NOP) handler for Compute management by decort_kvmvm module.
|
"""No operation (NOP) handler for k8s cluster management by decort_k8s module.
|
||||||
This function is intended to be called from the main switch construct of the module
|
This function is intended to be called from the main switch construct of the module
|
||||||
when current state -> desired state change logic does not require any changes to
|
when current state -> desired state change logic does not require any changes to
|
||||||
the actual Compute state.
|
the actual k8s cluster state.
|
||||||
"""
|
"""
|
||||||
self.result['failed'] = False
|
self.result['failed'] = False
|
||||||
self.result['changed'] = False
|
self.result['changed'] = False
|
||||||
|
|||||||
328
library/decort_lb.py
Normal file
328
library/decort_lb.py
Normal file
@@ -0,0 +1,328 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
#
|
||||||
|
# Digital Enegry Cloud Orchestration Technology (DECORT) modules for Ansible
|
||||||
|
# Copyright: (c) 2018-2022 Digital Energy Cloud Solutions LLC
|
||||||
|
#
|
||||||
|
# Apache License 2.0 (see http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||||
|
#
|
||||||
|
|
||||||
|
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||||
|
'status': ['preview'],
|
||||||
|
'supported_by': 'community'}
|
||||||
|
|
||||||
|
DOCUMENTATION = '''
|
||||||
|
TODO
|
||||||
|
'''
|
||||||
|
|
||||||
|
EXAMPLES = '''
|
||||||
|
TODO
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
from ansible.module_utils.basic import env_fallback
|
||||||
|
|
||||||
|
from ansible.module_utils.decort_utils import *
|
||||||
|
|
||||||
|
class decort_lb(DecortController):
|
||||||
|
def __init__(self,arg_amodule) -> None:
|
||||||
|
super(decort_lb,self).__init__(arg_amodule)
|
||||||
|
|
||||||
|
self.lb_id = 0
|
||||||
|
self.lb_facts = None
|
||||||
|
self.vins_id = 0
|
||||||
|
self.vins_facts = None
|
||||||
|
self.rg_id = 0
|
||||||
|
self.rg_facts = None
|
||||||
|
self.acc_id = 0
|
||||||
|
self.acc_facts = None
|
||||||
|
self.default_server_check = "enabled"
|
||||||
|
self.default_alg = "roundrobin"
|
||||||
|
self.default_settings = {
|
||||||
|
"downinter": 10000,
|
||||||
|
"fall": 2,
|
||||||
|
"inter": 5000,
|
||||||
|
"maxconn": 250,
|
||||||
|
"maxqueue": 256,
|
||||||
|
"rise": 2,
|
||||||
|
"slowstart": 60000,
|
||||||
|
"weight": 100,
|
||||||
|
}
|
||||||
|
if arg_amodule.params['lb_id']:
|
||||||
|
self.lb_id, self.lb_facts = self.lb_find(arg_amodule.params['lb_id'])
|
||||||
|
if not self.lb_id:
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['msg'] = "Specified LB ID {} not found."\
|
||||||
|
.format(arg_amodule.params['lb _id'])
|
||||||
|
self.fail_json(**self.result)
|
||||||
|
self.acc_id = self.lb_facts['accountId']
|
||||||
|
self.rg_id = self.lb_facts['rgId']
|
||||||
|
self.vins_id = self.lb_facts['vinsId']
|
||||||
|
return
|
||||||
|
|
||||||
|
if arg_amodule.params['rg_id']:
|
||||||
|
self.rg_id, self.rg_facts = self.rg_find(0,arg_amodule.params['rg_id'], arg_rg_name="")
|
||||||
|
if not self.rg_id:
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['msg'] = "Specified RG ID {} not found.".format(arg_amodule.params['vins_id'])
|
||||||
|
self.fail_json(**self.result)
|
||||||
|
|
||||||
|
if arg_amodule.params['vins_id']:
|
||||||
|
self.vins_id, self.vins_facts = self.vins_find(arg_amodule.params['vins_id'])
|
||||||
|
if not self.vins_id:
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['msg'] = "Specified ViNS ID {} not found.".format(arg_amodule.params['vins_id'])
|
||||||
|
self.fail_json(**self.result)
|
||||||
|
|
||||||
|
elif arg_amodule.params['account_id'] or arg_amodule.params['account_name'] != "":
|
||||||
|
|
||||||
|
if arg_amodule.params['rg_name']:
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['msg'] = ("RG name must be specified with account present")
|
||||||
|
self.fail_json(**self.result)
|
||||||
|
self.acc_id, self.acc_facts = self.account_find(arg_amodule.params['account_name'],
|
||||||
|
arg_amodule.params['account_id'])
|
||||||
|
if not self.acc_id:
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['msg'] = ("Current user does not have access to the requested account "
|
||||||
|
"or non-existent account specified.")
|
||||||
|
self.fail_json(**self.result)
|
||||||
|
self.rg_id, self.rg_facts = self.rg_find(self._acc_id,0, arg_rg_name=arg_amodule.params['rg_name'])
|
||||||
|
|
||||||
|
if self.rg_id and self.vins_id:
|
||||||
|
self.lb_id, self.lb_facts = self.lb_find(0,arg_amodule.params['lb_name'],self.rg_id)
|
||||||
|
return
|
||||||
|
|
||||||
|
def create(self):
|
||||||
|
self.lb_id = self.lb_provision(self.amodule.params['lb_name'],
|
||||||
|
self.rg_id,self.vins_id,
|
||||||
|
self.amodule.params['ext_net_id'],
|
||||||
|
self.amodule.params['annotation'])
|
||||||
|
if self.amodule.params['backends'] or self.amodule.params['frontends']:
|
||||||
|
self.lb_id, self.lb_facts = self.lb_find(0,self.amodule.params['lb_name'],self.rg_id)
|
||||||
|
self.lb_update(
|
||||||
|
self.lb_facts['backends'],
|
||||||
|
self.lb_facts['frontends'],
|
||||||
|
self.amodule.params['backends'],
|
||||||
|
self.amodule.params['servers'],
|
||||||
|
self.amodule.params['frontends']
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def action(self,d_state='',restore=False):
|
||||||
|
if restore == True:
|
||||||
|
self.lb_restore(arg_vins_id=self.lb_id)
|
||||||
|
self.lb_state(self.vins_facts, 'enabled')
|
||||||
|
self.lb_facts['status'] = "ENABLED"
|
||||||
|
self.lb_facts['techStatus'] = "STARTED"
|
||||||
|
|
||||||
|
self.lb_update(
|
||||||
|
self.lb_facts['backends'],
|
||||||
|
self.lb_facts['frontends'],
|
||||||
|
self.amodule.params['backends'],
|
||||||
|
self.amodule.params['servers'],
|
||||||
|
self.amodule.params['frontends']
|
||||||
|
)
|
||||||
|
|
||||||
|
if d_state != '':
|
||||||
|
self.lb_state(self.lb_facts, d_state)
|
||||||
|
return
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
self.lb_delete(self.lb_id, self.amodule.params['permanently'])
|
||||||
|
self.lb_facts['status'] = 'DESTROYED'
|
||||||
|
return
|
||||||
|
def nop(self):
|
||||||
|
"""No operation (NOP) handler for LB management by decort_lb module.
|
||||||
|
This function is intended to be called from the main switch construct of the module
|
||||||
|
when current state -> desired state change logic does not require any changes to
|
||||||
|
the actual LB state.
|
||||||
|
"""
|
||||||
|
self.result['failed'] = False
|
||||||
|
self.result['changed'] = False
|
||||||
|
if self.lb_id:
|
||||||
|
self.result['msg'] = ("No state change required for LB ID {} because of its "
|
||||||
|
"current status '{}'.").format(self.lb_id, self.vins_facts['status'])
|
||||||
|
else:
|
||||||
|
self.result['msg'] = ("No state change to '{}' can be done for "
|
||||||
|
"non-existent LB instance.").format(self.amodule.params['state'])
|
||||||
|
return
|
||||||
|
def error(self):
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['changed'] = False
|
||||||
|
if self.vins_id:
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['changed'] = False
|
||||||
|
self.result['msg'] = ("Invalid target state '{}' requested for LB ID {} in the "
|
||||||
|
"current status '{}'").format(self.lb_id,
|
||||||
|
self.amodule.params['state'],
|
||||||
|
self.lb_facts['status'])
|
||||||
|
else:
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['changed'] = False
|
||||||
|
self.result['msg'] = ("Invalid target state '{}' requested for non-existent "
|
||||||
|
"LB name '{}'").format(self.amodule.params['state'],
|
||||||
|
self.amodule.params['lb_name'])
|
||||||
|
return
|
||||||
|
def package_facts(self, arg_check_mode=False):
|
||||||
|
"""Package a dictionary of LB facts according to the decort_lb module specification.
|
||||||
|
This dictionary will be returned to the upstream Ansible engine at the completion of
|
||||||
|
the module run.
|
||||||
|
|
||||||
|
@param arg_check_mode: boolean that tells if this Ansible module is run in check mode
|
||||||
|
"""
|
||||||
|
|
||||||
|
ret_dict = dict(id=0,
|
||||||
|
name="none",
|
||||||
|
state="CHECK_MODE",
|
||||||
|
)
|
||||||
|
|
||||||
|
if arg_check_mode:
|
||||||
|
# in check mode return immediately with the default values
|
||||||
|
return ret_dict
|
||||||
|
|
||||||
|
if self.vins_facts is None:
|
||||||
|
# if void facts provided - change state value to ABSENT and return
|
||||||
|
ret_dict['state'] = "ABSENT"
|
||||||
|
return ret_dict
|
||||||
|
|
||||||
|
ret_dict['id'] = self.lb_facts['id']
|
||||||
|
ret_dict['name'] = self.lb_facts['name']
|
||||||
|
ret_dict['state'] = self.lb_facts['status']
|
||||||
|
#ret_dict['account_id'] = self.lb_facts['accountId']
|
||||||
|
ret_dict['rg_id'] = self.lb_facts['rgId']
|
||||||
|
ret_dict['gid'] = self.lb_facts['gid']
|
||||||
|
if self.amodule.params['state']!="absent":
|
||||||
|
ret_dict['backends'] = self.lb_facts['backends']
|
||||||
|
ret_dict['frontends'] = self.lb_facts['frontends']
|
||||||
|
return ret_dict
|
||||||
|
@staticmethod
|
||||||
|
def build_parameters():
|
||||||
|
"""Build and return a dictionary of parameters expected by decort_vins module in a form accepted
|
||||||
|
by AnsibleModule utility class."""
|
||||||
|
|
||||||
|
return dict(
|
||||||
|
account_id=dict(type='int', required=False),
|
||||||
|
account_name=dict(type='str', required=False, default=''),
|
||||||
|
annotation=dict(type='str', required=False, default='Managed by Ansible module decort_lb'),
|
||||||
|
app_id=dict(type='str',
|
||||||
|
required=False,
|
||||||
|
fallback=(env_fallback, ['DECORT_APP_ID'])),
|
||||||
|
app_secret=dict(type='str',
|
||||||
|
required=False,
|
||||||
|
fallback=(env_fallback, ['DECORT_APP_SECRET']),
|
||||||
|
no_log=True),
|
||||||
|
authenticator=dict(type='str',
|
||||||
|
required=True,
|
||||||
|
choices=['legacy', 'oauth2', 'jwt']),
|
||||||
|
controller_url=dict(type='str', required=True),
|
||||||
|
# datacenter=dict(type='str', required=False, default=''),
|
||||||
|
ext_net_id=dict(type='int', required=False, default=-1),
|
||||||
|
ext_ip_addr=dict(type='str', required=False, default=''),
|
||||||
|
jwt=dict(type='str',
|
||||||
|
required=False,
|
||||||
|
fallback=(env_fallback, ['DECORT_JWT']),
|
||||||
|
no_log=True),
|
||||||
|
oauth2_url=dict(type='str',
|
||||||
|
required=False,
|
||||||
|
fallback=(env_fallback, ['DECORT_OAUTH2_URL'])),
|
||||||
|
password=dict(type='str',
|
||||||
|
required=False,
|
||||||
|
fallback=(env_fallback, ['DECORT_PASSWORD']),
|
||||||
|
no_log=True),
|
||||||
|
state=dict(type='str',
|
||||||
|
default='present',
|
||||||
|
choices=['absent', 'disabled', 'enabled', 'present','restart']),
|
||||||
|
user=dict(type='str',
|
||||||
|
required=False,
|
||||||
|
fallback=(env_fallback, ['DECORT_USER'])),
|
||||||
|
rg_id=dict(type='int', required=False, default=0),
|
||||||
|
rg_name=dict(type='str', required=False, default=''),
|
||||||
|
vins_name=dict(type='str', required=False, default=''),
|
||||||
|
vins_id=dict(type='int', required=False, default=0),
|
||||||
|
verify_ssl=dict(type='bool', required=False, default=True),
|
||||||
|
lb_id=dict(type='int', required=False, default=0),
|
||||||
|
lb_name=dict(type='str', required=True),
|
||||||
|
backends=dict(type='list',required=False,default=[]),
|
||||||
|
frontends=dict(type='list',required=False,default=[]),
|
||||||
|
servers=dict(type='list',required=False,default=[]),
|
||||||
|
permanently=dict(type='bool', required=False, default=False),
|
||||||
|
workflow_callback=dict(type='str', required=False),
|
||||||
|
workflow_context=dict(type='str', required=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
module_parameters = decort_lb.build_parameters()
|
||||||
|
|
||||||
|
amodule = AnsibleModule(argument_spec=module_parameters,
|
||||||
|
supports_check_mode=True,
|
||||||
|
mutually_exclusive=[
|
||||||
|
['oauth2', 'password'],
|
||||||
|
['password', 'jwt'],
|
||||||
|
['jwt', 'oauth2'],
|
||||||
|
],
|
||||||
|
required_together=[
|
||||||
|
['app_id', 'app_secret'],
|
||||||
|
['user', 'password']
|
||||||
|
],
|
||||||
|
required_one_of=[
|
||||||
|
['rg_id','rg_name'],
|
||||||
|
['lb_id','lb_name'],
|
||||||
|
['vins_id','vins_name']
|
||||||
|
]
|
||||||
|
)
|
||||||
|
decon = decort_lb(amodule)
|
||||||
|
if decon.lb_id:
|
||||||
|
if decon.lb_facts['status'] in ["MODELED", "DISABLING", "ENABLING", "DELETING","DESTROYING","RESTORING"]:
|
||||||
|
decon.result['failed'] = True
|
||||||
|
decon.result['changed'] = False
|
||||||
|
decon.result['msg'] = ("No change can be done for existing LB ID {} because of its current "
|
||||||
|
"status '{}'").format(decon.lb_id, decon.lb_facts['status'])
|
||||||
|
elif decon.lb_facts['status'] == "DISABLED":
|
||||||
|
if amodule.params['state'] == 'absent':
|
||||||
|
decon.delete()
|
||||||
|
elif amodule.params['state'] in ('present', 'disabled'):
|
||||||
|
decon.action()
|
||||||
|
elif amodule.params['state'] == 'enabled':
|
||||||
|
decon.action('enabled')
|
||||||
|
elif decon.lb_facts['status'] in ["CREATED", "ENABLED"]:
|
||||||
|
if amodule.params['state'] == 'absent':
|
||||||
|
decon.delete()
|
||||||
|
elif amodule.params['state'] in ('present', 'enabled'):
|
||||||
|
decon.action()
|
||||||
|
elif amodule.params['state'] == 'disabled':
|
||||||
|
decon.action('disabled')
|
||||||
|
elif amodule.params['state'] in ('stopped', 'started','restart'):
|
||||||
|
decon.action(amodule.params['state'])
|
||||||
|
elif decon.lb_facts['status'] == "DELETED":
|
||||||
|
if amodule.params['state'] in ['present', 'enabled']:
|
||||||
|
decon.action(restore=True)
|
||||||
|
elif amodule.params['state'] == 'absent':
|
||||||
|
decon.delete()
|
||||||
|
elif amodule.params['state'] == 'disabled':
|
||||||
|
decon.error()
|
||||||
|
elif decon.lb_facts['status'] == "DESTROYED":
|
||||||
|
if amodule.params['state'] in ('present', 'enabled'):
|
||||||
|
decon.create()
|
||||||
|
elif amodule.params['state'] == 'absent':
|
||||||
|
decon.nop()
|
||||||
|
elif amodule.params['state'] == 'disabled':
|
||||||
|
decon.error()
|
||||||
|
else:
|
||||||
|
if amodule.params['state'] == 'absent':
|
||||||
|
decon.nop()
|
||||||
|
elif amodule.params['state'] in ('present', 'enabled'):
|
||||||
|
decon.create()
|
||||||
|
elif amodule.params['state'] == 'disabled':
|
||||||
|
decon.error()
|
||||||
|
|
||||||
|
if decon.result['failed']:
|
||||||
|
amodule.fail_json(**decon.result)
|
||||||
|
else:
|
||||||
|
if decon.result['changed'] and amodule.params['state'] != 'absent':
|
||||||
|
_, decon.lb_facts = decon.lb_find(decon.lb_id)
|
||||||
|
if decon.lb_id:
|
||||||
|
decon.result['facts'] = decon.package_facts(amodule.check_mode)
|
||||||
|
amodule.exit_json(**decon.result)
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -242,17 +242,185 @@ facts:
|
|||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils.basic import env_fallback
|
from ansible.module_utils.basic import env_fallback
|
||||||
import paramiko
|
|
||||||
|
|
||||||
from ansible.module_utils.decort_utils import *
|
from ansible.module_utils.decort_utils import *
|
||||||
|
|
||||||
|
class decort_vins(DecortController):
|
||||||
|
def __init__(self,arg_amodule):
|
||||||
|
super(decort_vins, self).__init__(arg_amodule)
|
||||||
|
|
||||||
def decort_vins_package_facts(arg_vins_facts, arg_check_mode=False):
|
self.vins_id = 0
|
||||||
|
self.vins_level = "" # "ID" if specified by ID, "RG" - at resource group, "ACC" - at account level
|
||||||
|
vins_facts = None # will hold ViNS facts
|
||||||
|
validated_rg_id = 0
|
||||||
|
rg_facts = None # will hold RG facts
|
||||||
|
validated_acc_id = 0
|
||||||
|
acc_facts = None # will hold Account facts
|
||||||
|
|
||||||
|
if arg_amodule.params['vins_id']:
|
||||||
|
# expect existing ViNS with the specified ID
|
||||||
|
# This call to vins_find will abort the module if no ViNS with such ID is present
|
||||||
|
self.vins_id, self.vins_facts = self.vins_find(arg_amodule.params['vins_id'])
|
||||||
|
if not self.vins_id:
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['msg'] = "Specified ViNS ID {} not found.".format(arg_amodule.params['vins_id'])
|
||||||
|
self.fail_json(**self.result)
|
||||||
|
self.vins_level = "ID"
|
||||||
|
validated_acc_id = vins_facts['accountId']
|
||||||
|
validated_rg_id = vins_facts['rgId']
|
||||||
|
|
||||||
|
elif arg_amodule.params['rg_id']:
|
||||||
|
# expect ViNS @ RG level in the RG with specified ID
|
||||||
|
self.vins_level = "RG"
|
||||||
|
# This call to rg_find will abort the module if no RG with such ID is present
|
||||||
|
validated_rg_id, rg_facts = self.rg_find(0, # account ID set to 0 as we search for RG by RG ID
|
||||||
|
arg_amodule.params['rg_id'], arg_rg_name="")
|
||||||
|
|
||||||
|
# This call to vins_find may return vins_id=0 if no ViNS found
|
||||||
|
self.vins_id, self.vins_facts = self.vins_find(vins_id=0, vins_name=arg_amodule.params['vins_name'],
|
||||||
|
account_id=0,
|
||||||
|
rg_id=arg_amodule.params['rg_id'],
|
||||||
|
rg_facts=rg_facts,
|
||||||
|
check_state=False)
|
||||||
|
# TODO: add checks and setup ViNS presence flags accordingly
|
||||||
|
pass
|
||||||
|
elif arg_amodule.params['account_id'] or arg_amodule.params['account_name'] != "":
|
||||||
|
# Specified account must be present and accessible by the user, otherwise abort the module
|
||||||
|
validated_acc_id, acc_facts = self.account_find(arg_amodule.params['account_name'], arg_amodule.params['account_id'])
|
||||||
|
if not validated_acc_id:
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['msg'] = ("Current user does not have access to the requested account "
|
||||||
|
"or non-existent account specified.")
|
||||||
|
self.fail_json(**self.result)
|
||||||
|
if arg_amodule.params['rg_name'] != "": # at this point we know that rg_id=0
|
||||||
|
# expect ViNS @ RG level in the RG with specified name under specified account
|
||||||
|
# RG with the specified name must be present under the account, otherwise abort the module
|
||||||
|
validated_rg_id, rg_facts = self.rg_find(validated_acc_id, 0, arg_amodule.params['rg_name'])
|
||||||
|
if (not validated_rg_id or
|
||||||
|
rg_facts['status'] in ["DESTROYING", "DESTROYED", "DELETING", "DELETED", "DISABLING", "ENABLING"]):
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['msg'] = "RG name '{}' not found or has invalid state.".format(arg_amodule.params['rg_name'])
|
||||||
|
self.fail_json(**self.result)
|
||||||
|
# This call to vins_find may return vins_id=0 if no ViNS with this name found under specified RG
|
||||||
|
self.vins_id, self.vins_facts = self.vins_find(vins_id=0, vins_name=arg_amodule.params['vins_name'],
|
||||||
|
account_id=0, # set to 0, as we are looking for ViNS under RG
|
||||||
|
rg_id=validated_rg_id,
|
||||||
|
rg_facts=rg_facts,
|
||||||
|
check_state=False)
|
||||||
|
self.vins_level = "RG"
|
||||||
|
# TODO: add checks and setup ViNS presence flags accordingly
|
||||||
|
else: # At this point we know for sure that rg_name="" and rg_id=0
|
||||||
|
# So we expect ViNS @ account level
|
||||||
|
# This call to vins_find may return vins_id=0 if no ViNS found
|
||||||
|
self.vins_id, self.vins_facts = self.vins_find(vins_id=0, vins_name=arg_amodule.params['vins_name'],
|
||||||
|
account_id=validated_acc_id,
|
||||||
|
rg_id=0,
|
||||||
|
rg_facts=rg_facts,
|
||||||
|
check_state=False)
|
||||||
|
self.vins_level = "ACC"
|
||||||
|
# TODO: add checks and setup ViNS presence flags accordingly
|
||||||
|
else:
|
||||||
|
# this is "invalid arguments combination" sink
|
||||||
|
# if we end up here, it means that module was invoked with vins_id=0 and rg_id=0
|
||||||
|
self.result['failed'] = True
|
||||||
|
if arg_amodule.params['account_id'] == 0 and arg_amodule.params['account_name'] == "":
|
||||||
|
self.result['msg'] = "Cannot find ViNS by name when account name is empty and account ID is 0."
|
||||||
|
if arg_amodule.params['rg_name'] == "":
|
||||||
|
# rg_name without account specified
|
||||||
|
self.result['msg'] = "Cannot find ViNS by name when RG name is empty and RG ID is 0."
|
||||||
|
self.fail_json(**self.result)
|
||||||
|
|
||||||
|
return
|
||||||
|
self.rg_id = validated_rg_id
|
||||||
|
self.acc_id = validated_acc_id
|
||||||
|
return
|
||||||
|
def create(self):
|
||||||
|
self.vins_id = self.vins_provision(self.amodule.params['vins_name'],
|
||||||
|
self.acc_id, self.rg_id,
|
||||||
|
self.amodule.params['ipcidr'],
|
||||||
|
self.amodule.params['ext_net_id'], self.amodule.params['ext_ip_addr'],
|
||||||
|
self.amodule.params['annotation'])
|
||||||
|
|
||||||
|
if self.amodule.params['mgmtaddr'] or self.amodule.params['connect_to']:
|
||||||
|
_, self.vins_facts = self.vins_find(self.vins_id)
|
||||||
|
if self.amodule.params['connect_to']:
|
||||||
|
self.vins_update_ifaces(self.vins_facts,self.amodule.params['connect_to'],)
|
||||||
|
if self.amodule.params['mgmtaddr']:
|
||||||
|
self.vins_update_mgmt(self.vins_facts,self.amodule.params['mgmtaddr'])
|
||||||
|
|
||||||
|
return
|
||||||
|
def action(self,d_state='',restore=False):
|
||||||
|
if restore == True:
|
||||||
|
self.vins_restore(arg_vins_id=self.vins_id)
|
||||||
|
self.vins_state(self.vins_facts, 'enabled')
|
||||||
|
self.vins_facts['status'] = "ENABLED"
|
||||||
|
self.vins_facts['VNFDev']['techStatus'] = "STARTED"
|
||||||
|
|
||||||
|
self.vins_update_extnet(self.vins_facts,
|
||||||
|
self.amodule.params['ext_net_id'],
|
||||||
|
self.amodule.params['ext_ip_addr'],
|
||||||
|
)
|
||||||
|
|
||||||
|
if d_state == 'enabled' and self.vins_facts['status'] == "DISABLED":
|
||||||
|
self.vins_state(self.vins_facts, d_state)
|
||||||
|
self.vins_facts['status'] = "ENABLED"
|
||||||
|
self.vins_facts['VNFDev']['techStatus'] = "STARTED"
|
||||||
|
d_state = ''
|
||||||
|
|
||||||
|
if self.vins_facts['status'] == "ENABLED" and self.vins_facts['VNFDev']['techStatus'] == "STARTED":
|
||||||
|
self.vins_update_ifaces(self.vins_facts,
|
||||||
|
self.amodule.params['connect_to'],
|
||||||
|
)
|
||||||
|
if self.result['changed']:
|
||||||
|
_, self.vins_facts = self.vins_find(self.vins_id)
|
||||||
|
self.vins_update_mgmt(self.vins_facts,
|
||||||
|
self.amodule.params['mgmtaddr'],
|
||||||
|
)
|
||||||
|
|
||||||
|
if d_state != '':
|
||||||
|
self.vins_state(self.vins_facts, d_state)
|
||||||
|
return
|
||||||
|
def delete(self):
|
||||||
|
self.vins_delete(self.vins_id, permanently=True)
|
||||||
|
self.vins_facts['status'] = 'DESTROYED'
|
||||||
|
return
|
||||||
|
def nop(self):
|
||||||
|
"""No operation (NOP) handler for ViNS management by decort_vins module.
|
||||||
|
This function is intended to be called from the main switch construct of the module
|
||||||
|
when current state -> desired state change logic does not require any changes to
|
||||||
|
the actual ViNS state.
|
||||||
|
"""
|
||||||
|
self.result['failed'] = False
|
||||||
|
self.result['changed'] = False
|
||||||
|
if self.vins_id:
|
||||||
|
self.result['msg'] = ("No state change required for ViNS ID {} because of its "
|
||||||
|
"current status '{}'.").format(self.vins_id, self.vins_facts['status'])
|
||||||
|
else:
|
||||||
|
self.result['msg'] = ("No state change to '{}' can be done for "
|
||||||
|
"non-existent ViNS instance.").format(self.amodule.params['state'])
|
||||||
|
return
|
||||||
|
def error(self):
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['changed'] = False
|
||||||
|
if self.vins_id:
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['changed'] = False
|
||||||
|
self.result['msg'] = ("Invalid target state '{}' requested for ViNS ID {} in the "
|
||||||
|
"current status '{}'").format(self.vins_id,
|
||||||
|
self.amodule.params['state'],
|
||||||
|
self.vins_facts['status'])
|
||||||
|
else:
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['changed'] = False
|
||||||
|
self.result['msg'] = ("Invalid target state '{}' requested for non-existent "
|
||||||
|
"ViNS name '{}'").format(self.amodule.params['state'],
|
||||||
|
self.amodule.params['vins_name'])
|
||||||
|
return
|
||||||
|
def package_facts(self, arg_check_mode=False):
|
||||||
"""Package a dictionary of ViNS facts according to the decort_vins module specification.
|
"""Package a dictionary of ViNS facts according to the decort_vins module specification.
|
||||||
This dictionary will be returned to the upstream Ansible engine at the completion of
|
This dictionary will be returned to the upstream Ansible engine at the completion of
|
||||||
the module run.
|
the module run.
|
||||||
|
|
||||||
@param arg_vins_facts: dictionary with viNS facts as returned by API call to .../vins/get
|
|
||||||
@param arg_check_mode: boolean that tells if this Ansible module is run in check mode
|
@param arg_check_mode: boolean that tells if this Ansible module is run in check mode
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -265,21 +433,32 @@ def decort_vins_package_facts(arg_vins_facts, arg_check_mode=False):
|
|||||||
# in check mode return immediately with the default values
|
# in check mode return immediately with the default values
|
||||||
return ret_dict
|
return ret_dict
|
||||||
|
|
||||||
if arg_vins_facts is None:
|
if self.vins_facts is None:
|
||||||
# if void facts provided - change state value to ABSENT and return
|
# if void facts provided - change state value to ABSENT and return
|
||||||
ret_dict['state'] = "ABSENT"
|
ret_dict['state'] = "ABSENT"
|
||||||
return ret_dict
|
return ret_dict
|
||||||
|
|
||||||
ret_dict['id'] = arg_vins_facts['id']
|
ret_dict['id'] = self.vins_facts['id']
|
||||||
ret_dict['name'] = arg_vins_facts['name']
|
ret_dict['name'] = self.vins_facts['name']
|
||||||
ret_dict['state'] = arg_vins_facts['status']
|
ret_dict['state'] = self.vins_facts['status']
|
||||||
ret_dict['account_id'] = arg_vins_facts['accountId']
|
ret_dict['account_id'] = self.vins_facts['accountId']
|
||||||
ret_dict['rg_id'] = arg_vins_facts['rgId']
|
ret_dict['rg_id'] = self.vins_facts['rgId']
|
||||||
ret_dict['int_net_addr'] = arg_vins_facts['network']
|
ret_dict['int_net_addr'] = self.vins_facts['network']
|
||||||
ret_dict['gid'] = arg_vins_facts['gid']
|
ret_dict['gid'] = self.vins_facts['gid']
|
||||||
|
custom_interfaces = list(filter(lambda i: i['type']=="CUSTOM",self.vins_facts['VNFDev']['interfaces']))
|
||||||
if arg_vins_facts['vnfs'].get('GW'):
|
if custom_interfaces:
|
||||||
gw_config = arg_vins_facts['vnfs']['GW']['config']
|
ret_dict['custom_net_addr'] = []
|
||||||
|
for runner in custom_interfaces:
|
||||||
|
ret_dict['custom_net_addr'].append(runner['ipAddress'])
|
||||||
|
mgmt_interfaces = list(filter(lambda i: i['listenSsh'] and i['name']!="ens9",self.vins_facts['VNFDev']['interfaces']))
|
||||||
|
if mgmt_interfaces:
|
||||||
|
ret_dict['ssh_ipaddr'] = []
|
||||||
|
for runner in mgmt_interfaces:
|
||||||
|
ret_dict['ssh_ipaddr'].append(runner['ipAddress'])
|
||||||
|
ret_dict['ssh_password'] = self.vins_facts['VNFDev']['config']['mgmt']['password']
|
||||||
|
ret_dict['ssh_port'] = 9022
|
||||||
|
if self.vins_facts['vnfs'].get('GW'):
|
||||||
|
gw_config = self.vins_facts['vnfs']['GW']['config']
|
||||||
ret_dict['ext_ip_addr'] = gw_config['ext_net_ip']
|
ret_dict['ext_ip_addr'] = gw_config['ext_net_ip']
|
||||||
ret_dict['ext_net_id'] = gw_config['ext_net_id']
|
ret_dict['ext_net_id'] = gw_config['ext_net_id']
|
||||||
else:
|
else:
|
||||||
@@ -293,8 +472,8 @@ def decort_vins_package_facts(arg_vins_facts, arg_check_mode=False):
|
|||||||
|
|
||||||
return ret_dict
|
return ret_dict
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
def decort_vins_parameters():
|
def build_parameters():
|
||||||
"""Build and return a dictionary of parameters expected by decort_vins module in a form accepted
|
"""Build and return a dictionary of parameters expected by decort_vins module in a form accepted
|
||||||
by AnsibleModule utility class."""
|
by AnsibleModule utility class."""
|
||||||
|
|
||||||
@@ -317,7 +496,7 @@ def decort_vins_parameters():
|
|||||||
ext_net_id=dict(type='int', required=False, default=-1),
|
ext_net_id=dict(type='int', required=False, default=-1),
|
||||||
ext_ip_addr=dict(type='str', required=False, default=''),
|
ext_ip_addr=dict(type='str', required=False, default=''),
|
||||||
ipcidr=dict(type='str', required=False, default=''),
|
ipcidr=dict(type='str', required=False, default=''),
|
||||||
mgmtaddr=dict(type='str',required=False, default=''),
|
mgmtaddr=dict(type='list',required=False, default=[]),
|
||||||
custom_config=dict(type='bool',required=False, default=False),
|
custom_config=dict(type='bool',required=False, default=False),
|
||||||
config_save=dict(type='bool',required=False, default=False),
|
config_save=dict(type='bool',required=False, default=False),
|
||||||
connect_to=dict(type='list', default=[], required=False),
|
connect_to=dict(type='list', default=[], required=False),
|
||||||
@@ -356,7 +535,7 @@ def decort_vins_parameters():
|
|||||||
# 5) report result to Ansible
|
# 5) report result to Ansible
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
module_parameters = decort_vins_parameters()
|
module_parameters = decort_vins.build_parameters()
|
||||||
|
|
||||||
amodule = AnsibleModule(argument_spec=module_parameters,
|
amodule = AnsibleModule(argument_spec=module_parameters,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
@@ -371,84 +550,7 @@ def main():
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
decon = DecortController(amodule)
|
decon = decort_vins(amodule)
|
||||||
|
|
||||||
vins_id = 0
|
|
||||||
vins_level = "" # "ID" if specified by ID, "RG" - at resource group, "ACC" - at account level
|
|
||||||
vins_facts = None # will hold ViNS facts
|
|
||||||
validated_rg_id = 0
|
|
||||||
rg_facts = None # will hold RG facts
|
|
||||||
validated_acc_id = 0
|
|
||||||
acc_facts = None # will hold Account facts
|
|
||||||
|
|
||||||
if amodule.params['vins_id']:
|
|
||||||
# expect existing ViNS with the specified ID
|
|
||||||
# This call to vins_find will abort the module if no ViNS with such ID is present
|
|
||||||
vins_id, vins_facts = decon.vins_find(amodule.params['vins_id'])
|
|
||||||
if not vins_id:
|
|
||||||
decon.result['failed'] = True
|
|
||||||
decon.result['msg'] = "Specified ViNS ID {} not found.".format(amodule.params['vins_id'])
|
|
||||||
decon.fail_json(**decon.result)
|
|
||||||
vins_level = "ID"
|
|
||||||
validated_acc_id = vins_facts['accountId']
|
|
||||||
validated_rg_id = vins_facts['rgId']
|
|
||||||
|
|
||||||
elif amodule.params['rg_id']:
|
|
||||||
# expect ViNS @ RG level in the RG with specified ID
|
|
||||||
vins_level = "RG"
|
|
||||||
# This call to rg_find will abort the module if no RG with such ID is present
|
|
||||||
validated_rg_id, rg_facts = decon.rg_find(0, # account ID set to 0 as we search for RG by RG ID
|
|
||||||
amodule.params['rg_id'], arg_rg_name="")
|
|
||||||
# This call to vins_find may return vins_id=0 if no ViNS found
|
|
||||||
vins_id, vins_facts = decon.vins_find(vins_id=0, vins_name=amodule.params['vins_name'],
|
|
||||||
account_id=0,
|
|
||||||
rg_id=amodule.params['rg_id'],
|
|
||||||
check_state=False)
|
|
||||||
# TODO: add checks and setup ViNS presence flags accordingly
|
|
||||||
pass
|
|
||||||
elif amodule.params['account_id'] or amodule.params['account_name'] != "":
|
|
||||||
# Specified account must be present and accessible by the user, otherwise abort the module
|
|
||||||
validated_acc_id, acc_facts = decon.account_find(amodule.params['account_name'], amodule.params['account_id'])
|
|
||||||
if not validated_acc_id:
|
|
||||||
decon.result['failed'] = True
|
|
||||||
decon.result['msg'] = ("Current user does not have access to the requested account "
|
|
||||||
"or non-existent account specified.")
|
|
||||||
decon.fail_json(**decon.result)
|
|
||||||
if amodule.params['rg_name'] != "": # at this point we know that rg_id=0
|
|
||||||
# expect ViNS @ RG level in the RG with specified name under specified account
|
|
||||||
# RG with the specified name must be present under the account, otherwise abort the module
|
|
||||||
validated_rg_id, rg_facts = decon.rg_find(validated_acc_id, 0, amodule.params['rg_name'])
|
|
||||||
if (not validated_rg_id or
|
|
||||||
rg_facts['status'] in ["DESTROYING", "DESTROYED", "DELETING", "DELETED", "DISABLING", "ENABLING"]):
|
|
||||||
decon.result['failed'] = True
|
|
||||||
decon.result['msg'] = "RG name '{}' not found or has invalid state.".format(amodule.params['rg_name'])
|
|
||||||
decon.fail_json(**decon.result)
|
|
||||||
# This call to vins_find may return vins_id=0 if no ViNS with this name found under specified RG
|
|
||||||
vins_id, vins_facts = decon.vins_find(vins_id=0, vins_name=amodule.params['vins_name'],
|
|
||||||
account_id=0, # set to 0, as we are looking for ViNS under RG
|
|
||||||
rg_id=validated_rg_id,
|
|
||||||
check_state=False)
|
|
||||||
vins_level = "RG"
|
|
||||||
# TODO: add checks and setup ViNS presence flags accordingly
|
|
||||||
else: # At this point we know for sure that rg_name="" and rg_id=0
|
|
||||||
# So we expect ViNS @ account level
|
|
||||||
# This call to vins_find may return vins_id=0 if no ViNS found
|
|
||||||
vins_id, vins_facts = decon.vins_find(vins_id=0, vins_name=amodule.params['vins_name'],
|
|
||||||
account_id=validated_acc_id,
|
|
||||||
rg_id=0,
|
|
||||||
check_state=False)
|
|
||||||
vins_level = "ACC"
|
|
||||||
# TODO: add checks and setup ViNS presence flags accordingly
|
|
||||||
else:
|
|
||||||
# this is "invalid arguments combination" sink
|
|
||||||
# if we end up here, it means that module was invoked with vins_id=0 and rg_id=0
|
|
||||||
decon.result['failed'] = True
|
|
||||||
if amodule.params['account_id'] == 0 and amodule.params['account_name'] == "":
|
|
||||||
decon.result['msg'] = "Cannot find ViNS by name when account name is empty and account ID is 0."
|
|
||||||
if amodule.params['rg_name'] == "":
|
|
||||||
# rg_name without account specified
|
|
||||||
decon.result['msg'] = "Cannot find ViNS by name when RG name is empty and RG ID is 0."
|
|
||||||
decon.fail_json(**decon.result)
|
|
||||||
#
|
#
|
||||||
# Initial validation of module arguments is complete
|
# Initial validation of module arguments is complete
|
||||||
#
|
#
|
||||||
@@ -465,127 +567,70 @@ def main():
|
|||||||
# if cconfig_save is true, only config save without other updates
|
# if cconfig_save is true, only config save without other updates
|
||||||
vins_should_exist = False
|
vins_should_exist = False
|
||||||
|
|
||||||
if vins_id:
|
if decon.vins_id:
|
||||||
vins_should_exist = True
|
vins_should_exist = True
|
||||||
if vins_facts['status'] in ["MODELED", "DISABLING", "ENABLING", "DELETING", "DESTROYING"]:
|
if decon.vins_facts['status'] in ["MODELED", "DISABLING", "ENABLING", "DELETING", "DESTROYING"]:
|
||||||
# error: nothing can be done to existing ViNS in the listed statii regardless of
|
# error: nothing can be done to existing ViNS in the listed statii regardless of
|
||||||
# the requested state
|
# the requested state
|
||||||
decon.result['failed'] = True
|
decon.result['failed'] = True
|
||||||
decon.result['changed'] = False
|
decon.result['changed'] = False
|
||||||
decon.result['msg'] = ("No change can be done for existing ViNS ID {} because of its current "
|
decon.result['msg'] = ("No change can be done for existing ViNS ID {} because of its current "
|
||||||
"status '{}'").format(vins_id, vins_facts['status'])
|
"status '{}'").format(decon.vins_id, decon.vins_facts['status'])
|
||||||
elif vins_facts['status'] == "DISABLED":
|
elif decon.vins_facts['status'] == "DISABLED":
|
||||||
if amodule.params['state'] == 'absent':
|
if amodule.params['state'] == 'absent':
|
||||||
decon.vins_delete(vins_id, permanently=True)
|
decon.delete()
|
||||||
vins_facts['status'] = 'DESTROYED'
|
|
||||||
vins_should_exist = False
|
vins_should_exist = False
|
||||||
elif amodule.params['state'] in ('present', 'disabled'):
|
elif amodule.params['state'] in ('present', 'disabled'):
|
||||||
# update ViNS, leave in disabled state
|
# update ViNS, leave in disabled state
|
||||||
decon.vins_update(vins_facts,
|
decon.action()
|
||||||
amodule.params['ext_net_id'], amodule.params['ext_ip_addr'])
|
|
||||||
elif amodule.params['state'] == 'enabled':
|
elif amodule.params['state'] == 'enabled':
|
||||||
# update ViNS and enable
|
# update ViNS and enable
|
||||||
decon.vins_update(vins_facts,
|
decon.action('enabled')
|
||||||
amodule.params['ext_net_id'], amodule.params['ext_ip_addr'])
|
elif decon.vins_facts['status'] in ["CREATED", "ENABLED"]:
|
||||||
decon.vins_state(vins_facts, 'enabled')
|
|
||||||
elif vins_facts['status'] in ["CREATED", "ENABLED"]:
|
|
||||||
if amodule.params['state'] == 'absent':
|
if amodule.params['state'] == 'absent':
|
||||||
decon.vins_delete(vins_id, permanently=True)
|
decon.delete()
|
||||||
vins_facts['status'] = 'DESTROYED'
|
|
||||||
vins_should_exist = False
|
vins_should_exist = False
|
||||||
elif amodule.params['state'] in ('present', 'enabled'):
|
elif amodule.params['state'] in ('present', 'enabled'):
|
||||||
# update ViNS
|
# update ViNS
|
||||||
decon.vins_update(vins_facts,
|
decon.action()
|
||||||
amodule.params['ext_net_id'], amodule.params['ext_ip_addr'],
|
|
||||||
|
|
||||||
)
|
|
||||||
decon.vins_update_mgmt(
|
|
||||||
vins_facts,
|
|
||||||
amodule.params['mgmtaddr'],
|
|
||||||
)
|
|
||||||
decon.vins_update_ifaces(
|
|
||||||
vins_facts,
|
|
||||||
amodule.params['connect_to'],
|
|
||||||
)
|
|
||||||
elif amodule.params['state'] == 'disabled':
|
elif amodule.params['state'] == 'disabled':
|
||||||
# disable and update ViNS
|
# disable and update ViNS
|
||||||
decon.vins_state(vins_facts, 'disabled')
|
decon.action('disabled')
|
||||||
decon.vins_update(vins_facts,
|
elif decon.vins_facts['status'] == "DELETED":
|
||||||
amodule.params['ext_net_id'], amodule.params['ext_ip_addr'])
|
|
||||||
elif vins_facts['status'] == "DELETED":
|
|
||||||
if amodule.params['state'] in ['present', 'enabled']:
|
if amodule.params['state'] in ['present', 'enabled']:
|
||||||
# restore and enable
|
# restore and enable
|
||||||
decon.vins_restore(arg_vins_id=vins_id)
|
decon.action(restore=True)
|
||||||
decon.vins_state(vins_facts, 'enabled')
|
|
||||||
vins_should_exist = True
|
vins_should_exist = True
|
||||||
elif amodule.params['state'] == 'absent':
|
elif amodule.params['state'] == 'absent':
|
||||||
# destroy permanently
|
# destroy permanently
|
||||||
decon.vins_delete(vins_id, permanently=True)
|
decon.delete()
|
||||||
vins_facts['status'] = 'DESTROYED'
|
|
||||||
vins_should_exist = False
|
vins_should_exist = False
|
||||||
elif amodule.params['state'] == 'disabled':
|
elif amodule.params['state'] == 'disabled':
|
||||||
# error
|
decon.error()
|
||||||
decon.result['failed'] = True
|
|
||||||
decon.result['changed'] = False
|
|
||||||
decon.result['msg'] = ("Invalid target state '{}' requested for ViNS ID {} in the "
|
|
||||||
"current status '{}'").format(vins_id,
|
|
||||||
amodule.params['state'],
|
|
||||||
vins_facts['status'])
|
|
||||||
vins_should_exist = False
|
vins_should_exist = False
|
||||||
elif vins_facts['status'] == "DESTROYED":
|
elif decon.vins_facts['status'] == "DESTROYED":
|
||||||
if amodule.params['state'] in ('present', 'enabled'):
|
if amodule.params['state'] in ('present', 'enabled'):
|
||||||
# need to re-provision ViNS; some attributes may be changed, some stay the same.
|
# need to re-provision ViNS;
|
||||||
# account and RG - stays the same
|
decon.create()
|
||||||
# vins_name - stays the same
|
|
||||||
# IPcidr - take from module arguments
|
|
||||||
# ext IP address - take from module arguments
|
|
||||||
# annotation - take from module arguments
|
|
||||||
vins_id = decon.vins_provision(vins_facts['name'],
|
|
||||||
validated_acc_id, validated_rg_id,
|
|
||||||
amodule.params['ipcidr'],
|
|
||||||
amodule.params['ext_net_id'], amodule.params['ext_ip_addr'],
|
|
||||||
amodule.params['annotation'])
|
|
||||||
vins_should_exist = True
|
vins_should_exist = True
|
||||||
elif amodule.params['state'] == 'absent':
|
elif amodule.params['state'] == 'absent':
|
||||||
# nop
|
decon.nop()
|
||||||
decon.result['failed'] = False
|
|
||||||
decon.result['changed'] = False
|
|
||||||
decon.result['msg'] = ("No state change required for ViNS ID {} because of its "
|
|
||||||
"current status '{}'").format(vins_id,
|
|
||||||
vins_facts['status'])
|
|
||||||
vins_should_exist = False
|
vins_should_exist = False
|
||||||
elif amodule.params['state'] == 'disabled':
|
elif amodule.params['state'] == 'disabled':
|
||||||
# error
|
decon.error()
|
||||||
decon.result['failed'] = True
|
|
||||||
decon.result['changed'] = False
|
|
||||||
decon.result['msg'] = ("Invalid target state '{}' requested for ViNS ID {} in the "
|
|
||||||
"current status '{}'").format(vins_id,
|
|
||||||
amodule.params['state'],
|
|
||||||
vins_facts['status'])
|
|
||||||
else:
|
else:
|
||||||
# Preexisting ViNS was not found.
|
# Preexisting ViNS was not found.
|
||||||
vins_should_exist = False # we will change it back to True if ViNS is created or restored
|
vins_should_exist = False # we will change it back to True if ViNS is created or restored
|
||||||
# If requested state is 'absent' - nothing to do
|
# If requested state is 'absent' - nothing to do
|
||||||
if amodule.params['state'] == 'absent':
|
if amodule.params['state'] == 'absent':
|
||||||
decon.result['failed'] = False
|
decon.nop()
|
||||||
decon.result['changed'] = False
|
|
||||||
decon.result['msg'] = ("Nothing to do as target state 'absent' was requested for "
|
|
||||||
"non-existent ViNS name '{}'").format(amodule.params['vins_name'])
|
|
||||||
elif amodule.params['state'] in ('present', 'enabled'):
|
elif amodule.params['state'] in ('present', 'enabled'):
|
||||||
decon.check_amodule_argument('vins_name')
|
decon.check_amodule_argument('vins_name')
|
||||||
# as we already have account ID and RG ID we can create ViNS and get vins_id on success
|
# as we already have account ID and RG ID we can create ViNS and get vins_id on success
|
||||||
vins_id = decon.vins_provision(amodule.params['vins_name'],
|
decon.create()
|
||||||
validated_acc_id, validated_rg_id,
|
|
||||||
amodule.params['ipcidr'],
|
|
||||||
amodule.params['ext_net_id'], amodule.params['ext_ip_addr'],
|
|
||||||
amodule.params['annotation'])
|
|
||||||
vins_should_exist = True
|
vins_should_exist = True
|
||||||
elif amodule.params['state'] == 'disabled':
|
elif amodule.params['state'] == 'disabled':
|
||||||
decon.result['failed'] = True
|
decon.error()
|
||||||
decon.result['changed'] = False
|
|
||||||
decon.result['msg'] = ("Invalid target state '{}' requested for non-existent "
|
|
||||||
"ViNS name '{}'").format(amodule.params['state'],
|
|
||||||
amodule.params['vins_name'])
|
|
||||||
#
|
#
|
||||||
# conditional switch end - complete module run
|
# conditional switch end - complete module run
|
||||||
#
|
#
|
||||||
@@ -593,18 +638,9 @@ def main():
|
|||||||
amodule.fail_json(**decon.result)
|
amodule.fail_json(**decon.result)
|
||||||
else:
|
else:
|
||||||
# prepare ViNS facts to be returned as part of decon.result and then call exit_json(...)
|
# prepare ViNS facts to be returned as part of decon.result and then call exit_json(...)
|
||||||
if vins_should_exist:
|
|
||||||
if decon.result['changed']:
|
if decon.result['changed']:
|
||||||
# If we arrive here, there is a good chance that the ViNS is present - get fresh ViNS
|
_, decon.vins_facts = decon.vins_find(decon.vins_id)
|
||||||
# facts from # the cloud by ViNS ID.
|
decon.result['facts'] = decon.package_facts(amodule.check_mode)
|
||||||
# Otherwise, ViNS facts from previous call (when the ViNS was still in existence) will
|
|
||||||
# be returned.
|
|
||||||
_, vins_facts = decon.vins_find(vins_id)
|
|
||||||
decon.result['facts'] = decort_vins_package_facts(vins_facts, amodule.check_mode)
|
|
||||||
# add password to facts if mgmtaddr is present
|
|
||||||
# need reworking
|
|
||||||
if amodule.params['mgmtaddr'] != "":
|
|
||||||
decon.result['facts'].update({'password': vins_facts['VNFDev']['config']['mgmt']['password']})
|
|
||||||
amodule.exit_json(**decon.result)
|
amodule.exit_json(**decon.result)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ Requirements:
|
|||||||
- DECORT cloud platform version 3.6.1 or higher
|
- DECORT cloud platform version 3.6.1 or higher
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import copy
|
|
||||||
import json
|
import json
|
||||||
import jwt
|
import jwt
|
||||||
import netaddr
|
import netaddr
|
||||||
@@ -1207,7 +1206,7 @@ class DecortController(object):
|
|||||||
affinityLabel=label,)
|
affinityLabel=label,)
|
||||||
self.decort_api_call(requests.post, "/restmachine/cloudapi/compute/affinityLabelSet", api_params)
|
self.decort_api_call(requests.post, "/restmachine/cloudapi/compute/affinityLabelSet", api_params)
|
||||||
if aff:
|
if aff:
|
||||||
if len(aff[0])>0:
|
if len(aff)>0:
|
||||||
for rule in aff:
|
for rule in aff:
|
||||||
api_params = dict(computeId=comp_dict['id'],
|
api_params = dict(computeId=comp_dict['id'],
|
||||||
key=rule['key'],
|
key=rule['key'],
|
||||||
@@ -1217,7 +1216,7 @@ class DecortController(object):
|
|||||||
policy=rule['policy'],)
|
policy=rule['policy'],)
|
||||||
self.decort_api_call(requests.post, "/restmachine/cloudapi/compute/affinityRuleAdd", api_params)
|
self.decort_api_call(requests.post, "/restmachine/cloudapi/compute/affinityRuleAdd", api_params)
|
||||||
if aaff:
|
if aaff:
|
||||||
if len(aaff[0])>0:
|
if len(aaff)>0:
|
||||||
for rule in aaff:
|
for rule in aaff:
|
||||||
api_params = dict(computeId=comp_dict['id'],
|
api_params = dict(computeId=comp_dict['id'],
|
||||||
key=rule['key'],
|
key=rule['key'],
|
||||||
@@ -1975,7 +1974,7 @@ class DecortController(object):
|
|||||||
if api_resp.status_code == 200:
|
if api_resp.status_code == 200:
|
||||||
locations = json.loads(api_resp.content.decode('utf8'))
|
locations = json.loads(api_resp.content.decode('utf8'))
|
||||||
if location_code == "" and locations:
|
if location_code == "" and locations:
|
||||||
ret_gid = locations[0]['gid']
|
ret_gid = locations['gid']
|
||||||
else:
|
else:
|
||||||
for runner in locations:
|
for runner in locations:
|
||||||
if runner['locationCode'] == location_code:
|
if runner['locationCode'] == location_code:
|
||||||
@@ -3298,7 +3297,7 @@ class DecortController(object):
|
|||||||
self.result['failed'] = True
|
self.result['failed'] = True
|
||||||
return
|
return
|
||||||
elif ret_info['status'] == "OK":
|
elif ret_info['status'] == "OK":
|
||||||
k8s_id = ret_info['result'][0]
|
k8s_id = ret_info['result']
|
||||||
self.result['changed'] = True
|
self.result['changed'] = True
|
||||||
return k8s_id
|
return k8s_id
|
||||||
else:
|
else:
|
||||||
@@ -3401,7 +3400,7 @@ class DecortController(object):
|
|||||||
k8ci_id_present = True
|
k8ci_id_present = True
|
||||||
break
|
break
|
||||||
|
|
||||||
if k8ci_id_present == False:
|
else:
|
||||||
self.result['failed'] = True
|
self.result['failed'] = True
|
||||||
self.result['msg'] = ("Cannot find k8ci id: {}.").format(arg_k8ci_id)
|
self.result['msg'] = ("Cannot find k8ci id: {}.").format(arg_k8ci_id)
|
||||||
self.amodule.fail_json(**self.result)
|
self.amodule.fail_json(**self.result)
|
||||||
@@ -3764,3 +3763,699 @@ class DecortController(object):
|
|||||||
self.result['msg'] = "group_delete() Group ID {} was deleted.".format(gr_id)
|
self.result['msg'] = "group_delete() Group ID {} was deleted.".format(gr_id)
|
||||||
self.result['changed'] = True
|
self.result['changed'] = True
|
||||||
return
|
return
|
||||||
|
####################
|
||||||
|
### LB MANAGMENT ###
|
||||||
|
####################
|
||||||
|
def _lb_get_by_id(self,lb_id):
|
||||||
|
"""Helper function that locates LB by ID and returns LB facts. This function
|
||||||
|
expects that the ViNS exists (albeit in DELETED or DESTROYED state) and will return
|
||||||
|
0 LB ID if not found.
|
||||||
|
|
||||||
|
@param (int) vins_id: ID of the LB to find and return facts for.
|
||||||
|
|
||||||
|
@return: LB ID and a dictionary of LB facts as provided by LB/get API call.
|
||||||
|
"""
|
||||||
|
ret_lb_id = 0
|
||||||
|
ret_lb_dict = dict()
|
||||||
|
|
||||||
|
if not lb_id:
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['msg'] = "lb_get_by_id(): zero LB ID specified."
|
||||||
|
self.amodule.fail_json(**self.result)
|
||||||
|
|
||||||
|
api_params = dict(lbId=lb_id)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/get", api_params)
|
||||||
|
if api_resp.status_code == 200:
|
||||||
|
ret_lb_id = lb_id
|
||||||
|
ret_lb_dict = json.loads(api_resp.content.decode('utf8'))
|
||||||
|
else:
|
||||||
|
self.result['warning'] = ("lb_get_by_id(): failed to get LB by ID {}. HTTP code {}, "
|
||||||
|
"response {}.").format(lb_id, api_resp.status_code, api_resp.reason)
|
||||||
|
|
||||||
|
return ret_lb_id, ret_lb_dict
|
||||||
|
def _rg_listlb(self,rg_id):
|
||||||
|
"""List all LB in the resource group
|
||||||
|
@param (int) rg_id: id onr resource group
|
||||||
|
"""
|
||||||
|
if not rg_id:
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['msg'] = "_rg_listlb(): zero RG ID specified."
|
||||||
|
self.amodule.fail_json(**self.result)
|
||||||
|
|
||||||
|
api_params = dict(rgId=rg_id)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/rg/listLb", api_params)
|
||||||
|
if api_resp.status_code == 200:
|
||||||
|
ret_rg_vins_list = json.loads(api_resp.content.decode('utf8'))
|
||||||
|
else:
|
||||||
|
self.result['warning'] = ("rg_listlb(): failed to get RG by ID {}. HTTP code {}, "
|
||||||
|
"response {}.").format(rg_id, api_resp.status_code, api_resp.reason)
|
||||||
|
return []
|
||||||
|
|
||||||
|
return ret_rg_vins_list
|
||||||
|
def lb_find(self,lb_id=0,lb_name="",rg_id=0):
|
||||||
|
"""Find specified LB.
|
||||||
|
|
||||||
|
@returns: LB ID and dictionary with LB facts.
|
||||||
|
"""
|
||||||
|
LB_INVALID_STATES = ["ENABLING", "DISABLING", "DELETING", "DELETED", "DESTROYING", "DESTROYED"]
|
||||||
|
|
||||||
|
ret_lb_id = 0
|
||||||
|
ret_lb_facts = None
|
||||||
|
|
||||||
|
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "lb_find")
|
||||||
|
|
||||||
|
if lb_id > 0:
|
||||||
|
ret_lb_id, ret_lb_facts = self._lb_get_by_id(lb_id)
|
||||||
|
if not ret_lb_id:
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['msg'] = "lb_find(): cannot find LB by ID {}.".format(lb_id)
|
||||||
|
self.amodule.fail_json(**self.result)
|
||||||
|
if not self.amodule.check_mode or ret_lb_facts['status'] not in LB_INVALID_STATES:
|
||||||
|
return ret_lb_id, ret_lb_facts
|
||||||
|
else:
|
||||||
|
return 0, None
|
||||||
|
elif lb_name != "":
|
||||||
|
if rg_id > 0:
|
||||||
|
list_lb = self._rg_listlb(rg_id)
|
||||||
|
for lb in list_lb:
|
||||||
|
if lb['name'] == lb_name:
|
||||||
|
ret_lb_id, ret_lb_facts = self._lb_get_by_id(lb['id'])
|
||||||
|
if not self.amodule.check_mode or ret_lb_facts['status'] not in LB_INVALID_STATES:
|
||||||
|
return ret_lb_id, ret_lb_facts
|
||||||
|
else:
|
||||||
|
return 0, None
|
||||||
|
else:
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['msg'] = ("vins_lb(): cannot find LB by name '{}' "
|
||||||
|
"when no account ID or RG ID is specified.").format(lb_name)
|
||||||
|
self.amodule.fail_json(**self.result)
|
||||||
|
else:
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['msg'] = "vins_find(): cannot find LB by zero ID and empty name."
|
||||||
|
self.amodule.fail_json(**self.result)
|
||||||
|
|
||||||
|
return 0, None
|
||||||
|
def lb_provision(self,lb_name,rg_id,vins_id,ext_net_id,annotation,start=True):
|
||||||
|
"""Provision LB according to the specified arguments.
|
||||||
|
If critical error occurs the embedded call to API function will abort further execution of
|
||||||
|
the script and relay error to Ansible.
|
||||||
|
Note, that when creating ViNS at account level, default location under DECORT controller
|
||||||
|
will be selected automatically.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "lb_provision")
|
||||||
|
|
||||||
|
if self.amodule.check_mode:
|
||||||
|
self.result['failed'] = False
|
||||||
|
self.result['msg'] = ("vins_lb() in check mode: provision LB name '{}' was "
|
||||||
|
"requested in RG with id: {}.").format(lb_name,rg_id)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
if lb_name == "":
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['msg'] = "lb_provision(): LB name cannot be empty."
|
||||||
|
self.amodule.fail_json(**self.result)
|
||||||
|
|
||||||
|
api_url = "/restmachine/cloudapi/lb/create"
|
||||||
|
api_params = dict(
|
||||||
|
name=lb_name,
|
||||||
|
rgId=rg_id,
|
||||||
|
extnetId=ext_net_id,
|
||||||
|
vinsId=vins_id,
|
||||||
|
start=start,
|
||||||
|
decs=annotation
|
||||||
|
)
|
||||||
|
api_resp = self.decort_api_call(requests.post, api_url, api_params)
|
||||||
|
# On success the above call will return here. On error it will abort execution by calling fail_json.
|
||||||
|
self.result['failed'] = False
|
||||||
|
self.result['changed'] = True
|
||||||
|
ret_lb_id = int(api_resp.content.decode('utf8'))
|
||||||
|
return ret_lb_id
|
||||||
|
def lb_delete(self,lb_id,permanently=False):
|
||||||
|
"""Deletes specified LB.
|
||||||
|
|
||||||
|
@param (int) lb_id: integer value that identifies the ViNS to be deleted.
|
||||||
|
@param (bool) permanently: a bool that tells if deletion should be permanent. If False, the LB will be
|
||||||
|
marked as DELETED and placed into a trash bin for predefined period of time (usually, a few days). Until
|
||||||
|
this period passes this LB can be restored by calling the corresponding 'restore' method.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "lb_delete")
|
||||||
|
|
||||||
|
if self.amodule.check_mode:
|
||||||
|
self.result['failed'] = False
|
||||||
|
self.result['msg'] = "lb_delete() in check mode: delete ViNS ID {} was requested.".format(lb_id)
|
||||||
|
return
|
||||||
|
|
||||||
|
api_params = dict(lbId=lb_id,
|
||||||
|
permanently=permanently)
|
||||||
|
self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/delete", api_params)
|
||||||
|
# On success the above call will return here. On error it will abort execution by calling fail_json.
|
||||||
|
self.result['failed'] = False
|
||||||
|
self.result['changed'] = True
|
||||||
|
return
|
||||||
|
def lb_state(self, lb_dict, desired_state):
|
||||||
|
"""Change state for LB.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "lb_state")
|
||||||
|
|
||||||
|
NOP_STATES_FOR_LB_CHANGE = ["MODELED", "DISABLING", "ENABLING", "DELETING", "DELETED", "DESTROYING",
|
||||||
|
"DESTROYED"]
|
||||||
|
VALID_TARGET_STATES = ["enabled", "disabled","restart"]
|
||||||
|
VALID_TARGET_TSTATES = ["STARTED","STOPPED"]
|
||||||
|
|
||||||
|
if lb_dict['status'] in NOP_STATES_FOR_LB_CHANGE:
|
||||||
|
self.result['failed'] = False
|
||||||
|
self.result['msg'] = ("lb_state(): no state change possible for LB ID {} "
|
||||||
|
"in its current state '{}'.").format(lb_dict['id'], lb_dict['status'])
|
||||||
|
return
|
||||||
|
|
||||||
|
if desired_state not in VALID_TARGET_STATES:
|
||||||
|
self.result['failed'] = False
|
||||||
|
self.result['warning'] = ("lb_state(): unrecognized desired state '{}' requested "
|
||||||
|
"for LB ID {}. No LB state change will be done.").format(desired_state,
|
||||||
|
lb_dict['id'])
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.amodule.check_mode:
|
||||||
|
self.result['failed'] = False
|
||||||
|
self.result['msg'] = ("lb_state() in check mode: setting state of LB ID {}, name '{}' to "
|
||||||
|
"'{}' was requested.").format(lb_dict['id'], lb_dict['name'],
|
||||||
|
desired_state)
|
||||||
|
return
|
||||||
|
|
||||||
|
state_api = ""
|
||||||
|
api_params = dict(lbId=lb_dict['id'])
|
||||||
|
expected_state = ""
|
||||||
|
if lb_dict['status'] in ["CREATED", "ENABLED"]:
|
||||||
|
if desired_state == 'disabled':
|
||||||
|
state_api = "/restmachine/cloudapi/lb/disable"
|
||||||
|
expected_state = "DISABLED"
|
||||||
|
if lb_dict['techStatus'] == "STARTED":
|
||||||
|
if desired_state == 'stopped':
|
||||||
|
state_api = "/restmachine/cloudapi/lb/stop"
|
||||||
|
if desired_state == 'restart':
|
||||||
|
state_api = "/restmachine/cloudapi/lb/restart"
|
||||||
|
elif lb_dict['techStatus'] == "STOPPED":
|
||||||
|
if desired_state == 'started':
|
||||||
|
state_api = "/restmachine/cloudapi/lb/start"
|
||||||
|
elif lb_dict['status'] == "DISABLED" and desired_state == 'enabled':
|
||||||
|
state_api = "/restmachine/cloudapi/lb/enable"
|
||||||
|
expected_state = "ENABLED"
|
||||||
|
|
||||||
|
if state_api != "":
|
||||||
|
self.decort_api_call(requests.post, state_api, api_params)
|
||||||
|
# On success the above call will return here. On error it will abort execution by calling fail_json.
|
||||||
|
self.result['failed'] = False
|
||||||
|
self.result['changed'] = True
|
||||||
|
lb_dict['status'] = expected_state
|
||||||
|
else:
|
||||||
|
self.result['failed'] = False
|
||||||
|
self.result['msg'] = ("lb_state(): no state change required for LB ID {} from current "
|
||||||
|
"state '{}' to desired state '{}'.").format(lb_dict['id'],
|
||||||
|
lb_dict['status'],
|
||||||
|
desired_state)
|
||||||
|
return
|
||||||
|
def lb_restore(self, lb_id):
|
||||||
|
"""Restores previously deleted LB identified by its ID.
|
||||||
|
|
||||||
|
@param lb_id: ID of the LB to restore.
|
||||||
|
|
||||||
|
@returns: nothing on success. On error this method will abort module execution.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "lb_restore")
|
||||||
|
|
||||||
|
if self.amodule.check_mode:
|
||||||
|
self.result['failed'] = False
|
||||||
|
self.result['msg'] = "lb_restore() in check mode: restore LB ID {} was requested.".format(lb_id)
|
||||||
|
return
|
||||||
|
|
||||||
|
api_params = dict(lbId=lb_id)
|
||||||
|
self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/restore", api_params)
|
||||||
|
# On success the above call will return here. On error it will abort execution by calling fail_json.
|
||||||
|
self.result['failed'] = False
|
||||||
|
self.result['changed'] = True
|
||||||
|
return
|
||||||
|
|
||||||
|
def lb_update_backends(self,lb_backends,mod_backends,mod_servers):
|
||||||
|
"""
|
||||||
|
backends
|
||||||
|
"""
|
||||||
|
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "lb_update_backends")
|
||||||
|
|
||||||
|
if mod_backends:
|
||||||
|
backs_out = [rec['name'] for rec in mod_backends]
|
||||||
|
else:
|
||||||
|
backs_out=""
|
||||||
|
backs_in = [rec['name'] for rec in lb_backends]
|
||||||
|
del_backs = set(backs_in).difference(backs_out)
|
||||||
|
add_becks = set(backs_out).difference(backs_in)
|
||||||
|
upd_becks = set(backs_in).intersection(backs_out)
|
||||||
|
|
||||||
|
for item in del_backs:
|
||||||
|
#need delete frontend
|
||||||
|
api_params = dict(lbId=self.lb_id,backendName = item)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/backendDelete", api_params)
|
||||||
|
self.result['changed'] = True
|
||||||
|
for item in add_becks:
|
||||||
|
backend, = list(filter(lambda i: i['name'] == item,mod_backends))
|
||||||
|
api_params = dict(
|
||||||
|
lbId=self.lb_id,
|
||||||
|
backendName = backend['name'],
|
||||||
|
algorithm = backend['algorithm'] if "algorithm" in backend else None,
|
||||||
|
**backend['default_settings'] if "default_settings" in backend else {},
|
||||||
|
)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/backendCreate", api_params)
|
||||||
|
self.result['changed'] = True
|
||||||
|
for item in upd_becks.union(add_becks):
|
||||||
|
|
||||||
|
backend, = list(filter(lambda i: i['name'] == item,lb_backends))
|
||||||
|
mod_backend, = list(filter(lambda i: i['name'] == item,mod_backends))
|
||||||
|
servers_in = [rec['name'] for rec in backend['servers']]
|
||||||
|
servers_out = []
|
||||||
|
#oO rework
|
||||||
|
if mod_servers:
|
||||||
|
for serv in mod_servers:
|
||||||
|
for bend in serv['backends']:
|
||||||
|
if bend['name'] == item:
|
||||||
|
servers_out.append(serv['name'])
|
||||||
|
|
||||||
|
del_srv = set(servers_in).difference(servers_out)
|
||||||
|
add_srv = set(servers_out).difference(servers_in)
|
||||||
|
upd_srv = set(servers_in).intersection(servers_out)
|
||||||
|
|
||||||
|
del backend['serverDefaultSettings']['guid']
|
||||||
|
|
||||||
|
if "default_settings" not in mod_backend:
|
||||||
|
mod_backend["default_settings"] = self.default_settings
|
||||||
|
|
||||||
|
if "algorithm" not in mod_backend:
|
||||||
|
mod_backend["algorithm"] = self.default_alg
|
||||||
|
|
||||||
|
if backend['serverDefaultSettings'] != mod_backend["default_settings"] or\
|
||||||
|
mod_backend["algorithm"] != backend['algorithm']:
|
||||||
|
api_params = dict(
|
||||||
|
lbId=self.lb_id,
|
||||||
|
backendName = item,
|
||||||
|
algorithm = mod_backend['algorithm'],
|
||||||
|
**mod_backend['default_settings'] if "default_settings" in mod_backend else {},
|
||||||
|
)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/backendUpdate", api_params)
|
||||||
|
self.result['changed'] = True
|
||||||
|
|
||||||
|
for srv in del_srv:
|
||||||
|
api_params = dict(lbId=self.lb_id,backendName = item,serverName=srv)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/backendServerDelete", api_params)
|
||||||
|
self.result['changed'] = True
|
||||||
|
for srv in add_srv:
|
||||||
|
server, = list(filter(lambda i: i['name'] == srv,mod_servers))
|
||||||
|
back, = list(filter(lambda i: i['name'] == item,server['backends']))
|
||||||
|
api_params = dict(
|
||||||
|
lbId=self.lb_id,
|
||||||
|
backendName = item,
|
||||||
|
serverName = server['name'],
|
||||||
|
address = server['address'],
|
||||||
|
port = back['port'],
|
||||||
|
check = server['check'] if "check" in server else None,
|
||||||
|
**server['server_settings'] if "server_settings" in server else {},
|
||||||
|
)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/backendServerAdd", api_params)
|
||||||
|
self.result['changed'] = True
|
||||||
|
for srv in upd_srv:
|
||||||
|
mod_server, = list(filter(lambda i: i['name'] == srv,mod_servers))
|
||||||
|
mod_server_back, = list(filter(lambda i: i['name'] == item,mod_server['backends']))
|
||||||
|
server, = list(filter(lambda i: i['name'] == srv, backend['servers']))
|
||||||
|
|
||||||
|
del server['serverSettings']['guid']
|
||||||
|
|
||||||
|
if "server_settings" not in mod_server_back:
|
||||||
|
mod_server_back['server_settings'] = self.default_settings
|
||||||
|
if "check" not in mod_server:
|
||||||
|
mod_server['check'] = self.default_server_check
|
||||||
|
|
||||||
|
if (mod_server['address'] != server['address'] or\
|
||||||
|
server['check']!=mod_server["check"]) or\
|
||||||
|
mod_server_back['server_settings'] != server['serverSettings']:
|
||||||
|
api_params = dict(
|
||||||
|
lbId=self.lb_id,
|
||||||
|
backendName = item,
|
||||||
|
serverName = mod_server['name'],
|
||||||
|
address = mod_server['address'],
|
||||||
|
port = mod_server_back['port'],
|
||||||
|
check = mod_server_back['check'] if "check" in mod_server_back else None,
|
||||||
|
**mod_server_back['server_settings'] if "server_settings" in mod_server_back else {},
|
||||||
|
)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/backendServerUpdate", api_params)
|
||||||
|
self.result['changed'] = True
|
||||||
|
|
||||||
|
return
|
||||||
|
def lb_update_frontends(self,lb_frontends,mod_frontends):
|
||||||
|
"""
|
||||||
|
frontends
|
||||||
|
"""
|
||||||
|
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "lb_update_frontends")
|
||||||
|
if mod_frontends:
|
||||||
|
front_out = [rec['name'] for rec in mod_frontends]
|
||||||
|
else:
|
||||||
|
front_out=""
|
||||||
|
front_in = [rec['name'] for rec in lb_frontends]
|
||||||
|
|
||||||
|
del_front = set(front_in).difference(front_out)
|
||||||
|
add_front = set(front_out).difference(front_in)
|
||||||
|
upd_front = set(front_in).intersection(front_out)
|
||||||
|
|
||||||
|
for front in del_front:
|
||||||
|
delete_front, = list(filter(lambda i: i['name'] == front,lb_frontends))
|
||||||
|
api_params = dict(
|
||||||
|
lbId=self.lb_id,
|
||||||
|
frontendName=delete_front['name'],
|
||||||
|
)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/frontendDelete", api_params)
|
||||||
|
self.result['changed'] = True
|
||||||
|
for front in add_front:
|
||||||
|
create_front, = list(filter(lambda i: i['name'] == front,mod_frontends))
|
||||||
|
api_params = dict(
|
||||||
|
lbId=self.lb_id,
|
||||||
|
frontendName=create_front['name'],
|
||||||
|
backendName=create_front['backend'],
|
||||||
|
)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/frontendCreate", api_params)
|
||||||
|
self.result['changed'] = True
|
||||||
|
if "bindings" in create_front:
|
||||||
|
for bind in create_front['bindings']:
|
||||||
|
self._lb_bind_frontend(
|
||||||
|
create_front['name'],
|
||||||
|
bind['name'],
|
||||||
|
bind['address'] if "address" in bind else None,
|
||||||
|
bind['port'] if "port" in bind else None
|
||||||
|
)
|
||||||
|
for front in upd_front:
|
||||||
|
update_front, = list(filter(lambda i: i['name'] == front,mod_frontends))
|
||||||
|
lb_front, = list(filter(lambda i: i['name'] == front,lb_frontends))
|
||||||
|
mod_bind = [rec['name'] for rec in update_front['bindings']]
|
||||||
|
lb_bind = [rec['name'] for rec in lb_front['bindings']]
|
||||||
|
|
||||||
|
del_bind_list = set(lb_bind).difference(mod_bind)
|
||||||
|
add_bind_list = set(mod_bind).difference(lb_bind)
|
||||||
|
upd_bind_list = set(lb_bind).intersection(mod_bind)
|
||||||
|
|
||||||
|
for bind_name in del_bind_list:
|
||||||
|
del_bind, = list(filter(lambda i: i['name'] == bind_name,lb_front['bindings']))
|
||||||
|
api_params = dict(
|
||||||
|
lbId=self.lb_id,
|
||||||
|
frontendName=update_front['name'],
|
||||||
|
bindingName=del_bind['name'],
|
||||||
|
)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/frontendBindDelete", api_params)
|
||||||
|
self.result['changed'] = True
|
||||||
|
for bind_name in add_bind_list:
|
||||||
|
add_bind, = list(filter(lambda i: i['name'] == bind_name,update_front['bindings']))
|
||||||
|
self._lb_bind_frontend(
|
||||||
|
update_front['name'],
|
||||||
|
add_bind['name'],
|
||||||
|
add_bind['address'] if "address" in add_bind else None,
|
||||||
|
add_bind['port'] if "port" in add_bind else None
|
||||||
|
)
|
||||||
|
for bind_name in upd_bind_list:
|
||||||
|
lb_act_bind, = list(filter(lambda i: i['name'] == bind_name,lb_front['bindings']))
|
||||||
|
mod_act_bind, = list(filter(lambda i: i['name'] == bind_name,update_front['bindings']))
|
||||||
|
del lb_act_bind['guid']
|
||||||
|
if lb_act_bind != mod_act_bind:
|
||||||
|
self._lb_bind_frontend(
|
||||||
|
update_front['name'],
|
||||||
|
mod_act_bind['name'],
|
||||||
|
mod_act_bind['address'] if "address" in mod_act_bind else None,
|
||||||
|
mod_act_bind['port'] if "port" in mod_act_bind else None,
|
||||||
|
update=True
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def _lb_bind_frontend(self,front_name,bind_name,bind_addr=None,bind_port=None,update=False):
|
||||||
|
api_params = dict(
|
||||||
|
lbId=self.lb_id,
|
||||||
|
frontendName=front_name,
|
||||||
|
bindingName=bind_name,
|
||||||
|
bindingAddress=bind_addr,
|
||||||
|
bindingPort=bind_port,
|
||||||
|
)
|
||||||
|
if update == True:
|
||||||
|
api_url = "/restmachine/cloudapi/lb/frontendBindingUpdate"
|
||||||
|
else:
|
||||||
|
api_url = "/restmachine/cloudapi/lb/frontendBind"
|
||||||
|
api_resp = self.decort_api_call(requests.post, api_url, api_params)
|
||||||
|
self.result['changed'] = True
|
||||||
|
|
||||||
|
def lb_update(self,lb_backends=[],lb_frontends=[],mod_backends=[],mod_servers=[],mod_frontends=[]):
|
||||||
|
#lists from module and cloud
|
||||||
|
mod_backs_list = [back['name'] for back in mod_backends]
|
||||||
|
lb_backs_list = [back['name'] for back in lb_backends]
|
||||||
|
#ADD\DEL\UPDATE LISTS OF BACKENDS
|
||||||
|
del_list_backs = set(lb_backs_list).difference(mod_backs_list)
|
||||||
|
add_back_list = set(mod_backs_list).difference(lb_backs_list)
|
||||||
|
upd_back_list = set(lb_backs_list).intersection(mod_backs_list)
|
||||||
|
|
||||||
|
#FE
|
||||||
|
|
||||||
|
mod_front_list = [front['name'] for front in mod_frontends]
|
||||||
|
lb_front_list = [front['name'] for front in lb_frontends]
|
||||||
|
|
||||||
|
if del_list_backs:
|
||||||
|
|
||||||
|
self._lb_delete_backends(
|
||||||
|
del_list_backs,
|
||||||
|
lb_frontends
|
||||||
|
)
|
||||||
|
|
||||||
|
if add_back_list:
|
||||||
|
self._lb_create_backends(
|
||||||
|
add_back_list,
|
||||||
|
mod_backends,
|
||||||
|
mod_servers
|
||||||
|
)
|
||||||
|
|
||||||
|
if upd_back_list:
|
||||||
|
self._lb_update_backends(
|
||||||
|
upd_back_list,
|
||||||
|
lb_backends,
|
||||||
|
mod_backends,
|
||||||
|
mod_servers
|
||||||
|
)
|
||||||
|
|
||||||
|
del_list_fronts = set(lb_front_list).difference(mod_front_list)
|
||||||
|
add_list_fronts = set(mod_front_list).difference(lb_front_list)
|
||||||
|
upd_front_list = set(lb_front_list).intersection(mod_front_list)
|
||||||
|
|
||||||
|
if del_list_fronts:
|
||||||
|
self._lb_delete_fronts(del_list_fronts)
|
||||||
|
|
||||||
|
if add_list_fronts:
|
||||||
|
self._lb_add_fronts(add_list_fronts,mod_frontends)
|
||||||
|
if upd_front_list:
|
||||||
|
self._lb_update_fronts(upd_front_list,lb_frontends,mod_frontends)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def _lb_delete_backends(self,back_list,lb_fronts):
|
||||||
|
|
||||||
|
#delete frontends with that backend
|
||||||
|
for back in back_list:
|
||||||
|
fronts = list(filter(lambda i: i['backend'] == back,lb_fronts))
|
||||||
|
if fronts:
|
||||||
|
self._lb_delete_fronts(fronts)
|
||||||
|
api_params = dict(
|
||||||
|
lbId=self.lb_id,
|
||||||
|
backendName = back
|
||||||
|
)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/backendDelete", api_params)
|
||||||
|
self.result['changed'] = True
|
||||||
|
return
|
||||||
|
def _lb_delete_fronts(self,d_fronts):
|
||||||
|
for front in d_fronts:
|
||||||
|
api_params = dict(
|
||||||
|
lbId=self.lb_id,
|
||||||
|
frontendName=front['name'] if "name" in front else front,
|
||||||
|
)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/frontendDelete", api_params)
|
||||||
|
#del from cloud dict
|
||||||
|
if type(front)==dict:
|
||||||
|
del self.lb_facts['frontends'][front['name']]
|
||||||
|
self.result['changed'] = True
|
||||||
|
|
||||||
|
return
|
||||||
|
def _lb_add_fronts(self,front_list,mod_fronts):
|
||||||
|
for front in front_list:
|
||||||
|
add_front, = list(filter(lambda i: i['name'] == front,mod_fronts))
|
||||||
|
api_params = dict(
|
||||||
|
lbId=self.lb_id,
|
||||||
|
frontendName=add_front['name'],
|
||||||
|
backendName=add_front['backend'],
|
||||||
|
)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/frontendCreate", api_params)
|
||||||
|
for bind in add_front['bindings']:
|
||||||
|
self._lb_bind_frontend(
|
||||||
|
add_front['name'],
|
||||||
|
bind['name'],
|
||||||
|
bind['address']if "address" in bind else None,
|
||||||
|
bind['port'] if "port" in bind else None,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
def _lb_create_backends(self,back_list,mod_backs,mod_serv):
|
||||||
|
'''
|
||||||
|
Create backends and add servers to them
|
||||||
|
'''
|
||||||
|
for back in back_list:
|
||||||
|
backend, = list(filter(lambda i: i['name'] == back,mod_backs))
|
||||||
|
api_params = dict(
|
||||||
|
lbId=self.lb_id,
|
||||||
|
backendName = back,
|
||||||
|
algorithm = backend['algorithm'] if "algorithm" in backend else None,
|
||||||
|
**backend['default_settings'] if "default_settings" in backend else {},
|
||||||
|
)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/backendCreate", api_params)
|
||||||
|
|
||||||
|
for server in mod_serv:
|
||||||
|
try:
|
||||||
|
srv_back, = list(filter(lambda i: i['name'] == back,server['backends']))
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
api_params = dict(
|
||||||
|
lbId=self.lb_id,
|
||||||
|
backendName = back,
|
||||||
|
serverName = server['name'],
|
||||||
|
address = server['address'],
|
||||||
|
port = srv_back['port'],
|
||||||
|
check = srv_back['check'] if "check" in srv_back else None,
|
||||||
|
**srv_back['server_settings'] if "server_settings" in srv_back else {},
|
||||||
|
)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/backendServerAdd", api_params)
|
||||||
|
|
||||||
|
self.result['changed'] = True
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def _lb_update_backends(self,back_list,lb_backs,mod_backs,mod_serv):
|
||||||
|
|
||||||
|
lb_backs = list(filter(lambda i: i['name'] in back_list,lb_backs))
|
||||||
|
#mod_back = list(filter(lambda i: i['name'] in back_list,mod_backs))
|
||||||
|
|
||||||
|
for back in lb_backs:
|
||||||
|
|
||||||
|
del back['serverDefaultSettings']['guid']
|
||||||
|
mod_back, = list(filter(lambda i: i['name']==back['name'],mod_backs))
|
||||||
|
#mod_servers = list(filter(lambda i: i['name']==back['name'],mod_serv))
|
||||||
|
#raise Exception(mod_servers)
|
||||||
|
if "default_settings" not in mod_back:
|
||||||
|
mod_back["default_settings"] = self.default_settings
|
||||||
|
else:
|
||||||
|
for param,value in self.default_settings.items():
|
||||||
|
if param not in mod_back["default_settings"]:
|
||||||
|
mod_back["default_settings"].update(param,value)
|
||||||
|
|
||||||
|
|
||||||
|
if "algorithm" not in mod_back:
|
||||||
|
mod_back["algorithm"] = self.default_alg
|
||||||
|
|
||||||
|
if back['serverDefaultSettings'] != mod_back["default_settings"] or\
|
||||||
|
mod_back["algorithm"] != back['algorithm']:
|
||||||
|
api_params = dict(
|
||||||
|
lbId=self.lb_id,
|
||||||
|
backendName = back['name'],
|
||||||
|
algorithm = mod_back['algorithm'],
|
||||||
|
**mod_back['default_settings'],
|
||||||
|
)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/backendUpdate", api_params)
|
||||||
|
self.result['changed'] = True
|
||||||
|
|
||||||
|
lb_servers_list = [srv['name'] for srv in back['servers']]
|
||||||
|
for server in mod_serv:
|
||||||
|
try:
|
||||||
|
mod_back, = list(filter(lambda i: i['name'] == back['name'],server['backends']))
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
if server['name'] not in lb_servers_list:
|
||||||
|
api_params = dict(
|
||||||
|
lbId=self.lb_id,
|
||||||
|
backendName = mod_back['name'],
|
||||||
|
serverName = server['name'],
|
||||||
|
address = server['address'],
|
||||||
|
port = mod_back['port'],
|
||||||
|
check = server['check'] if "check" in server else None,
|
||||||
|
**server['server_settings'] if "server_settings" in server else {},
|
||||||
|
)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/backendServerAdd", api_params)
|
||||||
|
self.result['changed'] = True
|
||||||
|
else:
|
||||||
|
lb_server, = list(filter(lambda i: i['name'] == server['name'],back['servers']))
|
||||||
|
del lb_server['serverSettings']['guid']
|
||||||
|
|
||||||
|
if "server_settings" not in mod_back:
|
||||||
|
mod_back['server_settings'] = self.default_settings
|
||||||
|
else:
|
||||||
|
for param,value in self.default_settings.items():
|
||||||
|
if param not in mod_back["server_settings"]:
|
||||||
|
mod_back["server_settings"].update(param,value)
|
||||||
|
|
||||||
|
if "check" not in mod_back:
|
||||||
|
mod_back['check'] = self.default_server_check
|
||||||
|
|
||||||
|
if (server['address'] != lb_server['address'] or\
|
||||||
|
lb_server['check']!=mod_back['check']) or\
|
||||||
|
mod_back['server_settings'] != lb_server['serverSettings']:
|
||||||
|
api_params = dict(
|
||||||
|
lbId=self.lb_id,
|
||||||
|
backendName = mod_back['name'],
|
||||||
|
serverName = server['name'],
|
||||||
|
address = server['address'],
|
||||||
|
port = mod_back['port'],
|
||||||
|
check = mod_back['check'],
|
||||||
|
**mod_back['server_settings'],
|
||||||
|
)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/backendServerUpdate", api_params)
|
||||||
|
self.result['changed'] = True
|
||||||
|
lb_servers_list.remove(server['name'])
|
||||||
|
for server in lb_servers_list:
|
||||||
|
api_params = dict(lbId=self.lb_id,backendName = back['name'],serverName=server)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/backendServerDelete", api_params)
|
||||||
|
self.result['changed'] = True
|
||||||
|
return
|
||||||
|
def _lb_update_fronts(self,upd_front_list,lb_frontends,mod_frontends):
|
||||||
|
|
||||||
|
for front in upd_front_list:
|
||||||
|
mod_front, = list(filter(lambda i: i['name'] == front,mod_frontends))
|
||||||
|
lb_front, = list(filter(lambda i: i['name'] == front,lb_frontends))
|
||||||
|
lb_binds_list = [bind['name'] for bind in lb_front['bindings']]
|
||||||
|
for bind in mod_front['bindings']:
|
||||||
|
if bind['name'] not in lb_binds_list:
|
||||||
|
pass
|
||||||
|
self._lb_bind_frontend(
|
||||||
|
front,
|
||||||
|
bind['name'],
|
||||||
|
bind['address']if "address" in bind else None,
|
||||||
|
bind['port'] if "port" in bind else None,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
lb_bind, = list(filter(lambda i: i['name'] == bind['name'],lb_front['bindings']))
|
||||||
|
del lb_bind['guid']
|
||||||
|
|
||||||
|
if dict(sorted(bind.items())) != dict(sorted(lb_bind.items())):
|
||||||
|
self._lb_bind_frontend(
|
||||||
|
front,
|
||||||
|
bind['name'],
|
||||||
|
bind['address']if "address" in bind else None,
|
||||||
|
bind['port'] if "port" in bind else None,
|
||||||
|
update=True,
|
||||||
|
)
|
||||||
|
lb_binds_list.remove(bind['name'])
|
||||||
|
|
||||||
|
for lb_bind in lb_binds_list:
|
||||||
|
api_params = dict(
|
||||||
|
lbId=self.lb_id,
|
||||||
|
frontendName=front,
|
||||||
|
bindingName=lb_bind,
|
||||||
|
)
|
||||||
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/lb/frontendBindDelete", api_params)
|
||||||
|
self.result['changed'] = True
|
||||||
|
|
||||||
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user