예제 #1
0
def generate_assible_template_vars(path, dest_path=None):
    b_path = to_bytes(path)
    try:
        template_uid = pwd.getpwuid(os.stat(b_path).st_uid).pw_name
    except (KeyError, TypeError):
        template_uid = os.stat(b_path).st_uid

    temp_vars = {
        'template_host': to_text(os.uname()[1]),
        'template_path': path,
        'template_mtime':
        datetime.datetime.fromtimestamp(os.path.getmtime(b_path)),
        'template_uid': to_text(template_uid),
        'template_fullpath': os.path.abspath(path),
        'template_run_date': datetime.datetime.now(),
        'template_destpath': to_native(dest_path) if dest_path else None,
    }

    managed_default = C.DEFAULT_MANAGED_STR
    managed_str = managed_default.format(
        host=temp_vars['template_host'],
        uid=temp_vars['template_uid'],
        file=temp_vars['template_path'],
    )
    temp_vars['assible_managed'] = to_text(
        time.strftime(to_native(managed_str),
                      time.localtime(os.path.getmtime(b_path))))

    return temp_vars
예제 #2
0
    def run(self):
        """Run the assible command

        Subclasses must implement this method.  It does the actual work of
        running an Assible command.
        """
        self.parse()

        display.vv(to_text(opt_help.version(self.parser.prog)))

        if C.CONFIG_FILE:
            display.v(u"Using %s as config file" % to_text(C.CONFIG_FILE))
        else:
            display.v(u"No config file found; using defaults")

        # warn about deprecated config options
        for deprecated in C.config.DEPRECATED:
            name = deprecated[0]
            why = deprecated[1]['why']
            if 'alternatives' in deprecated[1]:
                alt = ', use %s instead' % deprecated[1]['alternatives']
            else:
                alt = ''
            ver = deprecated[1].get('version')
            date = deprecated[1].get('date')
            collection_name = deprecated[1].get('collection_name')
            display.deprecated("%s option, %s %s" % (name, why, alt),
                               version=ver,
                               date=date,
                               collection_name=collection_name)
def test_build_requirement_from_path_with_manifest(version,
                                                   collection_artifact):
    manifest_path = os.path.join(collection_artifact[0], b'MANIFEST.json')
    manifest_value = json.dumps({
        'collection_info': {
            'namespace': 'namespace',
            'name': 'name',
            'version': version,
            'dependencies': {
                'assible_namespace.collection': '*'
            }
        }
    })
    with open(manifest_path, 'wb') as manifest_obj:
        manifest_obj.write(to_bytes(manifest_value))

    actual = collection.CollectionRequirement.from_path(
        collection_artifact[0], True)

    # While the folder name suggests a different collection, we treat MANIFEST.json as the source of truth.
    assert actual.namespace == u'namespace'
    assert actual.name == u'name'
    assert actual.b_path == collection_artifact[0]
    assert actual.api is None
    assert actual.skip is True
    assert actual.versions == set([to_text(version)])
    assert actual.latest_version == to_text(version)
    assert actual.dependencies == {'assible_namespace.collection': '*'}
예제 #4
0
def to_safe_group_name(name, replacer="_", force=False, silent=False):
    # Converts 'bad' characters in a string to underscores (or provided replacer) so they can be used as Assible hosts or groups

    warn = ''
    if name:  # when deserializing we might not have name yet
        invalid_chars = C.INVALID_VARIABLE_NAMES.findall(name)
        if invalid_chars:
            msg = 'invalid character(s) "%s" in group name (%s)' % (to_text(
                set(invalid_chars)), to_text(name))
            if C.TRANSFORM_INVALID_GROUP_CHARS not in ('never',
                                                       'ignore') or force:
                name = C.INVALID_VARIABLE_NAMES.sub(replacer, name)
                if not (silent
                        or C.TRANSFORM_INVALID_GROUP_CHARS == 'silently'):
                    display.vvvv('Replacing ' + msg)
                    warn = 'Invalid characters were found in group names and automatically replaced, use -vvvv to see details'
            else:
                if C.TRANSFORM_INVALID_GROUP_CHARS == 'never':
                    display.vvvv('Not replacing %s' % msg)
                    warn = 'Invalid characters were found in group names but not replaced, use -vvvv to see details'

    if warn:
        display.warning(warn)

    return name
예제 #5
0
파일: ios.py 프로젝트: katiestar99/ansible
def get_defaults_flag(module):
    connection = get_connection(module)
    try:
        out = connection.get_defaults_flag()
    except ConnectionError as exc:
        module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
    return to_text(out, errors="surrogate_then_replace").strip()
예제 #6
0
파일: ios.py 프로젝트: katiestar99/ansible
def get_config(module, flags=None):
    flags = to_list(flags)

    section_filter = False
    if flags and "section" in flags[-1]:
        section_filter = True

    flag_str = " ".join(flags)

    try:
        return _DEVICE_CONFIGS[flag_str]
    except KeyError:
        connection = get_connection(module)
        try:
            out = connection.get_config(flags=flags)
        except ConnectionError as exc:
            if section_filter:
                # Some ios devices don't understand `| section foo`
                out = get_config(module, flags=flags[:-1])
            else:
                module.fail_json(
                    msg=to_text(exc, errors="surrogate_then_replace"))
        cfg = to_text(out, errors="surrogate_then_replace").strip()
        _DEVICE_CONFIGS[flag_str] = cfg
        return cfg
예제 #7
0
    def _encode_script(self,
                       script,
                       as_list=False,
                       strict_mode=True,
                       preserve_rc=True):
        '''Convert a PowerShell script to a single base64-encoded command.'''
        script = to_text(script)

        if script == u'-':
            cmd_parts = _common_args + ['-Command', '-']

        else:
            if strict_mode:
                script = u'Set-StrictMode -Version Latest\r\n%s' % script
            # try to propagate exit code if present- won't work with begin/process/end-style scripts (ala put_file)
            # NB: the exit code returned may be incorrect in the case of a successful command followed by an invalid command
            if preserve_rc:
                script = u'%s\r\nIf (-not $?) { If (Get-Variable LASTEXITCODE -ErrorAction SilentlyContinue) { exit $LASTEXITCODE } Else { exit 1 } }\r\n'\
                    % script
            script = '\n'.join(
                [x.strip() for x in script.splitlines() if x.strip()])
            encoded_script = to_text(
                base64.b64encode(script.encode('utf-16-le')), 'utf-8')
            cmd_parts = _common_args + ['-EncodedCommand', encoded_script]

        if as_list:
            return cmd_parts
        return ' '.join(cmd_parts)
예제 #8
0
 def get_distribution(self, task_vars):
     # FIXME: only execute the module if we don't already have the facts we need
     distribution = {}
     display.debug(
         '{action}: running setup module to get distribution'.format(
             action=self._task.action))
     module_output = self._execute_module(
         task_vars=task_vars,
         module_name='assible.legacy.setup',
         module_args={'gather_subset': 'min'})
     try:
         if module_output.get('failed', False):
             raise AssibleError(
                 'Failed to determine system distribution. {0}, {1}'.format(
                     to_native(module_output['module_stdout']).strip(),
                     to_native(module_output['module_stderr']).strip()))
         distribution['name'] = module_output['assible_facts'][
             'assible_distribution'].lower()
         distribution['version'] = to_text(
             module_output['assible_facts']
             ['assible_distribution_version'].split('.')[0])
         distribution['family'] = to_text(
             module_output['assible_facts']['assible_os_family'].lower())
         display.debug("{action}: distribution: {dist}".format(
             action=self._task.action, dist=distribution))
         return distribution
     except KeyError as ke:
         raise AssibleError(
             'Failed to get distribution information. Missing "{0}" in output.'
             .format(ke.args[0]))
예제 #9
0
파일: json.py 프로젝트: katiestar99/ansible
 def default(self, o):
     if getattr(o, '__ENCRYPTED__', False):
         # vault object
         if self._vault_to_text:
             value = to_text(o, errors='surrogate_or_strict')
         else:
             value = {
                 '__assible_vault':
                 to_text(o._ciphertext,
                         errors='surrogate_or_strict',
                         nonstring='strict')
             }
     elif getattr(o, '__UNSAFE__', False):
         # unsafe object, this will never be triggered, see ``AssibleJSONEncoder.iterencode``
         value = {
             '__assible_unsafe':
             to_text(o, errors='surrogate_or_strict', nonstring='strict')
         }
     elif isinstance(o, Mapping):
         # hostvars and other objects
         value = dict(o)
     elif isinstance(o, (datetime.date, datetime.datetime)):
         # date object
         value = o.isoformat()
     else:
         # use default encoder
         value = super(AssibleJSONEncoder, self).default(o)
     return value
예제 #10
0
    def __init__(self,
                 message="",
                 obj=None,
                 show_content=True,
                 suppress_extended_error=False,
                 orig_exc=None,
                 paths=None,
                 file_name=None):

        self.file_name = file_name
        self.paths = paths

        if message:
            message += "\n"
        if self.file_name:
            message += "Could not find or access '%s'" % to_text(
                self.file_name)
        else:
            message += "Could not find file"

        if self.paths and isinstance(self.paths, Sequence):
            searched = to_text('\n\t'.join(self.paths))
            if message:
                message += "\n"
            message += "Searched in:\n\t%s" % searched

        message += " on the Assible Controller.\nIf you are using a module and expect the file to exist on the remote, see the remote_src option"

        super(AssibleFileNotFound,
              self).__init__(message=message,
                             obj=obj,
                             show_content=show_content,
                             suppress_extended_error=suppress_extended_error,
                             orig_exc=orig_exc)
예제 #11
0
    def _create_zip_tempfile(self, files, directories):
        tmpdir = tempfile.mkdtemp(dir=C.DEFAULT_LOCAL_TMP)
        zip_file_path = os.path.join(tmpdir, "win_copy.zip")
        zip_file = zipfile.ZipFile(zip_file_path, "w", zipfile.ZIP_STORED,
                                   True)

        # encoding the file/dir name with base64 so Windows can unzip a unicode
        # filename and get the right name, Windows doesn't handle unicode names
        # very well
        for directory in directories:
            directory_path = to_bytes(directory['src'],
                                      errors='surrogate_or_strict')
            archive_path = to_bytes(directory['dest'],
                                    errors='surrogate_or_strict')

            encoded_path = to_text(base64.b64encode(archive_path),
                                   errors='surrogate_or_strict')
            zip_file.write(directory_path, encoded_path, zipfile.ZIP_DEFLATED)

        for file in files:
            file_path = to_bytes(file['src'], errors='surrogate_or_strict')
            archive_path = to_bytes(file['dest'], errors='surrogate_or_strict')

            encoded_path = to_text(base64.b64encode(archive_path),
                                   errors='surrogate_or_strict')
            zip_file.write(file_path, encoded_path, zipfile.ZIP_DEFLATED)

        return zip_file_path
예제 #12
0
    def subset(self, subset_pattern):
        """
        Limits inventory results to a subset of inventory that matches a given
        pattern, such as to select a given geographic of numeric slice amongst
        a previous 'hosts' selection that only select roles, or vice versa.
        Corresponds to --limit parameter to assible-playbook
        """
        if subset_pattern is None:
            self._subset = None
        else:
            subset_patterns = split_host_pattern(subset_pattern)
            results = []
            # allow Unix style @filename data
            for x in subset_patterns:
                if not x:
                    continue

                if x[0] == "@":
                    b_limit_file = to_bytes(x[1:])
                    if not os.path.exists(b_limit_file):
                        raise AssibleError(u'Unable to find limit file %s' %
                                           b_limit_file)
                    with open(b_limit_file) as fd:
                        results.extend([
                            to_text(l.strip()) for l in fd.read().split("\n")
                        ])
                else:
                    results.append(to_text(x))
            self._subset = results
예제 #13
0
    def send_callback(self, method_name, *args, **kwargs):
        for callback_plugin in [self._stdout_callback
                                ] + self._callback_plugins:
            # a plugin that set self.disabled to True will not be called
            # see osx_say.py example for such a plugin
            if getattr(callback_plugin, 'disabled', False):
                continue

            # a plugin can opt in to implicit tasks (such as meta). It does this
            # by declaring self.wants_implicit_tasks = True.
            wants_implicit_tasks = getattr(callback_plugin,
                                           'wants_implicit_tasks', False)

            # try to find v2 method, fallback to v1 method, ignore callback if no method found
            methods = []
            for possible in [method_name, 'v2_on_any']:
                gotit = getattr(callback_plugin, possible, None)
                if gotit is None:
                    gotit = getattr(callback_plugin,
                                    possible.replace('v2_', ''), None)
                if gotit is not None:
                    methods.append(gotit)

            # send clean copies
            new_args = []

            # If we end up being given an implicit task, we'll set this flag in
            # the loop below. If the plugin doesn't care about those, then we
            # check and continue to the next iteration of the outer loop.
            is_implicit_task = False

            for arg in args:
                # FIXME: add play/task cleaners
                if isinstance(arg, TaskResult):
                    new_args.append(arg.clean_copy())
                # elif isinstance(arg, Play):
                # elif isinstance(arg, Task):
                else:
                    new_args.append(arg)

                if isinstance(arg, Task) and arg.implicit:
                    is_implicit_task = True

            if is_implicit_task and not wants_implicit_tasks:
                continue

            for method in methods:
                try:
                    method(*new_args, **kwargs)
                except Exception as e:
                    # TODO: add config toggle to make this fatal or not?
                    display.warning(
                        u"Failure using method (%s) in callback plugin (%s): %s"
                        % (to_text(method_name), to_text(callback_plugin),
                           to_text(e)))
                    from traceback import format_tb
                    from sys import exc_info
                    display.vvv('Callback Exception: \n' +
                                ' '.join(format_tb(exc_info()[2])))
예제 #14
0
    def has_changed(self,
                    want_dict,
                    current_dict,
                    only_keys=None,
                    skip_diff_for_keys=None):
        result = False
        for key, value in want_dict.items():

            # Optionally limit by a list of keys
            if only_keys and key not in only_keys:
                continue

            # Skip None values
            if value is None:
                continue

            if key in current_dict:
                if isinstance(value, (int, float, long, complex)):

                    # ensure we compare the same type
                    if isinstance(value, int):
                        current_dict[key] = int(current_dict[key])
                    elif isinstance(value, float):
                        current_dict[key] = float(current_dict[key])
                    elif isinstance(value, long):
                        current_dict[key] = long(current_dict[key])
                    elif isinstance(value, complex):
                        current_dict[key] = complex(current_dict[key])

                    if value != current_dict[key]:
                        if skip_diff_for_keys and key not in skip_diff_for_keys:
                            self.result['diff']['before'][key] = current_dict[
                                key]
                            self.result['diff']['after'][key] = value
                        result = True
                else:
                    before_value = to_text(current_dict[key])
                    after_value = to_text(value)

                    if self.case_sensitive_keys and key in self.case_sensitive_keys:
                        if before_value != after_value:
                            if skip_diff_for_keys and key not in skip_diff_for_keys:
                                self.result['diff']['before'][
                                    key] = before_value
                                self.result['diff']['after'][key] = after_value
                            result = True

                    # Test for diff in case insensitive way
                    elif before_value.lower() != after_value.lower():
                        if skip_diff_for_keys and key not in skip_diff_for_keys:
                            self.result['diff']['before'][key] = before_value
                            self.result['diff']['after'][key] = after_value
                        result = True
            else:
                if skip_diff_for_keys and key not in skip_diff_for_keys:
                    self.result['diff']['before'][key] = None
                    self.result['diff']['after'][key] = to_text(value)
                result = True
        return result
예제 #15
0
 def _encode_token(username, password):
     token = "%s:%s" % (to_text(username, errors='surrogate_or_strict'),
                        to_text(password,
                                errors='surrogate_or_strict',
                                nonstring='passthru') or '')
     b64_val = base64.b64encode(
         to_bytes(token, encoding='utf-8', errors='surrogate_or_strict'))
     return to_text(b64_val)
예제 #16
0
def ensure_subnet_present(conn, module):
    subnet = get_matching_subnet(conn, module, module.params['vpc_id'],
                                 module.params['cidr'])
    changed = False

    # Initialize start so max time does not exceed the specified wait_timeout for multiple operations
    start_time = time.time()

    if subnet is None:
        if not module.check_mode:
            subnet = create_subnet(conn,
                                   module,
                                   module.params['vpc_id'],
                                   module.params['cidr'],
                                   ipv6_cidr=module.params['ipv6_cidr'],
                                   az=module.params['az'],
                                   start_time=start_time)
        changed = True
        # Subnet will be None when check_mode is true
        if subnet is None:
            return {'changed': changed, 'subnet': {}}
    if module.params['wait']:
        handle_waiter(conn, module, 'subnet_exists',
                      {'SubnetIds': [subnet['id']]}, start_time)

    if module.params['ipv6_cidr'] != subnet.get('ipv6_cidr_block'):
        if ensure_ipv6_cidr_block(conn, module, subnet,
                                  module.params['ipv6_cidr'],
                                  module.check_mode, start_time):
            changed = True

    if module.params['map_public'] != subnet['map_public_ip_on_launch']:
        ensure_map_public(conn, module, subnet, module.params['map_public'],
                          module.check_mode, start_time)
        changed = True

    if module.params['assign_instances_ipv6'] != subnet.get(
            'assign_ipv6_address_on_creation'):
        ensure_assign_ipv6_on_create(conn, module, subnet,
                                     module.params['assign_instances_ipv6'],
                                     module.check_mode, start_time)
        changed = True

    if module.params['tags'] != subnet['tags']:
        stringified_tags_dict = dict(
            (to_text(k), to_text(v)) for k, v in module.params['tags'].items())
        if ensure_tags(conn, module, subnet, stringified_tags_dict,
                       module.params['purge_tags'], start_time):
            changed = True

    subnet = get_matching_subnet(conn, module, module.params['vpc_id'],
                                 module.params['cidr'])
    if not module.check_mode and module.params['wait']:
        # GET calls are not monotonic for map_public_ip_on_launch and assign_ipv6_address_on_creation
        # so we only wait for those if necessary just before returning the subnet
        subnet = ensure_final_subnet(conn, module, subnet, start_time)

    return {'changed': changed, 'subnet': subnet}
예제 #17
0
 def response(self, result=None):
     response = self.header()
     if isinstance(result, binary_type):
         result = to_text(result)
     if not isinstance(result, text_type):
         response["result_type"] = "pickle"
         result = to_text(cPickle.dumps(result, protocol=0))
     response['result'] = result
     return response
예제 #18
0
    def run(self, tmp=None, task_vars=None):
        if task_vars is None:
            task_vars = dict()

        if 'msg' in self._task.args and 'var' in self._task.args:
            return {
                "failed": True,
                "msg": "'msg' and 'var' are incompatible options"
            }

        result = super(ActionModule, self).run(tmp, task_vars)
        del tmp  # tmp no longer has any effect

        # get task verbosity
        verbosity = int(self._task.args.get('verbosity', 0))

        if verbosity <= self._display.verbosity:
            if 'msg' in self._task.args:
                result['msg'] = self._task.args['msg']

            elif 'var' in self._task.args:
                try:
                    results = self._templar.template(self._task.args['var'],
                                                     convert_bare=True,
                                                     fail_on_undefined=True)
                    if results == self._task.args['var']:
                        # if results is not str/unicode type, raise an exception
                        if not isinstance(results, string_types):
                            raise AssibleUndefinedVariable
                        # If var name is same as result, try to template it
                        results = self._templar.template(
                            "{{" + results + "}}",
                            convert_bare=True,
                            fail_on_undefined=True)
                except AssibleUndefinedVariable as e:
                    results = u"VARIABLE IS NOT DEFINED!"
                    if self._display.verbosity > 0:
                        results += u": %s" % to_text(e)

                if isinstance(self._task.args['var'], (list, dict)):
                    # If var is a list or dict, use the type as key to display
                    result[to_text(type(self._task.args['var']))] = results
                else:
                    result[self._task.args['var']] = results
            else:
                result['msg'] = 'Hello world!'

            # force flag to make debug output module always verbose
            result['_assible_verbose_always'] = True
        else:
            result['skipped_reason'] = "Verbosity threshold not met."
            result['skipped'] = True

        result['failed'] = False

        return result
예제 #19
0
def test_install_collection_with_download(galaxy_server, collection_artifact,
                                          monkeypatch):
    collection_tar = collection_artifact[1]
    output_path = os.path.join(os.path.split(collection_tar)[0], b'output')
    collection_path = os.path.join(output_path, b'assible_namespace',
                                   b'collection')

    mock_display = MagicMock()
    monkeypatch.setattr(Display, 'display', mock_display)

    mock_download = MagicMock()
    mock_download.return_value = collection_tar
    monkeypatch.setattr(collection, '_download_file', mock_download)

    monkeypatch.setattr(galaxy_server, '_available_api_versions',
                        {'v2': 'v2/'})
    temp_path = os.path.join(os.path.split(collection_tar)[0], b'temp')
    os.makedirs(temp_path)

    meta = api.CollectionVersionMetadata('assible_namespace', 'collection',
                                         '0.1.0', 'https://downloadme.com',
                                         'myhash', {})
    req = collection.CollectionRequirement('assible_namespace',
                                           'collection',
                                           None,
                                           galaxy_server, ['0.1.0'],
                                           '*',
                                           False,
                                           metadata=meta)
    req.install(to_text(output_path), temp_path)

    # Ensure the temp directory is empty, nothing is left behind
    assert os.listdir(temp_path) == []

    actual_files = os.listdir(collection_path)
    actual_files.sort()
    assert actual_files == [
        b'FILES.json', b'MANIFEST.json', b'README.md', b'docs', b'playbooks',
        b'plugins', b'roles', b'runme.sh'
    ]

    assert mock_display.call_count == 2
    assert mock_display.mock_calls[0][1][0] == "Installing 'assible_namespace.collection:0.1.0' to '%s'" \
        % to_text(collection_path)
    assert mock_display.mock_calls[1][1][
        0] == "assible_namespace.collection (0.1.0) was installed successfully"

    assert mock_download.call_count == 1
    assert mock_download.mock_calls[0][1][0] == 'https://downloadme.com'
    assert mock_download.mock_calls[0][1][1] == temp_path
    assert mock_download.mock_calls[0][1][2] == 'myhash'
    assert mock_download.mock_calls[0][1][3] is True
예제 #20
0
    def handle_request(self, request):
        request = json.loads(to_text(request, errors='surrogate_then_replace'))

        method = request.get('method')

        if method.startswith('rpc.') or method.startswith('_'):
            error = self.invalid_request()
            return json.dumps(error)

        args, kwargs = request.get('params')
        setattr(self, '_identifier', request.get('id'))

        rpc_method = None
        for obj in self._objects:
            rpc_method = getattr(obj, method, None)
            if rpc_method:
                break

        if not rpc_method:
            error = self.method_not_found()
            response = json.dumps(error)
        else:
            try:
                result = rpc_method(*args, **kwargs)
            except ConnectionError as exc:
                display.vvv(traceback.format_exc())
                try:
                    error = self.error(code=exc.code, message=to_text(exc))
                except AttributeError:
                    error = self.internal_error(data=to_text(exc))
                response = json.dumps(error)
            except Exception as exc:
                display.vvv(traceback.format_exc())
                error = self.internal_error(data=to_text(exc, errors='surrogate_then_replace'))
                response = json.dumps(error)
            else:
                if isinstance(result, dict) and 'jsonrpc' in result:
                    response = result
                else:
                    response = self.response(result)

                try:
                    response = json.dumps(response)
                except Exception as exc:
                    display.vvv(traceback.format_exc())
                    error = self.internal_error(data=to_text(exc, errors='surrogate_then_replace'))
                    response = json.dumps(error)

        delattr(self, '_identifier')

        return response
예제 #21
0
    def do_until_success_or_timeout(self,
                                    action,
                                    reboot_timeout,
                                    action_desc,
                                    distribution,
                                    action_kwargs=None):
        max_end_time = datetime.utcnow() + timedelta(seconds=reboot_timeout)
        if action_kwargs is None:
            action_kwargs = {}

        fail_count = 0
        max_fail_sleep = 12

        while datetime.utcnow() < max_end_time:
            try:
                action(distribution=distribution, **action_kwargs)
                if action_desc:
                    display.debug('{action}: {desc} success'.format(
                        action=self._task.action, desc=action_desc))
                return
            except Exception as e:
                if isinstance(e, AssibleConnectionFailure):
                    try:
                        self._connection.reset()
                    except AssibleConnectionFailure:
                        pass
                # Use exponential backoff with a max timout, plus a little bit of randomness
                random_int = random.randint(0, 1000) / 1000
                fail_sleep = 2**fail_count + random_int
                if fail_sleep > max_fail_sleep:

                    fail_sleep = max_fail_sleep + random_int
                if action_desc:
                    try:
                        error = to_text(e).splitlines()[-1]
                    except IndexError as e:
                        error = to_text(e)
                    display.debug(
                        "{action}: {desc} fail '{err}', retrying in {sleep:.4} seconds..."
                        .format(action=self._task.action,
                                desc=action_desc,
                                err=error,
                                sleep=fail_sleep))
                fail_count += 1
                time.sleep(fail_sleep)

        raise TimedOutException(
            'Timed out waiting for {desc} (timeout={timeout})'.format(
                desc=action_desc, timeout=reboot_timeout))
예제 #22
0
def get_config(module, flags=None, format=None):
    flags = [] if flags is None else flags
    global _DEVICE_CONFIGS

    if _DEVICE_CONFIGS != {}:
        return _DEVICE_CONFIGS
    else:
        connection = get_connection(module)
        try:
            out = connection.get_config(flags=flags, format=format)
        except ConnectionError as exc:
            module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
        cfg = to_text(out, errors="surrogate_then_replace").strip()
        _DEVICE_CONFIGS = cfg
        return cfg
예제 #23
0
    def path_dwim(self, given):
        '''
        make relative paths work like folks expect.
        '''

        given = unquote(given)
        given = to_text(given, errors='surrogate_or_strict')

        if given.startswith(to_text(os.path.sep)) or given.startswith(u'~'):
            path = given
        else:
            basedir = to_text(self._basedir, errors='surrogate_or_strict')
            path = os.path.join(basedir, given)

        return unfrackpath(path, follow=False)
예제 #24
0
def _gen_candidate_chars(characters):
    '''Generate a string containing all valid chars as defined by ``characters``

    :arg characters: A list of character specs. The character specs are
        shorthand names for sets of characters like 'digits', 'ascii_letters',
        or 'punctuation' or a string to be included verbatim.

    The values of each char spec can be:

    * a name of an attribute in the 'strings' module ('digits' for example).
      The value of the attribute will be added to the candidate chars.
    * a string of characters. If the string isn't an attribute in 'string'
      module, the string will be directly added to the candidate chars.

    For example::

        characters=['digits', '?|']``

    will match ``string.digits`` and add all ascii digits.  ``'?|'`` will add
    the question mark and pipe characters directly. Return will be the string::

        u'0123456789?|'
    '''
    chars = []
    for chars_spec in characters:
        # getattr from string expands things like "ascii_letters" and "digits"
        # into a set of characters.
        chars.append(
            to_text(getattr(string, to_native(chars_spec), chars_spec),
                    errors='strict'))
    chars = u''.join(chars).replace(u'"', u'').replace(u"'", u'')
    return chars
예제 #25
0
    def get_memory_facts(self):
        memory_facts = {}
        # Get free memory. vmstat output looks like:
        #  procs    memory       page                    disks    traps          cpu
        #  r b w    avm     fre  flt  re  pi  po  fr  sr wd0 fd0  int   sys   cs us sy id
        #  0 0 0  47512   28160   51   0   0   0   0   0   1   0  116    89   17  0  1 99
        rc, out, err = self.module.run_command("/usr/bin/vmstat")
        if rc == 0:
            memory_facts['memfree_mb'] = int(
                out.splitlines()[-1].split()[4]) // 1024
            memory_facts['memtotal_mb'] = int(
                self.sysctl['hw.usermem']) // 1024 // 1024

        # Get swapctl info. swapctl output looks like:
        # total: 69268 1K-blocks allocated, 0 used, 69268 available
        # And for older OpenBSD:
        # total: 69268k bytes allocated = 0k used, 69268k available
        rc, out, err = self.module.run_command("/sbin/swapctl -sk")
        if rc == 0:
            swaptrans = {ord(u'k'): None, ord(u'm'): None, ord(u'g'): None}
            data = to_text(out, errors='surrogate_or_strict').split()
            memory_facts['swapfree_mb'] = int(
                data[-2].translate(swaptrans)) // 1024
            memory_facts['swaptotal_mb'] = int(
                data[1].translate(swaptrans)) // 1024

        return memory_facts
예제 #26
0
    def _parse_config_file(self, cfile=None):
        ''' return flat configuration settings from file(s) '''
        # TODO: take list of files with merge/nomerge

        if cfile is None:
            cfile = self._config_file

        ftype = get_config_type(cfile)
        if cfile is not None:
            if ftype == 'ini':
                self._parsers[cfile] = configparser.ConfigParser()
                with open(to_bytes(cfile), 'rb') as f:
                    try:
                        cfg_text = to_text(f.read(), errors='surrogate_or_strict')
                    except UnicodeError as e:
                        raise AssibleOptionsError("Error reading config file(%s) because the config file was not utf8 encoded: %s" % (cfile, to_native(e)))
                try:
                    if PY3:
                        self._parsers[cfile].read_string(cfg_text)
                    else:
                        cfg_file = io.StringIO(cfg_text)
                        self._parsers[cfile].readfp(cfg_file)
                except configparser.Error as e:
                    raise AssibleOptionsError("Error reading config file (%s): %s" % (cfile, to_native(e)))
            # FIXME: this should eventually handle yaml config files
            # elif ftype == 'yaml':
            #     with open(cfile, 'rb') as config_stream:
            #         self._parsers[cfile] = yaml.safe_load(config_stream)
            else:
                raise AssibleOptionsError("Unsupported configuration file type: %s" % to_native(ftype))
예제 #27
0
    def _load_file(self, file_name):
        if not file_name or not isinstance(file_name, string_types):
            raise AssibleParserError("Invalid filename: '%s'" % to_native(file_name))

        b_file_name = to_bytes(self.loader.path_dwim(file_name))
        if not self.loader.path_exists(b_file_name):
            raise AssibleFileNotFound("Unable to retrieve file contents", file_name=file_name)

        try:
            (b_data, private) = self.loader._get_file_contents(file_name)
            return toml.loads(to_text(b_data, errors='surrogate_or_strict'))
        except toml.TomlDecodeError as e:
            raise AssibleParserError(
                'TOML file (%s) is invalid: %s' % (file_name, to_native(e)),
                orig_exc=e
            )
        except (IOError, OSError) as e:
            raise AssibleParserError(
                "An error occurred while trying to read the file '%s': %s" % (file_name, to_native(e)),
                orig_exc=e
            )
        except Exception as e:
            raise AssibleParserError(
                "An unexpected error occurred while parsing the file '%s': %s" % (file_name, to_native(e)),
                orig_exc=e
            )
예제 #28
0
    def _loop_entries(self, container, entry_list):
        ''' repeat code for value entry assignment '''

        value = None
        origin = None
        for entry in entry_list:
            name = entry.get('name')
            try:
                temp_value = container.get(name, None)
            except UnicodeEncodeError:
                self.WARNINGS.add(u'value for config entry {0} contains invalid characters, ignoring...'.format(to_text(name)))
                continue
            if temp_value is not None:  # only set if entry is defined in container
                # inline vault variables should be converted to a text string
                if isinstance(temp_value, AssibleVaultEncryptedUnicode):
                    temp_value = to_text(temp_value, errors='surrogate_or_strict')

                value = temp_value
                origin = name

                # deal with deprecation of setting source, if used
                if 'deprecated' in entry:
                    self.DEPRECATED.append((entry['name'], entry['deprecated']))

        return value, origin
예제 #29
0
    def __init__(self, loader=None, inventory=None, version_info=None):
        self._nonpersistent_fact_cache = defaultdict(dict)
        self._vars_cache = defaultdict(dict)
        self._extra_vars = defaultdict(dict)
        self._host_vars_files = defaultdict(dict)
        self._group_vars_files = defaultdict(dict)
        self._inventory = inventory
        self._loader = loader
        self._hostvars = None
        self._omit_token = '__omit_place_holder__%s' % sha1(
            os.urandom(64)).hexdigest()

        self._options_vars = load_options_vars(version_info)

        # If the basedir is specified as the empty string then it results in cwd being used.
        # This is not a safe location to load vars from.
        basedir = self._options_vars.get('basedir', False)
        self.safe_basedir = bool(basedir is False or basedir)

        # load extra vars
        self._extra_vars = load_extra_vars(loader=self._loader)

        # load fact cache
        try:
            self._fact_cache = FactCache()
        except AssibleError as e:
            # bad cache plugin is not fatal error
            # fallback to a dict as in memory cache
            display.warning(to_text(e))
            self._fact_cache = {}
예제 #30
0
def parse_kv(args, check_raw=False):
    '''
    Convert a string of key/value items to a dict. If any free-form params
    are found and the check_raw option is set to True, they will be added
    to a new parameter called '_raw_params'. If check_raw is not enabled,
    they will simply be ignored.
    '''

    args = to_text(args, nonstring='passthru')

    options = {}
    if args is not None:
        try:
            vargs = split_args(args)
        except IndexError as e:
            raise AssibleParserError("Unable to parse argument string",
                                     orig_exc=e)
        except ValueError as ve:
            if 'no closing quotation' in str(ve).lower():
                raise AssibleParserError(
                    "error parsing argument string, try quoting the entire line.",
                    orig_exc=ve)
            else:
                raise

        raw_params = []
        for orig_x in vargs:
            x = _decode_escapes(orig_x)
            if "=" in x:
                pos = 0
                try:
                    while True:
                        pos = x.index('=', pos + 1)
                        if pos > 0 and x[pos - 1] != '\\':
                            break
                except ValueError:
                    # ran out of string, but we must have some escaped equals,
                    # so replace those and append this to the list of raw params
                    raw_params.append(x.replace('\\=', '='))
                    continue

                k = x[:pos]
                v = x[pos + 1:]

                # FIXME: make the retrieval of this list of shell/command
                #        options a function, so the list is centralized
                if check_raw and k not in ('creates', 'removes', 'chdir',
                                           'executable', 'warn'):
                    raw_params.append(orig_x)
                else:
                    options[k.strip()] = unquote(v.strip())
            else:
                raw_params.append(orig_x)

        # recombine the free-form params, if any were found, and assign
        # them to a special option for use later by the shell/command module
        if len(raw_params) > 0:
            options[u'_raw_params'] = join_args(raw_params)

    return options