def get_connection(module): global _DEVICE_CONNECTION if not _DEVICE_CONNECTION: connection_proxy = Connection(module._socket_path) cap = json.loads(connection_proxy.get_capabilities()) if cap['network_api'] == 'cliconf': conn = Cli(module) elif cap['network_api'] == 'exosapi': conn = HttpApi(module) else: module.fail_json(msg='Invalid connection type %s' % cap['network_api']) _DEVICE_CONNECTION = conn return _DEVICE_CONNECTION
def get_connection(module): global _DEVICE_CONNECTION if not _DEVICE_CONNECTION: if is_local_eapi(module): conn = LocalEapi(module) else: connection_proxy = Connection(module._socket_path) cap = json.loads(connection_proxy.get_capabilities()) if cap['network_api'] == 'cliconf': conn = Cli(module) elif cap['network_api'] == 'eapi': conn = HttpApi(module) _DEVICE_CONNECTION = conn return _DEVICE_CONNECTION
def api_command(module, command): payload = get_payload_from_parameters(module.params) connection = Connection(module._socket_path) # if user insert a specific version, we add it to the url version = ('v' + module.params['version'] + '/') if module.params.get('version') else '' code, response = send_request(connection, version, command, payload) result = {'changed': True} if code == 200: if module.params['wait_for_task']: if 'task-id' in response: wait_for_task(module, version, connection, response['task-id']) elif 'tasks' in response: for task_id in response['tasks']: wait_for_task(module, version, connection, task_id) result[command] = response else: module.fail_json( msg='Checkpoint device returned error {0} with message {1}'.format( code, response)) return result
def __init__(self, connection=None, *args, **kwargs): super(NetworkModule, self).__init__(*args, **kwargs) if connection is None: connection = Connection(self._socket_path) self.connection = connection
def get_capabilities(module): if hasattr(module, '_edgeos_capabilities'): return module._edgeos_capabilities capabilities = Connection(module._socket_path).get_capabilities() module._edgeos_capabilities = json.loads(capabilities) return module._edgeos_capabilities
def get_connection(module): global _CONNECTION if _CONNECTION: return _CONNECTION _CONNECTION = Connection(module._socket_path) return _CONNECTION
def get_connection(module): global _CONNECTION if _CONNECTION: return _CONNECTION _CONNECTION = Connection(module._socket_path) # Not all modules include the 'context' key. context = module.params.get('context') if context: if context == 'system': command = 'changeto system' else: command = 'changeto context %s' % context _CONNECTION.get(command) return _CONNECTION
def get_capabilities(module): if hasattr(module, '_dellos6_capabilities'): return module._dellos6_capabilities try: capabilities = Connection(module._socket_path).get_capabilities() except ConnectionError as exc: module.fail_json(msg=to_text(exc, errors='surrogate_then_replace')) module._dellos6_capabilities = json.loads(capabilities) return module._dellos6_capabilities
def get_connection(module): global _CONNECTION if _CONNECTION: return _CONNECTION _CONNECTION = Connection(module._socket_path) context = None try: context = module.params['context'] except KeyError: context = None if context: if context == 'system': command = 'changeto system' else: command = 'changeto context %s' % context _CONNECTION.get(command) return _CONNECTION
def get_connection(module): if hasattr(module, '_dellos6_connection'): return module._dellos6_connection capabilities = get_capabilities(module) network_api = capabilities.get('network_api') if network_api == 'cliconf': module._dellos6_connection = Connection(module._socket_path) else: module.fail_json(msg='Invalid connection type %s' % network_api) return module._dellos6_connection
def get_capabilities(module): if hasattr(module, 'capabilities'): return module._capabilities try: capabilities = Connection(module._socket_path).get_capabilities() except ConnectionError as exc: module.fail_json(msg=to_text(exc, errors='surrogate_then_replace')) except AssertionError: # No socket_path, connection most likely local. return dict(network_api="local") module._capabilities = json.loads(capabilities) return module._capabilities
def run(self, tmp=None, task_vars=None): socket_path = None self.play_context = copy.deepcopy(self._play_context) self.results = super(ActionModule, self).run(task_vars=task_vars) if self.play_context.connection.split('.')[-1] != 'network_cli': # Plugin is supported only with network_cli self.results['failed'] = True self.results['msg'] = 'Connection type must be fully qualified name for network_cli connection type, got %s' % self.play_context.connection return self.results # Get playbook values self.playvals = self.process_playbook_values() file_pull = self.playvals['file_pull'] self.check_library_dependencies(file_pull) if socket_path is None: socket_path = self._connection.socket_path self.conn = Connection(socket_path) # Call get_capabilities() to start the connection to the device. self.conn.get_capabilities() self.socket_timeout = self.conn.get_option('persistent_command_timeout') # This action plugin support two modes of operation. # - file_pull is False - Push files from the ansible controller to nxos switch. # - file_pull is True - Initiate copy from the device to pull files to the nxos switch. self.results['transfer_status'] = 'No Transfer' self.results['file_system'] = self.playvals['file_system'] if file_pull: self.file_pull() else: self.file_push() return self.results
def get_resource_connection(module): if hasattr(module, '_connection'): return module._connection capabilities = get_capabilities(module) network_api = capabilities.get('network_api') if network_api in ('cliconf', 'nxapi', 'eapi', 'exosapi'): module._connection = Connection(module._socket_path) elif network_api == 'netconf': module._connection = NetconfConnection(module._socket_path) elif network_api == "local": # This isn't supported, but we shouldn't fail here. # Set the connection to a fake connection so it fails sensibly. module._connection = LocalResourceConnection(module) else: module.fail_json( msg='Invalid connection type {0!s}'.format(network_api)) return module._connection
def api_call_facts(module, api_call_object, api_call_object_plural_version): payload = get_payload_from_parameters(module.params) connection = Connection(module._socket_path) # if user insert a specific version, we add it to the url version = ('v' + module.params['version'] + '/') if module.params['version'] else '' # if there is neither name nor uid, the API command will be in plural version (e.g. show-hosts instead of show-host) if payload.get("name") is None and payload.get("uid") is None: api_call_object = api_call_object_plural_version code, response = send_request(connection, version, 'show-' + api_call_object, payload) if code != 200: module.fail_json( msg='Checkpoint device returned error {0} with message {1}'.format( code, response)) result = {api_call_object: response} return result
def run(self, tmp=None, task_vars=None): del tmp # tmp no longer has any effect module_name = self._task.action.split('.')[-1] self._config_module = True if module_name == 'nxos_config' else False persistent_connection = self._play_context.connection.split('.')[-1] warnings = [] if (self._play_context.connection in ('httpapi', 'local') or self._task.args.get('provider', {}).get('transport') == 'nxapi') \ and module_name in ('nxos_file_copy', 'nxos_nxapi'): return {'failed': True, 'msg': "Transport type 'nxapi' is not valid for '%s' module." % (module_name)} if module_name == 'nxos_file_copy': self._task.args['host'] = self._play_context.remote_addr self._task.args['password'] = self._play_context.password if self._play_context.connection == 'network_cli': self._task.args['username'] = self._play_context.remote_user elif self._play_context.connection == 'local': self._task.args['username'] = self._play_context.connection_user if module_name == 'nxos_install_os': connection = self._connection if connection.transport == 'local': persistent_command_timeout = C.PERSISTENT_COMMAND_TIMEOUT persistent_connect_timeout = C.PERSISTENT_CONNECT_TIMEOUT else: persistent_command_timeout = connection.get_option('persistent_command_timeout') persistent_connect_timeout = connection.get_option('persistent_connect_timeout') display.vvvv('PERSISTENT_COMMAND_TIMEOUT is %s' % str(persistent_command_timeout), self._play_context.remote_addr) display.vvvv('PERSISTENT_CONNECT_TIMEOUT is %s' % str(persistent_connect_timeout), self._play_context.remote_addr) if persistent_command_timeout < 600 or persistent_connect_timeout < 600: msg = 'PERSISTENT_COMMAND_TIMEOUT and PERSISTENT_CONNECT_TIMEOUT' msg += ' must be set to 600 seconds or higher when using nxos_install_os module.' msg += ' Current persistent_command_timeout setting:' + str(persistent_command_timeout) msg += ' Current persistent_connect_timeout setting:' + str(persistent_connect_timeout) return {'failed': True, 'msg': msg} if persistent_connection in ('network_cli', 'httpapi'): provider = self._task.args.get('provider', {}) if any(provider.values()): display.warning('provider is unnecessary when using %s and will be ignored' % self._play_context.connection) del self._task.args['provider'] if self._task.args.get('transport'): display.warning('transport is unnecessary when using %s and will be ignored' % self._play_context.connection) del self._task.args['transport'] if module_name == 'nxos_gir': conn = Connection(self._connection.socket_path) persistent_command_timeout = conn.get_option('persistent_command_timeout') gir_timeout = 200 if persistent_command_timeout < gir_timeout: conn.set_option('persistent_command_timeout', gir_timeout) msg = "timeout value extended to %ss for nxos_gir" % gir_timeout display.warning(msg) elif self._play_context.connection == 'local': provider = load_provider(nxos_provider_spec, self._task.args) transport = provider['transport'] or 'cli' display.vvvv('connection transport is %s' % transport, self._play_context.remote_addr) if transport == 'cli': pc = copy.deepcopy(self._play_context) pc.connection = 'ansible.netcommon.network_cli' pc.network_os = 'cisco.nxos.nxos' pc.remote_addr = provider['host'] or self._play_context.remote_addr pc.port = int(provider['port'] or self._play_context.port or 22) pc.remote_user = provider['username'] or self._play_context.connection_user pc.password = provider['password'] or self._play_context.password pc.private_key_file = provider['ssh_keyfile'] or self._play_context.private_key_file pc.become = provider['authorize'] or False if pc.become: pc.become_method = 'enable' pc.become_pass = provider['auth_pass'] connection = self._shared_loader_obj.connection_loader.get('ansible.netcommon.persistent', pc, sys.stdin, task_uuid=self._task._uuid) # TODO: Remove below code after ansible minimal is cut out if connection is None: pc.connection = 'network_cli' pc.network_os = 'nxos' connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin, task_uuid=self._task._uuid) display.vvv('using connection plugin %s (was local)' % pc.connection, pc.remote_addr) command_timeout = int(provider['timeout']) if provider['timeout'] else connection.get_option('persistent_command_timeout') connection.set_options(direct={'persistent_command_timeout': command_timeout}) socket_path = connection.run() display.vvvv('socket_path: %s' % socket_path, pc.remote_addr) if not socket_path: return {'failed': True, 'msg': 'unable to open shell. Please see: ' + 'https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell'} task_vars['ansible_socket'] = socket_path else: self._task.args['provider'] = ActionModule.nxapi_implementation(provider, self._play_context) warnings.append(['connection local support for this module is deprecated and will be removed in version 2.14,' ' use connection either httpapi or ansible.netcommon.httpapi (whichever is applicable)']) else: return {'failed': True, 'msg': 'Connection type %s is not valid for this module' % self._play_context.connection} result = super(ActionModule, self).run(task_vars=task_vars) if warnings: if 'warnings' in result: result['warnings'].extend(warnings) else: result['warnings'] = warnings return result
def exec_command(self, cmd, in_data=None, sudoable=True): display.vvvv('exec_command(), socket_path=%s' % self.socket_path, host=self._play_context.remote_addr) connection = SocketConnection(self.socket_path) out = connection.exec_command(cmd, in_data=in_data, sudoable=sudoable) return 0, out, ''
def run(self, tmp=None, task_vars=None): socket_path = None network_os = self._get_network_os(task_vars).split('.')[-1] persistent_connection = self._play_context.connection.split('.')[-1] result = super(ActionModule, self).run(task_vars=task_vars) if persistent_connection != 'network_cli': # It is supported only with network_cli result['failed'] = True result['msg'] = ( 'connection type %s is not valid for net_put module,' ' please use fully qualified name of network_cli connection type' % self._play_context.connection) return result try: src = self._task.args['src'] except KeyError as exc: return { 'failed': True, 'msg': 'missing required argument: %s' % exc } src_file_path_name = src # Get destination file if specified dest = self._task.args.get('dest') # Get proto proto = self._task.args.get('protocol') if proto is None: proto = 'scp' # Get mode if set mode = self._task.args.get('mode') if mode is None: mode = 'binary' if mode == 'text': try: self._handle_template(convert_data=False) except ValueError as exc: return dict(failed=True, msg=to_text(exc)) # Now src has resolved file write to disk in current diectory for scp src = self._task.args.get('src') filename = str(uuid.uuid4()) cwd = self._loader.get_basedir() output_file = os.path.join(cwd, filename) try: with open(output_file, 'wb') as f: f.write(to_bytes(src, encoding='utf-8')) except Exception: os.remove(output_file) raise else: try: output_file = self._get_binary_src_file(src) except ValueError as exc: return dict(failed=True, msg=to_text(exc)) if socket_path is None: socket_path = self._connection.socket_path conn = Connection(socket_path) sock_timeout = conn.get_option('persistent_command_timeout') if dest is None: dest = src_file_path_name try: changed = self._handle_existing_file(conn, output_file, dest, proto, sock_timeout) if changed is False: result['changed'] = changed result['destination'] = dest return result except Exception as exc: result['msg'] = ( 'Warning: %s idempotency check failed. Check dest' % exc) try: conn.copy_file(source=output_file, destination=dest, proto=proto, timeout=sock_timeout) except Exception as exc: if to_text(exc) == "No response from server": if network_os == 'iosxr': # IOSXR sometimes closes socket prematurely after completion # of file transfer result[ 'msg'] = 'Warning: iosxr scp server pre close issue. Please check dest' else: result['failed'] = True result['msg'] = 'Exception received: %s' % exc if mode == 'text': # Cleanup tmp file expanded wih ansible vars os.remove(output_file) result['changed'] = changed result['destination'] = dest return result
def _connection(self): if not self._connection_obj: self._connection_obj = Connection(self._module._socket_path) return self._connection_obj
def _get_connection(self): if not self._connection: self._connection = Connection(self._module._socket_path) return self._connection
class ActionModule(ActionBase): def process_playbook_values(self): ''' Get playbook values and perform input validation ''' argument_spec = dict( vrf=dict(type='str', default='management'), connect_ssh_port=dict(type='int', default=22), file_system=dict(type='str', default='bootflash:'), file_pull=dict(type='bool', default=False), file_pull_timeout=dict(type='int', default=300), file_pull_compact=dict(type='bool', default=False), file_pull_kstack=dict(type='bool', default=False), local_file=dict(type='path'), local_file_directory=dict(type='path'), remote_file=dict(type='path'), remote_scp_server=dict(type='str'), remote_scp_server_user=dict(type='str'), remote_scp_server_password=dict(no_log=True), ) playvals = {} # Process key value pairs from playbook task for key in argument_spec.keys(): playvals[key] = self._task.args.get(key, argument_spec[key].get('default')) if playvals[key] is None: continue option_type = argument_spec[key].get('type', 'str') try: if option_type == 'str': playvals[key] = validation.check_type_str(playvals[key]) elif option_type == 'int': playvals[key] = validation.check_type_int(playvals[key]) elif option_type == 'bool': playvals[key] = validation.check_type_bool(playvals[key]) elif option_type == 'path': playvals[key] = validation.check_type_path(playvals[key]) else: raise AnsibleError('Unrecognized type <{0}> for playbook parameter <{1}>'.format(option_type, key)) except (TypeError, ValueError) as e: raise AnsibleError("argument %s is of type %s and we were unable to convert to %s: %s" % (key, type(playvals[key]), option_type, to_native(e))) # Validate playbook dependencies if playvals['file_pull']: if playvals.get('remote_file') is None: raise AnsibleError('Playbook parameter <remote_file> required when <file_pull> is True') if playvals.get('remote_scp_server') is None: raise AnsibleError('Playbook parameter <remote_scp_server> required when <file_pull> is True') if playvals['remote_scp_server'] or \ playvals['remote_scp_server_user']: if None in (playvals['remote_scp_server'], playvals['remote_scp_server_user']): params = '<remote_scp_server>, <remote_scp_server_user>' raise AnsibleError('Playbook parameters {0} must be set together'.format(params)) return playvals def check_library_dependencies(self, file_pull): if file_pull: if not HAS_PEXPECT: msg = 'library pexpect is required when file_pull is True but does not appear to be ' msg += 'installed. It can be installed using `pip install pexpect`' raise AnsibleError(msg) else: if paramiko is None: msg = 'library paramiko is required when file_pull is False but does not appear to be ' msg += 'installed. It can be installed using `pip install paramiko`' raise AnsibleError(msg) if not HAS_SCP: msg = 'library scp is required when file_pull is False but does not appear to be ' msg += 'installed. It can be installed using `pip install scp`' raise AnsibleError(msg) def md5sum_check(self, dst, file_system): command = 'show file {0}{1} md5sum'.format(file_system, dst) remote_filehash = self.conn.exec_command(command) remote_filehash = to_bytes(remote_filehash, errors='surrogate_or_strict') local_file = self.playvals['local_file'] try: with open(local_file, 'rb') as f: filecontent = f.read() except (OSError, IOError) as exc: raise AnsibleError('Error reading the file: {0}'.format(to_text(exc))) filecontent = to_bytes(filecontent, errors='surrogate_or_strict') local_filehash = hashlib.md5(filecontent).hexdigest() if local_filehash == remote_filehash: return True else: return False def remote_file_exists(self, remote_file, file_system): command = 'dir {0}/{1}'.format(file_system, remote_file) body = self.conn.exec_command(command) if 'No such file' in body: return False else: return self.md5sum_check(remote_file, file_system) def verify_remote_file_exists(self, dst, file_system): command = 'dir {0}/{1}'.format(file_system, dst) body = self.conn.exec_command(command) if 'No such file' in body: return 0 return body.split()[0].strip() def local_file_exists(self, file): return os.path.isfile(file) def get_flash_size(self, file_system): command = 'dir {0}'.format(file_system) body = self.conn.exec_command(command) match = re.search(r'(\d+) bytes free', body) if match: bytes_free = match.group(1) return int(bytes_free) match = re.search(r'No such file or directory', body) if match: raise AnsibleError('Invalid nxos filesystem {0}'.format(file_system)) else: raise AnsibleError('Unable to determine size of filesystem {0}'.format(file_system)) def enough_space(self, file, file_system): flash_size = self.get_flash_size(file_system) file_size = os.path.getsize(file) if file_size > flash_size: return False return True def transfer_file_to_device(self, remote_file): timeout = self.socket_timeout local_file = self.playvals['local_file'] file_system = self.playvals['file_system'] if not self.enough_space(local_file, file_system): raise AnsibleError('Could not transfer file. Not enough space on device.') # frp = full_remote_path, flp = full_local_path frp = '{0}{1}'.format(file_system, remote_file) flp = os.path.join(os.path.abspath(local_file)) try: self.conn.copy_file(source=flp, destination=frp, proto='scp', timeout=timeout) except Exception as exc: self.results['failed'] = True self.results['msg'] = ('Exception received : %s' % exc) def file_push(self): local_file = self.playvals['local_file'] remote_file = self.playvals['remote_file'] or os.path.basename(local_file) file_system = self.playvals['file_system'] if not self.local_file_exists(local_file): raise AnsibleError('Local file {0} not found'.format(local_file)) remote_file = remote_file or os.path.basename(local_file) remote_exists = self.remote_file_exists(remote_file, file_system) if not remote_exists: self.results['changed'] = True file_exists = False else: self.results['transfer_status'] = 'No Transfer: File already copied to remote device.' file_exists = True if not self.play_context.check_mode and not file_exists: self.transfer_file_to_device(remote_file) self.results['transfer_status'] = 'Sent: File copied to remote device.' self.results['local_file'] = local_file if remote_file is None: remote_file = os.path.basename(local_file) self.results['remote_file'] = remote_file def copy_file_from_remote(self, local, local_file_directory, file_system): self.results['failed'] = False nxos_hostname = self.play_context.remote_addr nxos_username = self.play_context.remote_user nxos_password = self.play_context.password port = self.playvals['connect_ssh_port'] # Build copy command components that will be used to initiate copy from the nxos device. cmdroot = 'copy scp://' ruser = self.playvals['remote_scp_server_user'] + '@' rserver = self.playvals['remote_scp_server'] rfile = self.playvals['remote_file'] + ' ' vrf = ' vrf ' + self.playvals['vrf'] local_dir_root = '/' if self.playvals['file_pull_compact']: compact = ' compact ' else: compact = '' if self.playvals['file_pull_kstack']: kstack = ' use-kstack ' else: kstack = '' def process_outcomes(session, timeout=None): if timeout is None: timeout = 10 outcome = {} outcome['user_response_required'] = False outcome['password_prompt_detected'] = False outcome['existing_file_with_same_name'] = False outcome['final_prompt_detected'] = False outcome['copy_complete'] = False outcome['expect_timeout'] = False outcome['error'] = False outcome['error_data'] = None # Possible outcomes key: # 0) - Are you sure you want to continue connecting (yes/no) # 1) - Password: or @servers's password: # 2) - Warning: There is already a file existing with this name. Do you want to overwrite (y/n)?[n] # 3) - Timeout conditions # 4) - No space on nxos device file_system # 5) - Username/Password or file permission issues # 6) - File does not exist on remote scp server # 7) - invalid nxos command # 8) - compact option not supported # 9) - compaction attempt failed # 10) - other failures like attempting to compact non image file # 11) - failure to resolve hostname # 12) - Too many authentication failures # 13) - Copy to / from this server not permitted # 14) - Copy completed without issues # 15) - nxos_router_prompt# # 16) - pexpect timeout possible_outcomes = [r'sure you want to continue connecting \(yes/no\)\? ', '(?i)Password: '******'file existing with this name', 'timed out', '(?i)No space.*#', '(?i)Permission denied.*#', '(?i)No such file.*#', '.*Invalid command.*#', 'Compaction is not supported on this platform.*#', 'Compact of.*failed.*#', '(?i)Failed.*#', '(?i)Could not resolve hostname', '(?i)Too many authentication failures', r'(?i)Copying to\/from this server name is not permitted', '(?i)Copy complete', r'#\s', pexpect.TIMEOUT] index = session.expect(possible_outcomes, timeout=timeout) # Each index maps to items in possible_outcomes if index == 0: outcome['user_response_required'] = True return outcome elif index == 1: outcome['password_prompt_detected'] = True return outcome elif index == 2: outcome['existing_file_with_same_name'] = True return outcome elif index in [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]: before = session.before.strip().replace(' \x08', '') after = session.after.strip().replace(' \x08', '') outcome['error'] = True outcome['error_data'] = 'COMMAND {0} ERROR {1}'.format(before, after) return outcome elif index == 14: outcome['copy_complete'] = True return outcome elif index == 15: outcome['final_prompt_detected'] = True return outcome elif index == 16: # The before property will contain all text up to the expected string pattern. # The after string will contain the text that was matched by the expected pattern. outcome['expect_timeout'] = True outcome['error_data'] = 'Expect Timeout error occurred: BEFORE {0} AFTER {1}'.format(session.before, session.after) return outcome else: outcome['error'] = True outcome['error_data'] = 'Unrecognized error occurred: BEFORE {0} AFTER {1}'.format(session.before, session.after) return outcome return outcome # Spawn pexpect connection to NX-OS device. nxos_session = pexpect.spawn('ssh ' + nxos_username + '@' + nxos_hostname + ' -p' + str(port)) # There might be multiple user_response_required prompts or intermittent timeouts # spawning the expect session so loop up to 24 times during the spawn process. max_attempts = 24 for connect_attempt in range(max_attempts): outcome = process_outcomes(nxos_session) if outcome['user_response_required']: nxos_session.sendline('yes') continue if outcome['password_prompt_detected']: time.sleep(3) nxos_session.sendline(nxos_password) continue if outcome['final_prompt_detected']: break if outcome['error'] or outcome['expect_timeout']: # Error encountered, try to spawn expect session n more times up to max_attempts - 1 if connect_attempt < max_attempts: outcome['error'] = False outcome['expect_timeout'] = False nxos_session.close() nxos_session = pexpect.spawn('ssh ' + nxos_username + '@' + nxos_hostname + ' -p' + str(port)) continue self.results['failed'] = True outcome['error_data'] = re.sub(nxos_password, '', outcome['error_data']) self.results['error_data'] = 'Failed to spawn expect session! ' + outcome['error_data'] nxos_session.close() return else: # The before property will contain all text up to the expected string pattern. # The after string will contain the text that was matched by the expected pattern. msg = 'After {0} attempts, failed to spawn pexpect session to {1}' msg += 'BEFORE: {2}, AFTER: {3}' error_msg = msg.format(connect_attempt, nxos_hostname, nxos_session.before, nxos_session.after) re.sub(nxos_password, '', error_msg) nxos_session.close() raise AnsibleError(error_msg) # Create local file directory under NX-OS filesystem if # local_file_directory playbook parameter is set. if local_file_directory: dir_array = local_file_directory.split('/') for each in dir_array: if each: mkdir_cmd = 'mkdir ' + local_dir_root + each nxos_session.sendline(mkdir_cmd) outcome = process_outcomes(nxos_session) if outcome['error'] or outcome['expect_timeout']: self.results['mkdir_cmd'] = mkdir_cmd self.results['failed'] = True outcome['error_data'] = re.sub(nxos_password, '', outcome['error_data']) self.results['error_data'] = outcome['error_data'] return local_dir_root += each + '/' # Initiate file copy copy_cmd = (cmdroot + ruser + rserver + rfile + file_system + local_dir_root + local + compact + vrf + kstack) self.results['copy_cmd'] = copy_cmd nxos_session.sendline(copy_cmd) for copy_attempt in range(6): outcome = process_outcomes(nxos_session, self.playvals['file_pull_timeout']) if outcome['user_response_required']: nxos_session.sendline('yes') continue if outcome['password_prompt_detected']: if self.playvals.get('remote_scp_server_password'): nxos_session.sendline(self.playvals['remote_scp_server_password']) else: err_msg = 'Remote scp server {0} requires a password.'.format(rserver) err_msg += ' Set the <remote_scp_server_password> playbook parameter or configure nxos device for passwordless scp' raise AnsibleError(err_msg) continue if outcome['existing_file_with_same_name']: nxos_session.sendline('y') continue if outcome['copy_complete']: self.results['transfer_status'] = 'Received: File copied/pulled to nxos device from remote scp server.' break if outcome['error'] or outcome['expect_timeout']: self.results['failed'] = True outcome['error_data'] = re.sub(nxos_password, '', outcome['error_data']) if self.playvals.get('remote_scp_server_password'): outcome['error_data'] = re.sub(self.playvals['remote_scp_server_password'], '', outcome['error_data']) self.results['error_data'] = outcome['error_data'] nxos_session.close() return else: # The before property will contain all text up to the expected string pattern. # The after string will contain the text that was matched by the expected pattern. msg = 'After {0} attempts, failed to copy file to {1}' msg += 'BEFORE: {2}, AFTER: {3}, CMD: {4}' error_msg = msg.format(copy_attempt, nxos_hostname, nxos_session.before, nxos_session.before, copy_cmd) re.sub(nxos_password, '', error_msg) if self.playvals.get('remote_scp_server_password'): re.sub(self.playvals['remote_scp_server_password'], '', error_msg) nxos_session.close() raise AnsibleError(error_msg) nxos_session.close() def file_pull(self): local_file = self.playvals['local_file'] remote_file = self.playvals['remote_file'] file_system = self.playvals['file_system'] # Note: This is the local file directory on the remote nxos device. local_file_dir = self.playvals['local_file_directory'] local_file = local_file or self.playvals['remote_file'].split('/')[-1] if not self.play_context.check_mode: self.copy_file_from_remote(local_file, local_file_dir, file_system) if not self.results['failed']: self.results['changed'] = True self.results['remote_file'] = remote_file if local_file_dir: dir = local_file_dir else: dir = '' self.results['local_file'] = file_system + dir + '/' + local_file self.results['remote_scp_server'] = self.playvals['remote_scp_server'] # This is the main run method for the action plugin to copy files def run(self, tmp=None, task_vars=None): socket_path = None self.play_context = copy.deepcopy(self._play_context) self.results = super(ActionModule, self).run(task_vars=task_vars) if self.play_context.connection.split('.')[-1] != 'network_cli': # Plugin is supported only with network_cli self.results['failed'] = True self.results['msg'] = 'Connection type must be fully qualified name for network_cli connection type, got %s' % self.play_context.connection return self.results # Get playbook values self.playvals = self.process_playbook_values() file_pull = self.playvals['file_pull'] self.check_library_dependencies(file_pull) if socket_path is None: socket_path = self._connection.socket_path self.conn = Connection(socket_path) # Call get_capabilities() to start the connection to the device. self.conn.get_capabilities() self.socket_timeout = self.conn.get_option('persistent_command_timeout') # This action plugin support two modes of operation. # - file_pull is False - Push files from the ansible controller to nxos switch. # - file_pull is True - Initiate copy from the device to pull files to the nxos switch. self.results['transfer_status'] = 'No Transfer' self.results['file_system'] = self.playvals['file_system'] if file_pull: self.file_pull() else: self.file_push() return self.results
def api_call_for_rule(module, api_call_object): is_access_rule = True if 'access' in api_call_object else False payload = get_payload_from_parameters(module.params) connection = Connection(module._socket_path) result = {'changed': False} if module.check_mode: return result # if user insert a specific version, we add it to the url version = ('v' + module.params['version'] + '/') if module.params.get('version') else '' if is_access_rule: copy_payload_without_some_params = get_copy_payload_without_some_params( payload, ['action', 'position']) else: copy_payload_without_some_params = get_copy_payload_without_some_params( payload, ['position']) payload_for_equals = { 'type': api_call_object, 'params': copy_payload_without_some_params } equals_code, equals_response = send_request(connection, version, 'equals', payload_for_equals) result['checkpoint_session_uid'] = connection.get_session_uid() # if code is 400 (bad request) or 500 (internal error) - fail if equals_code == 400 or equals_code == 500: module.fail_json(msg=equals_response) if equals_code == 404 and equals_response[ 'code'] == 'generic_err_command_not_found': module.fail_json( msg= 'Relevant hotfix is not installed on Check Point server. See sk114661 on Check Point Support Center.' ) if module.params['state'] == 'present': if equals_code == 200: if equals_response['equals']: if not is_equals_with_all_params(payload, connection, version, api_call_object, is_access_rule): equals_response['equals'] = False if not equals_response['equals']: # if user insert param 'position' and needed to use the 'set' command, change the param name to 'new-position' if 'position' in payload: payload['new-position'] = payload['position'] del payload['position'] code, response = send_request(connection, version, 'set-' + api_call_object, payload) if code != 200: module.fail_json(msg=response) handle_publish(module, connection, version) result['changed'] = True result[api_call_object] = response else: # objects are equals and there is no need for set request pass elif equals_code == 404: code, response = send_request(connection, version, 'add-' + api_call_object, payload) if code != 200: module.fail_json(msg=response) handle_publish(module, connection, version) result['changed'] = True result[api_call_object] = response elif module.params['state'] == 'absent': if equals_code == 200: payload_for_delete = get_copy_payload_with_some_params( payload, delete_params) code, response = send_request(connection, version, 'delete-' + api_call_object, payload_for_delete) if code != 200: module.fail_json(msg=response) handle_publish(module, connection, version) result['changed'] = True elif equals_code == 404: # no need to delete because object dose not exist pass return result
def run(self, tmp=None, task_vars=None): socket_path = None self._get_network_os(task_vars) persistent_connection = self._play_context.connection.split('.')[-1] result = super(ActionModule, self).run(task_vars=task_vars) if persistent_connection != 'network_cli': # It is supported only with network_cli result['failed'] = True result['msg'] = ( 'connection type %s is not valid for net_get module,' ' please use fully qualified name of network_cli connection type' % self._play_context.connection) return result try: src = self._task.args['src'] except KeyError as exc: return { 'failed': True, 'msg': 'missing required argument: %s' % exc } # Get destination file if specified dest = self._task.args.get('dest') if dest is None: dest = self._get_default_dest(src) else: dest = self._handle_dest_path(dest) # Get proto proto = self._task.args.get('protocol') if proto is None: proto = 'scp' if socket_path is None: socket_path = self._connection.socket_path conn = Connection(socket_path) sock_timeout = conn.get_option('persistent_command_timeout') try: changed = self._handle_existing_file(conn, src, dest, proto, sock_timeout) if changed is False: result['changed'] = changed result['destination'] = dest return result except Exception as exc: result['msg'] = ( 'Warning: %s idempotency check failed. Check dest' % exc) try: conn.get_file(source=src, destination=dest, proto=proto, timeout=sock_timeout) except Exception as exc: result['failed'] = True result['msg'] = 'Exception received: %s' % exc result['changed'] = changed result['destination'] = dest return result
def exec_scp(module, command): connection = Connection(module._socket_path) return connection.scp(**command)
def get_connection(module): return Connection(module._socket_path)
def run(self, tmp=None, task_vars=None): socket_path = None transport = 'rest' persistent_connection = self._play_context.connection.split('.')[-1] if persistent_connection == 'network_cli': provider = self._task.args.get('provider', {}) if any(provider.values()): display.warning( "'provider' is unnecessary when using 'network_cli' and will be ignored" ) elif self._play_context.connection == 'local': provider = load_provider(f5_provider_spec, self._task.args) transport = provider['transport'] or transport display.vvvv('connection transport is %s' % transport, self._play_context.remote_addr) if transport == 'cli': pc = copy.deepcopy(self._play_context) pc.connection = 'network_cli' pc.network_os = 'bigiq' pc.remote_addr = provider.get('server', self._play_context.remote_addr) pc.port = int(provider['server_port'] or self._play_context.port or 22) pc.remote_user = provider.get( 'user', self._play_context.connection_user) pc.password = provider.get('password', self._play_context.password) pc.private_key_file = provider[ 'ssh_keyfile'] or self._play_context.private_key_file command_timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT) display.vvv('using connection plugin %s' % pc.connection, pc.remote_addr) connection = self._shared_loader_obj.connection_loader.get( 'persistent', pc, sys.stdin, task_uuid=self._task._uuid) connection.set_options( direct={'persistent_command_timeout': command_timeout}) socket_path = connection.run() display.vvvv('socket_path: %s' % socket_path, pc.remote_addr) if not socket_path: return { 'failed': True, 'msg': 'Unable to open shell. Please see: ' 'https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell' } task_vars['ansible_socket'] = socket_path if (self._play_context.connection == 'local' and transport == 'cli') or persistent_connection == 'network_cli': # make sure we are in the right cli context which should be # enable mode and not config module if socket_path is None: socket_path = self._connection.socket_path conn = Connection(socket_path) out = conn.get_prompt() while '(config' in to_text( out, errors='surrogate_then_replace').strip(): display.vvvv('wrong context, sending exit to device', self._play_context.remote_addr) conn.send_command('exit') out = conn.get_prompt() result = super(ActionModule, self).run(tmp, task_vars) return result