diff --git a/docs/avi_upgradeprofile.rst b/docs/avi_upgradeprofile.rst new file mode 100644 index 00000000..2b210390 --- /dev/null +++ b/docs/avi_upgradeprofile.rst @@ -0,0 +1,322 @@ +.. vmware.alb.avi_upgradeprofile: + + +********************************************** +vmware.alb.avi_upgradeprofile +********************************************** + +**Module for setup of UpgradeProfile Avi RESTful Object** + + +.. contents:: + :local: + :depth: 1 + + +Synopsis +-------- +- This module is used to configure UpgradeProfile object. +- More examples at (https://github.com/avinetworks/devops). + + +Parameters +---------- + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterChoices/DefaultsComments
+
+ state + +
+ str +
+
+
    +
  • absent
  • +
  • present ←
  • +
+
+
+ - The state that should be applied on the entity. +
+
+
+ avi_api_update_method + +
+ str +
+
+
    +
  • put ←
  • +
  • patch
  • +
+
+
+ - Default method for object update is HTTP PUT. +
+
+ - Setting to patch will override that behavior to use HTTP PATCH. +
+
+
+ avi_api_patch_op + +
+ str +
+
+
    +
  • add ←
  • +
  • replace
  • +
  • delete
  • +
  • remove
  • +
+
+
+ - Patch operation to use when using avi_api_update_method as patch. +
+
+
+ avi_patch_path + +
+ str +
+
+
+ - Patch path to use when using avi_api_update_method as patch. +
+
+
+ avi_patch_value + +
+ str +
+
+
+ - Patch value to use when using avi_api_update_method as patch. +
+
+
+ controller + +
+ dict +
+
+ +
+ - List of controller upgrade related configurable parameters. +
+
+ - Field introduced in 31.1.1. +
+
+ - Allowed with any value in enterprise, enterprise with cloud services edition. +
+
+
+ dry_run + +
+ dict +
+
+ +
+ - List of dryrun related configurable parameters. +
+
+ - Field introduced in 31.1.1. +
+
+ - Allowed with any value in enterprise, enterprise with cloud services edition. +
+
+
+ image + +
+ dict +
+
+ +
+ - List of image related configurable parameters. +
+
+ - Field introduced in 31.1.1. +
+
+ - Allowed with any value in enterprise, enterprise with cloud services edition. +
+
+
+ pre_checks + +
+ dict +
+
+ +
+ - List of upgrade pre-checks related configurable parameters. +
+
+ - Field introduced in 31.1.1. +
+
+ - Allowed with any value in enterprise, enterprise with cloud services edition. +
+
+
+ service_engine + +
+ dict +
+
+ +
+ - List of service engine upgrade related configurable parameters. +
+
+ - Field introduced in 31.1.1. +
+
+ - Allowed with any value in enterprise, enterprise with cloud services edition. +
+
+
+ url + +
+ str +
+
+ +
+ - Avi controller URL of the object. +
+
+
+ uuid + +
+ str +
+
+ +
+ - Uuid identifier for the upgradeprofile object. +
+
+ - Field introduced in 31.1.1. +
+
+ - Allowed with any value in enterprise, enterprise with cloud services edition. +
+
+
+ + +Examples +-------- + +.. code-block:: yaml + + - hosts: localhost + connection: local + collections: + - vmware.alb + vars: + avi_credentials: + username: "avi_user" + password: "avi_password" + controller: "192.168.138.18" + api_version: "21.1.1" + tasks: + - name: Example to create UpgradeProfile object + avi_upgradeprofile: + avi_credentials: "{{ avi_credentials }}" + state: present + name: sample_upgradeprofile + + +Authors +~~~~~~~ +- Gaurav Rastogi (grastogi@vmware.com) +- Sandeep Bandi (sbandi@vmware.com) +- Amol Shinde (samol@vmware.com) + + + diff --git a/galaxy.yml b/galaxy.yml index 47ee4fbe..bdfee08a 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -18,4 +18,4 @@ tags: - load - balancer - sdk -version: 31.1.1 +version: 31.1.2 diff --git a/plugins/module_utils/avi_api.py b/plugins/module_utils/avi_api.py index 409dd640..e1afb09e 100644 --- a/plugins/module_utils/avi_api.py +++ b/plugins/module_utils/avi_api.py @@ -99,7 +99,6 @@ class ApiResponse(Response): routines 1. obj: returns dictionary of Avi Object """ - def __init__(self, rsp): super(ApiResponse, self).__init__() for k, v in list(rsp.__dict__.items()): @@ -298,11 +297,9 @@ def __init__(self, controller_ip=None, username=None, password=None, # Check if the IP address is IPv6 if is_ipv6: - self.prefix = '{}://[{}]'.format(protocol, - self.avi_credentials.controller) + self.prefix = '{}://[{}]'.format(protocol, self.avi_credentials.controller) else: - self.prefix = '{}://{}'.format(protocol, - self.avi_credentials.controller) + self.prefix = '{}://{}'.format(protocol, self.avi_credentials.controller) # Include the port in the prefix if specified if port: @@ -329,10 +326,8 @@ def __init__(self, controller_ip=None, username=None, password=None, elif self.avi_credentials.csp_token: if self.avi_credentials.csp_host: if self.avi_credentials.csp_host.startswith('https'): - self.avi_credentials.csp_host = self.avi_credentials.csp_host.replace( - 'https://', '') - self.csp_prefix = 'https://{x}/csp/gateway'.format( - x=self.avi_credentials.csp_host) + self.avi_credentials.csp_host = self.avi_credentials.csp_host.replace('https://', '') + self.csp_prefix = 'https://{x}/csp/gateway'.format(x=self.avi_credentials.csp_host) self.generate_access_token() else: raise APIError("CSP host is not provided for csp login.") @@ -696,8 +691,7 @@ def _api(self, api_name, path, tenant, tenant_uuid, data=None, if connection_error or resp.status_code in (401, 419): if 'multipart/form-data' in api_hdrs['Content-Type']: if connection_error: - raise AviMultipartUploadError( - "Connection failed or aborted") + raise AviMultipartUploadError("Connection failed or aborted") else: raise AviMultipartUploadError('Received error,: %d Error ' 'Msg %s' % (resp.status_code, @@ -1151,7 +1145,6 @@ def is_ipv6_address(self, controller_ip): ip = ipaddress.ip_address(controller_ip) return ip.version == self.IPV6 except ValueError as ve: - logger.warning( - 'Invalid Controller IP6 Address: %s - %s', controller_ip, ve) + logger.warning('Invalid Controller IP6 Address: %s - %s', controller_ip, ve) return False # End of file diff --git a/plugins/module_utils/csp_avi_api.py b/plugins/module_utils/csp_avi_api.py index e8946d8c..f4e93c49 100644 --- a/plugins/module_utils/csp_avi_api.py +++ b/plugins/module_utils/csp_avi_api.py @@ -6,6 +6,7 @@ __metaclass__ = type from ansible_collections.vmware.alb.plugins.module_utils.avi_api import ApiSession, APIError +import sys import logging import time @@ -48,8 +49,7 @@ def generate_access_token(self): if self.avi_credentials.csp_token: body["api_token"] = self.avi_credentials.csp_token else: - raise APIError( - "CSP API Token is not provided for csp login %s" % self.csp_prefix) + raise APIError("CSP API Token is not provided for csp login %s" % self.csp_prefix) logger.debug('authenticating using api token %s prefix %s', self.avi_credentials.csp_token, self.csp_prefix) self.cookies.clear() @@ -61,8 +61,7 @@ def generate_access_token(self): if rsp.status_code == 200: self.num_session_retries = 0 - authorization_token = {"Authorization": "Bearer %s" % ( - rsp.json().get('access_token'))} + authorization_token = {"Authorization": "Bearer %s" % (rsp.json().get('access_token'))} self.headers.update(authorization_token) logger.debug("authentication success for user %s", self.avi_credentials.csp_token) diff --git a/plugins/module_utils/saml_avi_api.py b/plugins/module_utils/saml_avi_api.py index 3b5b5f1c..f1a9d38d 100644 --- a/plugins/module_utils/saml_avi_api.py +++ b/plugins/module_utils/saml_avi_api.py @@ -85,10 +85,8 @@ def saml_assertion(self, username, password): logger.error("SAML request not generated by controller.") raise APIError("SAML request not generated by controller.") saml_request = saml_request_match.group(1) - relay_state = re.search( - WS1loginSAMLApiSession.request_relay_state_regex, resp.text, re.M | re.S).group(1) - assertion_url = re.search( - WS1loginSAMLApiSession.request_assertion_url_regex, resp.text, re.M | re.S).group(1) + relay_state = re.search(WS1loginSAMLApiSession.request_relay_state_regex, resp.text, re.M | re.S).group(1) + assertion_url = re.search(WS1loginSAMLApiSession.request_assertion_url_regex, resp.text, re.M | re.S).group(1) headers = {'Content-Type': 'application/x-www-form-urlencoded'} saml_data = urllib.parse.urlencode({ 'SAMLRequest': saml_request, @@ -113,10 +111,8 @@ def saml_assertion(self, username, password): if "SAMLResponse" not in idp_resp.text: # credentials payload for given IDP parsed_uri = urllib.parse.urlparse(assertion_url) - auth_url = "{}://{}/SAAS/API/1.0/REST/auth/system/login".format( - parsed_uri.scheme, parsed_uri.netloc) - auth = {'username': username, - 'password': password, 'issueToken': 'true'} + auth_url = "{}://{}/SAAS/API/1.0/REST/auth/system/login".format(parsed_uri.scheme, parsed_uri.netloc) + auth = {'username': username, 'password': password, 'issueToken': 'true'} idp_session.headers.update({'content-type': 'application/json'}) idp_session.headers.update({'accept': 'application/json'}) idp_session.verify = False @@ -168,8 +164,7 @@ def authenticate_session(self): saml_response = saml_resp.find('textarea').string relay_state = re.search(WS1loginSAMLApiSession.response_relay_state_regex, content, re.M | re.S).group(1) - assertion_url = re.search( - WS1loginSAMLApiSession.response_assertion_url_regex, content, re.M | re.S).group(1) + assertion_url = re.search(WS1loginSAMLApiSession.response_assertion_url_regex, content, re.M | re.S).group(1) saml_data = urllib.parse.urlencode({ 'SAMLResponse': saml_response, 'RelayState': relay_state diff --git a/plugins/module_utils/utils/ansible_utils.py b/plugins/module_utils/utils/ansible_utils.py index cae6453a..e5462e2d 100644 --- a/plugins/module_utils/utils/ansible_utils.py +++ b/plugins/module_utils/utils/ansible_utils.py @@ -174,7 +174,6 @@ def get_unicode_type(): HTTP_REF_W_NAME_MATCH = re.compile(r'https://[\w.0-9:-]+/api/.*#.+') HTTP_REF_W_NAME_MATCH_IPV6 = re.compile(r'https://[[\w.0-9:-]+]/api/.*#.+') - def ref_n_str_cmp(x, y): """ compares two references diff --git a/plugins/modules/avi_albservicesconfig.py b/plugins/modules/avi_albservicesconfig.py index 36df5371..124ffb3d 100644 --- a/plugins/modules/avi_albservicesconfig.py +++ b/plugins/modules/avi_albservicesconfig.py @@ -218,6 +218,7 @@ returned: success, changed type: dict ''' + from ansible.module_utils.basic import AnsibleModule try: from ansible_collections.vmware.alb.plugins.module_utils.utils.ansible_utils import ( diff --git a/plugins/modules/avi_api_fileservice.py b/plugins/modules/avi_api_fileservice.py index 54b0edf0..f90f29f3 100644 --- a/plugins/modules/avi_api_fileservice.py +++ b/plugins/modules/avi_api_fileservice.py @@ -90,9 +90,10 @@ type: dict ''' -import os import json +import os from ansible.module_utils.basic import AnsibleModule + try: from requests_toolbelt import MultipartEncoder HAS_LIB = True @@ -159,8 +160,7 @@ def main(): uri = 'controller://upgrade_pkgs' path = 'fileservice/uploads' else: - uri = 'controller://%s' % module.params.get( - 'path', '').split('?')[0] + uri = 'controller://%s' % module.params.get('path', '').split('?')[0] changed = False file_uri = 'fileservice?uri=%s' % uri rsp = api.post(file_uri, tenant=tenant, tenant_uuid=tenant_uuid, diff --git a/plugins/modules/avi_api_image.py b/plugins/modules/avi_api_image.py index e7d86dd4..900f61de 100644 --- a/plugins/modules/avi_api_image.py +++ b/plugins/modules/avi_api_image.py @@ -61,6 +61,7 @@ import os from ansible.module_utils.basic import AnsibleModule + try: from requests_toolbelt import MultipartEncoder HAS_LIB = True diff --git a/plugins/modules/avi_api_session.py b/plugins/modules/avi_api_session.py index dec278b1..82109da5 100644 --- a/plugins/modules/avi_api_session.py +++ b/plugins/modules/avi_api_session.py @@ -119,10 +119,11 @@ type: dict ''' -from copy import deepcopy -import time import json +import time from ansible.module_utils.basic import AnsibleModule +from copy import deepcopy + try: from ansible_collections.vmware.alb.plugins.module_utils.utils.ansible_utils import ( avi_common_argument_spec, ansible_return, avi_obj_cmp, @@ -156,7 +157,7 @@ def main(): api_creds.controller, api_creds.username, password=api_creds.password, timeout=api_creds.timeout, tenant=api_creds.tenant, tenant_uuid=api_creds.tenant_uuid, token=api_creds.token, - port=api_creds.port, ssl_cert=api_creds.ssl_cert, + port=api_creds.port,ssl_cert=api_creds.ssl_cert, ssl_key=api_creds.ssl_key) tenant_uuid = api_creds.tenant_uuid @@ -178,8 +179,7 @@ def main(): gparams.update({'include_refs': '', 'include_name': ''}) # API methods not allowed - api_get_not_allowed = ["cluster", "gslbsiteops", - "server", "nsxt", "vcenter", "macro"] + api_get_not_allowed = ["cluster", "gslbsiteops", "server", "nsxt", "vcenter", "macro"] sub_api_get_not_allowed = ["scaleout", "scalein", "upgrade", "rollback"] api_post_not_allowed = ["alert", "fileservice"] api_put_not_allowed = ["backup"] diff --git a/plugins/modules/avi_api_version.py b/plugins/modules/avi_api_version.py index e65df27a..cb64f457 100644 --- a/plugins/modules/avi_api_version.py +++ b/plugins/modules/avi_api_version.py @@ -46,6 +46,7 @@ ''' from ansible.module_utils.basic import AnsibleModule + try: from ansible_collections.vmware.alb.plugins.module_utils.utils.ansible_utils import avi_common_argument_spec from ansible_collections.vmware.alb.plugins.module_utils.avi_api import ( diff --git a/plugins/modules/avi_bootstrap_controller.py b/plugins/modules/avi_bootstrap_controller.py index 85681c70..6882865b 100644 --- a/plugins/modules/avi_bootstrap_controller.py +++ b/plugins/modules/avi_bootstrap_controller.py @@ -93,8 +93,7 @@ def controller_wait(controller_ip, port=None, round_wait=10, wait_time=3600): count = 0 max_count = wait_time / round_wait ctrl_port = port if port else 80 - path = "http://{1}:{2}{3}".format(controller_ip, - ctrl_port, "/api/cluster/runtime") + path = "http://{1}:{2}{3}".format(controller_ip, ctrl_port, "/api/cluster/runtime") ctrl_status = False while True: if count >= max_count: @@ -147,16 +146,13 @@ def main(): password=new_password, timeout=api_creds.timeout, tenant=api_creds.tenant, tenant_uuid=api_creds.tenant_uuid, token=api_creds.token, port=api_creds.port) - module.exit_json( - msg="Already initialized controller password with a given password.", changed=False) + module.exit_json(msg="Already initialized controller password with a given password.", changed=False) except Exception as e: pass cmd = "ssh -o \"StrictHostKeyChecking no\" -t -i " + key_pair + " admin@" + \ api_creds.controller + " \"ls /opt/avi/scripts/initialize_admin_user.py && echo -e '" + \ - api_creds.controller + "\\n" + new_password + \ - "' | sudo /opt/avi/scripts/initialize_admin_user.py\"" - process = subprocess.Popen( - cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True) + api_creds.controller + "\\n" + new_password + "' | sudo /opt/avi/scripts/initialize_admin_user.py\"" + process = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True) stdout, stderr = process.communicate() cmd_status = process.returncode if cmd_status == 0: diff --git a/plugins/modules/avi_deploy_controller.py b/plugins/modules/avi_deploy_controller.py index 322f6bbe..1352edc2 100644 --- a/plugins/modules/avi_deploy_controller.py +++ b/plugins/modules/avi_deploy_controller.py @@ -210,8 +210,7 @@ def is_vm_exist(si, cl, vm_name): - container = si.content.viewManager.CreateContainerView( - cl, [vim.VirtualMachine], True) + container = si.content.viewManager.CreateContainerView(cl, [vim.VirtualMachine], True) for managed_object_ref in container.view: if managed_object_ref.name == vm_name: return True @@ -315,8 +314,7 @@ def get_sysadmin_key(keypath): with open(keypath, 'r') as keyfile: data = keyfile.read().rstrip('\n') return data - raise Exception( - 'Failed to find sysadmin public key file at %s\n' % keypath) + raise Exception('Failed to find sysadmin public key file at %s\n' % keypath) def get_largest_free_ds(cl): @@ -488,8 +486,7 @@ def main(): vcenter_user=dict(required=True, type='str'), vcenter_password=dict(required=True, type='str', no_log=True), ssl_verify=dict(required=False, type='bool', default=False), - state=dict(required=False, type='str', default='present', - choices=['absent', 'present']), + state=dict(required=False, type='str', default='present', choices=['absent', 'present']), con_datacenter=dict(required=False, type='str'), con_cluster=dict(required=False, type='str'), con_datastore=dict(required=False, type='str'), @@ -507,10 +504,8 @@ def main(): con_mgmt_mask_v6=dict(required=False, type='str'), con_default_gw=dict(required=False, type='str'), con_default_gw_v6=dict(required=False, type='str'), - con_mgmt_ip_v4_enable=dict( - required=False, type='bool', default=True), - con_mgmt_ip_v6_enable=dict( - required=False, type='bool', default=False), + con_mgmt_ip_v4_enable=dict(required=False, type='bool', default=True), + con_mgmt_ip_v6_enable=dict(required=False, type='bool', default=False), con_sysadmin_public_key=dict(required=False, type='str'), con_number_of_cpus=dict(required=False, type='int'), con_cpu_reserved=dict(required=False, type='int'), @@ -582,8 +577,7 @@ def main(): if is_vm_exist(si, cl, module.params['con_vm_name']): vm = get_vm_by_name(si, module.params['con_vm_name']) vm_path = compile_folder_path_for_object(vm) - folder = get_folder_by_path( - si, dc, module.params['con_vcenter_folder']) + folder = get_folder_by_path(si, dc, module.params['con_vcenter_folder']) folder_path = compile_folder_path_for_object(folder) changed = False if vm_path != folder_path: @@ -686,8 +680,7 @@ def main(): if (module.params['con_ova_path'].startswith('http')): if (requests.head(module.params['con_ova_path'], verify=module.params['ssl_verify']).status_code != 200): - module.fail_json( - msg='Controller OVA not found or readable from specified URL path') + module.fail_json(msg='Controller OVA not found or readable from specified URL path') else: if (not os.path.isfile(module.params['con_ova_path']) or not os.access(module.params['con_ova_path'], os.R_OK)): @@ -765,10 +758,10 @@ def main(): 'avi.default-gw.CONTROLLER', module.params['con_default_gw'])) command_tokens.append('--prop:%s=%s' % ( - 'avi.mgmt-ip-v6-enable.CONTROLLER', module.params['con_mgmt_ip_v6_enable'])) + 'avi.mgmt-ip-v6-enable.CONTROLLER', module.params['con_mgmt_ip_v6_enable'])) command_tokens.append('--prop:%s=%s' % ( - 'avi.mgmt-ip-v4-enable.CONTROLLER', module.params['con_mgmt_ip_v4_enable'])) + 'avi.mgmt-ip-v4-enable.CONTROLLER', module.params['con_mgmt_ip_v4_enable'])) if module.params.get('con_sysadmin_public_key', None): command_tokens.append('--prop:%s=%s' % ( @@ -834,8 +827,7 @@ def main(): timeout = 300 controller_ip = None while timeout > 0: - controller_ip = get_vm_ip_by_network( - vm, module.params['con_mgmt_network']) + controller_ip = get_vm_ip_by_network(vm, module.params['con_mgmt_network']) if controller_ip: controller_ip = controller_ip[0] break diff --git a/plugins/modules/avi_gslbservice_patch_member.py b/plugins/modules/avi_gslbservice_patch_member.py index a0068e21..e75bc13a 100644 --- a/plugins/modules/avi_gslbservice_patch_member.py +++ b/plugins/modules/avi_gslbservice_patch_member.py @@ -107,8 +107,9 @@ type: dict ''' -from copy import deepcopy from ansible.module_utils.basic import AnsibleModule +from copy import deepcopy + try: from ansible_collections.vmware.alb.plugins.module_utils.utils.ansible_utils import ( avi_common_argument_spec, ansible_return, AviCheckModeResponse, avi_obj_cmp, @@ -123,8 +124,7 @@ def delete_member(module, check_mode, api, tenant, tenant_uuid, existing_obj, data, api_version): members = data.get('group', {}).get('members', []) - patched_member_ids = set([m['ip']['addr'] - for m in members if 'fqdn' not in m]) + patched_member_ids = set([m['ip']['addr'] for m in members if 'fqdn' not in m]) patched_member_fqdns = set([m['fqdn'] for m in members if 'fqdn' in m]) changed = False @@ -134,10 +134,8 @@ def delete_member(module, check_mode, api, tenant, tenant_uuid, groups = [group for group in existing_obj.get('groups', []) if group['name'] == data['group']['name']] if groups: - changed = any((m['ip']['addr'] in patched_member_ids) - for m in groups[0].get('members', []) if 'fqdn' not in m) - changed = changed or any((m['fqdn'] in patched_member_fqdns) - for m in groups[0].get('members', []) if 'fqdn' in m) + changed = any((m['ip']['addr'] in patched_member_ids) for m in groups[0].get('members', []) if 'fqdn' not in m) + changed = changed or any((m['fqdn'] in patched_member_fqdns) for m in groups[0].get('members', []) if 'fqdn' in m) if check_mode or not changed: return changed, rsp # should not come here if not found diff --git a/plugins/modules/avi_ipaddrgroup.py b/plugins/modules/avi_ipaddrgroup.py index 5eb2255d..4323950f 100644 --- a/plugins/modules/avi_ipaddrgroup.py +++ b/plugins/modules/avi_ipaddrgroup.py @@ -165,7 +165,6 @@ type: dict ''' - from ansible.module_utils.basic import AnsibleModule try: from ansible_collections.vmware.alb.plugins.module_utils.utils.ansible_utils import ( diff --git a/plugins/modules/avi_pingaccessagent.py b/plugins/modules/avi_pingaccessagent.py index 1f65a499..ebe87b8e 100644 --- a/plugins/modules/avi_pingaccessagent.py +++ b/plugins/modules/avi_pingaccessagent.py @@ -66,7 +66,6 @@ - Allowed in enterprise edition with any value, essentials edition with any value, basic edition with any value, enterprise with cloud services - edition. type: list - elements: dict name: description: - Name of the pingaccess agent. diff --git a/plugins/modules/avi_pulse_registration.py b/plugins/modules/avi_pulse_registration.py index fedebf41..145ddd11 100644 --- a/plugins/modules/avi_pulse_registration.py +++ b/plugins/modules/avi_pulse_registration.py @@ -179,8 +179,9 @@ type: dict ''' -from ansible.module_utils.basic import AnsibleModule + import time +from ansible.module_utils.basic import AnsibleModule try: from ansible_collections.vmware.alb.plugins.module_utils.utils.ansible_utils import ( avi_common_argument_spec, AviCheckModeResponse, avi_obj_cmp) @@ -193,10 +194,8 @@ def main(): case_spec = dict( - enable_auto_case_creation_on_controller_failure=dict( - type='bool', default=False), - enable_auto_case_creation_on_se_failure=dict( - type='bool', default=False) + enable_auto_case_creation_on_controller_failure=dict(type='bool', default=False), + enable_auto_case_creation_on_se_failure=dict(type='bool', default=False) ) waf_spec = dict( enable_auto_download_waf_signatures=dict(type='bool', default=False), @@ -223,8 +222,7 @@ def main(): case_config=dict(type='dict', options=case_spec) ) argument_specs.update(avi_common_argument_spec()) - module = AnsibleModule(argument_spec=argument_specs, - supports_check_mode=True) + module = AnsibleModule(argument_spec=argument_specs, supports_check_mode=True) if not HAS_REQUESTS: return module.fail_json(msg=( 'Python requests package is not installed. ' @@ -250,33 +248,24 @@ def main(): account_id = module.params.get('account_id', None) portal_url = 'https://portal.avipulse.vmware.com' optins = module.params.get('optins', None) - enable_cleanup_of_attached_files = module.params.get( - 'enable_cleanup_of_attached_files', None) - enable_appsignature_sync = module.params.get( - 'enable_appsignature_sync', None) + enable_cleanup_of_attached_files = module.params.get('enable_cleanup_of_attached_files', None) + enable_appsignature_sync = module.params.get('enable_appsignature_sync', None) enable_ip_reputation = module.params.get('enable_ip_reputation', None) - enable_pulse_case_management = module.params.get( - 'enable_pulse_case_management', None) - enable_pulse_waf_management = module.params.get( - 'enable_pulse_waf_management', None) - enable_user_agent_db_sync = module.params.get( - 'enable_user_agent_db_sync', None) + enable_pulse_case_management = module.params.get('enable_pulse_case_management', None) + enable_pulse_waf_management = module.params.get('enable_pulse_waf_management', None) + enable_user_agent_db_sync = module.params.get('enable_user_agent_db_sync', None) use_tls = module.params.get('use_tls', None) waf_config = module.params.get('waf_config', None) case_config = module.params.get('case_config', None) if waf_config: - enable_auto_download_waf_signatures = module.params.get( - 'waf_config', dict()).get('enable_auto_download_waf_signatures', None) - enable_waf_signatures_notifications = module.params.get( - 'waf_config', dict()).get('enable_waf_signatures_notifications', None) + enable_auto_download_waf_signatures = module.params.get('waf_config', dict()).get('enable_auto_download_waf_signatures', None) + enable_waf_signatures_notifications = module.params.get('waf_config', dict()).get('enable_waf_signatures_notifications', None) else: enable_auto_download_waf_signatures = False enable_waf_signatures_notifications = False if case_config: - enable_auto_case_creation_on_controller_failure = module.params.get( - 'case_config', dict()).get('enable_auto_case_creation_on_controller_failure', None) - enable_auto_case_creation_on_se_failure = module.params.get( - 'case_config', dict()).get('enable_auto_case_creation_on_se_failure', None) + enable_auto_case_creation_on_controller_failure = module.params.get('case_config', dict()).get('enable_auto_case_creation_on_controller_failure', None) + enable_auto_case_creation_on_se_failure = module.params.get('case_config', dict()).get('enable_auto_case_creation_on_se_failure', None) else: enable_auto_case_creation_on_controller_failure = False enable_auto_case_creation_on_se_failure = False @@ -285,16 +274,13 @@ def main(): if state == 'present': # registration path = "albservices/status" - resp = api.get(path, tenant=tenant, - tenant_uuid=tenant_uuid, api_version=api_version) + resp = api.get(path, tenant=tenant, tenant_uuid=tenant_uuid, api_version=api_version) existing_obj = resp if not (check_mode) and resp.json().get("connectivity_status") == "ALBSERVICES_DISCONNECTED": - headers = {'Content-Type': 'application/json', - 'Authorization': 'Basic YWRtaW46YWRtaW4='} + headers = {'Content-Type': 'application/json', 'Authorization': 'Basic YWRtaW46YWRtaW4='} data = {"jwt_token": jwt_token} path = "portal/refresh-access-token" - rsp = api.post(path, api_version=api_version, - headers=headers, data=data) + rsp = api.post(path, api_version=api_version, headers=headers, data=data) if rsp.status_code > 300: return module.fail_json(msg='Failed: %s' % rsp.text) else: @@ -335,42 +321,31 @@ def main(): data["portal_url"] = portal_url data["polling_interval"] = 10 data["feature_opt_in_status"] = dict() - data[("feature_opt_in_status") - ]["enable_appsignature_sync"] = enable_appsignature_sync - data[("feature_opt_in_status") - ]["enable_ip_reputation"] = enable_ip_reputation - data[("feature_opt_in_status") - ]["enable_pulse_case_management"] = enable_pulse_case_management - data[("feature_opt_in_status") - ]["enable_pulse_waf_management"] = enable_pulse_waf_management - data[("feature_opt_in_status") - ]["enable_user_agent_db_sync"] = enable_user_agent_db_sync + data[("feature_opt_in_status")]["enable_appsignature_sync"] = enable_appsignature_sync + data[("feature_opt_in_status")]["enable_ip_reputation"] = enable_ip_reputation + data[("feature_opt_in_status")]["enable_pulse_case_management"] = enable_pulse_case_management + data[("feature_opt_in_status")]["enable_pulse_waf_management"] = enable_pulse_waf_management + data[("feature_opt_in_status")]["enable_user_agent_db_sync"] = enable_user_agent_db_sync data[("tenant_config")] = dict() data[("tenant_config")]["heartbeat_interval"] = 3 data[("tenant_config")]["token_refresh_interval"] = 57 data[("tenant_config")]["license_escrow_interval"] = 60 data["ip_reputation_config"] = dict() - data[("ip_reputation_config") - ]["ip_reputation_file_object_expiry_duration"] = 3 - data[("ip_reputation_config") - ]["ip_reputation_sync_interval"] = 60 + data[("ip_reputation_config")]["ip_reputation_file_object_expiry_duration"] = 3 + data[("ip_reputation_config")]["ip_reputation_sync_interval"] = 60 data["use_tls"] = use_tls data["mode"] = "MYVMWARE" data["app_signature_config"] = dict() - data[("app_signature_config") - ]["app_signature_sync_interval"] = 1440 + data[("app_signature_config")]["app_signature_sync_interval"] = 1440 data["user_agent_db_config"] = dict() data[("user_agent_db_config")]["allowed_batch_size"] = 500 data["waf_config"] = dict() - data[( - "waf_config")]["enable_auto_download_waf_signatures"] = enable_auto_download_waf_signatures - data[( - "waf_config")]["enable_waf_signatures_notifications"] = enable_waf_signatures_notifications + data[("waf_config")]["enable_auto_download_waf_signatures"] = enable_auto_download_waf_signatures + data[("waf_config")]["enable_waf_signatures_notifications"] = enable_waf_signatures_notifications data["case_config"] = dict() data[("case_config")]["enable_auto_case_creation_on_controller_failure"] = enable_auto_case_creation_on_controller_failure data[("case_config")]["enable_auto_case_creation_on_se_failure"] = enable_auto_case_creation_on_se_failure - data[( - "case_config")]["enable_cleanup_of_attached_files"] = enable_cleanup_of_attached_files + data[("case_config")]["enable_cleanup_of_attached_files"] = enable_cleanup_of_attached_files data["saas_licensing_config"] = dict() data[("saas_licensing_config")]["max_service_units"] = 1000 data[("saas_licensing_config")]["reserve_service_units"] = 0 diff --git a/plugins/modules/avi_saml_api_session.py b/plugins/modules/avi_saml_api_session.py index 2509df35..19b8b333 100644 --- a/plugins/modules/avi_saml_api_session.py +++ b/plugins/modules/avi_saml_api_session.py @@ -99,6 +99,7 @@ avi_common_argument_spec, ansible_return) from ansible_collections.vmware.alb.plugins.module_utils.avi_api import ( ApiSession, AviCredentials) + from pkg_resources import parse_version from requests import ConnectionError from ssl import SSLError from requests.exceptions import ChunkedEncodingError diff --git a/plugins/modules/avi_serviceenginegroup_advanced.py b/plugins/modules/avi_serviceenginegroup_advanced.py index b0902a9d..7b99d053 100644 --- a/plugins/modules/avi_serviceenginegroup_advanced.py +++ b/plugins/modules/avi_serviceenginegroup_advanced.py @@ -6,6 +6,7 @@ # Copyright 2021 VMware, Inc. All rights reserved. VMware Confidential # SPDX-License-Identifier: Apache License 2.0 from __future__ import absolute_import, division, print_function + __metaclass__ = type ANSIBLE_METADATA = { "metadata_version": "1.1", @@ -821,8 +822,7 @@ def main(): waf_mempool_size=dict(type="int"), ) argument_specs.update(avi_common_argument_spec()) - module = AnsibleModule(argument_spec=argument_specs, - supports_check_mode=True) + module = AnsibleModule(argument_spec=argument_specs, supports_check_mode=True) if not HAS_REQUESTS: return module.fail_json( msg="Python requests package is not installed. For installation instructions, visit https://pypi.org/project/requests." diff --git a/plugins/modules/avi_upgradeprofile.py b/plugins/modules/avi_upgradeprofile.py new file mode 100644 index 00000000..e755701f --- /dev/null +++ b/plugins/modules/avi_upgradeprofile.py @@ -0,0 +1,154 @@ +#!/usr/bin/python +# module_check: supported + +# Copyright 2021 VMware, Inc. All rights reserved. VMware Confidential +# SPDX-License-Identifier: Apache License 2.0 + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + +DOCUMENTATION = ''' +--- +module: avi_upgradeprofile +author: Gaurav Rastogi (@grastogi23) +short_description: Module for setup of UpgradeProfile Avi RESTful Object +description: + - This module is used to configure UpgradeProfile object + - more examples at U(https://github.com/avinetworks/devops) +options: + state: + description: + - The state that should be applied on the entity. + default: present + choices: ["absent", "present"] + type: str + avi_api_update_method: + description: + - Default method for object update is HTTP PUT. + - Setting to patch will override that behavior to use HTTP PATCH. + default: put + choices: ["put", "patch"] + type: str + avi_api_patch_op: + description: + - Patch operation to use when using avi_api_update_method as patch. + choices: ["add", "replace", "delete", "remove"] + type: str + avi_patch_path: + description: + - Patch path to use when using avi_api_update_method as patch. + type: str + avi_patch_value: + description: + - Patch value to use when using avi_api_update_method as patch. + type: str + controller: + description: + - List of controller upgrade related configurable parameters. + - Field introduced in 31.1.1. + - Allowed with any value in enterprise, enterprise with cloud services edition. + type: dict + dry_run: + description: + - List of dryrun related configurable parameters. + - Field introduced in 31.1.1. + - Allowed with any value in enterprise, enterprise with cloud services edition. + type: dict + image: + description: + - List of image related configurable parameters. + - Field introduced in 31.1.1. + - Allowed with any value in enterprise, enterprise with cloud services edition. + type: dict + pre_checks: + description: + - List of upgrade pre-checks related configurable parameters. + - Field introduced in 31.1.1. + - Allowed with any value in enterprise, enterprise with cloud services edition. + type: dict + service_engine: + description: + - List of service engine upgrade related configurable parameters. + - Field introduced in 31.1.1. + - Allowed with any value in enterprise, enterprise with cloud services edition. + type: dict + url: + description: + - Avi controller URL of the object. + type: str + uuid: + description: + - Uuid identifier for the upgradeprofile object. + - Field introduced in 31.1.1. + - Allowed with any value in enterprise, enterprise with cloud services edition. + type: str +extends_documentation_fragment: + - vmware.alb.avi +''' + +EXAMPLES = """ +- hosts: all + vars: + avi_credentials: + username: "admin" + password: "something" + controller: "192.168.15.18" + api_version: "21.1.1" + +- name: Example to create UpgradeProfile object + vmware.alb.avi_upgradeprofile: + avi_credentials: "{{ avi_credentials }}" + state: present + name: sample_upgradeprofile +""" + +RETURN = ''' +obj: + description: UpgradeProfile (api/upgradeprofile) object + returned: success, changed + type: dict +''' + +from ansible.module_utils.basic import AnsibleModule +try: + from ansible_collections.vmware.alb.plugins.module_utils.utils.ansible_utils import ( + avi_common_argument_spec, avi_ansible_api) + HAS_REQUESTS = True +except ImportError: + HAS_REQUESTS = False + + +def main(): + argument_specs = dict( + state=dict(default='present', + choices=['absent', 'present']), + avi_api_update_method=dict(default='put', + choices=['put', 'patch']), + avi_api_patch_op=dict(choices=['add', 'replace', 'delete', 'remove']), + avi_patch_path=dict(type='str',), + avi_patch_value=dict(type='str',), + controller=dict(type='dict',), + dry_run=dict(type='dict',), + image=dict(type='dict',), + pre_checks=dict(type='dict',), + service_engine=dict(type='dict',), + url=dict(type='str',), + uuid=dict(type='str',), + ) + argument_specs.update(avi_common_argument_spec()) + module = AnsibleModule( + argument_spec=argument_specs, supports_check_mode=True) + if not HAS_REQUESTS: + return module.fail_json(msg=( + 'Python requests package is not installed. ' + 'For installation instructions, visit https://pypi.org/project/requests.')) + return avi_ansible_api(module, 'upgradeprofile', + set()) + + +if __name__ == '__main__': + main() diff --git a/plugins/modules/avi_user.py b/plugins/modules/avi_user.py index cafbe59b..84e95534 100644 --- a/plugins/modules/avi_user.py +++ b/plugins/modules/avi_user.py @@ -168,8 +168,7 @@ def main(): default_tenant_ref=dict(type='str', default='/api/tenant?name=admin'), ) argument_specs.update(avi_common_argument_spec()) - module = AnsibleModule(argument_spec=argument_specs, - supports_check_mode=True) + module = AnsibleModule(argument_spec=argument_specs, supports_check_mode=True) if not HAS_REQUESTS: return module.fail_json(msg=( 'Python requests package is not installed. ' diff --git a/plugins/modules/avi_useraccount.py b/plugins/modules/avi_useraccount.py index 258da58c..301d1688 100644 --- a/plugins/modules/avi_useraccount.py +++ b/plugins/modules/avi_useraccount.py @@ -76,6 +76,7 @@ ''' from ansible.module_utils.basic import AnsibleModule + try: from ansible_collections.vmware.alb.plugins.module_utils.utils.ansible_utils import ( avi_common_argument_spec, ansible_return) diff --git a/plugins/modules/deploy_se.py b/plugins/modules/deploy_se.py index 2499d5fb..17c8d031 100644 --- a/plugins/modules/deploy_se.py +++ b/plugins/modules/deploy_se.py @@ -205,7 +205,7 @@ type: dict ''' -from ansible.module_utils.basic import AnsibleModule + import atexit try: from urllib import quote @@ -220,12 +220,12 @@ except ImportError: HAS_IMPORT = False +from ansible.module_utils.basic import AnsibleModule __author__ = 'shubhamavi' def is_vm_exist(si, cl, vm_name): - container = si.content.viewManager.CreateContainerView( - cl, [vim.VirtualMachine], True) + container = si.content.viewManager.CreateContainerView(cl, [vim.VirtualMachine], True) for managed_object_ref in container.view: if managed_object_ref.name == vm_name: return True @@ -347,8 +347,7 @@ def get_sysadmin_key(keypath): with open(keypath, 'r') as keyfile: data = keyfile.read().rstrip('\n') return data - raise Exception( - 'Failed to find sysadmin public key file at %s\n' % keypath) + raise Exception('Failed to find sysadmin public key file at %s\n' % keypath) def get_largest_free_ds(cl): @@ -555,8 +554,7 @@ def main(): if is_vm_exist(si, cl, module.params['se_vmw_vm_name']): vm = get_vm_by_name(si, module.params['se_vmw_vm_name']) vm_path = compile_folder_path_for_object(vm) - folder = get_folder_by_path( - si, dc, module.params['se_vmw_vcenter_folder']) + folder = get_folder_by_path(si, dc, module.params['se_vmw_vcenter_folder']) folder_path = compile_folder_path_for_object(folder) changed = False if vm_path != folder_path: @@ -602,8 +600,7 @@ def main(): ova_file = module.params['se_vmw_ova_path'] if (module.params['se_vmw_ova_path'].startswith('http')): if (requests.head(module.params['se_vmw_ova_path']).status_code != 200): - module.fail_json( - msg='SE OVA not found or readable from specified URL path') + module.fail_json(msg='SE OVA not found or readable from specified URL path') if (not os.path.isfile(ova_file) or not os.access(ova_file, os.R_OK)): module.fail_json(msg='SE OVA not found or not readable') @@ -641,10 +638,8 @@ def main(): command_tokens.append('--net:%s=%s' % (key, network_item)) command_tokens.extend([ '--prop:%s=%s' % ('AVICNTRL', module.params['se_leader_ctl_ip']), - '--prop:%s=%s' % ('AVICNTRL_AUTHTOKEN', - module.params['se_auth_token']), - '--prop:%s=%s' % ('AVICNTRL_CLUSTERUUID', - module.params['se_cluster_uuid']) + '--prop:%s=%s' % ('AVICNTRL_AUTHTOKEN', module.params['se_auth_token']), + '--prop:%s=%s' % ('AVICNTRL_CLUSTERUUID', module.params['se_cluster_uuid']) ]) if module.params.get('se_vmw_mgmt_ip', None): diff --git a/plugins/modules/verify_se.py b/plugins/modules/verify_se.py index ebdffacf..f20caf33 100644 --- a/plugins/modules/verify_se.py +++ b/plugins/modules/verify_se.py @@ -112,7 +112,7 @@ type: dict ''' -from ansible.module_utils.basic import AnsibleModule + import atexit try: import requests @@ -137,6 +137,7 @@ HAS_AVI = True except ImportError: HAS_AVI = False +from ansible.module_utils.basic import AnsibleModule def get_vm_by_name(si, vm_name): @@ -177,8 +178,7 @@ def main(): argument_spec=dict( se_leader_ctl_ip=dict(required=True, type='str'), se_leader_ctl_username=dict(required=True, type='str'), - se_leader_ctl_password=dict( - required=True, type='str', no_log=True), + se_leader_ctl_password=dict(required=True, type='str', no_log=True), se_leader_ctl_version=dict(required=True, type='str'), se_cloud_name=dict(required=True, type='str'), se_group_name=dict(required=True, type='str'), diff --git a/roles/aviconfig/tasks/upgradeprofile.yml b/roles/aviconfig/tasks/upgradeprofile.yml new file mode 100644 index 00000000..51d86caf --- /dev/null +++ b/roles/aviconfig/tasks/upgradeprofile.yml @@ -0,0 +1,26 @@ +# Automatically Generated File +# Copyright 2021 VMware, Inc. All rights reserved. VMware Confidential +--- +- name: Avi UpgradeProfile | Create or Update UpgradeProfile + no_log: "{{ avi_role_config_log_mode | default(False) }}" + vmware.alb.avi_upgradeprofile: + controller: "{{ avi_controller | default(omit) }}" + username: "{{ avi_username | default(omit) }}" + password: "{{ avi_password | default(omit) }}" + tenant: "{{ item.tenant | default(omit) }}" + state: "{{ avi_role_state_mode }}" + api_version: "{{ api_version | default(omit) }}" + avi_credentials: "{{ avi_credentials | default(omit) }}" + api_context: "{{ avi_api_context | default(omit) }}" + avi_api_update_method: "{{ item.avi_api_update_method | default(omit) }}" + avi_api_patch_op: "{{ item.avi_api_patch_op | default(omit) }}" + controller: "{{ item.controller | default(omit) }}" + dry_run: "{{ item.dry_run | default(omit) }}" + image: "{{ item.image | default(omit) }}" + pre_checks: "{{ item.pre_checks | default(omit) }}" + service_engine: "{{ item.service_engine | default(omit) }}" + uuid: "{{ item.uuid | default(omit) }}" + when: + - (avi_role_state_mode == "present" and avi_config_state == "present") + - (item.state | default("present") == avi_role_state_mode or avi_config_state == "absent") + with_items: "{{ avi_role_cfg.upgradeprofile | default([]) }}" diff --git a/roles/aviconfig/tasks/upgradeprofile_delete.yml b/roles/aviconfig/tasks/upgradeprofile_delete.yml new file mode 100644 index 00000000..6fe015e2 --- /dev/null +++ b/roles/aviconfig/tasks/upgradeprofile_delete.yml @@ -0,0 +1,28 @@ +# Automatically Generated File +# Copyright 2021 VMware, Inc. All rights reserved. VMware Confidential +--- +- name: Avi UpgradeProfile | Delete UpgradeProfile + no_log: "{{ avi_role_config_log_mode | default(False) }}" + vmware.alb.avi_upgradeprofile: + controller: "{{ avi_controller | default(omit) }}" + username: "{{ avi_username | default(omit) }}" + password: "{{ avi_password | default(omit) }}" + tenant: "{{ item.tenant | default(omit) }}" + api_version: "{{ api_version | default(omit) }}" + avi_credentials: "{{ avi_credentials | default(omit) }}" + api_context: "{{ avi_api_context | default(omit) }}" + state: "{{ avi_role_state_mode }}" + avi_api_update_method: "{{ item.avi_api_update_method | default(omit) }}" + avi_api_patch_op: "{{ item.avi_api_patch_op | default(omit) }}" + controller: "{{ item.controller | default(omit) }}" + dry_run: "{{ item.dry_run | default(omit) }}" + image: "{{ item.image | default(omit) }}" + pre_checks: "{{ item.pre_checks | default(omit) }}" + service_engine: "{{ item.service_engine | default(omit) }}" + uuid: "{{ item.uuid | default(omit) }}" + when: + - (item.name | length > 0) + - (not (item.system_default | default(false))) + - (avi_config_state == "absent" or avi_role_state_mode == "absent") + - (item.state | default("present") == avi_role_state_mode or avi_config_state == "absent") + with_items: "{{ avi_role_cfg.upgradeprofile | default([]) }}" diff --git a/roles/aviconfig/vars/main.yml b/roles/aviconfig/vars/main.yml index 50264573..7d6355a0 100644 --- a/roles/aviconfig/vars/main.yml +++ b/roles/aviconfig/vars/main.yml @@ -7,6 +7,7 @@ avi_resource_types: - useraccountprofile - cloudproperties - systemlimits + - upgradeprofile - licensestatus - controllerproperties - licenseledgerdetails diff --git a/roles/avise/files/systemd/avi_host_server.py b/roles/avise/files/systemd/avi_host_server.py index 082ea792..e4b757c9 100755 --- a/roles/avise/files/systemd/avi_host_server.py +++ b/roles/avise/files/systemd/avi_host_server.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python ############################################################################ # ======================================================================== # Copyright 2024 VMware, Inc. All rights reserved. VMware Confidential @@ -40,18 +39,20 @@ """ import socket +import sys import os import subprocess +import signal import logging import traceback import re from logging.handlers import RotatingFileHandler -log_file = "/var/log/avi_host.log" -logger = logging.getLogger() +log_file="/var/log/avi_host.log" +logger=logging.getLogger() logger.setLevel(logging.DEBUG) -# 20MB file limit for logging -handler = RotatingFileHandler(log_file, maxBytes=20 * 1024 * 1024, backupCount=1) +#20MB file limit for logging +handler = RotatingFileHandler(log_file, maxBytes=20*1024*1024, backupCount=1) formatter = logging.Formatter("%(asctime)s - %(message)s") handler.setFormatter(formatter) logger.addHandler(handler) @@ -59,42 +60,38 @@ SERVER_ADDRESS = '/root/se_domain_socket' CURRENT_VERSION = "v1" - def send_response(conn, version, returncode, output, error): # Send the response back to the client output, error = output.strip(), error.strip() if version == CURRENT_VERSION: - conn.sendall("#version:{}#ret:{}#aviout:".format( - CURRENT_VERSION, returncode).encode("utf-8")) + conn.sendall("#version:{}#ret:{}#aviout:".format(CURRENT_VERSION, returncode).encode("utf-8")) conn.sendall(output) conn.sendall("#avierror:".encode("utf-8")) conn.sendall(error) conn.sendall("#avidone#".encode("utf-8")) - logger.debug("Sent response for %s", CURRENT_VERSION) + logger.debug("Sent response for {}".format(CURRENT_VERSION)) return # Legacy handling of o/p and error differently if returncode: - logger.error( - "command execution failed %s %s", error, returncode) + logger.error("command execution failed {} {}".format(error, returncode)) conn.sendall(error) conn.sendall("#ret:{}#avierror#".format(returncode).encode("utf-8")) else: - logger.debug("command output %s", output) + logger.debug("command output {}".format(output)) conn.sendall(output) conn.sendall("#avidone#".encode("utf-8")) logger.debug("Sent response for Legacy version") - def block_and_recv(conn): # Receive the data in small chunks and retransmit it input_str = "" while True: data = conn.recv(64) input_str = input_str + data.decode("utf-8") - logger.debug("input_str=%s", input_str) + logger.debug("input_str={}".format(input_str)) if "#avicmddone#" in input_str: split_list = re.split("#version:|#cmd:|#avicmddone#", input_str) if len(split_list) == 2: @@ -106,7 +103,6 @@ def block_and_recv(conn): # split_list = ["", "", "", ""] return split_list[1:-1] - def create_uds_socket(): # Make sure the socket does not already exist try: @@ -114,10 +110,8 @@ def create_uds_socket(): except OSError as error: if os.path.exists(SERVER_ADDRESS): exception = traceback.format_exc() - logger.error( - "Failed to unlink domain stream socket: %s", exception) - raise Exception( - "Failed to unlink domain stream socket: {}".format(exception)) + logger.error("Failed to unlink domain stream socket: {}".format(exception)) + raise Exception("Failed to unlink domain stream socket: {}".format(exception)) # Create a UDS socket try: @@ -127,12 +121,11 @@ def create_uds_socket(): sock.listen(1) logger.info("Listening on %s", SERVER_ADDRESS) return sock - except Exception as ex: + except: exception = traceback.format_exc() - logger.error("socket listen failed: %s", exception) + logger.error("socket listen failed: {}".format(exception)) raise Exception("socket listen failed: {}".format(exception)) - def run(): sock = create_uds_socket() while True: @@ -157,8 +150,7 @@ def run(): # Empty command, send error response if not command: - send_response(conn, version, 255, b"", - b"Received empty command") + send_response(conn, version, 255, b"", b"Received empty command") continue # AVI induced crash (A way to restart the service) @@ -172,10 +164,9 @@ def run(): continue # Execute command with timeout of 120 seconds and send response for other commands - logger.debug("received command %s", command) + logger.debug("received command {}".format(command)) command = "timeout 120 " + command - op = subprocess.Popen( - command, shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE) + op = subprocess.Popen(command, shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE) output, error = op.communicate() returncode = op.returncode send_response(conn, version, returncode, output, error) @@ -184,7 +175,7 @@ def run(): # raise another exception and let the process crash except Exception as ex: exception = traceback.format_exc() - logger.error("Exception hit: %s", exception) + logger.error("Exception hit: {}".format(exception)) send_response(conn, version, 255, b"", exception.encode("utf-8")) raise Exception("Exception hit: {}".format(exception)) @@ -192,6 +183,5 @@ def run(): finally: conn.close() - if __name__ == "__main__": run() diff --git a/roles/avise/files/systemd/avihost_service_script.sh b/roles/avise/files/systemd/avihost_service_script.sh index bde6faa5..089f8702 100755 --- a/roles/avise/files/systemd/avihost_service_script.sh +++ b/roles/avise/files/systemd/avihost_service_script.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash -x ############################################################################ # ======================================================================== # Copyright 2024 VMware, Inc. All rights reserved. VMware Confidential @@ -7,7 +7,7 @@ start() { - if [ -f /opt/avitest_python_version ]; then + if [[ -f /opt/avitest_python_version ]]; then # For testing against python2 and python3 version=$(cat /opt/avitest_python_version) else @@ -18,8 +18,8 @@ start() command -v python3 >/dev/null 2>&1 && version='3' fi - if [ "$version" != '0' ]; then - exec python"$version" /usr/sbin/avi_host_server.py + if [[ $version != '0' ]]; then + exec python$version /usr/sbin/avi_host_server.py else echo "Unable to find any installed python" exit 1 diff --git a/roles/avise/files/systemd/install.py b/roles/avise/files/systemd/install.py index 2e9a88a4..fae6ceea 100755 --- a/roles/avise/files/systemd/install.py +++ b/roles/avise/files/systemd/install.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 ############################################################################ # ======================================================================== # Copyright 2024 VMware, Inc. All rights reserved. VMware Confidential @@ -20,8 +20,9 @@ import subprocess import shlex -log = logging.getLogger(__name__) +from avi.infrastructure.avi_logging import get_root_logger +log = logging.getLogger(__name__) def print_info(msg): """ @@ -31,7 +32,6 @@ def print_info(msg): print(msg) log.info(msg) - def print_error(msg): """ Wrapper function to prints the msg into stderr and log-file. @@ -40,7 +40,6 @@ def print_error(msg): print(msg) log.error(msg) - def copy_avihost_service_to_hostroot(): """ SCP and Copy the latest avi_host service files from controller to /hostroot @@ -49,76 +48,66 @@ def copy_avihost_service_to_hostroot(): try: parent_folder = os.path.dirname(os.path.realpath(__file__)) host_files = { - 'avihost.service': '/hostroot/etc/systemd/system/', - 'avihost_service_script.sh': '/hostroot/etc/systemd/system/', - 'avi_host_server.py': '/hostroot/usr/sbin/' + 'avihost.service' : '/hostroot/etc/systemd/system/', + 'avihost_service_script.sh' : '/hostroot/etc/systemd/system/', + 'avi_host_server.py' : '/hostroot/usr/sbin/' } replace_host_files = False for host_file, local_folder in host_files.items(): - remote_host_file = os.path.join(parent_folder, host_file) + remote_host_file = os.path.join(parent_folder,host_file) local_host_file = os.path.join(local_folder, host_file) if os.path.exists(remote_host_file): print_info("Copied latest: %s" % remote_host_file) - cmd = 'sha512sum %s' % (remote_host_file) + cmd = 'sha512sum %s' %(remote_host_file) latest_avi_host_md5 = subprocess.check_output(shlex.split(cmd)) if not isinstance(latest_avi_host_md5, str): - latest_avi_host_md5 = latest_avi_host_md5.decode( - sys.stdout.encoding) + latest_avi_host_md5 = latest_avi_host_md5.decode(sys.stdout.encoding) latest_avi_host_md5 = latest_avi_host_md5.split(' ')[0] - cmd = 'sha512sum %s' % (local_host_file) + cmd = 'sha512sum %s' %(local_host_file) current_avi_host_md5 = None try: - current_avi_host_md5 = subprocess.check_output( - shlex.split(cmd)) + current_avi_host_md5 = subprocess.check_output(shlex.split(cmd)) if not isinstance(current_avi_host_md5, str): - current_avi_host_md5 = current_avi_host_md5.decode( - sys.stdout.encoding) + current_avi_host_md5 = current_avi_host_md5.decode(sys.stdout.encoding) current_avi_host_md5 = current_avi_host_md5.split(' ')[0] except Exception as e: pass - print_info("Receive avihost checksum from controller: %s and current is: %s" % ( - latest_avi_host_md5, current_avi_host_md5)) + print_info("Receive avihost checksum from controller: %s and current is: %s" % (latest_avi_host_md5, current_avi_host_md5)) if latest_avi_host_md5 and current_avi_host_md5 and current_avi_host_md5 == latest_avi_host_md5: - print_info("No differences detected in file %s, controller checksum: %s and current checksum is: %s" % ( - host_file, latest_avi_host_md5, current_avi_host_md5)) + print_info("No differences detected in file %s, controller checksum: %s and current checksum is: %s" % (host_file, latest_avi_host_md5, current_avi_host_md5)) continue else: - print_info("Migration needed, differences detected in file %s, controller checksum: %s and current checksum is: %s" % ( - host_file, latest_avi_host_md5, current_avi_host_md5)) + print_info("Migration needed, differences detected in file %s, controller checksum: %s and current checksum is: %s" % (host_file, latest_avi_host_md5, current_avi_host_md5)) replace_host_files = True break if replace_host_files: - # download aviservice files and replace it on hostroot + #download aviservice files and replace it on hostroot print_info("Copying latest avihost files from controller.") for host_file, local_folder in host_files.items(): remote_tmp_file = os.path.join(parent_folder, host_file) local_tmp_file = os.path.join(local_folder, host_file) cmd = 'cp %s %s' % (remote_tmp_file, local_tmp_file) move_out = subprocess.check_output(shlex.split(cmd)) - msg = 'move %s to %s completed - done, out: %s' % ( - remote_tmp_file, local_tmp_file, move_out) + msg = 'move %s to %s completed - done, out: %s' %(remote_tmp_file, local_tmp_file, move_out) print_info(msg) else: print_info("Migration of avihost service not needed") return 2 except subprocess.CalledProcessError as e: - msg = 'Failed to replace avihost service files, error exception:%s' % str( - e) + msg = 'Failed to replace avihost service files, error exception:%s' % str(e) print_error(msg) return 1 print_info("Successfully replaced avihost service files.") return 0 - if __name__ == '__main__': exitCode = 0 try: exitCode = copy_avihost_service_to_hostroot() except Exception as e: traceback.print_exc() - print_error( - 'Failed to migrate avihost service files, error exception:%s' % str(e)) + print_error('Failed to migrate avihost service files, error exception:%s' % str(e)) sys.exit(1) sys.exit(exitCode) diff --git a/roles/avise/files/systemd/install.sh b/roles/avise/files/systemd/install.sh index 5e3fd382..850b99e3 100755 --- a/roles/avise/files/systemd/install.sh +++ b/roles/avise/files/systemd/install.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash ############################################################################ # ======================================================================== # Copyright 2024 VMware, Inc. All rights reserved. VMware Confidential @@ -7,16 +7,16 @@ set -e echo "Migrating avihost service files." -major_version=$(cmd < /bootstrap/VERSION | grep Version | awk '{print $2}' | awk '{split($0,a,".");}{print a[1]}') +major_version=`cat /bootstrap/VERSION | grep Version | awk '{print $2}' | awk '{split($0,a,".");}{print a[1]}'` BASEDIR=$(dirname "$0") python_cmd='python3' -if [ "$major_version" -lt 20 ] +if [ $major_version -lt 20 ] then echo "using python2" python_cmd="python" fi -"$python_cmd" "$BASEDIR"/install.py +$python_cmd $BASEDIR/install.py echo "Completed: Migration of avihost service files." \ No newline at end of file diff --git a/roles/avise/tasks/docker/docker_checks.yml b/roles/avise/tasks/docker/docker_checks.yml index 26bb58f7..88be7331 100644 --- a/roles/avise/tasks/docker/docker_checks.yml +++ b/roles/avise/tasks/docker/docker_checks.yml @@ -119,3 +119,5 @@ - name: Include error tasks if Docker disk size is insufficient ansible.builtin.include_tasks: error.yml when: docker_size_avail is defined and docker_size_avail|int < docker_size_req|int + + diff --git a/roles/avise/tasks/docker/dpdk.yml b/roles/avise/tasks/docker/dpdk.yml index 24192dda..0d4b8cb5 100644 --- a/roles/avise/tasks/docker/dpdk.yml +++ b/roles/avise/tasks/docker/dpdk.yml @@ -2,7 +2,8 @@ - name: Check for version set_fact: error_string: "{{ ansible_distribution }} {{ ansible_distribution_version }} is not supported in dpdk mode" - when: (not (ansible_distribution == 'OracleLinux' and ansible_distribution_version is match('9.4'))) and + when: (not (ansible_distribution == 'OracleLinux' and ansible_distribution_version is match('9.5'))) and + (not (ansible_distribution == 'OracleLinux' and ansible_distribution_version is match('9.4'))) and (not (ansible_distribution == 'OracleLinux' and ansible_distribution_version is match('9.3'))) and (not (ansible_distribution == 'OracleLinux' and ansible_distribution_version is match('9.2'))) and (not (ansible_distribution == 'OracleLinux' and ansible_distribution_version is match('9.1'))) and diff --git a/roles/avise/tasks/docker/requirements.yml b/roles/avise/tasks/docker/requirements.yml index 9cc3eb92..81cc9997 100644 --- a/roles/avise/tasks/docker/requirements.yml +++ b/roles/avise/tasks/docker/requirements.yml @@ -257,15 +257,6 @@ become: true ignore_errors: yes -- block: - - name: Check ports in use or not for range 5000-5100 except 5098 and 5054 - shell: echo '{{ ns_res.stdout }}' | awk '{print $4}' | grep -w {{ item }} - when: item|int != 5054 and item|int != 5098 - with_sequence: start=5000 end=5099 - register: port_res - ignore_errors: yes - when: ns_res.rc is defined and ns_res.rc == 0 - - name: Set failed port set_fact: failed_port: "{{ item.item }}" diff --git a/roles/avise/tasks/docker/version_check.yml b/roles/avise/tasks/docker/version_check.yml index c5364859..d302e4fd 100644 --- a/roles/avise/tasks/docker/version_check.yml +++ b/roles/avise/tasks/docker/version_check.yml @@ -6,7 +6,8 @@ - name: Include error.yml ansible.builtin.include_tasks: file: error.yml - when: (not (ansible_distribution == 'OracleLinux' and ansible_distribution_version is match('9.4'))) and + when: (not (ansible_distribution == 'OracleLinux' and ansible_distribution_version is match('9.5'))) and + (not (ansible_distribution == 'OracleLinux' and ansible_distribution_version is match('9.4'))) and (not (ansible_distribution == 'OracleLinux' and ansible_distribution_version is match('9.3'))) and (not (ansible_distribution == 'OracleLinux' and ansible_distribution_version is match('9.2'))) and (not (ansible_distribution == 'OracleLinux' and ansible_distribution_version is match('9.1'))) and diff --git a/roles/avise/tasks/main.yml b/roles/avise/tasks/main.yml index 6b3dd202..062b3d5c 100644 --- a/roles/avise/tasks/main.yml +++ b/roles/avise/tasks/main.yml @@ -5,3 +5,4 @@ # It was added to prevent mass "skipped" messages when deploying Avi. - name: Avi SE | Deployment include_tasks: docker/main.yml +