|
|
|
@ -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,40 +3263,29 @@ 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'))
|
|
|
|
|
|
|
|
|
|
if k8s_list['entryCount'] == 0:
|
|
|
|
|
return None,None
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
@ -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'])
|
|
|
|
|