示例#1
0
    def run(self, args, variables=None, vm=None, create=True, no_symbols=False, default=UNDEFINED):

        ret = []

        cmd = ['qvm-pass']
        if vm is not None:
            cmd += ['-d', vm]
        if create:
            cmd += ['get-or-generate']
            if no_symbols:
                cmd += ["-n"]
        else:
            cmd += ['get']
        cmd += ['--', args[0]]

        display.vvvv(u"Password lookup using command %s" % cmd)

        try:
            ret = subprocess.check_output(cmd)[:-1]
        except subprocess.CalledProcessError as e:
            if e.returncode == 8:
                if create or default is UNDEFINED:
                    raise AnsibleError("qubes-pass could not locate password entry %s in store" % args[0])
                return [default]
            else:
                raise AnsibleError("qubes-pass lookup failed: %s" % e)

        return [ret]
示例#2
0
    def _start_connection(self):
        '''
        Starts the persistent connection
        '''
        master, slave = pty.openpty()

        python = sys.executable

        def find_file_in_path(filename):
            # Check $PATH first, followed by same directory as sys.argv[0]
            paths = os.environ['PATH'].split(os.pathsep) + [os.path.dirname(sys.argv[0])]
            for dirname in paths:
                fullpath = os.path.join(dirname, filename)
                if os.path.isfile(fullpath):
                    return fullpath

            raise AnsibleError("Unable to find location of '%s'" % filename)

        p = subprocess.Popen(
            [python, find_file_in_path('ansible-connection'), to_text(os.getppid())],
            stdin=slave, stdout=subprocess.PIPE, stderr=subprocess.PIPE
        )
        stdin = os.fdopen(master, 'wb', 0)
        os.close(slave)

        # Need to force a protocol that is compatible with both py2 and py3.
        # That would be protocol=2 or less.
        # Also need to force a protocol that excludes certain control chars as
        # stdin in this case is a pty and control chars will cause problems.
        # that means only protocol=0 will work.
        src = cPickle.dumps(self._play_context.serialize(), protocol=0)
        stdin.write(src)

        stdin.write(b'\n#END_INIT#\n')
        stdin.flush()

        (stdout, stderr) = p.communicate()
        stdin.close()

        if p.returncode == 0:
            result = json.loads(to_text(stdout, errors='surrogate_then_replace'))
        else:
            try:
                result = json.loads(to_text(stderr, errors='surrogate_then_replace'))
            except getattr(json.decoder, 'JSONDecodeError', ValueError):
                # JSONDecodeError only available on Python 3.5+
                result = {'error': to_text(stderr, errors='surrogate_then_replace')}

        if 'messages' in result:
            for msg in result.get('messages'):
                display.vvvv('%s' % msg, host=self._play_context.remote_addr)

        if 'error' in result:
            if self._play_context.verbosity > 2:
                if result.get('exception'):
                    msg = "The full traceback is:\n" + result['exception']
                    display.display(msg, color=C.COLOR_ERROR)
            raise AnsibleError(result['error'])

        return result['socket_path']
示例#3
0
    def _connect(self):
        ''' activates the connection object '''

        if not self._connected:
            wrong_user = False
            tries = 3
            self.conn = socket.socket()
            self.conn.settimeout(C.ACCELERATE_CONNECT_TIMEOUT)
            display.vvvv("attempting connection to %s via the accelerated port %d" % (self._play_context.remote_addr, self._play_context.accelerate_port), host=self._play_context.remote_addr)
            while tries > 0:
                try:
                    self.conn.connect((self._play_context.remote_addr,self._play_context.accelerate_port))
                    break
                except socket.error:
                    display.vvvv("connection to %s failed, retrying..." % self._play_context.remote_addr, host=self._play_context.remote_addr)
                    time.sleep(0.1)
                    tries -= 1
            if tries == 0:
                display.vvv("Could not connect via the accelerated connection, exceeded # of tries", host=self._play_context.remote_addr)
                raise AnsibleConnectionFailure("Failed to connect to %s on the accelerated port %s" % (self._play_context.remote_addr, self._play_context.accelerate_port))
            elif wrong_user:
                display.vvv("Restarting daemon with a different remote_user", host=self._play_context.remote_addr)
                raise AnsibleError("The accelerated daemon was started on the remote with a different user")

            self.conn.settimeout(C.ACCELERATE_TIMEOUT)
            if not self.validate_user():
                # the accelerated daemon was started with a
                # different remote_user. The above command
                # should have caused the accelerate daemon to
                # shutdown, so we'll reconnect.
                wrong_user = True

        self._connected = True
        return self
示例#4
0
    def run(self, terms, variables=None, **kwargs):

        validate_certs = kwargs.get('validate_certs', True)
        split_lines = kwargs.get('split_lines', True)
        use_proxy = kwargs.get('use_proxy', True)

        ret = []
        for term in terms:
            display.vvvv("url lookup connecting to %s" % term)
            try:
                response = open_url(term, validate_certs=validate_certs, use_proxy=use_proxy)
            except HTTPError as e:
                raise AnsibleError("Received HTTP error for %s : %s" % (term, str(e)))
            except URLError as e:
                raise AnsibleError("Failed lookup url for %s : %s" % (term, str(e)))
            except SSLValidationError as e:
                raise AnsibleError("Error validating the server's certificate for %s: %s" % (term, str(e)))
            except ConnectionError as e:
                raise AnsibleError("Error connecting to %s: %s" % (term, str(e)))

            if split_lines:
                for line in response.read().splitlines():
                    ret.append(to_text(line))
            else:
                ret.append(to_text(response.read()))
        return ret
示例#5
0
文件: sros.py 项目: ernstp/ansible
    def run(self, tmp=None, task_vars=None):

        if self._play_context.connection != 'local':
            return dict(
                failed=True,
                msg='invalid connection specified, expected connection=local, '
                    'got %s' % self._play_context.connection
            )

        provider = load_provider(sros_provider_spec, self._task.args)

        pc = copy.deepcopy(self._play_context)
        pc.connection = 'network_cli'
        pc.network_os = 'sros'
        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.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)

        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

        result = super(ActionModule, self).run(tmp, task_vars)
        return result
 def run(self, tmp=None, task_vars=None):
     display.v("a log")
     display.vv("Kind of verbose")
     display.vvv("Verbose")
     display.vvvv("Lookout!")
     display.verbose("Super custom verbosity", caplevel=6)
     return {'msg': 'done'}
示例#7
0
    def run(self, tmp=None, task_vars=None):
        del tmp  # tmp no longer has any effect

        if self._play_context.connection == 'local':
            provider = load_provider(asa_provider_spec, self._task.args)
            pc = copy.deepcopy(self._play_context)
            pc.connection = 'network_cli'
            pc.network_os = 'asa'
            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.timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)
            pc.become = provider['authorize'] or False
            pc.become_pass = provider['auth_pass']
            pc.become_method = 'enable'

            display.vvv('using connection plugin %s (was local)' % pc.connection, pc.remote_addr)
            connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin)

            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

        result = super(ActionModule, self).run(task_vars=task_vars)

        return result
示例#8
0
    def run(self, terms, variables, **kwargs):

        convert_data_p = kwargs.get('convert_data', True)
        ret = []

        for term in terms:
            display.debug("File lookup term: %s" % term)

            lookupfile = self.find_file_in_search_path(variables, 'templates', term)
            display.vvvv("File lookup using %s as file" % lookupfile)
            if lookupfile:
                with open(to_bytes(lookupfile, errors='surrogate_or_strict'), 'rb') as f:
                    template_data = to_text(f.read(), errors='surrogate_or_strict')

                    # set jinja2 internal search path for includes
                    if 'ansible_search_path' in variables:
                        searchpath = variables['ansible_search_path']
                    else:
                        searchpath = [self._loader._basedir, os.path.dirname(lookupfile)]
                    self._templar.environment.loader.searchpath = searchpath

                    # do the templating
                    res = self._templar.template(template_data, preserve_trailing_newlines=True,convert_data=convert_data_p)
                    ret.append(res)
            else:
                raise AnsibleError("the template file %s could not be found for the lookup" % term)

        return ret
示例#9
0
    def _start_connection(self, play_context):

        display.vvv('using connection plugin %s' % play_context.connection, play_context.remote_addr)
        connection = self._shared_loader_obj.connection_loader.get('persistent',
                                                                   play_context, sys.stdin)

        socket_path = connection.run()
        display.vvvv('socket_path: %s' % socket_path, play_context.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'}

        # make sure we are in the right cli context which should be
        # enable mode and not config module
        rc, out, err = connection.exec_command('prompt()')
        if str(out).strip().endswith(')#'):
            display.vvvv('wrong context, sending exit to device', self._play_context.remote_addr)
            connection.exec_command('exit')

        if self._play_context.become_method == 'enable':
            self._play_context.become = False
            self._play_context.become_method = None

        return socket_path
    def run(self, terms, variables=None, **kwargs):
        # lookups in general are expected to both take a list as input and output a list
        # this is done so they work with the looping construct `with_`.
        # Only the gods know why you would want to look through several viya licenses files, but conventions are conventions for a reason... so here we are.
        ret = []
        for term in terms:
            display.debug("License lookup term: %s" % term)

            # Find the file in the expected search path, using a class method
            # that implements the 'expected' search path for Ansible plugins.
            lookupfile = self.find_file_in_search_path(variables, 'files', term)

            # Don't use print or your own logging, the display class
            # takes care of it in a unified way.
            display.vvvv(u"Sas License lookup using %s as file" % lookupfile)
            try:
                if lookupfile:
                    sas_license = SasLicense(lookupfile)
                    # contents, show_data = self._loader._get_file_contents(lookupfile)
                    ret.append(sas_license.get_ansible_dict())
                else:
                    # Always use ansible error classes to throw 'final' exceptions,
                    # so the Ansible engine will know how to deal with them.
                    # The Parser error indicates invalid options passed
                    raise AnsibleParserError()
            except AnsibleParserError:
                raise AnsibleError("could not locate file in lookup: %s" % term)

        return ret
示例#11
0
    def run(self, terms, variables, **kwargs):

        convert_data_p = kwargs.get('convert_data', True)
        basedir = self.get_basedir(variables)

        ret = []

        for term in terms:
            display.debug("File lookup term: %s" % term)

            lookupfile = self._loader.path_dwim_relative(basedir, 'templates', term)
            display.vvvv("File lookup using %s as file" % lookupfile)
            if lookupfile and os.path.exists(lookupfile):
                with open(lookupfile, 'r') as f:
                    template_data = to_unicode(f.read())

                    searchpath = [self._loader._basedir, os.path.dirname(lookupfile)]
                    if 'role_path' in variables:
                        searchpath.insert(1, C.DEFAULT_ROLES_PATH)
                        searchpath.insert(1, variables['role_path'])

                    self._templar.environment.loader.searchpath = searchpath
                    res = self._templar.template(template_data, preserve_trailing_newlines=True,convert_data=convert_data_p)
                    ret.append(res)
            else:
                raise AnsibleError("the template file %s could not be found for the lookup" % term)

        return ret
示例#12
0
文件: data.py 项目: ernstp/ansible
    def add_host(self, host, group=None, port=None):
        ''' adds a host to inventory and possibly a group if not there already '''

        g = None
        if group:
            if group in self.groups:
                g = self.groups[group]
            else:
                raise AnsibleError("Could not find group %s in inventory" % group)

        if host not in self.hosts:
            h = Host(host, port)
            self.hosts[host] = h
            if self.current_source:  # set to 'first source' in which host was encountered
                self.set_variable(host, 'inventory_file', os.path.basename(self.current_source))
                self.set_variable(host, 'inventory_dir', basedir(self.current_source))
            else:
                self.set_variable(host, 'inventory_file', None)
                self.set_variable(host, 'inventory_dir', None)
            display.debug("Added host %s to inventory" % (host))

            # set default localhost from inventory to avoid creating an implicit one. Last localhost defined 'wins'.
            if host in C.LOCALHOST:
                if self.localhost is None:
                    self.localhost = self.hosts[host]
                    display.vvvv("Set default localhost to %s" % h)
                else:
                    display.warning("A duplicate localhost-like entry was found (%s). First found localhost was %s" % (h, self.localhost.name))
        else:
            h = self.hosts[host]

        if g:
            g.add_host(h)
            self._groups_dict_cache = {}
            display.debug("Added host %s to group %s" % (host, group))
示例#13
0
    def run(self, terms, variables=None, **kwargs):

        ret = []

        basedir = self.get_basedir(variables)

        for term in terms:
            display.debug("File lookup term: %s" % term)

            # Special handling of the file lookup, used primarily when the
            # lookup is done from a role. If the file isn't found in the
            # basedir of the current file, use dwim_relative to look in the
            # role/files/ directory, and finally the playbook directory
            # itself (which will be relative to the current working dir)

            lookupfile = self._loader.path_dwim_relative(basedir, 'files', term)
            display.vvvv("File lookup using %s as file" % lookupfile)
            try:
                if lookupfile:
                    contents, show_data = self._loader._get_file_contents(lookupfile)
                    ret.append(contents.rstrip())
                else:
                    raise AnsibleParserError()
            except AnsibleParserError:
                raise AnsibleError("could not locate file in lookup: %s" % term)

        return ret
示例#14
0
    def run(self, terms, variables=None, **kwargs):

        ret = []

        for term in terms:
            display.debug("File lookup term: %s" % term)

            # Find the file in the expected search path
            lookupfile = self.find_file_in_search_path(variables, 'files', term)
            display.vvvv(u"File lookup using %s as file" % lookupfile)
            try:
                if lookupfile:
                    b_contents, show_data = self._loader._get_file_contents(lookupfile)
                    contents = to_text(b_contents, errors='surrogate_or_strict')
                    if kwargs.get('lstrip', False):
                        contents = contents.lstrip()
                    if kwargs.get('rstrip', True):
                        contents = contents.rstrip()
                    ret.append(contents)
                else:
                    raise AnsibleParserError()
            except AnsibleParserError:
                raise AnsibleError("could not locate file in lookup: %s" % term)

        return ret
示例#15
0
 def fetch_file(self, in_path, out_path):
     '''Fetch a file from VM to local.'''
     super(Connection, self).fetch_file(in_path, out_path)
     display.vvvv("FETCH %s to %s" % (in_path, out_path), host=self._play_context.remote_addr)
     in_path = _prefix_login_path(in_path)
     out_file = open(out_path, "wb")
     try:
         payload = 'fetch(%r, %r)\n' % (in_path, BUFSIZE)
         self._transport.stdin.write(payload)
         self._transport.stdin.flush()
         while True:
             chunk_len = self._transport.stdout.readline(16)
             try:
                 chunk_len = int(chunk_len)
             except Exception:
                 if chunk_len == "N\n":
                     exc = decode_exception(self._transport.stdin)
                     raise exc
                 else:
                     self._abort_transport()
                     raise errors.AnsibleError("chunk size from remote end is unexpected: %r" % chunk_len)
             if chunk_len > BUFSIZE or chunk_len < 0:
                 raise errors.AnsibleError("chunk size from remote end is invalid: %r" % chunk_len)
             if chunk_len == 0:
                 break
             chunk = self._transport.stdout.read(chunk_len)
             if len(chunk) != chunk_len:
                 raise errors.AnsibleError("stderr size from remote end does not match actual stderr length: %s != %s" % (chunk_len, len(chunk)))
             out_file.write(chunk)
     except Exception:
         self._abort_transport()
         raise
示例#16
0
 def reset(self):
     '''
     Reset the connection
     '''
     if self._socket_path:
         display.vvvv('resetting persistent connection for socket_path %s' % self._socket_path, host=self._play_context.remote_addr)
         self.close()
     display.vvvv('reset call on connection instance', host=self._play_context.remote_addr)
示例#17
0
    def _winrm_connect(self):
        '''
        Establish a WinRM connection over HTTP/HTTPS.
        '''
        display.vvv("ESTABLISH WINRM CONNECTION FOR USER: %s on PORT %s TO %s" %
                    (self._winrm_user, self._winrm_port, self._winrm_host), host=self._winrm_host)

        winrm_host = self._winrm_host
        if HAS_IPADDRESS:
            display.vvvv("checking if winrm_host %s is an IPv6 address" % winrm_host)
            try:
                ipaddress.IPv6Address(winrm_host)
            except ipaddress.AddressValueError:
                pass
            else:
                winrm_host = "[%s]" % winrm_host

        netloc = '%s:%d' % (winrm_host, self._winrm_port)
        endpoint = urlunsplit((self._winrm_scheme, netloc, self._winrm_path, '', ''))
        errors = []
        for transport in self._winrm_transport:
            if transport == 'kerberos':
                if not HAVE_KERBEROS:
                    errors.append('kerberos: the python kerberos library is not installed')
                    continue
                if self._kerb_managed:
                    self._kerb_auth(self._winrm_user, self._winrm_pass)
            display.vvvvv('WINRM CONNECT: transport=%s endpoint=%s' % (transport, endpoint), host=self._winrm_host)
            try:
                winrm_kwargs = self._winrm_kwargs.copy()
                if self._winrm_connection_timeout:
                    winrm_kwargs['operation_timeout_sec'] = self._winrm_connection_timeout
                    winrm_kwargs['read_timeout_sec'] = self._winrm_connection_timeout + 1
                protocol = Protocol(endpoint, transport=transport, **winrm_kwargs)

                # open the shell from connect so we know we're able to talk to the server
                if not self.shell_id:
                    self.shell_id = protocol.open_shell(codepage=65001)  # UTF-8
                    display.vvvvv('WINRM OPEN SHELL: %s' % self.shell_id, host=self._winrm_host)

                return protocol
            except Exception as e:
                err_msg = to_text(e).strip()
                if re.search(to_text(r'Operation\s+?timed\s+?out'), err_msg, re.I):
                    raise AnsibleError('the connection attempt timed out')
                m = re.search(to_text(r'Code\s+?(\d{3})'), err_msg)
                if m:
                    code = int(m.groups()[0])
                    if code == 401:
                        err_msg = 'the specified credentials were rejected by the server'
                    elif code == 411:
                        return protocol
                errors.append(u'%s: %s' % (transport, err_msg))
                display.vvvvv(u'WINRM CONNECTION ERROR: %s\n%s' % (err_msg, to_text(traceback.format_exc())), host=self._winrm_host)
        if errors:
            raise AnsibleConnectionFailure(', '.join(map(to_native, errors)))
        else:
            raise AnsibleError('No transport found for WinRM connection')
示例#18
0
	def run(self, terms, variables=None, **kwargs):
		for term in terms:
			display.debug("Fileexists lookup term: %s" % term)

			try:
				lookupfile = self.find_file_in_search_path(variables, 'files', term)
				display.vvvv(u"Fileexists lookup using %s as file" % lookupfile)
			except AnsibleError:
				return False
		return True
示例#19
0
def _fetch_conjur_token(conjur_url, account, username, api_key):
    conjur_url = '{0}/authn/{1}/{2}/authenticate'.format(conjur_url, account, username)
    display.vvvv('Authentication request to Conjur at: {0}, with user: {1}'.format(conjur_url, username))

    response = open_url(conjur_url, data=api_key, method='POST')
    code = response.getcode()
    if code != 200:
        raise AnsibleError('Failed to authenticate as \'{0}\' (got {1} response)'
                           .format(username, code))

    return response.read()
示例#20
0
    def _kerb_auth(self, principal, password):
        if password is None:
            password = ""

        self._kerb_ccache = tempfile.NamedTemporaryFile()
        display.vvvvv("creating Kerberos CC at %s" % self._kerb_ccache.name)
        krb5ccname = "FILE:%s" % self._kerb_ccache.name
        os.environ["KRB5CCNAME"] = krb5ccname
        krb5env = dict(KRB5CCNAME=krb5ccname)

        # stores various flags to call with kinit, we currently only use this
        # to set -f so we can get a forward-able ticket (cred delegation)
        kinit_flags = []
        if boolean(self.get_option('_extras').get('ansible_winrm_kerberos_delegation', False)):
            kinit_flags.append('-f')

        kinit_cmdline = [self._kinit_cmd]
        kinit_cmdline.extend(kinit_flags)
        kinit_cmdline.append(principal)

        # pexpect runs the process in its own pty so it can correctly send
        # the password as input even on MacOS which blocks subprocess from
        # doing so. Unfortunately it is not available on the built in Python
        # so we can only use it if someone has installed it
        if HAS_PEXPECT:
            kinit_cmdline = " ".join(kinit_cmdline)
            password = to_text(password, encoding='utf-8',
                               errors='surrogate_or_strict')

            display.vvvv("calling kinit with pexpect for principal %s"
                         % principal)
            events = {
                ".*:": password + "\n"
            }
            # technically this is the stdout but to match subprocess we will
            # call it stderr
            stderr, rc = pexpect.run(kinit_cmdline, withexitstatus=True, events=events, env=krb5env, timeout=60)
        else:
            password = to_bytes(password, encoding='utf-8',
                                errors='surrogate_or_strict')

            display.vvvv("calling kinit with subprocess for principal %s"
                         % principal)
            p = subprocess.Popen(kinit_cmdline, stdin=subprocess.PIPE,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE,
                                 env=krb5env)
            stdout, stderr = p.communicate(password + b'\n')
            rc = p.returncode != 0

        if rc != 0:
            raise AnsibleConnectionFailure("Kerberos auth failure: %s" % to_native(stderr.strip()))

        display.vvvvv("kinit succeeded for principal %s" % principal)
示例#21
0
    def run(self, tmp=None, task_vars=None):
        del tmp  # tmp no longer has any effect

        socket_path = None

        if self._play_context.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')
                del self._task.args['provider']
        elif self._play_context.connection == 'local':
            provider = load_provider(ios_provider_spec, self._task.args)
            pc = copy.deepcopy(self._play_context)
            pc.connection = 'network_cli'
            pc.network_os = 'ios'
            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.timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)
            pc.become = provider['authorize'] or False
            if pc.become:
                pc.become_method = 'enable'
            pc.become_pass = provider['auth_pass']

            display.vvv('using connection plugin %s (was local)' % pc.connection, pc.remote_addr)
            connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin)

            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:
            return {'failed': True, 'msg': 'Connection type %s is not valid for this module' % self._play_context.connection}

        # 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 to_text(out, errors='surrogate_then_replace').strip().endswith(')#'):
            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(task_vars=task_vars)
        return result
示例#22
0
    def run(self, tmp=None, task_vars=None):
        del tmp  # tmp no longer has any effect

        if self._play_context.connection != 'local':
            return dict(
                failed=True,
                msg='invalid connection specified, expected connection=local, '
                    'got %s' % self._play_context.connection
            )

        provider = load_provider(ironware_provider_spec, self._task.args)

        pc = copy.deepcopy(self._play_context)
        pc.connection = 'network_cli'
        pc.network_os = 'ironware'
        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.timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)
        pc.become = provider['authorize'] or False
        if pc.become:
            pc.become_method = 'enable'
        pc.become_pass = provider['auth_pass']

        display.vvv('using connection plugin %s (was local)' % pc.connection, pc.remote_addr)
        connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin)

        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'}

        # make sure we are in the right cli context which should be
        # enable mode and not config module
        conn = Connection(socket_path)
        out = conn.get_prompt()
        if to_text(out, errors='surrogate_then_replace').strip().endswith(')#'):
            display.vvvv('wrong context, sending end to device', self._play_context.remote_addr)
            conn.send_command('end')

        task_vars['ansible_socket'] = socket_path

        if self._play_context.become_method == 'enable':
            self._play_context.become = False
            self._play_context.become_method = None

        result = super(ActionModule, self).run(task_vars=task_vars)

        return result
示例#23
0
    def run(self):
        """Returns the path of the persistent connection socket.

        Attempts to ensure (within playcontext.timeout seconds) that the
        socket path exists. If the path exists (or the timeout has expired),
        returns the socket path.
        """
        display.vvvv('starting connection from persistent connection plugin', host=self._play_context.remote_addr)
        socket_path = self._start_connection()
        display.vvvv('local domain socket path is %s' % socket_path, host=self._play_context.remote_addr)
        setattr(self, '_socket_path', socket_path)
        return socket_path
示例#24
0
 def exec_command(self, cmd, in_data=None, sudoable=False):
     '''Run a command on the VM.'''
     super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
     if isinstance(cmd, basestring):
         cmd = shlex.split(cmd)
     display.vvvv("EXEC %s" % cmd, host=self._play_context.remote_addr)
     try:
         payload = 'popen(%r, %r)\n' % (cmd, in_data)
         self._transport.stdin.write(payload)
         self._transport.stdin.flush()
         yesno = self._transport.stdout.readline(2)
     except Exception:
         self._abort_transport()
         raise
     if yesno == "Y\n":
         try:
             retcode = self._transport.stdout.readline(16)
             try:
                 retcode = int(retcode)
             except Exception:
                 raise errors.AnsibleError("return code from remote end is unexpected: %r" % retcode)
             if retcode > 65536 or retcode < -65535:
                 raise errors.AnsibleError("return code from remote end is outside the range: %r" % retcode)
             stdout_len = self._transport.stdout.readline(16)
             try:
                 stdout_len = int(stdout_len)
             except Exception:
                 raise errors.AnsibleError("stdout size from remote end is unexpected: %r" % stdout_len)
             if stdout_len > 1024*1024*1024 or stdout_len < 0:
                 raise errors.AnsibleError("stdout size from remote end is invalid: %r" % stdout_len)
             stdout = self._transport.stdout.read(stdout_len) if stdout_len != 0 else ''
             if len(stdout) != stdout_len:
                 raise errors.AnsibleError("stdout size from remote end does not match actual stdout length: %s != %s" % (stdout_len, len(stdout)))
             stderr_len = self._transport.stdout.readline(16)
             try:
                 stderr_len = int(stderr_len)
             except Exception:
                 raise errors.AnsibleError("stderr size from remote end is unexpected: %r" % stderr_len)
             if stdout_len > 1024*1024*1024 or stdout_len < 0:
                 raise errors.AnsibleError("stderr size from remote end is invalid: %s" % stderr_len)
             stderr = self._transport.stdout.read(stderr_len) if stderr_len != 0 else ''
             if len(stderr) != stderr_len:
                 raise errors.AnsibleError("stderr size from remote end does not match actual stderr length: %s != %s" % (stderr_len, len(stderr)))
             return (retcode, stdout, stderr)
         except Exception:
             self._abort_transport()
             raise
     elif yesno == "N\n":
         exc = decode_exception(self._transport.stdin)
         raise exc
     else:
         self._abort_transport()
         raise errors.AnsibleError("pass/fail from remote end is unexpected: %r" % yesno)
示例#25
0
    def wrapped(self, *args, **kwargs):
        if not self.initialized:
            display.vvvv("Initial connection to galaxy_server: %s" % self._api_server)
            server_version = self._get_server_api_version()
            if server_version not in self.SUPPORTED_VERSIONS:
                raise AnsibleError("Unsupported Galaxy server API version: %s" % server_version)

            self.baseurl = '%s/api/%s' % (self._api_server, server_version)
            self.version = server_version  # for future use
            display.vvvv("Base API: %s" % self.baseurl)
            self.initialized = True
        return method(self, *args, **kwargs)
示例#26
0
文件: doc.py 项目: ernstp/ansible
    def find_plugins(self, path, ptype):

        display.vvvv("Searching %s for plugins" % path)

        if not os.path.exists(path):
            display.vvvv("%s does not exist" % path)
            return

        bkey = ptype.upper()
        for plugin in os.listdir(path):
            display.vvvv("Found %s" % plugin)
            full_path = '/'.join([path, plugin])

            if plugin.startswith('.'):
                continue
            elif os.path.isdir(full_path):
                continue
            elif any(plugin.endswith(x) for x in C.BLACKLIST_EXTS):
                continue
            elif plugin.startswith('__'):
                continue
            elif plugin in C.IGNORE_FILES:
                continue
            elif plugin .startswith('_'):
                if os.path.islink(full_path):  # avoids aliases
                    continue

            plugin = os.path.splitext(plugin)[0]  # removes the extension
            plugin = plugin.lstrip('_')  # remove underscore from deprecated plugins

            if plugin not in plugin_docs.BLACKLIST.get(bkey, ()):
                self.plugin_list.add(plugin)
                display.vvvv("Added %s" % plugin)
示例#27
0
    def run(self, terms, variables=None, **kwargs):

        display.vvvv(terms)
        if isinstance(terms, list):
            return_values = []
            for term in terms:
                display.vvvv("Term: %s" % term)
                cyberark_conn = CyberarkPassword(**term)
                return_values.append(cyberark_conn.get())
            return return_values
        else:
            cyberark_conn = CyberarkPassword(**terms)
            result = cyberark_conn.get()
            return result
示例#28
0
def _load_conf_from_file(conf_path):
    display.vvv('conf file: {0}'.format(conf_path))

    if not os.path.exists(conf_path):
        raise AnsibleError('Conjur configuration file `{0}` was not found on the controlling host'
                           .format(conf_path))

    display.vvvv('Loading configuration from: {0}'.format(conf_path))
    with open(conf_path) as f:
        config = yaml.safe_load(f.read())
        if 'account' not in config or 'appliance_url' not in config:
            raise AnsibleError('{0} on the controlling host must contain an `account` and `appliance_url` entry'
                               .format(conf_path))
        return config
示例#29
0
    def run(self, terms, **kwargs):
        if not HAS_KEYRING:
            raise AnsibleError(u"Can't LOOKUP(keyring): missing required python library 'keyring'")

        display.vvvv(u"keyring: %s" % keyring.get_keyring())
        ret = []
        for term in terms:
            (servicename, username) = (term.split()[0], term.split()[1])
            display.vvvv(u"username: %s, servicename: %s " % (username, servicename))
            password = keyring.get_password(servicename, username)
            if password is None:
                raise AnsibleError(u"servicename: %s for user %s not found" % (servicename, username))
            ret.append(password.rstrip())
        return ret
示例#30
0
 def send(self, command, prompt=None, answer=None, newline=True, sendonly=False, prompt_retry_check=False):
     '''
     Sends the command to the device in the opened shell
     '''
     try:
         self._history.append(command)
         self._ssh_shell.sendall(b'%s\r' % command)
         if sendonly:
             return
         response = self.receive(command, prompt, answer, newline, prompt_retry_check)
         return to_text(response, errors='surrogate_or_strict')
     except (socket.timeout, AttributeError):
         display.vvvv(traceback.format_exc(), host=self._play_context.remote_addr)
         raise AnsibleConnectionFailure("timeout trying to send command: %s" % command.strip())
示例#31
0
    def run(self, tmp=None, task_vars=None):
        if self._play_context.connection != 'local':
            return dict(
                failed=True,
                msg='invalid connection specified, expected connection=local, '
                'got %s' % self._play_context.connection)

        play_context = copy.deepcopy(self._play_context)
        play_context.network_os = self._get_network_os(task_vars)

        self.provider = self._load_provider(play_context.network_os)

        if play_context.network_os == 'junos':
            play_context.connection = 'netconf'
            play_context.port = int(self.provider['port']
                                    or self._play_context.port or 830)
        elif self.provider.get('transport') in (
                'nxapi', 'eapi') and play_context.network_os in ('nxos',
                                                                 'eos'):
            play_context.connection = play_context.connection
            play_context.port = int(self.provider['port']
                                    or self._play_context.port or 22)
        else:
            play_context.connection = 'network_cli'
            play_context.port = int(self.provider['port']
                                    or self._play_context.port or 22)

        play_context.remote_addr = self.provider[
            'host'] or self._play_context.remote_addr
        play_context.remote_user = self.provider[
            'username'] or self._play_context.connection_user
        play_context.password = self.provider[
            'password'] or self._play_context.password
        play_context.private_key_file = self.provider[
            'ssh_keyfile'] or self._play_context.private_key_file
        play_context.timeout = int(self.provider['timeout']
                                   or C.PERSISTENT_COMMAND_TIMEOUT)
        if 'authorize' in self.provider.keys():
            play_context.become = self.provider['authorize'] or False
            play_context.become_pass = self.provider['auth_pass']

        if self.provider.get(
                'transport') == 'nxapi' and play_context.network_os == 'nxos':
            self._task.args[
                'provider'] = _NxosActionModule.nxapi_implementation(
                    self.provider, self._play_context)
        elif self.provider.get(
                'transport') == 'eapi' and play_context.network_os == 'eos':
            self._task.args['provider'] = _EosActionModule.eapi_implementation(
                self.provider, self._play_context)
        else:
            socket_path = self._start_connection(play_context)
            task_vars['ansible_socket'] = socket_path

        if 'fail_on_missing_module' not in self._task.args:
            self._task.args['fail_on_missing_module'] = False

        result = super(ActionModule, self).run(tmp, task_vars)

        module = self._get_implementation_module(play_context.network_os,
                                                 self._task.action)

        if not module:
            if self._task.args['fail_on_missing_module']:
                result['failed'] = True
            else:
                result['failed'] = False

            result['msg'] = ('Could not find implementation module %s for %s' %
                             (self._task.action, play_context.network_os))
        else:
            new_module_args = self._task.args.copy()
            # perhaps delete the provider argument here as well since the
            # module code doesn't need the information, the connection is
            # already started
            if 'network_os' in new_module_args:
                del new_module_args['network_os']

            del new_module_args['fail_on_missing_module']

            display.vvvv('Running implementation module %s' % module)
            result.update(
                self._execute_module(module_name=module,
                                     module_args=new_module_args,
                                     task_vars=task_vars,
                                     wrap_async=self._task. async))

            display.vvvv('Caching network OS %s in facts' %
                         play_context.network_os)
            result['ansible_facts'] = {'network_os': play_context.network_os}

        return result
示例#32
0
    def run(self, tmp=None, task_vars=None):

        if self._play_context.connection != 'local':
            return dict(
                failed=True,
                msg='invalid connection specified, expected connection=local, '
                'got %s' % self._play_context.connection)

        provider = load_provider(ironware_provider_spec, self._task.args)

        pc = copy.deepcopy(self._play_context)
        pc.connection = 'network_cli'
        pc.network_os = 'ironware'
        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.timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)
        pc.become = provider['authorize'] or False
        if pc.become:
            pc.become_method = 'enable'
        pc.become_pass = provider['auth_pass']

        display.vvv('using connection plugin %s' % pc.connection,
                    pc.remote_addr)
        connection = self._shared_loader_obj.connection_loader.get(
            'persistent', pc, sys.stdin)

        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'
            }

        # make sure we are in the right cli context which should be
        # enable mode and not config module
        conn = Connection(socket_path)
        out = conn.get_prompt()
        if to_text(out,
                   errors='surrogate_then_replace').strip().endswith(')#'):
            display.vvvv('wrong context, sending end to device',
                         self._play_context.remote_addr)
            conn.send_command('end')

        task_vars['ansible_socket'] = socket_path

        if self._play_context.become_method == 'enable':
            self._play_context.become = False
            self._play_context.become_method = None

        result = super(ActionModule, self).run(tmp, task_vars)

        return result
示例#33
0
    def _start_connection(self, variables):
        '''
        Starts the persistent connection
        '''
        candidate_paths = [
            C.ANSIBLE_CONNECTION_PATH or os.path.dirname(sys.argv[0])
        ]
        candidate_paths.extend(os.environ['PATH'].split(os.pathsep))
        for dirname in candidate_paths:
            ansible_connection = os.path.join(dirname, 'ansible-connection')
            if os.path.isfile(ansible_connection):
                break
        else:
            raise AnsibleError(
                "Unable to find location of 'ansible-connection'. "
                "Please set or check the value of ANSIBLE_CONNECTION_PATH")

        python = sys.executable
        master, slave = pty.openpty()
        p = subprocess.Popen(
            [python, ansible_connection,
             to_text(os.getppid())],
            stdin=slave,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE)
        os.close(slave)

        # We need to set the pty into noncanonical mode. This ensures that we
        # can receive lines longer than 4095 characters (plus newline) without
        # truncating.
        old = termios.tcgetattr(master)
        new = termios.tcgetattr(master)
        new[3] = new[3] & ~termios.ICANON

        try:
            termios.tcsetattr(master, termios.TCSANOW, new)
            write_to_file_descriptor(master, variables)
            write_to_file_descriptor(master, self._play_context.serialize())

            (stdout, stderr) = p.communicate()
        finally:
            termios.tcsetattr(master, termios.TCSANOW, old)
        os.close(master)

        if p.returncode == 0:
            result = json.loads(
                to_text(stdout, errors='surrogate_then_replace'))
        else:
            try:
                result = json.loads(
                    to_text(stderr, errors='surrogate_then_replace'))
            except getattr(json.decoder, 'JSONDecodeError', ValueError):
                # JSONDecodeError only available on Python 3.5+
                result = {
                    'error': to_text(stderr, errors='surrogate_then_replace')
                }

        if 'messages' in result:
            for msg in result.get('messages'):
                display.vvvv('%s' % msg, host=self._play_context.remote_addr)

        if 'error' in result:
            if self._play_context.verbosity > 2:
                if result.get('exception'):
                    msg = "The full traceback is:\n" + result['exception']
                    display.display(msg, color=C.COLOR_ERROR)
            raise AnsibleError(result['error'])

        return result['socket_path']
示例#34
0
    def run(self,
            terms,
            variables=None,
            boto_profile=None,
            aws_profile=None,
            aws_secret_key=None,
            aws_access_key=None,
            aws_security_token=None,
            region=None,
            bypath=False,
            shortnames=False,
            recursive=False,
            decrypt=True):
        '''
            :arg terms: a list of lookups to run.
                e.g. ['parameter_name', 'parameter_name_too' ]
            :kwarg variables: ansible variables active at the time of the lookup
            :kwarg aws_secret_key: identity of the AWS key to use
            :kwarg aws_access_key: AWS seret key (matching identity)
            :kwarg aws_security_token: AWS session key if using STS
            :kwarg decrypt: Set to True to get decrypted parameters
            :kwarg region: AWS region in which to do the lookup
            :kwarg bypath: Set to True to do a lookup of variables under a path
            :kwarg recursive: Set to True to recurse below the path (requires bypath=True)
            :returns: A list of parameter values or a list of dictionaries if bypath=True.
        '''

        if not HAS_BOTO3:
            raise AnsibleError(
                'botocore and boto3 are required for aws_ssm lookup.')

        ret = []
        response = {}
        ssm_dict = {}

        credentials = {}
        if aws_profile:
            credentials['boto_profile'] = aws_profile
        else:
            credentials['boto_profile'] = boto_profile
        credentials['aws_secret_access_key'] = aws_secret_key
        credentials['aws_access_key_id'] = aws_access_key
        credentials['aws_session_token'] = aws_security_token

        client = _boto3_conn(region, credentials)

        ssm_dict['WithDecryption'] = decrypt

        # Lookup by path
        if bypath:
            ssm_dict['Recursive'] = recursive
            for term in terms:
                ssm_dict["Path"] = term
                display.vvv("AWS_ssm path lookup term: %s in region: %s" %
                            (term, region))
                try:
                    response = client.get_parameters_by_path(**ssm_dict)
                except ClientError as e:
                    raise AnsibleError("SSM lookup exception: {0}".format(
                        to_native(e)))
                paramlist = list()
                paramlist.extend(response['Parameters'])

                # Manual pagination, since boto doesn't support it yet for get_parameters_by_path
                while 'NextToken' in response:
                    response = client.get_parameters_by_path(
                        NextToken=response['NextToken'], **ssm_dict)
                    paramlist.extend(response['Parameters'])

                # shorten parameter names. yes, this will return duplicate names with different values.
                if shortnames:
                    for x in paramlist:
                        x['Name'] = x['Name'][x['Name'].rfind('/') + 1:]

                display.vvvv("AWS_ssm path lookup returned: %s" %
                             str(paramlist))
                if len(paramlist):
                    ret.append(
                        boto3_tag_list_to_ansible_dict(
                            paramlist,
                            tag_name_key_name="Name",
                            tag_value_key_name="Value"))
                else:
                    ret.append({})
            # Lookup by parameter name - always returns a list with one or no entry.
        else:
            display.vvv("AWS_ssm name lookup term: %s" % terms)
            ssm_dict["Names"] = terms
            try:
                response = client.get_parameters(**ssm_dict)
            except ClientError as e:
                raise AnsibleError("SSM lookup exception: {0}".format(
                    to_native(e)))
            params = boto3_tag_list_to_ansible_dict(response['Parameters'],
                                                    tag_name_key_name="Name",
                                                    tag_value_key_name="Value")
            for i in terms:
                if i in params:
                    ret.append(params[i])
                elif i in response['InvalidParameters']:
                    ret.append(None)
                else:
                    raise AnsibleError(
                        "Ansible internal error: aws_ssm lookup failed to understand boto3 return value: {0}"
                        .format(str(response)))
            return ret

        display.vvvv("AWS_ssm path lookup returning: %s " % str(ret))
        return ret
示例#35
0
    def run(self, tmp=None, task_vars=None):
        transport = self._task.args.get('transport', 'rest')

        display.vvvv('connection transport is %s' % transport,
                     self._play_context.remote_addr)

        if self._play_context.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 'rest'

            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 = 'bigip'
                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
                pc.timeout = int(
                    provider.get('timeout', 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)

                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.rest_implementation(
                    provider, self._play_context)
        else:
            return {
                'failed':
                True,
                'msg':
                'Connection type %s is not valid for this module' %
                self._play_context.connection
            }

        if (self._play_context.connection == 'local' and transport
                == 'cli') or self._play_context.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
示例#36
0
    def run(self, tmp=None, task_vars=None):
        if self._play_context.connection != 'local':
            return dict(
                failed=True,
                msg='invalid connection specified, expected connection=local, '
                'got %s' % self._play_context.connection)

        provider = self.load_provider()
        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 = 'network_cli'
            pc.network_os = 'ce'
            pc.remote_addr = provider['host'] or self._play_context.remote_addr
            pc.port = int(provider['port']) or int(
                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.timeout = provider['timeout'] or self._play_context.timeout
            self._task.args['provider'] = provider.update(
                host=pc.remote_addr,
                port=pc.port,
                username=pc.remote_user,
                password=pc.password,
                ssh_keyfile=pc.private_key_file)
            display.vvv('using connection plugin %s' % pc.connection,
                        pc.remote_addr)
            connection = self._shared_loader_obj.connection_loader.get(
                'persistent', pc, sys.stdin)
            socket_path = self._get_socket_path(pc)
            display.vvvv('socket_path: %s' % socket_path, pc.remote_addr)

            if not os.path.exists(socket_path):
                # start the connection if it isn't started
                rc, out, err = connection.exec_command('open_shell()')
                display.vvvv('open_shell() returned %s %s %s' % (rc, out, err))
                if rc != 0:
                    return {
                        'failed': True,
                        'msg': 'unable to open shell. Please see: ' +
                        'https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell',
                        'rc': rc
                    }
            else:
                # make sure we are in the right cli context which should be
                # enable mode and not config module
                rc, out, err = connection.exec_command('prompt()')
                while str(out).strip().endswith(']'):
                    display.vvvv('wrong context, sending exit to device',
                                 self._play_context.remote_addr)
                    connection.exec_command('return')
                    rc, out, err = connection.exec_command('prompt()')

            task_vars['ansible_socket'] = socket_path

        # make sure a transport value is set in args
        self._task.args['transport'] = transport
        self._task.args['provider'] = provider

        result = super(ActionModule, self).run(tmp, task_vars)
        return result
示例#37
0
    def run(self, tmp=None, task_vars=None):

        socket_path = None
        if self._play_context.connection == 'local':
            provider = load_provider(eos_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 = 'network_cli'
                pc.network_os = 'eos'
                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.timeout = int(provider['timeout']
                                 or C.PERSISTENT_COMMAND_TIMEOUT)
                pc.become = provider['authorize'] or False
                if pc.become:
                    pc.become_method = 'enable'
                pc.become_pass = provider['auth_pass']

                display.vvv('using connection plugin %s' % pc.connection,
                            pc.remote_addr)
                connection = self._shared_loader_obj.connection_loader.get(
                    'persistent', pc, sys.stdin)

                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:
                provider['transport'] = 'eapi'

                if provider.get('host') is None:
                    provider['host'] = self._play_context.remote_addr

                if provider.get('port') is None:
                    default_port = 443 if provider['use_ssl'] else 80
                    provider['port'] = int(self._play_context.port
                                           or default_port)

                if provider.get('timeout') is None:
                    provider['timeout'] = C.PERSISTENT_COMMAND_TIMEOUT

                if provider.get('username') is None:
                    provider['username'] = self._play_context.connection_user

                if provider.get('password') is None:
                    provider['password'] = self._play_context.password

                if provider.get('authorize') is None:
                    provider['authorize'] = False

                self._task.args['provider'] = provider

        if (self._play_context.connection == 'local' and transport
                == 'cli') or self._play_context.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('abort')
                out = conn.get_prompt()

        result = super(ActionModule, self).run(tmp, task_vars)
        return result
示例#38
0
    def _connect(self):
        '''
        Connects to the remote device and starts the terminal
        '''
        if self.connected:
            return

        self.paramiko_conn = connection_loader.get('paramiko',
                                                   self._play_context,
                                                   '/dev/null')
        self.paramiko_conn.set_options(
            direct={
                'look_for_keys':
                not bool(self._play_context.password
                         and not self._play_context.private_key_file)
            })
        self.paramiko_conn.force_persistence = self.force_persistence
        ssh = self.paramiko_conn._connect()

        display.vvvv('ssh connection done, setting terminal',
                     host=self._play_context.remote_addr)

        self._ssh_shell = ssh.ssh.invoke_shell()
        self._ssh_shell.settimeout(self._play_context.timeout)

        network_os = self._play_context.network_os
        if not network_os:
            raise AnsibleConnectionFailure(
                'Unable to automatically determine host network os. Please '
                'manually configure ansible_network_os value for this host')

        self._terminal = terminal_loader.get(network_os, self)
        if not self._terminal:
            raise AnsibleConnectionFailure('network os %s is not supported' %
                                           network_os)

        display.vvvv('loaded terminal plugin for network_os %s' % network_os,
                     host=self._play_context.remote_addr)

        self._cliconf = cliconf_loader.get(network_os, self)
        if self._cliconf:
            display.vvvv('loaded cliconf plugin for network_os %s' %
                         network_os,
                         host=self._play_context.remote_addr)
        else:
            display.vvvv('unable to load cliconf for network_os %s' %
                         network_os)

        self.receive()

        display.vvvv('firing event: on_open_shell()',
                     host=self._play_context.remote_addr)
        self._terminal.on_open_shell()

        if self._play_context.become and self._play_context.become_method == 'enable':
            display.vvvv('firing event: on_become',
                         host=self._play_context.remote_addr)
            auth_pass = self._play_context.become_pass
            self._terminal.on_become(passwd=auth_pass)

        display.vvvv('ssh connection has completed successfully',
                     host=self._play_context.remote_addr)
        self._connected = True

        return self
示例#39
0
    def run(self, tmp=None, task_vars=None):
        del tmp  # tmp no longer has any effect

        socket_path = None

        if (self._play_context.connection == 'httpapi' or self._task.args.get('provider', {}).get('transport') == 'nxapi') \
                and self._task.action == 'nxos_nxapi':
            return {
                'failed':
                True,
                'msg':
                "Transport type 'nxapi' is not valid for '%s' module." %
                (self._task.action)
            }

        if self._play_context.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']
        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 = 'network_cli'
                pc.network_os = '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.timeout = int(
                    provider['timeout']) if provider['timeout'] else None
                pc.become = provider['authorize'] or False
                if pc.become:
                    pc.become_method = 'enable'
                pc.become_pass = provider['auth_pass']

                display.vvv(
                    'using connection plugin %s (was local)' % pc.connection,
                    pc.remote_addr)
                connection = self._shared_loader_obj.connection_loader.get(
                    'persistent', pc, sys.stdin)

                if connection._play_context.timeout is None:
                    connection._play_context.timeout = connection.get_option(
                        'persistent_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)
        else:
            return {
                'failed':
                True,
                'msg':
                'Connection type %s is not valid for this module' %
                self._play_context.connection
            }

        if (self._play_context.connection == 'local' and transport
                == 'cli') or self._play_context.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 to_text(
                    out,
                    errors='surrogate_then_replace').strip().endswith(')#'):
                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(task_vars=task_vars)
        return result
示例#40
0
    def run(self, tmp=None, task_vars=None):
        del tmp  # tmp no longer has any effect

        socket_path = None

        if self._play_context.connection == 'local':
            provider = load_provider(ce_provider_spec, self._task.args)

            pc = copy.deepcopy(self._play_context)
            pc.connection = 'network_cli'
            pc.network_os = 'ce'
            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
            command_timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)
            self._task.args['provider'] = provider.update(
                host=pc.remote_addr,
                port=pc.port,
                username=pc.remote_user,
                password=pc.password
            )
            if self._task.action in ['ce_netconf'] or self._task.action not in CLI_SUPPORTED_MODULES:
                pc.connection = 'netconf'
            display.vvv('using connection plugin %s (was local)' % pc.connection, pc.remote_addr)
            connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin)
            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
            self._task.args['provider'] = provider
        elif self._play_context.connection in ('netconf', 'network_cli'):
            provider = self._task.args.get('provider', {})
            if any(provider.values()):
                display.warning('provider is unnessary whene using %s and will be ignored' % self._play_context.connection)
                del self._task.args['provider']

            if (self._play_context.connection == 'network_cli' and self._task.action not in CLI_SUPPORTED_MODULES) or \
                    (self._play_context.connection == 'netconf' and self._task.action in CLI_SUPPORTED_MODULES):
                return {'failed': True, 'msg': "Connection type '%s' is not valid for '%s' module."
                        % (self._play_context.connection, self._task.action)}

        if (self._play_context.connection == 'local' and self._task.action in CLI_SUPPORTED_MODULES) \
                or self._play_context.connection == 'network_cli':
            # make sure we are in the right cli context whitch 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 to_text(out, errors='surrogate_then_replace').strip().endswith(']'):
                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(task_vars=task_vars)
        return result
示例#41
0
    def decrypt(self, vaulttext, filename=None):
        """Decrypt a piece of vault encrypted data.

        :arg vaulttext: a string to decrypt.  Since vault encrypted data is an
            ascii text format this can be either a byte str or unicode string.
        :kwarg filename: a filename that the data came from.  This is only
            used to make better error messages in case the data cannot be
            decrypted.
        :returns: a byte string containing the decrypted data
        """
        b_vaulttext = to_bytes(vaulttext, errors='strict', encoding='utf-8')

        if self.secrets is None:
            raise AnsibleVaultError(
                "A vault password must be specified to decrypt data")

        if not is_encrypted(b_vaulttext):
            msg = "input is not vault encrypted data"
            if filename:
                msg += "%s is not a vault encrypted file" % filename
            raise AnsibleError(msg)

        b_vaulttext, b_version, cipher_name, vault_id = parse_vaulttext_envelope(
            b_vaulttext)

        # create the cipher object, note that the cipher used for decrypt can
        # be different than the cipher used for encrypt
        if cipher_name in CIPHER_WHITELIST:
            this_cipher = CIPHER_MAPPING[cipher_name]()
        else:
            raise AnsibleError(
                "{0} cipher could not be found".format(cipher_name))

        b_plaintext = None

        if not self.secrets:
            raise AnsibleVaultError(
                'Attempting to decrypt but no vault secrets found')

        # WARNING: Currently, the vault id is not required to match the vault id in the vault blob to
        #          decrypt a vault properly. The vault id in the vault blob is not part of the encrypted
        #          or signed vault payload. There is no cryptographic checking/verification/validation of the
        #          vault blobs vault id. It can be tampered with and changed. The vault id is just a nick
        #          name to use to pick the best secret and provide some ux/ui info.

        # iterate over all the applicable secrets (all of them by default) until one works...
        # if we specify a vault_id, only the corresponding vault secret is checked and
        # we check it first.

        vault_id_matchers = []

        if vault_id:
            display.vvvvv('Found a vault_id (%s) in the vaulttext' %
                          (vault_id))
            vault_id_matchers.append(vault_id)
            _matches = match_secrets(self.secrets, vault_id_matchers)
            if _matches:
                display.vvvvv(
                    'We have a secret associated with vault id (%s), will try to use to decrypt %s'
                    % (vault_id, filename))
            else:
                display.vvvvv(
                    'Found a vault_id (%s) in the vault text, but we do not have a associated secret (--vault-id)'
                    % (vault_id))

        # Not adding the other secrets to vault_secret_ids enforces a match between the vault_id from the vault_text and
        # the known vault secrets.
        if not C.DEFAULT_VAULT_ID_MATCH:
            # Add all of the known vault_ids as candidates for decrypting a vault.
            vault_id_matchers.extend([
                _vault_id for _vault_id, _secret in self.secrets
                if _vault_id != vault_id
            ])

        matched_secrets = match_secrets(self.secrets, vault_id_matchers)

        # for vault_secret_id in vault_secret_ids:
        for vault_secret_id, vault_secret in matched_secrets:
            display.vvvvv(
                'Trying to use vault secret=(%s) id=%s to decrypt %s' %
                (vault_secret, vault_secret_id, filename))

            try:
                # secret = self.secrets[vault_secret_id]
                display.vvvv('Trying secret %s for vault_id=%s' %
                             (vault_secret, vault_secret_id))
                b_plaintext = this_cipher.decrypt(b_vaulttext, vault_secret)
                if b_plaintext is not None:
                    display.vvvvv(
                        'decrypt succesful with secret=%s and vault_id=%s' %
                        (vault_secret, vault_secret_id))
                    break
            except AnsibleError as e:
                display.vvvv(
                    'Tried to use the vault secret (%s) to decrypt (%s) but it failed. Error: %s'
                    % (vault_secret_id, filename, e))
                continue
        else:
            msg = "Decryption failed (no vault secrets would found that could decrypt)"
            if filename:
                msg += " on %s" % filename
            raise AnsibleVaultError(msg)

        if b_plaintext is None:
            msg = "Decryption failed"
            if filename:
                msg += " on %s" % filename
            raise AnsibleError(msg)

        return b_plaintext
示例#42
0
    def run(self, tmp=None, task_vars=None):
        del tmp  # tmp no longer has any effect

        socket_path = None
        play_context = copy.deepcopy(self._play_context)
        play_context.network_os = self._get_network_os(task_vars)

        if play_context.connection == 'local':
            # we should be able to stream line this a bit by creating a common
            # provider argument spec in module_utils/network/common/utils.py or another
            # option is that there isn't a need to push provider into the module
            # since the connection is started in the action handler.
            module_name = 'ansible.module_utils.network.{0}.{0}'.format(play_context.network_os)
            f, p, d = find_module('ansible')
            for package in module_name.split('.')[1:]:
                f, p, d = find_module(package, [p])
            module = load_module(module_name, f, p, d)

            self.provider = load_provider(module.get_provider_argspec(), self._task.args)
            if self.provider.get('transport') == 'netconf' and play_context.network_os in _NETCONF_SUPPORTED_PLATFORMS \
                    and self._task.action not in _CLI_ONLY_MODULES:
                play_context.connection = 'netconf'
                play_context.port = int(self.provider['port'] or self._play_context.port or 830)
            elif self.provider.get('transport') in ('nxapi', 'eapi') and play_context.network_os in ('nxos', 'eos'):
                play_context.connection = play_context.connection
                play_context.port = int(self.provider['port'] or self._play_context.port or 22)
            else:
                play_context.connection = 'network_cli'
                play_context.port = int(self.provider['port'] or self._play_context.port or 22)

            play_context.remote_addr = self.provider['host'] or self._play_context.remote_addr
            play_context.remote_user = self.provider['username'] or self._play_context.connection_user
            play_context.password = self.provider['password'] or self._play_context.password
            play_context.private_key_file = self.provider['ssh_keyfile'] or self._play_context.private_key_file
            play_context.timeout = int(self.provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)
            if 'authorize' in self.provider.keys():
                play_context.become = self.provider['authorize'] or False
                play_context.become_pass = self.provider['auth_pass']
                play_context.become_method = 'enable'

            if self._play_context.connection == 'local':
                if self.provider.get('transport') == 'nxapi' and play_context.network_os == 'nxos':
                    self._task.args['provider'] = _NxosActionModule.nxapi_implementation(self.provider, self._play_context)
                elif self.provider.get('transport') == 'eapi' and play_context.network_os == 'eos':
                    self._task.args['provider'] = _EosActionModule.eapi_implementation(self.provider, self._play_context)
                else:
                    socket_path = self._start_connection(play_context)
                    task_vars['ansible_socket'] = socket_path

        else:
            provider = self._task.args.get('provider', {})
            if any(provider.values()):
                display.warning('provider is unnecessary when using %s and will be ignored' % play_context.connection)
                del self._task.args['provider']

        if play_context.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()
            if to_text(out, errors='surrogate_then_replace').strip().endswith(')#'):
                display.vvvv('wrong context, sending exit to device', self._play_context.remote_addr)
                conn.send_command('exit')

        if 'fail_on_missing_module' not in self._task.args:
            self._task.args['fail_on_missing_module'] = False

        result = super(ActionModule, self).run(task_vars=task_vars)

        module = self._get_implementation_module(play_context.network_os, self._task.action)

        if not module:
            if self._task.args['fail_on_missing_module']:
                result['failed'] = True
            else:
                result['failed'] = False

            result['msg'] = ('Could not find implementation module %s for %s' %
                             (self._task.action, play_context.network_os))
        else:
            new_module_args = self._task.args.copy()
            # perhaps delete the provider argument here as well since the
            # module code doesn't need the information, the connection is
            # already started
            if 'network_os' in new_module_args:
                del new_module_args['network_os']

            del new_module_args['fail_on_missing_module']

            display.vvvv('Running implementation module %s' % module)
            result.update(self._execute_module(module_name=module,
                          module_args=new_module_args, task_vars=task_vars,
                          wrap_async=self._task.async_val))

            display.vvvv('Caching network OS %s in facts' % play_context.network_os)
            result['ansible_facts'] = {'network_os': play_context.network_os}

        return result
示例#43
0
 def _handle_buffer_read_timeout(self, signum, frame):
     display.vvvv("Response received, triggered 'persistent_buffer_read_timeout' timer of %s seconds"
                  % self.get_option('persistent_buffer_read_timeout'), host=self._play_context.remote_addr)
     raise AnsibleCmdRespRecv()
示例#44
0
    def run(self, tmp=None, task_vars=None):
        if self._play_context.connection != 'local':
            return dict(
                failed=True,
                msg='invalid connection specified, expected connection=local, '
                    'got %s' % self._play_context.connection
            )

        provider = self.load_provider()
        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 = 'network_cli'
            pc.network_os = 'nxos'
            pc.port = 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.timeout = provider['timeout'] or self._play_context.timeout

            connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin)

            socket_path = self._get_socket_path(pc)
            display.vvvv('socket_path: %s' % socket_path, pc.remote_addr)

            if not os.path.exists(socket_path):
                # start the connection if it isn't started
                rc, out, err = connection.exec_command('open_shell()')
                display.vvvv('open_shell() returned %s %s %s' % (rc, out, err))
                if rc != 0:
                    return {'failed': True, 'msg': 'unable to open shell', 'rc': rc}
            else:
                # make sure we are in the right cli context which should be
                # enable mode and not config module
                rc, out, err = connection.exec_command('prompt()')
                while str(out).strip().endswith(')#'):
                    display.vvvv('wrong context, sending exit to device', self._play_context.remote_addr)
                    connection.exec_command('exit')
                    rc, out, err = connection.exec_command('prompt()')


            task_vars['ansible_socket'] = socket_path

        else:
            provider['transport'] = 'nxapi'

            if provider.get('host') is None:
                provider['host'] = self._play_context.remote_addr

            if provider.get('port') is None:
                provider['port'] = 80

            if provider.get('timeout') is None:
                provider['timeout'] = self._play_context.timeout

            if provider.get('username') is None:
                provider['username'] = self._play_context.connection_user

            if provider.get('password') is None:
                provider['password'] = self._play_context.password

            if provider.get('use_ssl') is None:
                provider['use_ssl'] = False

            if provider.get('validate_certs') is None:
                provider['validate_certs'] = True

            self._task.args['provider'] = provider

        # make sure a transport value is set in args
        self._task.args['transport'] = transport

        return super(ActionModule, self).run(tmp, task_vars)
示例#45
0
    def _connect(self):
        '''
        Connects to the remote device and starts the terminal
        '''
        if not self.connected:
            if not self._network_os:
                raise AnsibleConnectionFailure(
                    'Unable to automatically determine host network os. Please '
                    'manually configure ansible_network_os value for this host'
                )
            display.display('network_os is set to %s' % self._network_os, log_only=True)

            self.paramiko_conn = connection_loader.get('paramiko', self._play_context, '/dev/null')
            self.paramiko_conn._set_log_channel(self._get_log_channel())
            self.paramiko_conn.set_options(direct={'look_for_keys': not bool(self._play_context.password and not self._play_context.private_key_file)})
            self.paramiko_conn.force_persistence = self.force_persistence
            ssh = self.paramiko_conn._connect()

            host = self.get_option('host')
            display.vvvv('ssh connection done, setting terminal', host=host)

            self._ssh_shell = ssh.ssh.invoke_shell()
            self._ssh_shell.settimeout(self.get_option('persistent_command_timeout'))

            self._terminal = terminal_loader.get(self._network_os, self)
            if not self._terminal:
                raise AnsibleConnectionFailure('network os %s is not supported' % self._network_os)

            display.vvvv('loaded terminal plugin for network_os %s' % self._network_os, host=host)

            self.cliconf = cliconf_loader.get(self._network_os, self)
            if self.cliconf:
                display.vvvv('loaded cliconf plugin for network_os %s' % self._network_os, host=host)
                self._implementation_plugins.append(self.cliconf)
            else:
                display.vvvv('unable to load cliconf for network_os %s' % self._network_os)

            super(Connection, self)._connect()

            self.receive(prompts=self._terminal.terminal_initial_prompt, answer=self._terminal.terminal_initial_answer,
                         newline=self._terminal.terminal_inital_prompt_newline)

            display.vvvv('firing event: on_open_shell()', host=host)
            self._terminal.on_open_shell()

            if self._play_context.become and self._play_context.become_method == 'enable':
                display.vvvv('firing event: on_become', host=host)
                auth_pass = self._play_context.become_pass
                self._terminal.on_become(passwd=auth_pass)

            display.vvvv('ssh connection has completed successfully', host=host)
            self._connected = True

        return self
示例#46
0
    def run(self, tmp=None, task_vars=None):
        if self._play_context.connection != 'local':
            return dict(
                failed=True,
                msg='invalid connection specified, expected connection=local, '
                'got %s' % self._play_context.connection)

        play_context = copy.deepcopy(self._play_context)
        play_context.network_os = self._get_network_os(task_vars)
        # TODO this can be netconf
        play_context.connection = 'network_cli'

        self.provider = self._load_provider(play_context.network_os)

        play_context.remote_addr = self.provider[
            'host'] or self._play_context.remote_addr
        play_context.port = self.provider[
            'port'] or self._play_context.port or 22
        play_context.remote_user = self.provider[
            'username'] or self._play_context.connection_user
        play_context.password = self.provider[
            'password'] or self._play_context.password
        play_context.private_key_file = self.provider[
            'ssh_keyfile'] or self._play_context.private_key_file
        play_context.timeout = self.provider[
            'timeout'] or self._play_context.timeout
        if 'authorize' in self.provider.keys():
            play_context.become = self.provider['authorize'] or False
            play_context.become_pass = self.provider['auth_pass']

        socket_path = self._start_connection(play_context)
        task_vars['ansible_socket'] = socket_path

        result = super(ActionModule, self).run(tmp, task_vars)

        module = self._get_implementation_module(play_context.network_os,
                                                 self._task.action)

        if not module:
            result['failed'] = True
            result['msg'] = ('Could not find implementation module %s for %s' %
                             (self._task.action, play_context.network_os))
        else:
            new_module_args = self._task.args.copy()
            # perhaps delete the provider argument here as well since the
            # module code doesn't need the information, the connection is
            # already started
            if 'network_os' in new_module_args:
                del new_module_args['network_os']

            display.vvvv('Running implementation module %s' % module)
            result.update(
                self._execute_module(module_name=module,
                                     module_args=new_module_args,
                                     task_vars=task_vars,
                                     wrap_async=self._task. async))

            display.vvvv('Caching network OS %s in facts' %
                         play_context.network_os)
            result['ansible_facts'] = {'network_os': play_context.network_os}

        return result
示例#47
0
 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, ''
示例#48
0
 def connection_unlock(self):
     f = self._play_context.connection_lockfd
     fcntl.lockf(f, fcntl.LOCK_UN)
     display.vvvv('CONNECTION: pid %d released lock on %d' % (os.getpid(), f))
示例#49
0
    def run(self, terms, variables=None, **kwargs):

        if len(terms) > 0 and isinstance(terms, dict):
            # to do, use terms to specify the options
            display.vvvv('terms is a dict')
        else:
            length = int(kwargs.get('length', 12))
            special_characters = kwargs.pop('special_characters',
                                            SPECIAL_CHARACTERS)
            forbidden_characters = kwargs.pop('forbidden_characters', '')
            prevent_repeating_characters = kwargs.pop(
                'prevent_repeating_characters', True)

            min_upper_case = int(kwargs.pop('min_upper_case', 2))
            min_lower_case = int(kwargs.pop('min_lower_case', 2))
            min_digit = int(kwargs.pop('min_digit', 2))
            min_special = int(kwargs.pop('min_special', 2))

        if 1 > length or length > 128:
            raise AnsibleError("valid length must be in range 1 - 128")

        display.vvvv('length: %s' % (length))
        display.vvvv('min_upper_case: %s' % (min_upper_case))
        display.vvvv('min_lower_case: %s' % (min_lower_case))
        display.vvvv('min_digit: %s' % (min_digit))
        display.vvvv('min_special: %s' % (min_special))
        display.vvvv('special_characters: %s' % (special_characters))
        display.vvvv('forbidden_characters: %s' % (forbidden_characters))
        display.vvvv('prevent_repeating_characters: %s' %
                     (prevent_repeating_characters))

        results = []
        params = {}

        params['length'] = length
        params['min_upper_case'] = min_upper_case
        params['min_lower_case'] = min_lower_case
        params['min_digit'] = min_digit
        params['min_special'] = min_special
        params['special_chars'] = special_characters
        params['forbidden_chars'] = forbidden_characters
        params['prevent_repeating_chars'] = prevent_repeating_characters

        try:
            complex_password = mkpasswd(**params)
        except ValueError as e:
            raise AnsibleError(to_text(e))

        results.extend([complex_password])

        return results
示例#50
0
    def run(self, tmp=None, task_vars=None):
        del tmp  # tmp no longer has any effect

        module = module_loader._load_module_source(self._task.action, module_loader.find_plugin(self._task.action))
        if not getattr(module, 'USE_PERSISTENT_CONNECTION', False):
            return super(ActionModule, self).run(task_vars=task_vars)

        socket_path = None

        if self._play_context.connection == 'local':
            provider = load_provider(junos_provider_spec, self._task.args)
            pc = copy.deepcopy(self._play_context)
            pc.network_os = 'junos'
            pc.remote_addr = provider['host'] or self._play_context.remote_addr

            if provider['transport'] == 'cli' and self._task.action not in CLI_SUPPORTED_MODULES:
                return {'failed': True, 'msg': "Transport type '%s' is not valid for '%s' module. "
                                               "Please see http://docs.ansible.com/ansible/latest/network/user_guide/platform_junos.html"
                                               % (provider['transport'], self._task.action)}

            if self._task.action == 'junos_netconf' or (provider['transport'] == 'cli' and self._task.action == 'junos_command'):
                pc.connection = 'network_cli'
                pc.port = int(provider['port'] or self._play_context.port or 22)
            else:
                pc.connection = 'netconf'
                pc.port = int(provider['port'] or self._play_context.port or 830)

            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.timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)

            display.vvv('using connection plugin %s (was local)' % pc.connection, pc.remote_addr)
            connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin)

            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
        elif self._play_context.connection in ('netconf', 'network_cli'):
            provider = self._task.args.get('provider', {})
            if any(provider.values()):
                display.warning('provider is unnecessary when using connection=%s and will be ignored' % self._play_context.connection)

            if (self._play_context.connection == 'network_cli' and self._task.action not in CLI_SUPPORTED_MODULES) or \
                    (self._play_context.connection == 'netconf' and self._task.action == 'junos_netconf'):
                return {'failed': True, 'msg': "Connection type '%s' is not valid for '%s' module. "
                                               "Please see http://docs.ansible.com/ansible/latest/network/user_guide/platform_junos.html"
                                               % (self._play_context.connection, self._task.action)}

        if (self._play_context.connection == 'local' and pc.connection == 'network_cli') or self._play_context.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 to_text(out, errors='surrogate_then_replace').strip().endswith('#'):
                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(None, task_vars)
        return result
示例#51
0
                async_result = normal_handler.run(task_vars=task_vars)
                # We do not bail out of the loop in cases where the failure
                # is associated with a parsing error. The async_runner can
                # have issues which result in a half-written/unparseable result
                # file on disk, which manifests to the user as a timeout happening
                # before it's time to timeout.
                if (int(async_result.get('finished', 0)) == 1
                        or ('failed' in async_result
                            and async_result.get('_ansible_parsed', False))
                        or 'skipped' in async_result):
                    break
            except Exception as e:
                # Connections can raise exceptions during polling (eg, network bounce, reboot); these should be non-fatal.
                # On an exception, call the connection's reset method if it has one
                # (eg, drop/recreate WinRM connection; some reused connections are in a broken state)
                display.vvvv("Exception during async poll, retrying... (%s)" %
                             to_text(e))
                display.debug("Async poll exception was:\n%s" %
                              to_text(traceback.format_exc()))
                try:
                    normal_handler._connection._reset()
                except AttributeError:
                    pass

            time_left -= self._task.poll

        if int(async_result.get('finished', 0)) != 1:
            if async_result.get('_ansible_parsed'):
                return dict(
                    failed=True,
                    msg="async task did not complete within the requested time"
                )
示例#52
0
    def parse_inventory(self, host_list):

        if isinstance(host_list, string_types):
            if "," in host_list:
                host_list = host_list.split(",")
                host_list = [h for h in host_list if h and h.strip()]

        self.parser = None

        # Always create the 'all' and 'ungrouped' groups, even if host_list is
        # empty: in this case we will subsequently an the implicit 'localhost' to it.

        ungrouped = Group('ungrouped')
        all = Group('all')
        all.add_child_group(ungrouped)

        self.groups = dict(all=all, ungrouped=ungrouped)

        if host_list is None:
            pass
        elif isinstance(host_list, list):
            for h in host_list:
                try:
                    (host, port) = parse_address(h, allow_ranges=False)
                except AnsibleError as e:
                    display.vvv(
                        "Unable to parse address from hostname, leaving unchanged: %s"
                        % to_unicode(e))
                    host = h
                    port = None

                new_host = Host(host, port)
                if h in C.LOCALHOST:
                    # set default localhost from inventory to avoid creating an implicit one. Last localhost defined 'wins'.
                    if self.localhost is not None:
                        display.warning(
                            "A duplicate localhost-like entry was found (%s). First found localhost was %s"
                            % (h, self.localhost.name))
                    display.vvvv("Set default localhost to %s" % h)
                    self.localhost = new_host
                all.add_host(new_host)
        elif self._loader.path_exists(host_list):
            #TODO: switch this to a plugin loader and a 'condition' per plugin on which it should be tried, restoring 'inventory pllugins'
            if self.is_directory(host_list):
                # Ensure basedir is inside the directory
                host_list = os.path.join(self.host_list, "")
                self.parser = InventoryDirectory(loader=self._loader,
                                                 groups=self.groups,
                                                 filename=host_list)
            else:
                self.parser = get_file_parser(host_list, self.groups,
                                              self._loader)
                vars_loader.add_directory(self._basedir, with_subdir=True)

            if not self.parser:
                # should never happen, but JIC
                raise AnsibleError(
                    "Unable to parse %s as an inventory source" % host_list)
        else:
            display.warning("Host file not found: %s" % to_unicode(host_list))

        self._vars_plugins = [x for x in vars_loader.all(self)]

        # set group vars from group_vars/ files and vars plugins
        for g in self.groups:
            group = self.groups[g]
            group.vars = combine_vars(group.vars,
                                      self.get_group_variables(group.name))
            self.get_group_vars(group)

        # get host vars from host_vars/ files and vars plugins
        for host in self.get_hosts(ignore_limits_and_restrictions=True):
            host.vars = combine_vars(host.vars,
                                     self.get_host_variables(host.name))
            self.get_host_vars(host)
示例#53
0
    def run(self, tmp=None, task_vars=None):

        if self._play_context.connection != 'local':
            return dict(
                failed=True,
                msg='invalid connection specified, expected connection=local, '
                'got %s' % self._play_context.connection)

        module = module_loader._load_module_source(
            self._task.action, module_loader.find_plugin(self._task.action))

        if not getattr(module, 'USE_PERSISTENT_CONNECTION', False):
            return super(ActionModule, self).run(tmp, task_vars)

        provider = self.load_provider()

        pc = copy.deepcopy(self._play_context)
        pc.network_os = 'junos'

        pc.remote_addr = provider['host'] or self._play_context.remote_addr

        if self._task.action == 'junos_netconf':
            pc.connection = 'network_cli'
            pc.port = provider['port'] or self._play_context.port or 22
        else:
            pc.connection = 'netconf'
            pc.port = provider['port'] or self._play_context.port or 830

        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.timeout = provider['timeout'] or self._play_context.timeout

        display.vvv('using connection plugin %s' % pc.connection)
        connection = self._shared_loader_obj.connection_loader.get(
            'persistent', pc, sys.stdin)

        socket_path = self._get_socket_path(pc)
        display.vvvv('socket_path: %s' % socket_path, pc.remote_addr)

        if not os.path.exists(socket_path):
            # start the connection if it isn't started
            if pc.connection == 'netconf':
                rc, out, err = connection.exec_command('open_session()')
            else:
                rc, out, err = connection.exec_command('open_shell()')

            if rc != 0:
                return {
                    'failed': True,
                    'msg': 'unable to connect to control socket'
                }

        elif pc.connection == 'network_cli':
            # make sure we are in the right cli context which should be
            # enable mode and not config module
            rc, out, err = connection.exec_command('prompt()')
            while str(out).strip().endswith(')#'):
                display.vvvv('wrong context, sending exit to device',
                             self._play_context.remote_addr)
                connection.exec_command('exit')
                rc, out, err = connection.exec_command('prompt()')

        task_vars['ansible_socket'] = socket_path

        return super(ActionModule, self).run(tmp, task_vars)
示例#54
0
    def run(self, terms, variables, **kwargs):

        res = []
        try:
            xml_data = terms[0]
        except IndexError:
            raise AnsibleError("Either xml string or path to xml file must be specified")

        try:
            yang_file = kwargs['yang_file']
        except KeyError:
            raise AnsibleError("value of 'yang_file' must be specified")

        yang_file = os.path.realpath(os.path.expanduser(yang_file))
        if not os.path.isfile(yang_file):
            # Maybe we are passing a glob?
            yang_files = glob.glob(yang_file)
            if not yang_files:
                # Glob returned no files
                raise AnsibleError('%s invalid file path' % yang_file)
        else:
            yang_files = [yang_file]

        search_path = kwargs.pop('search_path', '')
        keep_tmp_files = kwargs.pop('keep_tmp_files', False)

        abs_search_path = None
        for path in search_path.split(':'):
            path = os.path.realpath(os.path.expanduser(path))
            if abs_search_path is None:
                abs_search_path = path
            else:
                abs_search_path += ':' + path
            if path is not '' and not os.path.isdir(path):
                raise AnsibleError('%s is invalid directory path' % path)

        search_path = abs_search_path

        plugindir = unfrackpath(XM2JSONL_DIR_PATH)
        makedirs_safe(plugindir)

        if os.path.isfile(xml_data):
            # input is xml file path
            xml_file_path = xml_data
        else:
            # input is xml string, copy it to file in temporary location
            xml_file_path = os.path.join(XM2JSONL_DIR_PATH, '%s.%s' % (str(uuid.uuid4()), 'xml'))
            xml_file_path = os.path.realpath(os.path.expanduser(xml_file_path))
            with open(xml_file_path, 'w') as f:
                if not xml_data.startswith('<?xml version'):
                    xml_data = '<?xml version="1.0" encoding="UTF-8"?>\n' + xml_data
                data = xml_data
                f.write(data)

        xml_file_path = os.path.realpath(os.path.expanduser(xml_file_path))

        try:
            # validate xml
            etree.parse(xml_file_path)
            display.vvvv("Parsing xml data from temporary file: %s" % xml_file_path)
        except Exception as exc:
            if not keep_tmp_files:
                shutil.rmtree(os.path.realpath(os.path.expanduser(XM2JSONL_DIR_PATH)), ignore_errors=True)
            raise AnsibleError("Failed to load xml data: %s" % (to_text(exc, errors='surrogate_or_strict')))

        base_pyang_path = sys.modules['pyang'].__file__
        pyang_exec_path = find_file_in_path('pyang')
        pyang_exec = imp.load_source('pyang', pyang_exec_path)

        saved_arg = deepcopy(sys.argv)
        sys.modules['pyang'].__file__ = base_pyang_path

        saved_stdout = sys.stdout
        saved_stderr = sys.stderr
        sys.stdout = sys.stderr = StringIO()

        xsl_file_path = os.path.join(XM2JSONL_DIR_PATH, '%s.%s' % (str(uuid.uuid4()), 'xsl'))
        json_file_path = os.path.join(XM2JSONL_DIR_PATH, '%s.%s' % (str(uuid.uuid4()), 'json'))
        xls_file_path = os.path.realpath(os.path.expanduser(xsl_file_path))
        json_file_path = os.path.realpath(os.path.expanduser(json_file_path))

        # fill in the sys args before invoking pyang
        sys.argv = [pyang_exec_path, '-f', 'jsonxsl', '-o', xls_file_path, '-p', search_path,
                    "--lax-quote-checks"] + yang_files
        display.display("Generating xsl file '%s' by executing command '%s'" % (xls_file_path, ' '.join(sys.argv)), log_only=True)
        try:
            pyang_exec.run()
        except SystemExit:
            pass
        except Exception as e:
            if not keep_tmp_files:
                shutil.rmtree(os.path.realpath(os.path.expanduser(XM2JSONL_DIR_PATH)), ignore_errors=True)
            raise AnsibleError('Error while generating intermediate (xsl) file: %s' % e)
        finally:
            err = sys.stderr.getvalue()
            if err and 'error' in err.lower():
                if not keep_tmp_files:
                    shutil.rmtree(os.path.realpath(os.path.expanduser(XM2JSONL_DIR_PATH)), ignore_errors=True)
                raise AnsibleError('Error while generating (xsl) intermediate file: %s' % err)

        xsltproc_exec_path = find_file_in_path('xsltproc')

        # fill in the sys args before invoking xsltproc
        sys.argv = [xsltproc_exec_path, '-o', json_file_path, xsl_file_path, xml_file_path]
        display.display("Generating json data in temp file '%s' by executing command '%s'" % (json_file_path, ' '.join(sys.argv)), log_only=True)
        time.sleep(5)
        try:
            os.system(' '.join(sys.argv))
        except SystemExit:
            pass
        finally:
            err = sys.stderr.getvalue()
            if err and 'error' in err.lower():
                if not keep_tmp_files:
                    shutil.rmtree(os.path.realpath(os.path.expanduser(XM2JSONL_DIR_PATH)), ignore_errors=True)
                raise AnsibleError('Error while translating to json: %s' % err)
            sys.argv = saved_arg
            sys.stdout = saved_stdout
            sys.stderr = saved_stderr

        try:
            display.vvvv("Reading output json data from temporary file: %s" % json_file_path)
            with open(json_file_path) as fp:
                content = json.load(fp)
        except Exception as e:
            raise AnsibleError('Error while reading json document: %s' % e)
        finally:
            if not keep_tmp_files:
                shutil.rmtree(os.path.realpath(os.path.expanduser(XM2JSONL_DIR_PATH)), ignore_errors=True)
        res.append(content)

        return res
示例#55
0
    def put_file(self, in_path, out_path):
        ''' transfer a file from local to remote '''
        display.vvv("PUT %s TO %s" % (in_path, out_path),
                    host=self._play_context.remote_addr)

        in_path = to_bytes(in_path, errors='surrogate_or_strict')

        if not os.path.exists(in_path):
            raise AnsibleFileNotFound("file or module does not exist: %s" %
                                      in_path)

        fd = file(in_path, 'rb')
        fstat = os.stat(in_path)
        try:
            display.vvv("PUT file is %d bytes" % fstat.st_size,
                        host=self._play_context.remote_addr)
            last = False
            while fd.tell() <= fstat.st_size and not last:
                display.vvvv("file position currently %ld, file size is %ld" %
                             (fd.tell(), fstat.st_size),
                             host=self._play_context.remote_addr)
                data = fd.read(CHUNK_SIZE)
                if fd.tell() >= fstat.st_size:
                    last = True
                data = dict(mode='put',
                            data=base64.b64encode(data),
                            out_path=out_path,
                            last=last)
                if self._play_context.become:
                    data['user'] = self._play_context.become_user
                data = jsonify(data)
                data = keyczar_encrypt(self.key, data)

                if self.send_data(data):
                    raise AnsibleError("failed to send the file to %s" %
                                       self._play_context.remote_addr)

                response = self.recv_data()
                if not response:
                    raise AnsibleError("Failed to get a response from %s" %
                                       self._play_context.remote_addr)
                response = keyczar_decrypt(self.key, response)
                response = json.loads(response)

                if response.get('failed', False):
                    raise AnsibleError(
                        "failed to put the file in the requested location")
        finally:
            fd.close()
            display.vvvv("waiting for final response after PUT",
                         host=self._play_context.remote_addr)
            response = self.recv_data()
            if not response:
                raise AnsibleError("Failed to get a response from %s" %
                                   self._play_context.remote_addr)
            response = keyczar_decrypt(self.key, response)
            response = json.loads(response)

            if response.get('failed', False):
                raise AnsibleError(
                    "failed to put the file in the requested location")
示例#56
0
    def run(self, tmp=None, task_vars=None):
        socket_path = None

        if self._play_context.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(iosxr_provider_spec, self._task.args)
            pc = copy.deepcopy(self._play_context)
            if self._task.action in ['iosxr_netconf', 'iosxr_config', 'iosxr_command'] or \
                    (provider['transport'] == 'cli' and (self._task.action == 'iosxr_banner' or
                                                         self._task.action == 'iosxr_facts' or self._task.action == 'iosxr_logging' or
                                                         self._task.action == 'iosxr_system' or self._task.action == 'iosxr_user' or
                                                         self._task.action == 'iosxr_interface')):
                pc.connection = 'network_cli'
                pc.port = int(provider['port'] or self._play_context.port
                              or 22)
            else:
                pc.connection = 'netconf'
                pc.port = int(provider['port'] or self._play_context.port
                              or 830)

            pc.network_os = 'iosxr'
            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.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)

            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

        # make sure we are in the right cli context which should be
        # enable mode and not config module
        if (self._play_context.connection == 'local'
                and pc.connection == 'network_cli'
            ) or self._play_context.connection == 'network_cli':
            if socket_path is None:
                socket_path = self._connection.socket_path

            conn = Connection(socket_path)
            out = conn.get_prompt()
            while to_text(
                    out,
                    errors='surrogate_then_replace').strip().endswith(')#'):
                display.vvvv('wrong context, sending exit to device',
                             self._play_context.remote_addr)
                conn.send_command('abort')
                out = conn.get_prompt()

        result = super(ActionModule, self).run(tmp, task_vars)
        return result
示例#57
0
 def connection_lock(self):
     f = self._play_context.connection_lockfd
     display.vvvv('CONNECTION: pid %d waiting for lock on %d' % (os.getpid(), f))
     fcntl.lockf(f, fcntl.LOCK_EX)
     display.vvvv('CONNECTION: pid %d acquired lock on %d' % (os.getpid(), f))
示例#58
0
    def _start_connection(self):
        '''
        Starts the persistent connection
        '''
        master, slave = pty.openpty()

        python = sys.executable

        def find_file_in_path(filename):
            # Check $PATH first, followed by same directory as sys.argv[0]
            paths = os.environ['PATH'].split(
                os.pathsep) + [os.path.dirname(sys.argv[0])]
            for dirname in paths:
                fullpath = os.path.join(dirname, filename)
                if os.path.isfile(fullpath):
                    return fullpath

            raise AnsibleError("Unable to find location of '%s'" % filename)

        p = subprocess.Popen([
            python,
            find_file_in_path('ansible-connection'),
            to_text(os.getppid())
        ],
                             stdin=slave,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
        stdin = os.fdopen(master, 'wb', 0)
        os.close(slave)

        # Need to force a protocol that is compatible with both py2 and py3.
        # That would be protocol=2 or less.
        # Also need to force a protocol that excludes certain control chars as
        # stdin in this case is a pty and control chars will cause problems.
        # that means only protocol=0 will work.
        src = cPickle.dumps(self._play_context.serialize(), protocol=0)
        stdin.write(src)

        stdin.write(b'\n#END_INIT#\n')
        stdin.flush()

        (stdout, stderr) = p.communicate()
        stdin.close()

        if p.returncode == 0:
            result = json.loads(
                to_text(stdout, errors='surrogate_then_replace'))
        else:
            try:
                result = json.loads(
                    to_text(stderr, errors='surrogate_then_replace'))
            except getattr(json.decoder, 'JSONDecodeError', ValueError):
                # JSONDecodeError only available on Python 3.5+
                result = {
                    'error': to_text(stderr, errors='surrogate_then_replace')
                }

        if 'messages' in result:
            for msg in result.get('messages'):
                display.vvvv('%s' % msg, host=self._play_context.remote_addr)

        if 'error' in result:
            if self._play_context.verbosity > 2:
                if result.get('exception'):
                    msg = "The full traceback is:\n" + result['exception']
                    display.display(msg, color=C.COLOR_ERROR)
            raise AnsibleError(result['error'])

        return result['socket_path']
示例#59
0
    def _poll_async_result(self, result, templar, task_vars=None):
        '''
        Polls for the specified JID to be complete
        '''

        if task_vars is None:
            task_vars = self._job_vars

        async_jid = result.get('ansible_job_id')
        if async_jid is None:
            return dict(failed=True, msg="No job id was returned by the async task")

        # Create a new pseudo-task to run the async_status module, and run
        # that (with a sleep for "poll" seconds between each retry) until the
        # async time limit is exceeded.

        async_task = Task().load(dict(action='async_status jid=%s' % async_jid, environment=self._task.environment))

        # FIXME: this is no longer the case, normal takes care of all, see if this can just be generalized
        # Because this is an async task, the action handler is async. However,
        # we need the 'normal' action handler for the status check, so get it
        # now via the action_loader
        normal_handler = self._shared_loader_obj.action_loader.get(
            'normal',
            task=async_task,
            connection=self._connection,
            play_context=self._play_context,
            loader=self._loader,
            templar=templar,
            shared_loader_obj=self._shared_loader_obj,
        )

        time_left = self._task.async_val
        while time_left > 0:
            time.sleep(self._task.poll)

            try:
                async_result = normal_handler.run(task_vars=task_vars)
                # We do not bail out of the loop in cases where the failure
                # is associated with a parsing error. The async_runner can
                # have issues which result in a half-written/unparseable result
                # file on disk, which manifests to the user as a timeout happening
                # before it's time to timeout.
                if (int(async_result.get('finished', 0)) == 1 or
                        ('failed' in async_result and async_result.get('_ansible_parsed', False)) or
                        'skipped' in async_result):
                    break
            except Exception as e:
                # Connections can raise exceptions during polling (eg, network bounce, reboot); these should be non-fatal.
                # On an exception, call the connection's reset method if it has one
                # (eg, drop/recreate WinRM connection; some reused connections are in a broken state)
                display.vvvv("Exception during async poll, retrying... (%s)" % to_text(e))
                display.debug("Async poll exception was:\n%s" % to_text(traceback.format_exc()))
                try:
                    normal_handler._connection._reset()
                except AttributeError:
                    pass

                # Little hack to raise the exception if we've exhausted the timeout period
                time_left -= self._task.poll
                if time_left <= 0:
                    raise
            else:
                time_left -= self._task.poll

        if int(async_result.get('finished', 0)) != 1:
            if async_result.get('_ansible_parsed'):
                return dict(failed=True, msg="async task did not complete within the requested time")
            else:
                return dict(failed=True, msg="async task produced unparseable results", async_result=async_result)
        else:
            return async_result
示例#60
0
    def run(self, tmp=None, task_vars=None):
        if self._play_context.connection != 'local':
            return dict(
                failed=True,
                msg='invalid connection specified, expected connection=local, '
                'got %s' % self._play_context.connection)

        provider = self.load_provider()
        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 = 'network_cli'
            pc.network_os = 'eos'
            pc.remote_user = provider[
                'username'] or self._play_context.connection_user
            pc.password = provider[
                'password'] or self._play_context.password or 22
            pc.privateip_key_file = provider[
                'ssh_keyfile'] or self._play_context.private_key_file
            pc.timeout = provider['timeout'] or self._play_context.timeout
            pc.become = provider['authorize'] or False
            pc.become_pass = provider['auth_pass']

            connection = self._shared_loader_obj.connection_loader.get(
                'persistent', pc, sys.stdin)

            socket_path = self._get_socket_path(pc)
            display.vvvv('socket_path: %s' % socket_path, pc.remote_addr)

            if not os.path.exists(socket_path):
                # start the connection if it isn't started
                display.vvvv('calling open_shell()', pc.remote_addr)
                rc, out, err = connection.exec_command('open_shell()')
                if not rc == 0:
                    return {'failed': True, 'msg': 'unable to open shell'}
            else:
                # make sure we are in the right cli context which should be
                # enable mode and not config module
                rc, out, err = connection.exec_command('prompt()')
                while str(out).strip().endswith(')#'):
                    display.debug('wrong context, sending exit to device',
                                  self._play_context.remote_addr)
                    connection.exec_command('exit')
                    rc, out, err = connection.exec_command('prompt()')

            task_vars['ansible_socket'] = socket_path

        else:
            provider_arg = {
                'host': provider.get('host') or self._play_context.remote_addr,
                'port': provider.get('port'),
                'username': provider.get('username')
                or self._play_context.connection_user,
                'password': provider.get('password')
                or self._play_context.password,
                'authorize': provider.get('authorize') or False,
                'auth_pass': provider.get('auth_pass'),
                'timeout': provider.get('timeout')
                or self._play_context.timeout,
                'use_ssl': task_vars.get('eapi_use_ssl') or False,
                'validate_certs': task_vars.get('eapi_validate_certs') or True
            }
            self._task.args['provider'] = provider_arg

        if self._play_context.become_method == 'enable':
            self._play_context.become = False
            self._play_context.become_method = None

        return super(ActionModule, self).run(tmp, task_vars)