def main(): argument_specs = dict( full_name=dict(type='str'), email=dict(type='str'), old_password=dict(type='str', required=True, no_log=True), # Flag to specify priority of old/new password while establishing session with controller. # To handle both Saas and conventional (Entire state in playbook) scenario. force_change=dict(type='bool', default=False)) argument_specs.update(avi_common_argument_spec()) module = AnsibleModule(argument_spec=argument_specs) if not HAS_REQUESTS: return module.fail_json(msg=( 'Python requests package is not installed. ' 'For installation instructions, visit https://pypi.org/project/requests.' )) api_creds = AviCredentials() api_creds.update_from_ansible_module(module) full_name = module.params.get('full_name') email = module.params.get('email') old_password = module.params.get('old_password') force_change = module.params.get('force_change', False) data = {'old_password': old_password, 'password': api_creds.password} if full_name: data['full_name'] = full_name if email: data['email'] = email api = None if not force_change: # check if the new password is already set. try: api = ApiSession.get_session(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) data['old_password'] = api_creds.password except Exception: # create a new session using the old password. pass if not api: api = ApiSession.get_session(api_creds.controller, api_creds.username, password=old_password, timeout=api_creds.timeout, tenant=api_creds.tenant, tenant_uuid=api_creds.tenant_uuid, token=api_creds.token, port=api_creds.port) rsp = api.put('useraccount', data=data) return ansible_return(module, rsp, True, req=data)
def main(): argument_specs = dict( idp_class=dict(type=str, required=True, ), ) argument_specs.update(avi_common_argument_spec()) module = AnsibleModule(argument_spec=argument_specs) if not HAS_REQUESTS: return module.fail_json(msg=( 'Python requests package is not installed. ' 'For installation instructions, visit https://pypi.org/project/requests.')) idp_class = module.params.get("idp_class", None) idp = get_idp_class(idp_class) if not idp: msg = "IDP {1} not supported yet.".format(idp_class) return module.fail_json(msg=msg) avi_credentials = AviCredentials() avi_credentials.update_from_ansible_module(module) try: api = ApiSession.get_session( avi_credentials.controller, avi_credentials.username, password=avi_credentials.password, timeout=avi_credentials.timeout, tenant=avi_credentials.tenant, tenant_uuid=avi_credentials.tenant_uuid, port=avi_credentials.port, idp_class=idp) changed = True except (ConnectionError, SSLError, ChunkedEncodingError) as e: msg = "Error during get session {1}".format(e.message) return module.fail_json(msg=msg) return ansible_return(module, None, changed, None, api_context=api.get_context())
def main(): argument_specs = dict() argument_specs.update(avi_common_argument_spec()) module = AnsibleModule(argument_spec=argument_specs) if not HAS_REQUESTS: return module.fail_json(msg=( 'Python requests package is not installed. ' 'For installation instructions, visit https://pypi.org/project/requests.' )) try: api_creds = AviCredentials() api_creds.update_from_ansible_module(module) api = ApiSession.get_session(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) remote_api_version = api.remote_api_version remote = {} for key in remote_api_version.keys(): remote[key.lower()] = remote_api_version[key] api.close() module.exit_json(changed=False, obj=remote) except Exception as e: module.fail_json(msg=("Unable to get an AVI session. %s" % e))
def main(): argument_specs = dict( data_vnics_config=dict(type='list', ), se_name=dict(type='str', required=True), ) 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.')) # Create controller session api_creds = AviCredentials() api_creds.update_from_ansible_module(module) api = ApiSession.get_session( 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) path = 'serviceengine' # Get existing SE object se_obj = api.get_object_by_name( path, module.params['se_name'], api_version=api_creds.api_version) data_vnics_config = module.params['data_vnics_config'] for d_vnic in se_obj['data_vnics']: for obj in data_vnics_config: config_for = obj.get('if_name', None) if not config_for: return module.fail_json(msg=( "if_name in a configuration is mandatory. Please provide if_name i.e. vnic's interface name.")) if config_for == d_vnic['if_name']: # modify existing object for key, val in obj.items(): d_vnic[key] = val if config_for == d_vnic['if_name']: for key, val in obj.items(): d_vnic[key] = val module.params.update(se_obj) module.params.update( { 'avi_api_update_method': 'put', 'state': 'present' } ) module.params.pop('data_vnics_config') return avi_ansible_api(module, 'serviceengine', set([]))
def main(): argument_specs = dict(file_path=dict(type='str', required=True), params=dict(type='dict'), timeout=dict(type='int', default=300)) argument_specs.update(avi_common_argument_spec()) module = AnsibleModule(argument_spec=argument_specs) if not HAS_REQUESTS: return module.fail_json(msg=( 'Python requests package is not installed. ' 'For installation instructions, visit https://pypi.org/project/requests.' )) if not HAS_LIB: return module.fail_json( msg='avi_api_image, requests_toolbelt is required for this module') api_creds = AviCredentials() api_creds.update_from_ansible_module(module) api = ApiSession.get_session(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) tenant_uuid = api_creds.tenant_uuid tenant = api_creds.tenant timeout = int(module.params.get('timeout')) params = module.params.get('params', None) # Get the api_version from module. api_version = api_creds.api_version file_path = module.params['file_path'] if not os.path.exists(file_path): return module.fail_json(msg=('File not found : %s' % file_path)) file_name = os.path.basename(file_path) with open(file_path, "rb") as f: f_data = {"file": (file_name, f, "application/octet-stream")} m = MultipartEncoder(fields=f_data) headers = {'Content-Type': m.content_type} rsp = api.post("image", data=m, headers=headers, verify=False) if rsp.status_code > 300: return module.fail_json(msg='Fail to upload file: %s' % rsp.text) else: return module.exit_json(changed=True, msg="File uploaded successfully")
def main(): case_spec=dict( enable_auto_case_creation_on_controller_failure=dict(default='False',choices=['True', 'False']), enable_auto_case_creation_on_se_failure=dict(default='False',choices=['True', 'False']) ) waf_spec=dict( enable_auto_download_waf_signatures=dict(default='False',choices=['True', 'False']), enable_waf_signatures_notifications=dict(default='False',choices=['True', 'False']) ) argument_specs = dict( state=dict(default='present',choices=['absent', 'present']), jwt_token=dict(type='str', required=True,no_log=True), name=dict(required=True,type='str'), params=dict(type='dict'), description=dict(type='str', required=True), email=dict(type='str', required=True), account_id=dict(type='str',required=True), optins=dict(default='present',choices=['absent', 'present']), enable_cleanup_of_attached_files=dict(default='False',choices=['True', 'False']), enable_appsignature_sync=dict(default='False',choices=['True', 'False']), enable_ip_reputation=dict(default='False',choices=['True', 'False']), enable_pulse_case_management=dict(default='False',choices=['True', 'False']), enable_pulse_waf_management=dict(default='False',choices=['True', 'False']), enable_user_agent_db_sync=dict(default='False',choices=['True', 'False']), use_tls=dict(default='False',choices=['True', 'False']), waf_config=dict(type='dict',options=waf_spec), 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) if not HAS_REQUESTS: return module.fail_json(msg=( 'Python requests package is not installed. ' 'For installation instructions, visit https://pypi.org/project/requests.')) api_creds = AviCredentials() api_creds.update_from_ansible_module(module) api = ApiSession.get_session(api_creds.controller, api_creds.username, password=api_creds.password,api_version=api_creds.api_version,timeout=api_creds.timeout, tenant=api_creds.tenant, tenant_uuid=api_creds.tenant_uuid, token=api_creds.token, port=api_creds.port) api_version = api_creds.api_version tenant_uuid = api_creds.tenant_uuid tenant = api_creds.tenant check_mode = module.check_mode path = module.params.get('path', '') state= module.params.get('state', None) jwt_token = module.params.get('jwt_token', None) name= module.params.get('name', None) description=module.params.get('description', None) email = module.params.get('email', None) 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_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) use_tls=module.params.get('use_tls', None) waf_config=module.params.get('waf_config',None) case_config=module.params.get('case_config',None) enable_auto_download_waf_signatures = module.params.get('waf_config')['enable_auto_download_waf_signatures'] enable_waf_signatures_notifications = module.params.get('waf_config')['enable_waf_signatures_notifications'] enable_auto_case_creation_on_controller_failure= module.params.get('case_config')['enable_auto_case_creation_on_controller_failure'] enable_auto_case_creation_on_se_failure=module.params.get('case_config')['enable_auto_case_creation_on_se_failure'] reg=True if state == 'present': #registration path="albservices/status" 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='} data={"jwt_token":jwt_token} path="portal/refresh-access-token" 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: changed=True time.sleep(10) if resp.json().get("registration_status") == "ALBSERVICES_DEREGISTERED": if not check_mode: path="albservices/register" data= {"name":name,"description":description,"email":email,"account_id":account_id} rsp = api.post(path, data=data) changed=True time.sleep(5) else: # No need to process any further. rsp = AviCheckModeResponse(obj=existing_obj) changed=True if resp.json().get("registration_status") == "ALBSERVICES_REGISTERED": changed=False reg=False if reg and rsp.status_code>300: return module.fail_json(msg='Failed: %s' %rsp.text) else: if optins == 'present': if enable_pulse_case_management=='False' and (enable_auto_case_creation_on_se_failure or enable_auto_case_creation_on_controller_failure): return module.fail_json(msg='Unable to enable the options as enable_pulse_case_management is not enabled.') if enable_pulse_waf_management=='False' and (enable_auto_download_waf_signatures or enable_waf_signatures_notifications): return module.fail_json(msg='Unable to enable the options as enable_pulse_waf_management is not enabled.') path="albservicesconfig" response=api.get(path,tenant=tenant, tenant_uuid=tenant_uuid,api_version=api_version) path= "albservicesconfig" data = dict() 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["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["use_tls"]=use_tls data["mode"]="MYVMWARE" data["app_signature_config"]=dict() 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["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["saas_licensing_config"]=dict() data[("saas_licensing_config")]["max_service_units"]= 1000 data[("saas_licensing_config")]["reserve_service_units"]= 0 data_for_cmp = data response_data = response.json() ch = not avi_obj_cmp(data_for_cmp,response_data) if ch: if not check_mode: rsp = api.put(path, data=data) changed=True else: rsp = AviCheckModeResponse(obj=existing_obj) changed=True return module.exit_json(changed=changed,msg='Registered successfully') else: #deregistration reg=True path="albservices/status" resp=api.get(path,tenant=tenant, tenant_uuid=tenant_uuid,api_version=api_version) existing_obj=resp if resp.json().get("registration_status")=="ALBSERVICES_REGISTERED": if not check_mode: path="albservices/register" data={"status":'Obsolete'} rsp = api.put(path, data=data) changed=True else: rsp = AviCheckModeResponse(obj=existing_obj) changed=True if resp.json().get("registration_status")=="ALBSERVICES_DEREGISTERED": changed=False reg=False if reg and rsp.status_code > 300: return module.fail_json(msg='Failed: %s' % rsp.text) else: return module.exit_json( changed=changed, msg="Deregistered successfully")
def main(): argument_specs = dict( force_mode=dict(type='bool', default=True), upload=dict(required=True, type='bool'), path=dict(type='str', required=True), file_path=dict(type='str', required=True), params=dict(type='dict'), timeout=dict(type='int', default=60) ) argument_specs.update(avi_common_argument_spec()) module = AnsibleModule(argument_spec=argument_specs) if not HAS_REQUESTS: return module.fail_json(msg=( 'Python API requests is not installed.')) if not HAS_LIB: return module.fail_json( msg='avi_api_fileservice, requests_toolbelt is required for this module') api_creds = AviCredentials() api_creds.update_from_ansible_module(module) api = ApiSession.get_session( 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) tenant_uuid = api_creds.tenant_uuid tenant = api_creds.tenant timeout = int(module.params.get('timeout')) # path is a required argument path = 'fileservice/%s' % module.params.get('path', '') params = module.params.get('params', None) data = module.params.get('data', None) # Get the api_version from module. api_version = api_creds.api_version if data is not None: data = json.loads(data) upload = module.params['upload'] file_path = module.params['file_path'] force_mode = module.params['force_mode'] if upload: if not os.path.exists(file_path): return module.fail_json(msg=('File not found : %s' % file_path)) file_name = os.path.basename(file_path) # Handle special case of upgrade controller using .pkg file which will be uploaded to upgrade_pkgs directory if file_name.lower().endswith('.pkg'): uri = 'controller://upgrade_pkgs' path = 'fileservice/uploads' else: 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, timeout=timeout) with open(file_path, "rb") as f: f_data = {"file": (file_name, f, "application/octet-stream"), "uri": uri} m = MultipartEncoder(fields=f_data) headers = {'Content-Type': m.content_type} rsp = api.post(path, data=m, headers=headers, verify=False) if rsp.status_code > 300: return module.fail_json(msg='Fail to upload file: %s' % rsp.text) else: return module.exit_json( changed=True, msg="File uploaded successfully") elif not upload: # Removing existing file. if force_mode and os.path.exists(file_path): os.remove(file_path) rsp = api.get(path, params=params, stream=True) if rsp.status_code > 300: return module.fail_json(msg='Fail to download file: %s' % rsp.text) with open(file_path, 'wb') as f: for chunk in rsp.iter_content(chunk_size=1024): if chunk: f.write(chunk) return module.exit_json(msg='File downloaded successfully', changed=True)
def main(): argument_specs = dict( params=dict(type='dict'), data=dict(type='dict'), name=dict(type='str', required=True), state=dict(default='present', choices=['absent', 'present']) ) argument_specs.update(avi_common_argument_spec()) module = AnsibleModule(argument_spec=argument_specs) if not HAS_REQUESTS: return module.fail_json(msg=( 'Python requests package is not installed. ' 'For installation instructions, visit https://pypi.org/project/requests.')) api_creds = AviCredentials() api_creds.update_from_ansible_module(module) api = ApiSession.get_session( 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) tenant = api_creds.tenant tenant_uuid = api_creds.tenant_uuid params = module.params.get('params', None) data = module.params.get('data', None) gparams = deepcopy(params) if params else {} gparams.update({'include_refs': '', 'include_name': ''}) name = module.params.get('name', '') state = module.params['state'] # Get the api version from module. api_version = api_creds.api_version """ state: present 1. Check if the GSLB service is present 2. If not then create the GSLB service with the member 3. Check if the group exists 4. if not then create the group with the member 5. Check if the member is present if not then add the member state: absent 1. check if GSLB service is present if not then exit 2. check if group is present. if not then exit 3. check if member is present. if present then remove it. """ obj_type = 'gslbservice' # Added api version to call existing_obj = api.get_object_by_name( obj_type, name, tenant=tenant, tenant_uuid=tenant_uuid, params={'include_refs': '', 'include_name': ''}, api_version=api_version) check_mode = module.check_mode if state == 'absent': # Added api version to call changed, rsp = delete_member(module, check_mode, api, tenant, tenant_uuid, existing_obj, data, api_version) else: # Added api version to call changed, rsp = add_member(module, check_mode, api, tenant, tenant_uuid, existing_obj, data, name, api_version) if check_mode or not changed: return module.exit_json(changed=changed, obj=existing_obj) return ansible_return(module, rsp, changed, req=data)
def main(): argument_specs = dict( http_method=dict(required=True, choices=['get', 'put', 'post', 'patch', 'delete']), path=dict(type='str', required=True), params=dict(type='dict'), data=dict(type='jsonarg'), timeout=dict(type='int', default=60) ) argument_specs.update(avi_common_argument_spec()) module = AnsibleModule(argument_spec=argument_specs) if not HAS_REQUESTS: return module.fail_json(msg=( 'Python requests package is not installed. ' 'For installation instructions, visit https://pypi.org/project/requests.')) api_creds = AviCredentials() api_creds.update_from_ansible_module(module) api = ApiSession.get_session( 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) tenant_uuid = api_creds.tenant_uuid tenant = api_creds.tenant timeout = int(module.params.get('timeout')) # path is a required argument path = module.params.get('path', '') params = module.params.get('params', None) data = module.params.get('data', None) # Get the api_version from module. api_version = api_creds.api_version if data is not None: data = json.loads(data) method = module.params['http_method'] existing_obj = None changed = method != 'get' gparams = deepcopy(params) if params else {} gparams.update({'include_refs': '', 'include_name': ''}) # API methods not allowed 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"] if method == 'post' and not any(path.startswith(uri) for uri in api_post_not_allowed): # TODO: Above condition should be updated after AV-38981 is fixed # need to check if object already exists. In that case # change the method to be put try: using_collection = False if (not any(path.startswith(uri) for uri in api_get_not_allowed) and not any(path.endswith(uri) for uri in sub_api_get_not_allowed)): if 'name' in data: gparams['name'] = data['name'] using_collection = True if (not any(path.startswith(uri) for uri in api_get_not_allowed) and not any(path.endswith(uri) for uri in sub_api_get_not_allowed)): rsp = api.get(path, tenant=tenant, tenant_uuid=tenant_uuid, params=gparams, api_version=api_version) existing_obj = rsp.json() if using_collection: existing_obj = existing_obj['results'][0] except (IndexError, KeyError): # object is not found pass else: if (not any(path.startswith(uri) for uri in api_get_not_allowed) and not any(path.endswith(uri) for uri in sub_api_get_not_allowed)): # object is present method = 'put' path += '/' + existing_obj['uuid'] if method == 'put' and not any(path.startswith(uri) for uri in api_put_not_allowed): # put can happen with when full path is specified or it is put + post get_path = path data_for_cmp = data if existing_obj is None: using_collection = False if ((len(path.split('/')) == 1) and ('name' in data) and (not any(path.startswith(uri) for uri in api_get_not_allowed))): gparams['name'] = data['name'] using_collection = True if path.startswith('wafpolicy') and path.endswith('update-crs-rules'): get_path = path.rstrip('/update-crs-rules') data_for_cmp = deepcopy(data) if data else {} data_for_cmp.pop("commit", None) rsp = api.get(get_path, tenant=tenant, tenant_uuid=tenant_uuid, params=gparams, api_version=api_version) rsp_data = rsp.json() if using_collection: if rsp_data['results']: existing_obj = rsp_data['results'][0] path += '/' + existing_obj['uuid'] else: method = 'post' else: if rsp.status_code == 404: method = 'post' else: existing_obj = rsp_data if existing_obj: changed = not avi_obj_cmp(data_for_cmp, existing_obj) cleanup_absent_fields(data) if method == 'patch': rsp = api.get(path, tenant=tenant, tenant_uuid=tenant_uuid, params=gparams, api_version=api_version) existing_obj = rsp.json() if (method == 'put' and changed) or (method != 'put'): fn = getattr(api, method) rsp = fn(path, tenant=tenant, tenant_uuid=tenant, timeout=timeout, params=params, data=data, api_version=api_version) else: rsp = None if method == 'delete' and rsp.status_code == 404: changed = False rsp.status_code = 200 if method == 'patch' and existing_obj and rsp.status_code < 299: # Ideally the comparison should happen with the return values # from the patch API call. However, currently Avi API are # returning different hostname when GET is used vs Patch. # tracked as AV-12561 if path.startswith('pool'): time.sleep(1) gparams = deepcopy(params) if params else {} gparams.update({'include_refs': '', 'include_name': ''}) rsp = api.get(path, tenant=tenant, tenant_uuid=tenant_uuid, params=gparams, api_version=api_version) new_obj = rsp.json() changed = not avi_obj_cmp(new_obj, existing_obj) if rsp is None: return module.exit_json(changed=changed, obj=existing_obj) return ansible_return(module, rsp, changed, req=data)
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', ), patch_level=dict(type='str', default='/site/dns_vses', choices=['/site/dns_vses', '/site']), async_interval=dict(type='int', ), clear_on_max_retries=dict(type='int', ), client_ip_addr_group=dict(type='dict', ), configpb_attributes=dict(type='dict', ), description=dict(type='str', ), dns_configs=dict(type='list', ), enable_config_by_members=dict(type='bool', ), error_resync_interval=dict(type='int', ), is_federated=dict(type='bool', ), leader_cluster_uuid=dict(type='str', required=True), maintenance_mode=dict(type='bool', ), name=dict(type='str', required=True), replication_policy=dict(type='dict', ), send_interval=dict(type='int', ), send_interval_prior_to_maintenance_mode=dict(type='int', ), sites=dict(type='list', required=True), tenant_ref=dict(type='str', ), tenant_scoped=dict(type='bool', ), third_party_sites=dict(type='list', ), url=dict(type='str', ), uuid=dict(type='str', ), view_id=dict(type='int', ), ) 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.' )) api_method = module.params['avi_api_update_method'] if str(api_method).lower() == 'patch': patch_op = module.params['avi_api_patch_op'] # Create controller session api_creds = AviCredentials() api_creds.update_from_ansible_module(module) api = ApiSession.get_session(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) # Get existing gslb objects rsp = api.get('gslb', api_version=api_creds.api_version) existing_gslb = rsp.json() gslb = existing_gslb['results'] for gslb_obj in gslb: if (gslb_obj['leader_cluster_uuid'] == module.params['leader_cluster_uuid']): if str(patch_op).lower() == 'add': patch_add_gslb(module, gslb_obj) elif str(patch_op).lower() == 'replace': patch_replace_gslb(module, gslb_obj) elif str(patch_op).lower() == 'delete': patch_delete_gslb(module, gslb_obj) module.params.update(gslb_obj) module.params.pop("patch_level") module.params.update({ 'avi_api_update_method': 'put', 'state': 'present' }) return avi_ansible_api(module, 'gslb', set())
def avi_ansible_api(module, obj_type, sensitive_fields): """ This converts the Ansible module into AVI object and invokes APIs :param module: Ansible module :param obj_type: string representing Avi object type :param sensitive_fields: sensitive fields to be excluded for comparison purposes. Returns: success: module.exit_json with obj=avi object faliure: module.fail_json """ api_creds = AviCredentials() api_creds.update_from_ansible_module(module) api_context = get_api_context(module, api_creds) if api_context: api = ApiSession.get_session( 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_context['csrftoken'], port=api_creds.port, session_id=api_context['session_id'], csrftoken=api_context['csrftoken']) else: api = ApiSession.get_session( 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,) state = module.params['state'] # Get the api version. avi_update_method = module.params.get('avi_api_update_method', 'put') avi_patch_op = module.params.get('avi_api_patch_op', 'add') avi_patch_path = module.params.get('avi_patch_path') avi_patch_value = module.params.get('avi_patch_value', None) api_version = api_creds.api_version name = module.params.get('name', None) # Added Support to get uuid uuid = module.params.get('uuid', None) check_mode = module.check_mode if uuid and obj_type not in NO_UUID_OBJ: obj_path = '%s/%s' % (obj_type, uuid) else: obj_path = '%s/' % obj_type obj = deepcopy(module.params) tenant = obj.pop('tenant', '') tenant_uuid = obj.pop('tenant_uuid', '') # obj.pop('cloud_ref', None) for k in POP_FIELDS: obj.pop(k, None) purge_optional_fields(obj, module) # Special code to handle situation where object has a field # named username/password/state. The following code copies # username, password and state from the obj_username, obj_password # and obj_state fields. if 'obj_username' in obj: obj['username'] = obj['obj_username'] obj.pop('obj_username') if 'obj_password' in obj: obj['password'] = obj['obj_password'] obj.pop('obj_password') if 'obj_state' in obj: obj['state'] = obj['obj_state'] obj.pop('obj_state') if 'full_name' not in obj and 'name' in obj and obj_type == "user": obj['full_name'] = obj['name'] # Special case as name represent full_name in user module # As per API response, name is always same as username regardless of full_name obj['name'] = obj['username'] log.info('passed object %s ', obj) if uuid: # Get the object based on uuid. try: existing_obj = api.get( obj_path, tenant=tenant, tenant_uuid=tenant_uuid, params={'include_refs': '', 'include_name': ''}, api_version=api_version) existing_obj = existing_obj.json() except ObjectNotFound: existing_obj = None elif name: params = {'include_refs': '', 'include_name': ''} if obj.get('cloud_ref', None): # this is the case when gets have to be scoped with cloud cloud = obj['cloud_ref'].split('name=')[1] params['cloud_ref.name'] = cloud existing_obj = api.get_object_by_name( obj_type, name, tenant=tenant, tenant_uuid=tenant_uuid, params=params, api_version=api_version) # Need to check if tenant_ref was provided and the object returned # is actually in admin tenant. if existing_obj and 'tenant_ref' in obj and 'tenant_ref' in existing_obj: # https://10.10.25.42/api/tenant/admin#admin existing_obj_tenant = existing_obj['tenant_ref'].split('#')[1] obj_tenant = obj['tenant_ref'].split('name=')[1] if obj_tenant != existing_obj_tenant: existing_obj = None else: # added api version to avi api call. existing_obj = api.get(obj_path, tenant=tenant, tenant_uuid=tenant_uuid, params={'include_refs': '', 'include_name': ''}, api_version=api_version).json() if state == 'absent': rsp = None changed = False err = False if not check_mode and existing_obj: try: if name is not None: # added api version to avi api call. rsp = api.delete_by_name( obj_type, name, tenant=tenant, tenant_uuid=tenant_uuid, api_version=api_version) else: # added api version to avi api call. rsp = api.delete( obj_path, tenant=tenant, tenant_uuid=tenant_uuid, api_version=api_version) except ObjectNotFound: pass if check_mode and existing_obj: changed = True if rsp: if rsp.status_code == 204: changed = True elif not any(error in str(rsp.text) for error in SKIP_DELETE_ERROR): err = True if not err: return ansible_return( module, rsp, changed, existing_obj=existing_obj, api_context=api.get_context()) elif rsp: return module.fail_json(msg=rsp.text) rsp = None req = None if existing_obj: # this is case of modify as object exists. should find out # if changed is true or not if name is not None and obj_type not in NO_UUID_OBJ: obj_uuid = existing_obj['uuid'] obj_path = '%s/%s' % (obj_type, obj_uuid) if avi_update_method == 'put': changed = not avi_obj_cmp(obj, existing_obj, sensitive_fields) obj = cleanup_absent_fields(obj) if changed: req = obj if check_mode: # No need to process any further. rsp = AviCheckModeResponse(obj=existing_obj) else: rsp = api.put( obj_path, data=req, tenant=tenant, tenant_uuid=tenant_uuid, api_version=api_version) elif check_mode: rsp = AviCheckModeResponse(obj=existing_obj) else: if check_mode: # No need to process any further. rsp = AviCheckModeResponse(obj=existing_obj) changed = True else: obj.pop('name', None) patch_data = {} if avi_patch_path: if avi_patch_value: avi_patch_value = yaml.load(avi_patch_value) patch_data = { "json_patch": [{ "op": avi_patch_op, "path": avi_patch_path, "value": avi_patch_value }] } else: patch_data.update({avi_patch_op: obj}) try: rsp = api.patch( obj_path, data=patch_data, tenant=tenant, tenant_uuid=tenant_uuid, api_version=api_version) obj = rsp.json() changed = not avi_obj_cmp(obj, existing_obj) except ObjectNotFound: changed = False if avi_patch_op == 'delete': rsp = None if changed: log.debug('EXISTING OBJ %s', existing_obj) log.debug('NEW OBJ %s', obj) else: changed = True req = obj if check_mode: rsp = AviCheckModeResponse(obj=None) else: rsp = api.post(obj_type, data=obj, tenant=tenant, tenant_uuid=tenant_uuid, api_version=api_version) return ansible_return(module, rsp, changed, req, existing_obj=existing_obj, api_context=api.get_context())
def main(): argument_specs = dict( password=dict(type='str', required=True, no_log=True), ssh_key_pair=dict(type='str', required=True), force_mode=dict(type='bool', default=False), # Max time to wait for controller up state con_wait_time=dict(type='int', default=3600), # Retry after every rount_wait time to check for controller state. round_wait=dict(type='int', default=10), ) argument_specs.update(avi_common_argument_spec()) module = AnsibleModule(argument_spec=argument_specs) if not HAS_REQUESTS: return module.fail_json(msg=( 'Python requests package is not installed. ' 'For installation instructions, visit https://pypi.org/project/requests.' )) api_creds = AviCredentials() api_creds.update_from_ansible_module(module) new_password = module.params.get('password') key_pair = module.params.get('ssh_key_pair') force_mode = module.params.get('force_mode') # Wait for controller to come up for given con_wait_time controller_up = controller_wait(api_creds.controller, api_creds.port, module.params['round_wait'], module.params['con_wait_time']) if not controller_up: return module.fail_json( msg= 'Something wrong with the controller. The Controller is not in the up state.' ) if not force_mode: # Check for admin login with new password before initializing controller password. try: ApiSession.get_session(api_creds.controller, "admin", 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) 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) stdout, stderr = process.communicate() cmd_status = process.returncode if cmd_status == 0: return module.exit_json( changed=True, msg="Successfully initialized controller with new password. " "return_code: %s output: %s error: %s" % (cmd_status, stdout, stderr)) else: return module.fail_json( msg='Fail to initialize password for controllers return_code: %s ' 'output: %s error: %s' % (cmd_status, stdout, stderr))