k8s/lb update && bug fixes

rc-5.2.6
Alex_geth 1 year ago
parent 9222fdd866
commit a8f50bfb6b

Binary file not shown.

@ -29,7 +29,7 @@ class decort_group(DecortController):
self.result['failed'] = True
self.result['changed'] = False
self.result['msg'] = ("Cannot find B-service ID {}.").format(arg_amodule.params['bservice_id'])
self.fail_json(**self.result)
self.amodule.fail_json(**self.result)
#find group
self.bservice_id = validated_bservice_id
self.bservice_info = bservice_info

@ -132,6 +132,7 @@ class decort_k8s(DecortController):
k8s_name=arg_amodule.params['name'],
rg_id=validated_rg_id,
check_state=False)
if self.k8s_id:
self.k8s_should_exist = True
self.acc_id = self.k8s_info['accountId']
@ -165,6 +166,9 @@ class decort_k8s(DecortController):
ret_dict['rg_id'] = self.rg_id
ret_dict['vins_id'] = self.k8s_vins_id
ret_dict['account_id'] = self.acc_id
ret_dict['k8s_Masters'] = self.k8s_info['k8sGroups']['masters']
ret_dict['k8s_Workers'] = self.k8s_info['k8sGroups']['workers']
if self.amodule.params['getConfig'] and self.k8s_info['techStatus'] == "STARTED":
ret_dict['config'] = self.k8s_getConfig()
@ -206,6 +210,7 @@ class decort_k8s(DecortController):
k8s_id = self.k8s_provision(self.amodule.params['name'],
self.amodule.params['k8ci_id'],
self.amodule.params['rg_id'],
self.amodule.params['vins_id'],
self.amodule.params['network_plugin'],
self.amodule.params['master_count'],
self.amodule.params['master_cpu'],
@ -216,7 +221,17 @@ class decort_k8s(DecortController):
self.amodule.params['workers'][0],
self.amodule.params['extnet_id'],
self.amodule.params['with_lb'],
self.amodule.params['description'],)
self.amodule.params['ha_lb'],
self.amodule.params['additionalSANs'],
self.amodule.params['init_conf'],
self.amodule.params['cluster_conf'],
self.amodule.params['kublet_conf'],
self.amodule.params['kubeproxy_conf'],
self.amodule.params['join_conf'],
self.amodule.params['oidc_cert'],
self.amodule.params['description'],
self.amodule.params['extnet_only'],
)
if not k8s_id:
self.result['failed'] = True
@ -241,7 +256,8 @@ class decort_k8s(DecortController):
def action(self,disared_state,started=True):
self.k8s_state(self.k8s_info, disared_state,started)
#k8s state
self.k8s_state(self.k8s_info, disared_state, started)
self.k8s_id,self.k8s_info = self.k8s_find(k8s_id=self.amodule.params['id'],
k8s_name=self.amodule.params['name'],
rg_id=self.rg_id,
@ -249,7 +265,11 @@ class decort_k8s(DecortController):
if started == True and self.k8s_info['techStatus'] == "STOPPED":
self.k8s_state(self.k8s_info, disared_state,started)
self.k8s_info['techStatus'] == "STARTED"
#check groups and modify if needed
self.k8s_workers_modify(self.k8s_info,self.amodule.params['workers'])
if self.result['changed'] == True:
self.k8s_info = self.k8s_get_by_id(k8s_id=self.k8s_id)
#TODO check workers metadata and modify if needed
return
@staticmethod
@ -295,23 +315,29 @@ class decort_k8s(DecortController):
getConfig=dict(type='bool',required=False, default=False),
rg_id=dict(type='int', default=0),
rg_name=dict(type='str',default=""),
vins_id=dict(type='int', required=False,default=None),
k8ci_id=dict(type='int', required=True),
network_plugin=dict(type='str',required=False,default="flannel"),
wg_name=dict(type='str', required=False),
master_count=dict(type='int', default=1),
master_cpu=dict(type='int', default=2),
master_ram=dict(type='int', default=2048),
master_disk=dict(type='int', default=10),
master_sepid=dict(type='int', required=False, default=None),
master_pool=dict(type='str', required=False, default=None),
worker_count=dict(type='int', default=1),
worker_cpu=dict(type='int', default=1),
worker_ram_mb=dict(type='int', default=1024),
worker_disk_gb=dict(type='int', default=10),
workers=dict(type='list',required=True),
workers_metadata=dict(type='bool',required=False,default=False),
extnet_id=dict(type='int', default=0),
description=dict(type='str', default="Created by decort ansible module"),
with_lb=dict(type='bool', default=True),
ha_lb=dict(type='bool', default=False),
extnet_only=dict(type='bool', default=False),
additionalSANs=dict(type='list',required=False, default=None),
init_conf=dict(type='dict', required=False, default=None),
cluster_conf=dict(type='str', required=False, default=None),
kublet_conf=dict(type='str', required=False, default=None),
kubeproxy_conf=dict(type='str', required=False, default=None),
join_conf=dict(type='str', required=False, default=None),
oidc_cert=dict(type='raw',required=False,default=None),
verify_ssl=dict(type='bool', required=False, default=True),
workflow_callback=dict(type='str', required=False),
workflow_context=dict(type='str', required=False),)

@ -531,9 +531,7 @@ class decort_kvmvm(DecortController):
"shell": '/bin/bash'}
]}
elif self.amodule.params['ci_user_data']:
cloud_init_params = {}
for ci_param in self.amodule.params['ci_user_data']:
cloud_init_params.update(ci_param)
cloud_init_params = self.amodule.params['ci_user_data']
else:
cloud_init_params = None
# if we get through here, all parameters required to create new Compute instance should be at hand

@ -21,7 +21,6 @@ EXAMPLES = '''
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):
@ -65,28 +64,28 @@ class decort_lb(DecortController):
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)
self.amodule.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)
self.amodule.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.amodule.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.amodule.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:
@ -97,10 +96,14 @@ class decort_lb(DecortController):
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['ha_lb'],
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['primaryNode'],
self.lb_facts['frontendHAIP'],
self.lb_facts['backendHAIP'],
self.lb_facts['backends'],
self.lb_facts['frontends'],
self.amodule.params['backends'],
@ -117,11 +120,14 @@ class decort_lb(DecortController):
self.lb_facts['techStatus'] = "STARTED"
self.lb_update(
self.lb_facts['primaryNode'],
self.lb_facts['frontendHAIP'],
self.lb_facts['backendHAIP'],
self.lb_facts['backends'],
self.lb_facts['frontends'],
self.amodule.params['backends'],
self.amodule.params['servers'],
self.amodule.params['frontends']
self.amodule.params['frontends'],
)
if d_state != '':
@ -243,6 +249,7 @@ class decort_lb(DecortController):
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),
ha_lb=dict(type='bool', required=False, default=False),
backends=dict(type='list',required=False,default=[]),
frontends=dict(type='list',required=False,default=[]),
servers=dict(type='list',required=False,default=[]),

@ -260,7 +260,7 @@ class decort_vins(DecortController):
if self.vins_id == 0:
self.result['failed'] = True
self.result['msg'] = "Specified ViNS ID {} not found.".format(arg_amodule.params['vins_id'])
self.fail_json(**self.result)
self.amodule.fail_json(**self.result)
self.vins_level = "ID"
#raise Exception(self.vins_facts)
validated_acc_id = self.vins_facts['accountId']

@ -335,7 +335,7 @@ class DecortController(object):
return True
def decort_api_call(self, arg_req_function, arg_api_name, arg_params):
def decort_api_call(self, arg_req_function, arg_api_name, arg_params, arg_files=None):
"""Wrapper around DECORT API calls. It uses authorization mode and credentials validated at the class
instance creation to properly format API call and send it to the DECORT controller URL.
If connection errors are detected, it aborts execution of the script and relay error messages to upstream
@ -366,7 +366,12 @@ class DecortController(object):
while retry_counter > 0:
try:
api_resp = arg_req_function(req_url, params=arg_params, headers=http_headers, verify=self.verify_ssl)
api_resp = arg_req_function(
req_url,
files=arg_files,
params=arg_params,
headers=http_headers,
verify=self.verify_ssl)
except requests.exceptions.ConnectionError:
self.result['failed'] = True
self.result['msg'] = "Failed to connect to '{}' when calling DECORT API.".format(api_resp.url)
@ -801,7 +806,8 @@ class DecortController(object):
sepId=sep_id,
pool=pool_name,
start=start_on_create, # start_machine parameter requires DECORT API ver 3.3.1 or higher
interfaces='[]') # we create VM without any network connections
interfaces='[]'# we create VM without any network connections
)
if userdata:
api_params['userdata'] = json.dumps(userdata) # we need to pass a string object as "userdata"
@ -3209,8 +3215,12 @@ class DecortController(object):
ret_rules = self._pfw_get(comp_facts['id'], vins_facts['id'])
return ret_rules
def _k8s_get_by_id(self, k8s_id):
##############################
#
# K8s management
#
##############################
def k8s_get_by_id(self, k8s_id):
"""Helper function that locates k8s by ID and returns k8s facts.
@param (int) k8s_id: ID of the k8s to find and return facts for.
@ -3230,19 +3240,13 @@ class DecortController(object):
api_params = dict(k8sId=k8s_id, )
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/k8s/get", api_params)
if api_resp.status_code == 200:
ret_k8s_id = k8s_id
ret_k8s_dict = json.loads(api_resp.content.decode('utf8'))
else:
self.result['warning'] = ("k8s_get_by_id(): failed to get k8s by ID {}. HTTP code {}, "
"response {}.").format(k8s_id, api_resp.status_code, api_resp.reason)
return ret_k8s_id, ret_k8s_dict
return ret_k8s_dict
##############################
#
# K8s management
#
##############################
def k8s_find(self, k8s_id, k8s_name="",rg_id=0,check_state=True):
"""Returns non zero k8s ID and a dictionary with k8s details on success, 0 and empty dictionary otherwise.
This method does not fail the run if k8s cannot be located by its name (arg_k8s_name), because this could be
@ -3259,41 +3263,30 @@ class DecortController(object):
@return: dictionary with k8s facts if k8s is present. Empty dictionary otherwise. None on error.
"""
# Resource group can be in one of the following states:
# MODELED, CREATED, DISABLING, DISABLED, ENABLING, DELETING, DELETED, DESTROYED, DESTROYED
#
# Transient state (ending with ING) are invalid from k8s manipulation viewpoint
#
K8S_INVALID_STATES = ["MODELED","DESTROYED","DESTROYING"]
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "k8s_find")
ret_k8s_id = 0
api_params = dict(includedeleted=True)
api_params = dict(includedeleted=True,name=k8s_name,rgId=rg_id)
ret_k8s_dict = None
if k8s_id:
ret_k8s_id, ret_k8s_dict = self._k8s_get_by_id(k8s_id)
if not ret_k8s_id:
self.result['failed'] = True
self.result['msg'] = "k8s_find(): cannot find k8s cluster by ID {}.".format(k8s_id)
self.amodule.fail_json(**self.result)
else:
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/k8s/list", api_params)
if api_resp.status_code == 200:
k8s_list = json.loads(api_resp.content.decode('utf8'))
for k8s_item in k8s_list['data']:
if k8s_item['name'] == k8s_name and k8s_item['rgId'] == rg_id:
if not check_state or k8s_item['status'] not in K8S_INVALID_STATES:
# TODO: rework after k8s/get wilb be updated
self.k8s_vins_id = None
self.k8s_vins_id = k8s_item['vinsId']
#
ret_k8s_id = k8s_item['id']
_, ret_k8s_dict = self._k8s_get_by_id(ret_k8s_id)
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/k8s/list", api_params)
if api_resp.status_code == 200:
k8s_list = json.loads(api_resp.content.decode('utf8'))
if k8s_list['entryCount'] == 0:
return None,None
for k8s_item in k8s_list['data']:
if not check_state or k8s_item['status'] not in K8S_INVALID_STATES:
ret_k8s_id = k8s_item['id']
ret_k8s_dict = self.k8s_get_by_id(ret_k8s_id)
self.k8s_vins_id = k8s_item['vinsId']
return ret_k8s_id, ret_k8s_dict
def k8s_state(self, arg_k8s_dict, arg_desired_state, arg_started=False):
@ -3414,7 +3407,9 @@ class DecortController(object):
return
def k8s_provision(self, k8s_name,
k8ci_id,rg_id,
k8ci_id,
rg_id,
vins_id,
plugin,
master_count,
master_cpu,
@ -3425,7 +3420,17 @@ class DecortController(object):
default_worker,
extnet_id,
with_lb,
annotation, ):
ha_lb,
sans,
init_conf,
cluster_conf,
kublet_conf,
kubeproxy_conf,
join_conf,
oidc_cert,
annotation,
extnet_only,
):
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "k8s_provision")
@ -3441,6 +3446,8 @@ class DecortController(object):
def_wg_disk = default_worker['disk']
def_wg_sepid = default_worker['sep_id']
def_wg_pool = default_worker['pool']
def_wg_ud = json.dumps(default_worker['ci_user_data']) if \
"ci_user_data" in default_worker else None
def_wg_lab = default_worker['labels'] if "labels" in default_worker else None
def_wg_taints = default_worker['taints'] if "taints" in default_worker else None
def_wg_ann = default_worker['annotations'] if "annotations" in default_worker else None
@ -3449,6 +3456,7 @@ class DecortController(object):
api_params = dict(name=k8s_name,
rgId=rg_id,
k8ciId=k8ci_id,
vins_Id=vins_id,
workerGroupName=def_wg_name,
networkPlugin=plugin,
masterNum=master_count,
@ -3468,9 +3476,22 @@ class DecortController(object):
annotations=def_wg_ann,
extnetId=extnet_id,
withLB=with_lb,
highlyAvailableLB=ha_lb,
additionalSANs=sans,
initConfiguration=json.dumps(init_conf) if init_conf else None,
clusterConfiguration=json.dumps(cluster_conf) if cluster_conf else None,
kubeletConfiguration=json.dumps(kublet_conf) if kublet_conf else None,
kubeProxyConfiguration=json.dumps(kubeproxy_conf)if kubeproxy_conf else None,
joinConfiguration=json.dumps(join_conf)if join_conf else None,
desc=annotation,
userData=def_wg_ud,
extnetOnly=extnet_only,
)
api_resp = self.decort_api_call(requests.post, api_url, api_params)
if oidc_cert:
upload_files = {'oidcCertificate': ('cert.pem', str(oidc_cert),'application/x-x509-ca-cert')}
api_resp = self.decort_api_call(requests.post, api_url, api_params, upload_files)
k8s_id = ""
if api_resp.status_code == 200:
for i in range(300):
@ -3490,7 +3511,7 @@ class DecortController(object):
self.result['changed'] = False
return
elif ret_info['status'] == "OK":
k8s_id = ret_info['result']
k8s_id = ret_info['result'][0]
self.result['msg'] = f"k8s_provision(): K8s cluster {k8s_name} created successful"
self.result['changed'] = True
return k8s_id
@ -3564,6 +3585,7 @@ class DecortController(object):
labels=wg['labels'] if "labels" in wg else None,
taints=wg['taints'] if "taints" in wg else None,
annotations=wg['annotations'] if "annotations" in wg else None,
userData=json.dumps(wg['ci_user_data']) if 'ci_user_data' in wg else None
)
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/k8s/workersGroupAdd", api_params)
self.result['changed'] = True
@ -4054,7 +4076,7 @@ class DecortController(object):
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):
def lb_provision(self,lb_name,rg_id,vins_id,ext_net_id,ha_status,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.
@ -4081,6 +4103,7 @@ class DecortController(object):
rgId=rg_id,
extnetId=ext_net_id,
vinsId=vins_id,
highlyAvailable=ha_status,
start=start,
decs=annotation
)
@ -4392,6 +4415,9 @@ class DecortController(object):
return
def _lb_bind_frontend(self,front_name,bind_name,bind_addr=None,bind_port=None,update=False):
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "lb_bind_frontend")
api_params = dict(
lbId=self.lb_id,
frontendName=front_name,
@ -4406,7 +4432,9 @@ class DecortController(object):
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=[]):
def lb_update(self,prime,front_ha_ip,back_ha_ip,lb_backends=[],lb_frontends=[],mod_backends=[],mod_servers=[],mod_frontends=[]):
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "lb_update")
#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]
@ -4449,16 +4477,30 @@ class DecortController(object):
if del_list_fronts:
self._lb_delete_fronts(del_list_fronts)
#set bind_ip
if front_ha_ip != "":
bind_ip = front_ha_ip
if front_ha_ip == "" and back_ha_ip != "":
bind_ip = back_ha_ip
if front_ha_ip == "" and back_ha_ip == "":
if prime["frontendIp"] != "":
bind_ip = prime["frontendIp"]
else:
bind_ip = prime["backendIp"]
if add_list_fronts:
self._lb_add_fronts(add_list_fronts,mod_frontends)
self._lb_add_fronts(add_list_fronts,mod_frontends,bind_ip)
if upd_front_list:
self._lb_update_fronts(upd_front_list,lb_frontends,mod_frontends)
self._lb_update_fronts(upd_front_list,lb_frontends,mod_frontends,bind_ip)
return
def _lb_delete_backends(self,back_list,lb_fronts):
#delete frontends with that backend
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "lb_delete_backends")
for back in back_list:
fronts = list(filter(lambda i: i['backend'] == back,lb_fronts))
if fronts:
@ -4471,6 +4513,9 @@ class DecortController(object):
self.result['changed'] = True
return
def _lb_delete_fronts(self,d_fronts):
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "lb_delete_fronts")
for front in d_fronts:
api_params = dict(
lbId=self.lb_id,
@ -4483,7 +4528,10 @@ class DecortController(object):
self.result['changed'] = True
return
def _lb_add_fronts(self,front_list,mod_fronts):
def _lb_add_fronts(self,front_list,mod_fronts,bind_ip):
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "lb_add_fronts")
for front in front_list:
add_front, = list(filter(lambda i: i['name'] == front,mod_fronts))
api_params = dict(
@ -4496,14 +4544,17 @@ class DecortController(object):
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,
bind['address']if "address" in bind else bind_ip,
bind['port'],
)
return
def _lb_create_backends(self,back_list,mod_backs,mod_serv):
'''
Create backends and add servers to them
'''
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "lb_create_backends")
for back in back_list:
backend, = list(filter(lambda i: i['name'] == back,mod_backs))
api_params = dict(
@ -4536,15 +4587,14 @@ class DecortController(object):
def _lb_update_backends(self,back_list,lb_backs,mod_backs,mod_serv):
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "lb_update_backends")
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:
@ -4619,7 +4669,9 @@ class DecortController(object):
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):
def _lb_update_fronts(self,upd_front_list,lb_frontends,mod_frontends,bind_ip):
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "lb_update_fronts")
for front in upd_front_list:
mod_front, = list(filter(lambda i: i['name'] == front,mod_frontends))
@ -4631,8 +4683,8 @@ class DecortController(object):
self._lb_bind_frontend(
front,
bind['name'],
bind['address']if "address" in bind else None,
bind['port'] if "port" in bind else None,
bind['address']if "address" in bind else bind_ip,
bind['port'],
)
else:
lb_bind, = list(filter(lambda i: i['name'] == bind['name'],lb_front['bindings']))
@ -4642,8 +4694,8 @@ class DecortController(object):
self._lb_bind_frontend(
front,
bind['name'],
bind['address']if "address" in bind else None,
bind['port'] if "port" in bind else None,
bind['address'] if "address" in bind else bind_ip,
bind['port'],
update=True,
)
lb_binds_list.remove(bind['name'])

Loading…
Cancel
Save