def get_capabilities(module): if hasattr(module, "_netconf_capabilities"): return module._netconf_capabilities capabilities = Connection(module._socket_path).get_capabilities() module._netconf_capabilities = json.loads(capabilities) return module._netconf_capabilities
def main(): """main entry point for execution """ backup_spec = dict(filename=dict(), dir_path=dict(type="path")) argument_spec = dict( backup=dict(default=False, type="bool"), backup_options=dict(type="dict", options=backup_spec), config=dict(type="str"), commit=dict(type="bool"), replace=dict(type="str"), rollback=dict(type="int"), commit_comment=dict(type="str"), defaults=dict(default=False, type="bool"), multiline_delimiter=dict(type="str"), diff_replace=dict(choices=["line", "block", "config"]), diff_match=dict(choices=["line", "strict", "exact", "none"]), diff_ignore_lines=dict(type="list"), ) mutually_exclusive = [("config", "rollback")] required_one_of = [["backup", "config", "rollback"]] module = AssibleModule( argument_spec=argument_spec, mutually_exclusive=mutually_exclusive, required_one_of=required_one_of, supports_check_mode=True, ) result = {"changed": False} connection = Connection(module._socket_path) capabilities = module.from_json(connection.get_capabilities()) if capabilities: device_operations = capabilities.get("device_operations", dict()) validate_args(module, device_operations) else: device_operations = dict() if module.params["defaults"]: if "get_default_flag" in capabilities.get("rpc"): flags = connection.get_default_flag() else: flags = "all" else: flags = [] candidate = module.params["config"] candidate = ( to_text(candidate, errors="surrogate_then_replace") if candidate else None ) running = connection.get_config(flags=flags) rollback_id = module.params["rollback"] if module.params["backup"]: result["__backup__"] = running if candidate or rollback_id or module.params["replace"]: try: result.update( run( module, device_operations, connection, candidate, running, rollback_id, ) ) except Exception as exc: module.fail_json(msg=to_text(exc)) module.exit_json(**result)
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 assible vars os.remove(output_file) result["changed"] = changed result["destination"] = dest return result
def main(): """ Called to initiate the connect to the remote device """ rc = 0 result = {} messages = list() socket_path = None # Need stdin as a byte stream if PY3: stdin = sys.stdin.buffer else: stdin = sys.stdin # Note: update the below log capture code after Display.display() is refactored. saved_stdout = sys.stdout sys.stdout = StringIO() try: # read the play context data via stdin, which means depickling it vars_data = read_stream(stdin) init_data = read_stream(stdin) if PY3: pc_data = cPickle.loads(init_data, encoding='bytes') variables = cPickle.loads(vars_data, encoding='bytes') else: pc_data = cPickle.loads(init_data) variables = cPickle.loads(vars_data) play_context = PlayContext() play_context.deserialize(pc_data) display.verbosity = play_context.verbosity except Exception as e: rc = 1 result.update({ 'error': to_text(e), 'exception': traceback.format_exc() }) if rc == 0: ssh = connection_loader.get('ssh', class_only=True) assible_playbook_pid = sys.argv[1] task_uuid = sys.argv[2] cp = ssh._create_control_path(play_context.remote_addr, play_context.port, play_context.remote_user, play_context.connection, assible_playbook_pid) # create the persistent connection dir if need be and create the paths # which we will be using later tmp_path = unfrackpath(C.PERSISTENT_CONTROL_PATH_DIR) makedirs_safe(tmp_path) socket_path = unfrackpath(cp % dict(directory=tmp_path)) lock_path = unfrackpath("%s/.assible_pc_lock_%s" % os.path.split(socket_path)) with file_lock(lock_path): if not os.path.exists(socket_path): messages.append(('vvvv', 'local domain socket does not exist, starting it')) original_path = os.getcwd() r, w = os.pipe() pid = fork_process() if pid == 0: try: os.close(r) wfd = os.fdopen(w, 'w') process = ConnectionProcess(wfd, play_context, socket_path, original_path, task_uuid, assible_playbook_pid) process.start(variables) except Exception: messages.append(('error', traceback.format_exc())) rc = 1 if rc == 0: process.run() else: process.shutdown() sys.exit(rc) else: os.close(w) rfd = os.fdopen(r, 'r') data = json.loads(rfd.read(), cls=AssibleJSONDecoder) messages.extend(data.pop('messages')) result.update(data) else: messages.append(('vvvv', 'found existing local domain socket, using it!')) conn = Connection(socket_path) conn.set_options(var_options=variables) pc_data = to_text(init_data) try: conn.update_play_context(pc_data) conn.set_check_prompt(task_uuid) except Exception as exc: # Only network_cli has update_play context and set_check_prompt, so missing this is # not fatal e.g. netconf if isinstance(exc, ConnectionError) and getattr(exc, 'code', None) == -32601: pass else: result.update({ 'error': to_text(exc), 'exception': traceback.format_exc() }) if os.path.exists(socket_path): messages.extend(Connection(socket_path).pop_messages()) messages.append(('vvvv', sys.stdout.getvalue())) result.update({ 'messages': messages, 'socket_path': socket_path }) sys.stdout = saved_stdout if 'exception' in result: rc = 1 sys.stderr.write(json.dumps(result, cls=AssibleJSONEncoder)) else: rc = 0 sys.stdout.write(json.dumps(result, cls=AssibleJSONEncoder)) sys.exit(rc)