Ejemplo n.º 1
0
def build_command(module, mode, path, follow, default, recursive, entry=''):
    '''Builds and returns a getfacl/setfacl command.'''
    if mode == 'set':
        cmd = [module.get_bin_path('setfacl', True)]
        cmd.append('-m "%s"' % entry)
    elif mode == 'rm':
        cmd = [module.get_bin_path('setfacl', True)]
        cmd.append('-x "%s"' % entry)
    else:  # mode == 'get'
        cmd = [module.get_bin_path('getfacl', True)]
        # prevents absolute path warnings and removes headers
        if get_platform().lower() == 'linux':
            cmd.append('--omit-header')
            cmd.append('--absolute-names')

    if recursive:
        cmd.append('--recursive')

    if not follow:
        if get_platform().lower() == 'linux':
            cmd.append('--physical')
        elif get_platform().lower() == 'freebsd':
            cmd.append('-h')

    if default:
        cmd.insert(1, '-d')

    cmd.append(path)
    return cmd
Ejemplo n.º 2
0
def build_command(module, mode, path, follow, default, recursive, entry=''):
    '''Builds and returns a getfacl/setfacl command.'''
    if mode == 'set':
        cmd = [module.get_bin_path('setfacl', True)]
        cmd.append('-m "%s"' % entry)
    elif mode == 'rm':
        cmd = [module.get_bin_path('setfacl', True)]
        cmd.append('-x "%s"' % entry)
    else:  # mode == 'get'
        cmd = [module.get_bin_path('getfacl', True)]
        # prevents absolute path warnings and removes headers
        if get_platform().lower() == 'linux':
            cmd.append('--omit-header')
            cmd.append('--absolute-names')

    if recursive:
        cmd.append('--recursive')

    if not follow:
        if get_platform().lower() == 'linux':
            cmd.append('--physical')
        elif get_platform().lower() == 'freebsd':
            cmd.append('-h')

    if default:
        if(mode == 'rm'):
            cmd.insert(1, '-k')
        else:  # mode == 'set' or mode == 'get'
            cmd.insert(1, '-d')

    cmd.append(path)
    return cmd
Ejemplo n.º 3
0
def unset_mount(module, args):
    """Remove a mount point from fstab."""

    to_write = []
    changed = False
    escaped_name = _escape_fstab(args['name'])

    for line in open(args['fstab'], 'r').readlines():
        if not line.strip():
            to_write.append(line)

            continue

        if line.strip().startswith('#'):
            to_write.append(line)

            continue

        # Check if we got a valid line for splitting
        if (
                get_platform() == 'SunOS' and len(line.split()) != 7 or
                get_platform() != 'SunOS' and len(line.split()) != 6):
            to_write.append(line)

            continue

        ld = {}

        if get_platform() == 'SunOS':
            (
                ld['src'],
                dash,
                ld['name'],
                ld['fstype'],
                ld['passno'],
                ld['boot'],
                ld['opts']
            ) = line.split()
        else:
            (
                ld['src'],
                ld['name'],
                ld['fstype'],
                ld['opts'],
                ld['dump'],
                ld['passno']
            ) = line.split()

        if ld['name'] != escaped_name:
            to_write.append(line)

            continue

        # If we got here we found a match - continue and mark changed
        changed = True

    if changed and not module.check_mode:
        write_fstab(to_write, args['fstab'])

    return (args['name'], changed)
Ejemplo n.º 4
0
def main():

    module = AnsibleModule(argument_spec=dict(
        msg=dict(required=True),
        voice=dict(required=False),
    ),
                           supports_check_mode=True)

    msg = module.params['msg']
    voice = module.params['voice']

    executable = module.get_bin_path('say')
    if not executable:
        executable = module.get_bin_path('espeak')
    elif get_platform() != 'Darwin':
        # 'say' binary available, it might be GNUstep tool which doesn't support 'voice' parameter
        voice = None
        module.warn(
            "'say' executable found but system is '%s': ignoring voice parameter"
            % get_platform())

    if not executable:
        module.fail_json(
            msg="Unable to find either 'say' or 'espeak' executable")

    if module.check_mode:
        module.exit_json(msg=msg, changed=False)

    say(module, executable, msg, voice)

    module.exit_json(msg=msg, changed=True)
Ejemplo n.º 5
0
def unset_mount(module, args):
    """Remove a mount point from fstab."""

    to_write = []
    changed = False
    escaped_name = _escape_fstab(args['name'])

    for line in open(args['fstab'], 'r').readlines():
        if not line.strip():
            to_write.append(line)

            continue

        if line.strip().startswith('#'):
            to_write.append(line)

            continue

        # Check if we got a valid line for splitting
        if (
                get_platform() == 'SunOS' and len(line.split()) != 7 or
                get_platform() != 'SunOS' and len(line.split()) != 6):
            to_write.append(line)

            continue

        ld = {}

        if get_platform() == 'SunOS':
            (
                ld['src'],
                dash,
                ld['name'],
                ld['fstype'],
                ld['passno'],
                ld['boot'],
                ld['opts']
            ) = line.split()
        else:
            (
                ld['src'],
                ld['name'],
                ld['fstype'],
                ld['opts'],
                ld['dump'],
                ld['passno']
            ) = line.split()

        if ld['name'] != escaped_name:
            to_write.append(line)

            continue

        # If we got here we found a match - continue and mark changed
        changed = True

    if changed and not module.check_mode:
        write_fstab(module, to_write, args['fstab'])

    return (args['name'], changed)
Ejemplo n.º 6
0
def _set_fstab_args(fstab_file):
    result = []

    if (fstab_file and fstab_file != '/etc/fstab'
            and get_platform().lower() != 'sunos'):
        if get_platform().lower().endswith('bsd'):
            result.append('-F')
        else:
            result.append('-T')

        result.append(fstab_file)

    return result
Ejemplo n.º 7
0
def _set_fstab_args(fstab_file):
    result = []

    if (
            fstab_file and
            fstab_file != '/etc/fstab' and
            get_platform().lower() != 'sunos'):
        if get_platform().lower().endswith('bsd'):
            result.append('-F')
        else:
            result.append('-T')

        result.append(fstab_file)

    return result
Ejemplo n.º 8
0
def remount(module, args):
    """Try to use 'remount' first and fallback to (u)mount if unsupported."""
    mount_bin = module.get_bin_path('mount', required=True)
    cmd = [mount_bin]

    # Multiplatform remount opts
    if get_platform().lower().endswith('bsd'):
        cmd += ['-u']
    else:
        cmd += ['-o', 'remount']

    if get_platform().lower() == 'openbsd':
        # Use module.params['fstab'] here as args['fstab'] has been set to the
        # default value.
        if module.params['fstab'] is not None:
            module.fail_json(
                msg=(
                    'OpenBSD does not support alternate fstab files. Do not '
                    'specify the fstab parameter for OpenBSD hosts'))
    else:
        cmd += _set_fstab_args(args['fstab'])

    cmd += [args['name']]
    out = err = ''

    try:
        if get_platform().lower().endswith('bsd'):
            # Note: Forcing BSDs to do umount/mount due to BSD remount not
            # working as expected (suspect bug in the BSD mount command)
            # Interested contributor could rework this to use mount options on
            # the CLI instead of relying on fstab
            # https://github.com/ansible/ansible-modules-core/issues/5591
            rc = 1
        else:
            rc, out, err = module.run_command(cmd)
    except:
        rc = 1

    msg = ''

    if rc != 0:
        msg = out + err
        rc, msg = umount(module, args['name'])

        if rc == 0:
            rc, msg = mount(module, args)

    return rc, msg
Ejemplo n.º 9
0
def is_bind_mounted(module, dest, src=None, fstype=None):
    """Return whether the dest is bind mounted

    :arg module: The AnsibleModule (used for helper functions)
    :arg dest: The directory to be mounted under. This is the primary means
        of identifying whether the destination is mounted.
    :kwarg src: The source directory. If specified, this is used to help
        ensure that we are detecting that the correct source is mounted there.
    :kwarg fstype: The filesystem type. If specified this is also used to
        help ensure that we are detecting the right mount.
    :returns: True if the dest is mounted with src otherwise False.
    """

    is_mounted = False
    bin_path = module.get_bin_path('mount', required=True)
    cmd = '%s -l' % bin_path

    if get_platform().lower() == 'linux':
        bin_path = module.get_bin_path('findmnt', required=True)
        cmd = '%s -nr %s' % (bin_path, dest)

    rc, out, err = module.run_command(cmd)
    mounts = []

    if len(out):
        mounts = out.strip().split('\n')

    mount_pattern = re.compile('\[(.*)\]')

    for mnt in mounts:
        arguments = mnt.split()

        if get_platform().lower() == 'linux':
            result = mount_pattern.search(arguments[1])

            if len(result.groups()) == 1:
                if arguments[0] == dest:
                    is_mounted = True
        elif (
                (arguments[0] == src or src is None) and
                arguments[2] == dest and
                (arguments[4] == fstype or fstype is None)):
            is_mounted = True

        if is_mounted:
            break

    return is_mounted
Ejemplo n.º 10
0
def remount(module, args):
    """Try to use 'remount' first and fallback to (u)mount if unsupported."""
    mount_bin = module.get_bin_path('mount', required=True)
    cmd = [mount_bin]

    # Multiplatform remount opts
    if get_platform().lower().endswith('bsd'):
        cmd += ['-u']
    else:
        cmd += ['-o', 'remount']

    if get_platform().lower() == 'openbsd':
        # Use module.params['fstab'] here as args['fstab'] has been set to the
        # default value.
        if module.params['fstab'] is not None:
            module.fail_json(
                msg=(
                    'OpenBSD does not support alternate fstab files. Do not '
                    'specify the fstab parameter for OpenBSD hosts'))
    else:
        cmd += _set_fstab_args(args['fstab'])

    cmd += [args['name']]
    out = err = ''

    try:
        if get_platform().lower().endswith('bsd'):
            # Note: Forcing BSDs to do umount/mount due to BSD remount not
            # working as expected (suspect bug in the BSD mount command)
            # Interested contributor could rework this to use mount options on
            # the CLI instead of relying on fstab
            # https://github.com/ansible/ansible-modules-core/issues/5591
            rc = 1
        else:
            rc, out, err = module.run_command(cmd)
    except:
        rc = 1

    msg = ''

    if rc != 0:
        msg = out + err
        rc, msg = umount(module, args['name'])

        if rc == 0:
            rc, msg = mount(module, args)

    return rc, msg
Ejemplo n.º 11
0
def main():

    module = AnsibleModule(
        argument_spec=dict(
            msg=dict(required=True),
            voice=dict(required=False),
        ),
        supports_check_mode=True
    )

    msg = module.params['msg']
    voice = module.params['voice']

    executable = module.get_bin_path('say')
    if not executable:
        executable = module.get_bin_path('espeak')
    elif get_platform() != 'Darwin':
        # 'say' binary available, it might be GNUstep tool which doesn't support 'voice' parameter
        voice = None
        module.warn("'say' executable found but system is '%s': ignoring voice parameter" % get_platform())

    if not executable:
        module.fail_json(msg="Unable to find either 'say' or 'espeak' executable")

    if module.check_mode:
        module.exit_json(msg=msg, changed=False)

    say(module, executable, msg, voice)

    module.exit_json(msg=msg, changed=True)
Ejemplo n.º 12
0
def mount(module, args):
    """Mount up a path or remount if needed."""

    mount_bin = module.get_bin_path('mount', required=True)
    name = args['name']
    cmd = [mount_bin]

    if ismount(name):
        return remount(module, mount_bin, args)

    if get_platform().lower() == 'openbsd':
        # Use module.params['fstab'] here as args['fstab'] has been set to the
        # default value.
        if module.params['fstab'] is not None:
            module.fail_json(msg='OpenBSD does not support alternate fstab files.  Do not specify the fstab parameter for OpenBSD hosts')
    else:
        cmd += _set_fstab_args(args['fstab'])

    cmd += [name]

    rc, out, err = module.run_command(cmd)

    if rc == 0:
        return 0, ''
    else:
        return rc, out+err
Ejemplo n.º 13
0
Archivo: at.py Proyecto: czi/ansible
def get_matching_jobs(module, at_cmd, script_file):
    matching_jobs = []

    atq_cmd = module.get_bin_path('atq', True)

    # Get list of job numbers for the user.
    atq_command = "%s" % atq_cmd
    rc, out, err = module.run_command(atq_command, check_rc=True)
    current_jobs = out.splitlines()
    if len(current_jobs) == 0:
        return matching_jobs

    # Read script_file into a string.
    with open(script_file) as script_fh:
        script_file_string = script_fh.read().strip()

    # Loop through the jobs.
    #   If the script text is contained in a job add job number to list.
    for current_job in current_jobs:
        split_current_job = current_job.split()
        if get_platform() == 'AIX':
            at_command = "%s -lv %s" % (at_cmd, split_current_job[0])
        else:
            at_command = "%s -c %s" % (at_cmd, split_current_job[0])
        rc, out, err = module.run_command(at_command, check_rc=True)
        if script_file_string in out:
            matching_jobs.append(split_current_job[0])

    # Return the list.
    return matching_jobs
Ejemplo n.º 14
0
def remount(module, mount_bin, args):
    ''' will try to use -o remount first and fallback to unmount/mount if unsupported'''
    msg = ''
    cmd = [mount_bin]

    # multiplatform remount opts
    if get_platform().lower().endswith('bsd'):
        cmd += ['-u']
    else:
        cmd += ['-o', 'remount']

    cmd += _set_fstab_args(args)
    cmd += [
        args['name'],
    ]
    try:
        rc, out, err = module.run_command(cmd)
    except:
        rc = 1
    if rc != 0:
        msg = out + err
        if ismount(args['name']):
            rc, msg = umount(module, args['name'])
        if rc == 0:
            rc, msg = mount(module, args)
    return rc, msg
Ejemplo n.º 15
0
def mount(module, args):
    """Mount up a path or remount if needed."""

    mount_bin = module.get_bin_path('mount', required=True)
    name = args['name']
    cmd = [mount_bin]

    if get_platform().lower() == 'openbsd':
        # Use module.params['fstab'] here as args['fstab'] has been set to the
        # default value.
        if module.params['fstab'] is not None:
            module.fail_json(
                msg=('OpenBSD does not support alternate fstab files. Do not '
                     'specify the fstab parameter for OpenBSD hosts'))
    else:
        cmd += _set_fstab_args(args['fstab'])

    cmd += [name]

    rc, out, err = module.run_command(cmd)

    if rc == 0:
        return 0, ''
    else:
        return rc, out + err
Ejemplo n.º 16
0
def main():

    module = AnsibleModule(argument_spec=dict(
        msg=dict(required=True),
        voice=dict(required=False),
    ),
                           supports_check_mode=True)

    msg = module.params['msg']
    voice = module.params['voice']
    possibles = ('say', 'espeak', 'espeak-ng')

    if get_platform() != 'Darwin':
        # 'say' binary available, it might be GNUstep tool which doesn't support 'voice' parameter
        voice = None

    for possible in possibles:
        executable = module.get_bin_path(possible)
        if executable:
            break
    else:
        module.fail_json(msg='Unable to find either %s' % ', '.join(possibles))

    if module.check_mode:
        module.exit_json(msg=msg, changed=False)

    say(module, executable, msg, voice)

    module.exit_json(msg=msg, changed=True)
Ejemplo n.º 17
0
    def __new__(cls, module):
        """Return the platform-specific subclass.

        It does not use load_platform_subclass() because it needs to judge based
        on whether the `timedatectl` command exists and is available.

        Args:
            module: The AnsibleModule.
        """
        if get_platform() == 'Linux':
            timedatectl = module.get_bin_path('timedatectl')
            if timedatectl is not None and module.run_command(timedatectl)[0] == 0:
                return super(Timezone, SystemdTimezone).__new__(SystemdTimezone)
            else:
                return super(Timezone, NosystemdTimezone).__new__(NosystemdTimezone)
        elif re.match('^joyent_.*Z', platform.version()):
            # get_platform() returns SunOS, which is too broad. So look at the
            # platform version instead. However we have to ensure that we're not
            # running in the global zone where changing the timezone has no effect.
            zonename_cmd = module.get_bin_path('zonename')
            if zonename_cmd is not None:
                (rc, stdout, _ ) = module.run_command(zonename_cmd)
                if rc == 0 and stdout.strip() == 'global':
                    module.fail_json(msg='Adjusting timezone is not supported in Global Zone')

            return super(Timezone, SmartOSTimezone).__new__(SmartOSTimezone)
        elif re.match('^(Free|Net|Open)BSD', platform.platform()):
            return super(Timezone, BSDTimezone).__new__(BSDTimezone)
        else:
            # Not supported yet
            return super(Timezone, Timezone).__new__(Timezone)
Ejemplo n.º 18
0
def main():
    module = AnsibleModule(argument_spec=dict(), )
    p = get_platform()
    if p in FW_VTABLE:
        f = FW_VTABLE[p](module)
        module.exit_json(changed=False, ansible_facts={'firewall': f})
    else:
        module.fail_json()
Ejemplo n.º 19
0
    def process(self):

        self.platform = get_platform().lower()

        # Whitespace is bad
        self.args['name'] = self.args['name'].strip()
        self.args['value'] = self._parse_value(self.args['value'])

        thisname = self.args['name']

        # get the current proc fs value
        self.proc_value = self.get_token_curr_value(thisname)

        # get the currect sysctl file value
        self.read_sysctl_file()
        if thisname not in self.file_values:
            self.file_values[thisname] = None

        # update file contents with desired token/value
        self.fix_lines()

        # what do we need to do now?
        if self.file_values[thisname] is None and self.args['state'] == "present":
            self.changed = True
            self.write_file = True
        elif self.file_values[thisname] is None and self.args['state'] == "absent":
            self.changed = False
        elif self.file_values[thisname] and self.args['state'] == "absent":
            self.changed = True
            self.write_file = True
        elif self.file_values[thisname] != self.args['value']:
            self.changed = True
            self.write_file = True
        # with reload=yes we should check if the current system values are
        # correct, so that we know if we should reload
        elif self.args['reload']:
            if self.proc_value is None:
                self.changed = True
            elif not self._values_is_equal(self.proc_value, self.args['value']):
                self.changed = True

        # use the sysctl command or not?
        if self.args['sysctl_set'] and self.args['state'] == "present":
            if self.proc_value is None:
                self.changed = True
            elif not self._values_is_equal(self.proc_value, self.args['value']):
                self.changed = True
                self.set_proc = True

        # Do the work
        if not self.module.check_mode:
            if self.write_file:
                self.write_sysctl()
            if self.changed and self.args['reload']:
                self.reload_sysctl()
            if self.set_proc:
                self.set_token_value(self.args['name'], self.args['value'])
Ejemplo n.º 20
0
 def unimplemented_error(self):
     platform = get_platform()
     distribution = get_distribution()
     if distribution is not None:
         msg_platform = '%s (%s)' % (platform, distribution)
     else:
         msg_platform = platform
     self.module.fail_json(
         msg='hostname module cannot be used on platform %s' % msg_platform)
Ejemplo n.º 21
0
 def unimplemented_error(self):
     platform = get_platform()
     distribution = get_distribution()
     if distribution is not None:
         msg_platform = '%s (%s)' % (platform, distribution)
     else:
         msg_platform = platform
     self.module.fail_json(
         msg='hostname module cannot be used on platform %s' % msg_platform)
Ejemplo n.º 22
0
def _set_fstab_args(args):
    result = []
    if 'fstab' in args and args['fstab'] != '/etc/fstab':
        if get_platform().lower().endswith('bsd'):
            result.append('-F')
        else:
            result.append('-T')
        result.append(args['fstab'])
    return result
Ejemplo n.º 23
0
def mount(module, **kwargs):
    """Mount up a path or remount if needed."""

    # solaris kwargs:
    #   name, src, fstype, opts, boot, passno, state, fstab=/etc/vfstab
    # linux kwargs:
    #   name, src, fstype, opts, dump, passno, state, fstab=/etc/fstab
    if get_platform() == 'SunOS':
        args = dict(
            opts='-',
            passno='-',
            fstab='/etc/vfstab',
            boot='yes'
        )
    else:
        args = dict(
            opts='default',
            dump='0',
            passno='0',
            fstab='/etc/fstab'
        )
    args.update(kwargs)

    mount_bin = module.get_bin_path('mount', required=True)
    name = kwargs['name']
    cmd = [mount_bin]

    if ismount(name):
        cmd += ['-o', 'remount']

    if get_platform().lower() == 'freebsd':
        cmd += ['-F', args['fstab']]
    elif get_platform().lower() == 'linux' and args['fstab'] != '/etc/fstab':
        cmd += ['-T', args['fstab']]

    cmd += [name]

    rc, out, err = module.run_command(cmd)

    if rc == 0:
        return 0, ''
    else:
        return rc, out+err
Ejemplo n.º 24
0
def is_bind_mounted(module, linux_mounts, dest, src=None, fstype=None):
    """Return whether the dest is bind mounted

    :arg module: The AnsibleModule (used for helper functions)
    :arg dest: The directory to be mounted under. This is the primary means
        of identifying whether the destination is mounted.
    :kwarg src: The source directory. If specified, this is used to help
        ensure that we are detecting that the correct source is mounted there.
    :kwarg fstype: The filesystem type. If specified this is also used to
        help ensure that we are detecting the right mount.
    :kwarg linux_mounts: Cached list of mounts for Linux.
    :returns: True if the dest is mounted with src otherwise False.
    """

    is_mounted = False

    if get_platform() == 'Linux' and linux_mounts is not None:
        if src is None:
            # That's for unmounted/absent
            for m in linux_mounts:
                if m['dst'] == dest:
                    is_mounted = True
        else:
            mounted_src = None

            for m in linux_mounts:
                if m['dst'] == dest:
                    mounted_src = m['src']

            # That's for mounted
            if mounted_src is not None and mounted_src == src:
                is_mounted = True
    else:
        bin_path = module.get_bin_path('mount', required=True)
        cmd = '%s -l' % bin_path
        rc, out, err = module.run_command(cmd)
        mounts = []

        if len(out):
            mounts = to_native(out).strip().split('\n')

        for mnt in mounts:
            arguments = mnt.split()

            if (
                    (arguments[0] == src or src is None) and
                    arguments[2] == dest and
                    (arguments[4] == fstype or fstype is None)):
                is_mounted = True

            if is_mounted:
                break

    return is_mounted
Ejemplo n.º 25
0
Archivo: at.py Proyecto: czi/ansible
def delete_job(module, result, at_cmd, command, script_file):
    for matching_job in get_matching_jobs(module, at_cmd, script_file):
        if get_platform() == 'AIX':
            at_command = "%s -r %s" % (at_cmd, matching_job)
        else:
            at_command = "%s -d %s" % (at_cmd, matching_job)
        rc, out, err = module.run_command(at_command, check_rc=True)
        result['changed'] = True
    if command:
        os.unlink(script_file)
    module.exit_json(**result)
Ejemplo n.º 26
0
def build_command(module,
                  mode,
                  path,
                  follow,
                  default,
                  recursive,
                  recalculate_mask,
                  entry=''):
    '''Builds and returns a getfacl/setfacl command.'''
    if mode == 'set':
        cmd = [module.get_bin_path('setfacl', True)]
        cmd.extend(['-m', entry])
    elif mode == 'rm':
        cmd = [module.get_bin_path('setfacl', True)]
        cmd.extend(['-x', entry])
    else:  # mode == 'get'
        cmd = [module.get_bin_path('getfacl', True)]
        # prevents absolute path warnings and removes headers
        if get_platform().lower() == 'linux':
            cmd.append('--omit-header')
            cmd.append('--absolute-names')

    if recursive:
        cmd.append('--recursive')

    if recalculate_mask == 'mask' and mode in ['set', 'rm']:
        cmd.append('--mask')
    elif recalculate_mask == 'no_mask' and mode in ['set', 'rm']:
        cmd.append('--no-mask')

    if not follow:
        if get_platform().lower() == 'linux':
            cmd.append('--physical')
        elif get_platform().lower() == 'freebsd':
            cmd.append('-h')

    if default:
        cmd.insert(1, '-d')

    cmd.append(path)
    return cmd
Ejemplo n.º 27
0
def acl_changed(module, cmd):
    '''Returns true if the provided command affects the existing ACLs, false otherwise.'''
    # FreeBSD do not have a --test flag, so by default, it is safer to always say "true"
    if get_platform().lower() == 'freebsd':
        return True

    cmd = cmd[:]  # lists are mutables so cmd would be overwritten without this
    cmd.insert(1, '--test')
    lines = run_acl(module, cmd)

    for line in lines:
        if not line.endswith('*,*'):
            return True
    return False
Ejemplo n.º 28
0
def acl_changed(module, cmd):
    '''Returns true if the provided command affects the existing ACLs, false otherwise.'''
    # FreeBSD do not have a --test flag, so by default, it is safer to always say "true"
    if get_platform().lower() == 'freebsd':
        return True

    cmd = cmd[:]  # lists are mutables so cmd would be overwritten without this
    cmd.insert(1, '--test')
    lines = run_acl(module, cmd)

    for line in lines:
        if not line.endswith('*,*'):
            return True
    return False
Ejemplo n.º 29
0
def remount(module, mount_bin, args):
    ''' will try to use -o remount first and fallback to unmount/mount if unsupported'''
    msg = ''
    cmd = [mount_bin]

    # multiplatform remount opts
    if get_platform().lower().endswith('bsd'):
        cmd += ['-u']
    else:
        cmd += ['-o', 'remount']

    cmd += _set_fstab_args(args)
    cmd += [
        args['name'],
    ]
    out = err = ''
    try:
        if get_platform().lower().endswith('bsd'):
            # Note: Forcing BSDs to do umount/mount due to BSD remount not
            # working as expected (suspect bug in the BSD mount command)
            # Interested contributor could rework this to use mount options on
            # the CLI instead of relying on fstab
            # https://github.com/ansible/ansible-modules-core/issues/5591
            rc = 1
        else:
            rc, out, err = module.run_command(cmd)
    except:
        rc = 1

    if rc != 0:
        msg = out + err
        if ismount(args['name']):
            rc, msg = umount(module, args['name'])
        if rc == 0:
            rc, msg = mount(module, args)
    return rc, msg
Ejemplo n.º 30
0
def mount(module, args):
    """Mount up a path or remount if needed."""

    mount_bin = module.get_bin_path('mount', required=True)
    name = args['name']
    cmd = [mount_bin]

    if ismount(name):
        cmd += ['-o', 'remount']

    if args['fstab'] != '/etc/fstab':
        if get_platform() == 'FreeBSD':
            cmd += ['-F', args['fstab']]
        elif get_platform() == 'Linux':
            cmd += ['-T', args['fstab']]

    cmd += [name]

    rc, out, err = module.run_command(cmd)

    if rc == 0:
        return 0, ''
    else:
        return rc, out+err
Ejemplo n.º 31
0
def mount(module, args):
    """Mount up a path or remount if needed."""

    mount_bin = module.get_bin_path('mount', required=True)
    name = args['name']
    cmd = [mount_bin]

    if ismount(name):
        cmd += ['-o', 'remount']

    if args['fstab'] != '/etc/fstab':
        if get_platform() == 'FreeBSD':
            cmd += ['-F', args['fstab']]
        elif get_platform() == 'Linux':
            cmd += ['-T', args['fstab']]

    cmd += [name]

    rc, out, err = module.run_command(cmd)

    if rc == 0:
        return 0, ''
    else:
        return rc, out + err
Ejemplo n.º 32
0
def is_bind_mounted(module, linux_mounts, dest, src=None, fstype=None):
    """Return whether the dest is bind mounted

    :arg module: The AnsibleModule (used for helper functions)
    :arg dest: The directory to be mounted under. This is the primary means
        of identifying whether the destination is mounted.
    :kwarg src: The source directory. If specified, this is used to help
        ensure that we are detecting that the correct source is mounted there.
    :kwarg fstype: The filesystem type. If specified this is also used to
        help ensure that we are detecting the right mount.
    :kwarg linux_mounts: Cached list of mounts for Linux.
    :returns: True if the dest is mounted with src otherwise False.
    """

    is_mounted = False

    if get_platform() == 'Linux' and linux_mounts is not None:
        if src is None:
            # That's for unmounted/absent
            if dest in linux_mounts:
                is_mounted = True
        else:
            # That's for mounted
            if dest in linux_mounts and linux_mounts[dest]['src'] == src:
                is_mounted = True
    else:
        bin_path = module.get_bin_path('mount', required=True)
        cmd = '%s -l' % bin_path
        rc, out, err = module.run_command(cmd)
        mounts = []

        if len(out):
            mounts = to_native(out).strip().split('\n')

        for mnt in mounts:
            arguments = mnt.split()

            if (
                    (arguments[0] == src or src is None) and
                    arguments[2] == dest and
                    (arguments[4] == fstype or fstype is None)):
                is_mounted = True

            if is_mounted:
                break

    return is_mounted
Ejemplo n.º 33
0
    def process(self):

        self.platform = get_platform().lower()

        # Whitespace is bad
        self.args['name'] = self.args['name'].strip()
        self.args['value'] = self._parse_value(self.args['value'])

        thisname = self.args['name']

        # get the current proc fs value
        self.proc_value = self.get_token_curr_value(thisname)

        # get the currect sysctl file value
        self.read_sysctl_file()
        if thisname not in self.file_values:
            self.file_values[thisname] = None

        # update file contents with desired token/value
        self.fix_lines()

        # what do we need to do now?
        if self.file_values[thisname] is None and self.args['state'] == "present":
            self.changed = True
            self.write_file = True
        elif self.file_values[thisname] is None and self.args['state'] == "absent":
            self.changed = False
        elif self.file_values[thisname] != self.args['value']:
            self.changed = True
            self.write_file = True

        # use the sysctl command or not?
        if self.args['sysctl_set']:
            if self.proc_value is None:
                self.changed = True
            elif not self._values_is_equal(self.proc_value, self.args['value']):
                self.changed = True
                self.set_proc = True

        # Do the work
        if not self.module.check_mode:
            if self.write_file:
                self.write_sysctl()
            if self.write_file and self.args['reload']:
                self.reload_sysctl()
            if self.set_proc:
                self.set_token_value(self.args['name'], self.args['value'])
Ejemplo n.º 34
0
    def __new__(cls, module):
        """Return the platform-specific subclass.

        It does not use load_platform_subclass() because it need to judge based
        on whether the `timedatectl` command exists.

        Args:
            module: The AnsibleModule.
        """
        if get_platform() == 'Linux':
            if module.get_bin_path('timedatectl') is not None:
                return super(Timezone, SystemdTimezone).__new__(SystemdTimezone)
            else:
                return super(Timezone, NosystemdTimezone).__new__(NosystemdTimezone)
        else:
            # Not supported yet
            return super(Timezone, Timezone).__new__(Timezone)
Ejemplo n.º 35
0
    def __new__(cls, module):
        """Return the platform-specific subclass.

        It does not use load_platform_subclass() because it need to judge based
        on whether the `timedatectl` command exists.

        Args:
            module: The AnsibleModule.
        """
        if get_platform() == 'Linux':
            if module.get_bin_path('timedatectl') is not None:
                return super(Timezone, SystemdTimezone).__new__(SystemdTimezone)
            else:
                return super(Timezone, NosystemdTimezone).__new__(NosystemdTimezone)
        else:
            # Not supported yet
            return super(Timezone, Timezone).__new__(Timezone)
Ejemplo n.º 36
0
class VFAT(Filesystem):
    if get_platform() == 'FreeBSD':
        MKFS = "newfs_msdos"
    else:
        MKFS = 'mkfs.vfat'
    GROW = 'fatresize'

    def get_fs_size(self, dev):
        cmd = self.module.get_bin_path(self.GROW, required=True)
        _, output, _ = self.module.run_command([cmd, '--info', str(dev)], check_rc=True)
        for line in output.splitlines()[1:]:
            param, value = line.split(':', 1)
            if param.strip() == 'Size':
                return int(value.strip())
        self.module.fail_json(msg="fatresize failed to provide filesystem size for %s" % dev)

    def grow_cmd(self, dev):
        cmd = self.module.get_bin_path(self.GROW)
        return [cmd, "-s", str(dev.size()), str(dev.path)]
Ejemplo n.º 37
0
    def __new__(cls, module):
        """Return the platform-specific subclass.

        It does not use load_platform_subclass() because it needs to judge based
        on whether the `timedatectl` command exists and is available.

        Args:
            module: The AnsibleModule.
        """
        if get_platform() == 'Linux':
            timedatectl = module.get_bin_path('timedatectl')
            if timedatectl is not None:
                rc, stdout, stderr = module.run_command(timedatectl)
                if rc == 0:
                    return super(Timezone, SystemdTimezone).__new__(SystemdTimezone)
                else:
                    module.warn('timedatectl command was found but not usable: %s. using other method.' % stderr)
                    return super(Timezone, NosystemdTimezone).__new__(NosystemdTimezone)
            else:
                return super(Timezone, NosystemdTimezone).__new__(NosystemdTimezone)
        elif re.match('^joyent_.*Z', platform.version()):
            # get_platform() returns SunOS, which is too broad. So look at the
            # platform version instead. However we have to ensure that we're not
            # running in the global zone where changing the timezone has no effect.
            zonename_cmd = module.get_bin_path('zonename')
            if zonename_cmd is not None:
                (rc, stdout, _) = module.run_command(zonename_cmd)
                if rc == 0 and stdout.strip() == 'global':
                    module.fail_json(msg='Adjusting timezone is not supported in Global Zone')

            return super(Timezone, SmartOSTimezone).__new__(SmartOSTimezone)
        elif re.match('^Darwin', platform.platform()):
            return super(Timezone, DarwinTimezone).__new__(DarwinTimezone)
        elif re.match('^(Free|Net|Open)BSD', platform.platform()):
            return super(Timezone, BSDTimezone).__new__(BSDTimezone)
        else:
            # Not supported yet
            return super(Timezone, Timezone).__new__(Timezone)
Ejemplo n.º 38
0
def main():
    # The following example playbooks:
    #
    # - cron: name="check dirs" hour="5,2" job="ls -alh > /dev/null"
    #
    # - name: do the job
    #   cron: name="do the job" hour="5,2" job="/some/dir/job.sh"
    #
    # - name: no job
    #   cron: name="an old job" state=absent
    #
    # - name: sets env
    #   cron: name="PATH" env=yes value="/bin:/usr/bin"
    #
    # Would produce:
    # PATH=/bin:/usr/bin
    # # Ansible: check dirs
    # * * 5,2 * * ls -alh > /dev/null
    # # Ansible: do the job
    # * * 5,2 * * /some/dir/job.sh

    module = AnsibleModule(
        argument_spec=dict(
            name=dict(type='str'),
            user=dict(type='str'),
            job=dict(type='str', aliases=['value']),
            cron_file=dict(type='str'),
            state=dict(type='str', default='present', choices=['present', 'absent']),
            backup=dict(type='bool', default=False),
            minute=dict(type='str', default='*'),
            hour=dict(type='str', default='*'),
            day=dict(type='str', default='*', aliases=['dom']),
            month=dict(type='str', default='*'),
            weekday=dict(type='str', default='*', aliases=['dow']),
            reboot=dict(type='bool', default=False),
            special_time=dict(type='str', choices=["reboot", "yearly", "annually", "monthly", "weekly", "daily", "hourly"]),
            disabled=dict(type='bool', default=False),
            env=dict(type='bool'),
            insertafter=dict(type='str'),
            insertbefore=dict(type='str'),
        ),
        supports_check_mode=True,
        mutually_exclusive=[
            ['reboot', 'special_time'],
            ['insertafter', 'insertbefore'],
        ],
    )

    name = module.params['name']
    user = module.params['user']
    job = module.params['job']
    cron_file = module.params['cron_file']
    state = module.params['state']
    backup = module.params['backup']
    minute = module.params['minute']
    hour = module.params['hour']
    day = module.params['day']
    month = module.params['month']
    weekday = module.params['weekday']
    reboot = module.params['reboot']
    special_time = module.params['special_time']
    disabled = module.params['disabled']
    env = module.params['env']
    insertafter = module.params['insertafter']
    insertbefore = module.params['insertbefore']
    do_install = state == 'present'

    changed = False
    res_args = dict()
    warnings = list()

    if cron_file:
        cron_file_basename = os.path.basename(cron_file)
        if not re.search(r'^[A-Z0-9_-]+$', cron_file_basename, re.I):
            warnings.append('Filename portion of cron_file ("%s") should consist' % cron_file_basename +
                            ' solely of upper- and lower-case letters, digits, underscores, and hyphens')

    # Ensure all files generated are only writable by the owning user.  Primarily relevant for the cron_file option.
    os.umask(int('022', 8))
    crontab = CronTab(module, user, cron_file)

    module.debug('cron instantiated - name: "%s"' % name)

    if module._diff:
        diff = dict()
        diff['before'] = crontab.existing
        if crontab.cron_file:
            diff['before_header'] = crontab.cron_file
        else:
            if crontab.user:
                diff['before_header'] = 'crontab for user "%s"' % crontab.user
            else:
                diff['before_header'] = 'crontab'

    # --- user input validation ---

    if (special_time or reboot) and \
       (True in [(x != '*') for x in [minute, hour, day, month, weekday]]):
        module.fail_json(msg="You must specify time and date fields or special time.")

    # cannot support special_time on solaris
    if (special_time or reboot) and get_platform() == 'SunOS':
        module.fail_json(msg="Solaris does not support special_time=... or @reboot")

    if cron_file and do_install:
        if not user:
            module.fail_json(msg="To use cron_file=... parameter you must specify user=... as well")

    if job is None and do_install:
        module.fail_json(msg="You must specify 'job' to install a new cron job or variable")

    if (insertafter or insertbefore) and not env and do_install:
        module.fail_json(msg="Insertafter and insertbefore parameters are valid only with env=yes")

    if reboot:
        special_time = "reboot"

    # if requested make a backup before making a change
    if backup and not module.check_mode:
        (backuph, backup_file) = tempfile.mkstemp(prefix='crontab')
        crontab.write(backup_file)

    if crontab.cron_file and not name and not do_install:
        if module._diff:
            diff['after'] = ''
            diff['after_header'] = '/dev/null'
        else:
            diff = dict()
        if module.check_mode:
            changed = os.path.isfile(crontab.cron_file)
        else:
            changed = crontab.remove_job_file()
        module.exit_json(changed=changed, cron_file=cron_file, state=state, diff=diff)

    if env:
        if ' ' in name:
            module.fail_json(msg="Invalid name for environment variable")
        decl = '%s="%s"' % (name, job)
        old_decl = crontab.find_env(name)

        if do_install:
            if len(old_decl) == 0:
                crontab.add_env(decl, insertafter, insertbefore)
                changed = True
            if len(old_decl) > 0 and old_decl[1] != decl:
                crontab.update_env(name, decl)
                changed = True
        else:
            if len(old_decl) > 0:
                crontab.remove_env(name)
                changed = True
    else:
        if do_install:
            for char in ['\r', '\n']:
                if char in job.strip('\r\n'):
                    warnings.append('Job should not contain line breaks')
                    break

            job = crontab.get_cron_job(minute, hour, day, month, weekday, job, special_time, disabled)
            old_job = crontab.find_job(name, job)

            if len(old_job) == 0:
                crontab.add_job(name, job)
                changed = True
            if len(old_job) > 0 and old_job[1] != job:
                crontab.update_job(name, job)
                changed = True
            if len(old_job) > 2:
                crontab.update_job(name, job)
                changed = True
        else:
            old_job = crontab.find_job(name)

            if len(old_job) > 0:
                crontab.remove_job(name)
                changed = True

    # no changes to env/job, but existing crontab needs a terminating newline
    if not changed and not crontab.existing == '':
        if not (crontab.existing.endswith('\r') or crontab.existing.endswith('\n')):
            changed = True

    res_args = dict(
        jobs=crontab.get_jobnames(),
        envs=crontab.get_envnames(),
        warnings=warnings,
        changed=changed
    )

    if changed:
        if not module.check_mode:
            crontab.write()
        if module._diff:
            diff['after'] = crontab.render()
            if crontab.cron_file:
                diff['after_header'] = crontab.cron_file
            else:
                if crontab.user:
                    diff['after_header'] = 'crontab for user "%s"' % crontab.user
                else:
                    diff['after_header'] = 'crontab'

            res_args['diff'] = diff

    # retain the backup only if crontab or cron file have changed
    if backup and not module.check_mode:
        if changed:
            res_args['backup_file'] = backup_file
        else:
            os.unlink(backup_file)

    if cron_file:
        res_args['cron_file'] = cron_file

    module.exit_json(**res_args)

    # --- should never get here
    module.exit_json(msg="Unable to execute cron task.")
Ejemplo n.º 39
0
 def test_module_utils_basic_get_platform(self):
     with patch('platform.system', return_value='foo'):
         from ansible.module_utils.basic import get_platform
         self.assertEqual(get_platform(), 'foo')
Ejemplo n.º 40
0
def main():
    module = AnsibleModule(
        argument_spec=dict(path=dict(type='path',
                                     required=True,
                                     aliases=['name']),
                           entry=dict(type='str'),
                           entity=dict(type='str', default=''),
                           etype=dict(
                               type='str',
                               choices=['group', 'mask', 'other', 'user'],
                           ),
                           permissions=dict(type='str'),
                           state=dict(
                               type='str',
                               default='query',
                               choices=['absent', 'present', 'query'],
                           ),
                           follow=dict(type='bool', default=True),
                           default=dict(type='bool', default=False),
                           recursive=dict(type='bool', default=False),
                           recalculate_mask=dict(
                               type='str',
                               default='default',
                               choices=['default', 'mask', 'no_mask'],
                           ),
                           use_nfsv4_acls=dict(type='bool', default=False)),
        supports_check_mode=True,
    )

    if get_platform().lower() not in ['linux', 'freebsd']:
        module.fail_json(msg="The acl module is not available on this system.")

    path = module.params.get('path')
    entry = module.params.get('entry')
    entity = module.params.get('entity')
    etype = module.params.get('etype')
    permissions = module.params.get('permissions')
    state = module.params.get('state')
    follow = module.params.get('follow')
    default = module.params.get('default')
    recursive = module.params.get('recursive')
    recalculate_mask = module.params.get('recalculate_mask')
    use_nfsv4_acls = module.params.get('use_nfsv4_acls')

    if not os.path.exists(path):
        module.fail_json(msg="Path not found or not accessible.")

    if state == 'query':
        if recursive:
            module.fail_json(
                msg="'recursive' MUST NOT be set when 'state=query'.")

        if recalculate_mask in ['mask', 'no_mask']:
            module.fail_json(
                msg=
                "'recalculate_mask' MUST NOT be set to 'mask' or 'no_mask' when 'state=query'."
            )

    if not entry:
        if state == 'absent' and permissions:
            module.fail_json(
                msg="'permissions' MUST NOT be set when 'state=absent'.")

        if state == 'absent' and not entity:
            module.fail_json(msg="'entity' MUST be set when 'state=absent'.")

        if state in ['present', 'absent'] and not etype:
            module.fail_json(msg="'etype' MUST be set when 'state=%s'." %
                             state)

    if entry:
        if etype or entity or permissions:
            module.fail_json(
                msg=
                "'entry' MUST NOT be set when 'entity', 'etype' or 'permissions' are set."
            )

        if state == 'present' and not entry.count(":") in [2, 3]:
            module.fail_json(
                msg=
                "'entry' MUST have 3 or 4 sections divided by ':' when 'state=present'."
            )

        if state == 'absent' and not entry.count(":") in [1, 2]:
            module.fail_json(
                msg=
                "'entry' MUST have 2 or 3 sections divided by ':' when 'state=absent'."
            )

        if state == 'query':
            module.fail_json(msg="'entry' MUST NOT be set when 'state=query'.")

        default_flag, etype, entity, permissions = split_entry(entry)
        if default_flag is not None:
            default = default_flag

    if get_platform().lower() == 'freebsd':
        if recursive:
            module.fail_json(
                msg="recursive is not supported on that platform.")

    changed = False
    msg = ""

    if state == 'present':
        entry = build_entry(etype, entity, permissions, use_nfsv4_acls)
        command = build_command(module, 'set', path, follow, default,
                                recursive, recalculate_mask, entry)
        changed = acl_changed(module, command)

        if changed and not module.check_mode:
            run_acl(module, command)
        msg = "%s is present" % entry

    elif state == 'absent':
        entry = build_entry(etype, entity, use_nfsv4_acls)
        command = build_command(module, 'rm', path, follow, default, recursive,
                                recalculate_mask, entry)
        changed = acl_changed(module, command)

        if changed and not module.check_mode:
            run_acl(module, command, False)
        msg = "%s is absent" % entry

    elif state == 'query':
        msg = "current acl"

    acl = run_acl(
        module,
        build_command(module, 'get', path, follow, default, recursive,
                      recalculate_mask))

    module.exit_json(changed=changed, msg=msg, acl=acl)
Ejemplo n.º 41
0
def test_get_platform():
    with patch('platform.system', return_value='foo'):
        assert get_platform() == 'foo'
Ejemplo n.º 42
0
def main():
    module = AnsibleModule(argument_spec=dict(
        boot=dict(default='yes', choices=['yes', 'no']),
        dump=dict(),
        fstab=dict(default='/etc/fstab'),
        fstype=dict(),
        name=dict(required=True, type='path'),
        opts=dict(),
        passno=dict(type='str'),
        src=dict(type='path'),
        state=dict(required=True,
                   choices=['present', 'absent', 'mounted', 'unmounted']),
    ),
                           supports_check_mode=True,
                           required_if=([
                               'state', 'mounted', ['src', 'fstype']
                           ], ['state', 'present', ['src', 'fstype']]))

    changed = False
    # solaris args:
    #   name, src, fstype, opts, boot, passno, state, fstab=/etc/vfstab
    # linux args:
    #   name, src, fstype, opts, dump, passno, state, fstab=/etc/fstab
    if get_platform() == 'SunOS':
        args = dict(name=module.params['name'],
                    opts='-',
                    passno='-',
                    fstab='/etc/vfstab',
                    boot='yes')
    else:
        args = dict(name=module.params['name'],
                    opts='defaults',
                    dump='0',
                    passno='0',
                    fstab='/etc/fstab')

    # FreeBSD doesn't have any 'default' so set 'rw' instead
    if get_platform() == 'FreeBSD':
        args['opts'] = 'rw'

    linux_mounts = []

    # Cache all mounts here in order we have consistent results if we need to
    # call is_bind_mouted() multiple times
    if get_platform() == 'Linux':
        linux_mounts = get_linux_mounts(module)

        if linux_mounts is None:
            args['warnings'] = ('Cannot open file /proc/self/mountinfo. '
                                'Bind mounts might be misinterpreted.')

    # Override defaults with user specified params
    for key in ('src', 'fstype', 'passno', 'opts', 'dump', 'fstab'):
        if module.params[key] is not None:
            args[key] = module.params[key]

    if get_platform() == 'SunOS' and args['fstab'] == '/etc/fstab':
        args['fstab'] = '/etc/vfstab'

    # If fstab file does not exist, we first need to create it. This mainly
    # happens when fstab option is passed to the module.
    if not os.path.exists(args['fstab']):
        if not os.path.exists(os.path.dirname(args['fstab'])):
            os.makedirs(os.path.dirname(args['fstab']))

        open(args['fstab'], 'a').close()

    # absent:
    #   Remove from fstab and unmounted.
    # unmounted:
    #   Do not change fstab state, but unmount.
    # present:
    #   Add to fstab, do not change mount state.
    # mounted:
    #   Add to fstab if not there and make sure it is mounted. If it has
    #   changed in fstab then remount it.

    state = module.params['state']
    name = module.params['name']

    if state == 'absent':
        name, changed = unset_mount(module, args)

        if changed and not module.check_mode:
            if ismount(name) or is_bind_mounted(module, linux_mounts, name):
                res, msg = umount(module, name)

                if res:
                    module.fail_json(msg="Error unmounting %s: %s" %
                                     (name, msg))

            if os.path.exists(name):
                try:
                    os.rmdir(name)
                except (OSError, IOError):
                    e = get_exception()
                    module.fail_json(msg="Error rmdir %s: %s" % (name, str(e)))
    elif state == 'unmounted':
        if ismount(name) or is_bind_mounted(module, linux_mounts, name):
            if not module.check_mode:
                res, msg = umount(module, name)

                if res:
                    module.fail_json(msg="Error unmounting %s: %s" %
                                     (name, msg))

            changed = True
    elif state == 'mounted':
        if not os.path.exists(name) and not module.check_mode:
            try:
                os.makedirs(name)
            except (OSError, IOError):
                e = get_exception()
                module.fail_json(msg="Error making dir %s: %s" %
                                 (name, str(e)))

        name, changed = set_mount(module, args)
        res = 0

        if ismount(name):
            if changed and not module.check_mode:
                res, msg = mount(module, args)
                changed = True
        elif 'bind' in args.get('opts', []):
            changed = True

            if is_bind_mounted(module, linux_mounts, name, args['src'],
                               args['fstype']):
                changed = False

            if changed and not module.check_mode:
                res, msg = mount(module, args)
        else:
            changed = True

            if not module.check_mode:
                res, msg = mount(module, args)

        if res:
            module.fail_json(msg="Error mounting %s: %s" % (name, msg))
    elif state == 'present':
        name, changed = set_mount(module, args)
    else:
        module.fail_json(msg='Unexpected position reached')

    module.exit_json(changed=changed, **args)
Ejemplo n.º 43
0
def set_mount(module, args):
    """Set/change a mount point location in fstab."""

    to_write = []
    exists = False
    changed = False
    escaped_args = dict([(k, _escape_fstab(v)) for k, v in iteritems(args)])
    new_line = '%(src)s %(name)s %(fstype)s %(opts)s %(dump)s %(passno)s\n'

    if get_platform() == 'SunOS':
        new_line = (
            '%(src)s - %(name)s %(fstype)s %(passno)s %(boot)s %(opts)s\n')

    for line in open(args['fstab'], 'r').readlines():
        if not line.strip():
            to_write.append(line)

            continue

        if line.strip().startswith('#'):
            to_write.append(line)

            continue

        # Check if we got a valid line for splitting
        if (
                get_platform() == 'SunOS' and len(line.split()) != 7 or
                get_platform() != 'SunOS' and len(line.split()) != 6):
            to_write.append(line)

            continue

        ld = {}

        if get_platform() == 'SunOS':
            (
                ld['src'],
                dash,
                ld['name'],
                ld['fstype'],
                ld['passno'],
                ld['boot'],
                ld['opts']
            ) = line.split()
        else:
            (
                ld['src'],
                ld['name'],
                ld['fstype'],
                ld['opts'],
                ld['dump'],
                ld['passno']
            ) = line.split()

        # Check if we found the correct line
        if ld['name'] != escaped_args['name']:
            to_write.append(line)

            continue

        # If we got here we found a match - let's check if there is any
        # difference
        exists = True
        args_to_check = ('src', 'fstype', 'opts', 'dump', 'passno')

        if get_platform() == 'SunOS':
            args_to_check = ('src', 'fstype', 'passno', 'boot', 'opts')

        for t in args_to_check:
            if ld[t] != escaped_args[t]:
                ld[t] = escaped_args[t]
                changed = True

        if changed:
            to_write.append(new_line % ld)
        else:
            to_write.append(line)

    if not exists:
        to_write.append(new_line % escaped_args)
        changed = True

    if changed and not module.check_mode:
        write_fstab(to_write, args['fstab'])

    return (args['name'], changed)
Ejemplo n.º 44
0
def main():
    module = AnsibleModule(
        argument_spec=dict(
            boot=dict(default='yes', choices=['yes', 'no']),
            dump=dict(),
            fstab=dict(default=None),
            fstype=dict(),
            name=dict(required=True, type='path'),
            opts=dict(),
            passno=dict(type='str'),
            src=dict(type='path'),
            state=dict(
                required=True,
                choices=['present', 'absent', 'mounted', 'unmounted']),
        ),
        supports_check_mode=True,
        required_if=(
            ['state', 'mounted', ['src', 'fstype']],
            ['state', 'present', ['src', 'fstype']]
        )
    )

    changed = False
    # solaris args:
    #   name, src, fstype, opts, boot, passno, state, fstab=/etc/vfstab
    # linux args:
    #   name, src, fstype, opts, dump, passno, state, fstab=/etc/fstab
    # Note: Do not modify module.params['fstab'] as we need to know if the user
    # explicitly specified it in mount() and remount()
    if get_platform().lower() == 'sunos':
        args = dict(
            name=module.params['name'],
            opts='-',
            passno='-',
            fstab=module.params['fstab'],
            boot='yes'
        )
        if args['fstab'] is None:
            args['fstab'] = '/etc/vfstab'
    else:
        args = dict(
            name=module.params['name'],
            opts='defaults',
            dump='0',
            passno='0',
            fstab=module.params['fstab']
        )
        if args['fstab'] is None:
            args['fstab'] = '/etc/fstab'

        # FreeBSD doesn't have any 'default' so set 'rw' instead
        if get_platform() == 'FreeBSD':
            args['opts'] = 'rw'

    linux_mounts = []

    # Cache all mounts here in order we have consistent results if we need to
    # call is_bind_mouted() multiple times
    if get_platform() == 'Linux':
        linux_mounts = get_linux_mounts(module)

        if linux_mounts is None:
            args['warnings'] = (
                'Cannot open file /proc/self/mountinfo. '
                'Bind mounts might be misinterpreted.')

    # Override defaults with user specified params
    for key in ('src', 'fstype', 'passno', 'opts', 'dump', 'fstab'):
        if module.params[key] is not None:
            args[key] = module.params[key]

    # If fstab file does not exist, we first need to create it. This mainly
    # happens when fstab option is passed to the module.
    if not os.path.exists(args['fstab']):
        if not os.path.exists(os.path.dirname(args['fstab'])):
            os.makedirs(os.path.dirname(args['fstab']))

        open(args['fstab'], 'a').close()

    # absent:
    #   Remove from fstab and unmounted.
    # unmounted:
    #   Do not change fstab state, but unmount.
    # present:
    #   Add to fstab, do not change mount state.
    # mounted:
    #   Add to fstab if not there and make sure it is mounted. If it has
    #   changed in fstab then remount it.

    state = module.params['state']
    name = module.params['name']

    if state == 'absent':
        name, changed = unset_mount(module, args)

        if changed and not module.check_mode:
            if ismount(name) or is_bind_mounted(module, linux_mounts, name):
                res, msg = umount(module, name)

                if res:
                    module.fail_json(
                        msg="Error unmounting %s: %s" % (name, msg))

            if os.path.exists(name):
                try:
                    os.rmdir(name)
                except (OSError, IOError):
                    e = get_exception()
                    module.fail_json(msg="Error rmdir %s: %s" % (name, str(e)))
    elif state == 'unmounted':
        if ismount(name) or is_bind_mounted(module, linux_mounts, name):
            if not module.check_mode:
                res, msg = umount(module, name)

                if res:
                    module.fail_json(
                        msg="Error unmounting %s: %s" % (name, msg))

            changed = True
    elif state == 'mounted':
        if not os.path.exists(name) and not module.check_mode:
            try:
                os.makedirs(name)
            except (OSError, IOError):
                e = get_exception()
                module.fail_json(
                    msg="Error making dir %s: %s" % (name, str(e)))

        name, changed = set_mount(module, args)
        res = 0

        if ismount(name):
            if changed and not module.check_mode:
                res, msg = mount(module, args)
                changed = True
        elif 'bind' in args.get('opts', []):
            changed = True

            if is_bind_mounted( module, linux_mounts, name, args['src'], args['fstype']):
                changed = False

            if changed and not module.check_mode:
                res, msg = mount(module, args)
        else:
            changed = True

            if not module.check_mode:
                res, msg = mount(module, args)

        if res:
            module.fail_json(msg="Error mounting %s: %s" % (name, msg))
    elif state == 'present':
        name, changed = set_mount(module, args)
    else:
        module.fail_json(msg='Unexpected position reached')

    module.exit_json(changed=changed, **args)
Ejemplo n.º 45
0
def main():
    module = AnsibleModule(
        argument_spec=dict(
            path=dict(required=True, aliases=['name'], type='path'),
            entry=dict(required=False, type='str'),
            entity=dict(required=False, type='str', default=''),
            etype=dict(
                required=False,
                choices=['other', 'user', 'group', 'mask'],
                type='str'
            ),
            permissions=dict(required=False, type='str'),
            state=dict(
                required=False,
                default='query',
                choices=['query', 'present', 'absent'],
                type='str'
            ),
            follow=dict(required=False, type='bool', default=True),
            default=dict(required=False, type='bool', default=False),
            recursive=dict(required=False, type='bool', default=False),
            use_nfsv4_acls=dict(required=False, type='bool', default=False)
        ),
        supports_check_mode=True,
    )

    if get_platform().lower() not in ['linux', 'freebsd']:
        module.fail_json(msg="The acl module is not available on this system.")

    path = module.params.get('path')
    entry = module.params.get('entry')
    entity = module.params.get('entity')
    etype = module.params.get('etype')
    permissions = module.params.get('permissions')
    state = module.params.get('state')
    follow = module.params.get('follow')
    default = module.params.get('default')
    recursive = module.params.get('recursive')
    use_nfsv4_acls = module.params.get('use_nfsv4_acls')

    if not os.path.exists(path):
        module.fail_json(msg="Path not found or not accessible.")

    if state == 'query' and recursive:
        module.fail_json(msg="'recursive' MUST NOT be set when 'state=query'.")

    if not entry:
        if state == 'absent' and permissions:
            module.fail_json(msg="'permissions' MUST NOT be set when 'state=absent'.")

        if state == 'absent' and not entity:
            module.fail_json(msg="'entity' MUST be set when 'state=absent'.")

        if state in ['present', 'absent'] and not etype:
            module.fail_json(msg="'etype' MUST be set when 'state=%s'." % state)

    if entry:
        if etype or entity or permissions:
            module.fail_json(msg="'entry' MUST NOT be set when 'entity', 'etype' or 'permissions' are set.")

        if state == 'present' and not entry.count(":") in [2, 3]:
            module.fail_json(msg="'entry' MUST have 3 or 4 sections divided by ':' when 'state=present'.")

        if state == 'absent' and not entry.count(":") in [1, 2]:
            module.fail_json(msg="'entry' MUST have 2 or 3 sections divided by ':' when 'state=absent'.")

        if state == 'query':
            module.fail_json(msg="'entry' MUST NOT be set when 'state=query'.")

        default_flag, etype, entity, permissions = split_entry(entry)
        if default_flag is not None:
            default = default_flag

    if get_platform().lower() == 'freebsd':
        if recursive:
            module.fail_json(msg="recursive is not supported on that platform.")

    changed = False
    msg = ""

    if state == 'present':
        entry = build_entry(etype, entity, permissions, use_nfsv4_acls)
        command = build_command(
            module, 'set', path, follow,
            default, recursive, entry
        )
        changed = acl_changed(module, command)

        if changed and not module.check_mode:
            run_acl(module, command)
        msg = "%s is present" % entry

    elif state == 'absent':
        entry = build_entry(etype, entity, use_nfsv4_acls)
        command = build_command(
            module, 'rm', path, follow,
            default, recursive, entry
        )
        changed = acl_changed(module, command)

        if changed and not module.check_mode:
            run_acl(module, command, False)
        msg = "%s is absent" % entry

    elif state == 'query':
        msg = "current acl"

    acl = run_acl(
        module,
        build_command(module, 'get', path, follow, default, recursive)
    )

    module.exit_json(changed=changed, msg=msg, acl=acl)
Ejemplo n.º 46
0
def set_mount(module, args):
    """Set/change a mount point location in fstab."""

    to_write = []
    exists = False
    changed = False
    escaped_args = dict([(k, _escape_fstab(v)) for k, v in iteritems(args)])
    new_line = '%(src)s %(name)s %(fstype)s %(opts)s %(dump)s %(passno)s\n'

    if get_platform() == 'SunOS':
        new_line = (
            '%(src)s - %(name)s %(fstype)s %(passno)s %(boot)s %(opts)s\n')

    for line in open(args['fstab'], 'r').readlines():
        if not line.strip():
            to_write.append(line)

            continue

        if line.strip().startswith('#'):
            to_write.append(line)

            continue

        # Check if we got a valid line for splitting
        if (get_platform() == 'SunOS' and len(line.split()) != 7
                or get_platform() != 'SunOS' and len(line.split()) != 6):
            to_write.append(line)

            continue

        ld = {}

        if get_platform() == 'SunOS':
            (ld['src'], dash, ld['name'], ld['fstype'], ld['passno'],
             ld['boot'], ld['opts']) = line.split()
        else:
            (ld['src'], ld['name'], ld['fstype'], ld['opts'], ld['dump'],
             ld['passno']) = line.split()

        # Check if we found the correct line
        if ld['name'] != escaped_args['name']:
            to_write.append(line)

            continue

        # If we got here we found a match - let's check if there is any
        # difference
        exists = True
        args_to_check = ('src', 'fstype', 'opts', 'dump', 'passno')

        if get_platform() == 'SunOS':
            args_to_check = ('src', 'fstype', 'passno', 'boot', 'opts')

        for t in args_to_check:
            if ld[t] != escaped_args[t]:
                ld[t] = escaped_args[t]
                changed = True

        if changed:
            to_write.append(new_line % ld)
        else:
            to_write.append(line)

    if not exists:
        to_write.append(new_line % escaped_args)
        changed = True

    if changed and not module.check_mode:
        write_fstab(to_write, args['fstab'])

    return (args['name'], changed)
Ejemplo n.º 47
0
 def test_module_utils_basic_get_platform(self):
     with patch('platform.system', return_value='foo'):
         from ansible.module_utils.basic import get_platform
         self.assertEqual(get_platform(), 'foo')
Ejemplo n.º 48
0
def main():
    # The following example playbooks:
    #
    # - cron: name="check dirs" hour="5,2" job="ls -alh > /dev/null"
    #
    # - name: do the job
    #   cron: name="do the job" hour="5,2" job="/some/dir/job.sh"
    #
    # - name: no job
    #   cron: name="an old job" state=absent
    #
    # - name: sets env
    #   cron: name="PATH" env=yes value="/bin:/usr/bin"
    #
    # Would produce:
    # PATH=/bin:/usr/bin
    # # Ansible: check dirs
    # * * 5,2 * * ls -alh > /dev/null
    # # Ansible: do the job
    # * * 5,2 * * /some/dir/job.sh

    module = AnsibleModule(argument_spec=dict(
        name=dict(required=False),
        user=dict(required=False),
        job=dict(required=False, aliases=['value']),
        cron_file=dict(required=False),
        state=dict(default='present', choices=['present', 'absent']),
        backup=dict(default=False, type='bool'),
        minute=dict(default='*'),
        hour=dict(default='*'),
        day=dict(aliases=['dom'], default='*'),
        month=dict(default='*'),
        weekday=dict(aliases=['dow'], default='*'),
        reboot=dict(required=False, default=False, type='bool'),
        special_time=dict(required=False,
                          default=None,
                          choices=[
                              "reboot", "yearly", "annually", "monthly",
                              "weekly", "daily", "hourly"
                          ],
                          type='str'),
        disabled=dict(default=False, type='bool'),
        env=dict(required=False, type='bool'),
        insertafter=dict(required=False),
        insertbefore=dict(required=False),
    ),
                           supports_check_mode=True,
                           mutually_exclusive=[
                               ['reboot', 'special_time'],
                               ['insertafter', 'insertbefore'],
                           ])

    name = module.params['name']
    user = module.params['user']
    job = module.params['job']
    cron_file = module.params['cron_file']
    state = module.params['state']
    backup = module.params['backup']
    minute = module.params['minute']
    hour = module.params['hour']
    day = module.params['day']
    month = module.params['month']
    weekday = module.params['weekday']
    reboot = module.params['reboot']
    special_time = module.params['special_time']
    disabled = module.params['disabled']
    env = module.params['env']
    insertafter = module.params['insertafter']
    insertbefore = module.params['insertbefore']
    do_install = state == 'present'

    changed = False
    res_args = dict()
    warnings = list()

    if cron_file:
        cron_file_basename = os.path.basename(cron_file)
        if not re.search(r'^[A-Z0-9_-]+$', cron_file_basename, re.I):
            warnings.append(
                'Filename portion of cron_file ("%s") should consist' %
                cron_file_basename +
                ' solely of upper- and lower-case letters, digits, underscores, and hyphens'
            )

    # Ensure all files generated are only writable by the owning user.  Primarily relevant for the cron_file option.
    os.umask(int('022', 8))
    crontab = CronTab(module, user, cron_file)

    module.debug('cron instantiated - name: "%s"' % name)

    if module._diff:
        diff = dict()
        diff['before'] = crontab.existing
        if crontab.cron_file:
            diff['before_header'] = crontab.cron_file
        else:
            if crontab.user:
                diff['before_header'] = 'crontab for user "%s"' % crontab.user
            else:
                diff['before_header'] = 'crontab'

    # --- user input validation ---

    if (special_time or reboot) and \
       (True in [(x != '*') for x in [minute, hour, day, month, weekday]]):
        module.fail_json(
            msg="You must specify time and date fields or special time.")

    # cannot support special_time on solaris
    if (special_time or reboot) and get_platform() == 'SunOS':
        module.fail_json(
            msg="Solaris does not support special_time=... or @reboot")

    if cron_file and do_install:
        if not user:
            module.fail_json(
                msg=
                "To use cron_file=... parameter you must specify user=... as well"
            )

    if job is None and do_install:
        module.fail_json(
            msg="You must specify 'job' to install a new cron job or variable")

    if (insertafter or insertbefore) and not env and do_install:
        module.fail_json(
            msg=
            "Insertafter and insertbefore parameters are valid only with env=yes"
        )

    if reboot:
        special_time = "reboot"

    # if requested make a backup before making a change
    if backup and not module.check_mode:
        (backuph, backup_file) = tempfile.mkstemp(prefix='crontab')
        crontab.write(backup_file)

    if crontab.cron_file and not name and not do_install:
        if module._diff:
            diff['after'] = ''
            diff['after_header'] = '/dev/null'
        else:
            diff = dict()
        if module.check_mode:
            changed = os.path.isfile(crontab.cron_file)
        else:
            changed = crontab.remove_job_file()
        module.exit_json(changed=changed,
                         cron_file=cron_file,
                         state=state,
                         diff=diff)

    if env:
        if ' ' in name:
            module.fail_json(msg="Invalid name for environment variable")
        decl = '%s="%s"' % (name, job)
        old_decl = crontab.find_env(name)

        if do_install:
            if len(old_decl) == 0:
                crontab.add_env(decl, insertafter, insertbefore)
                changed = True
            if len(old_decl) > 0 and old_decl[1] != decl:
                crontab.update_env(name, decl)
                changed = True
        else:
            if len(old_decl) > 0:
                crontab.remove_env(name)
                changed = True
    else:
        if do_install:
            for char in ['\r', '\n']:
                if char in job.strip('\r\n'):
                    warnings.append('Job should not contain line breaks')
                    break

            job = crontab.get_cron_job(minute, hour, day, month, weekday, job,
                                       special_time, disabled)
            old_job = crontab.find_job(name, job)

            if len(old_job) == 0:
                crontab.add_job(name, job)
                changed = True
            if len(old_job) > 0 and old_job[1] != job:
                crontab.update_job(name, job)
                changed = True
            if len(old_job) > 2:
                crontab.update_job(name, job)
                changed = True
        else:
            old_job = crontab.find_job(name)

            if len(old_job) > 0:
                crontab.remove_job(name)
                changed = True

    # no changes to env/job, but existing crontab needs a terminating newline
    if not changed and not crontab.existing == '':
        if not (crontab.existing.endswith('\r')
                or crontab.existing.endswith('\n')):
            changed = True

    res_args = dict(jobs=crontab.get_jobnames(),
                    envs=crontab.get_envnames(),
                    warnings=warnings,
                    changed=changed)

    if changed:
        if not module.check_mode:
            crontab.write()
        if module._diff:
            diff['after'] = crontab.render()
            if crontab.cron_file:
                diff['after_header'] = crontab.cron_file
            else:
                if crontab.user:
                    diff[
                        'after_header'] = 'crontab for user "%s"' % crontab.user
                else:
                    diff['after_header'] = 'crontab'

            res_args['diff'] = diff

    # retain the backup only if crontab or cron file have changed
    if backup and not module.check_mode:
        if changed:
            res_args['backup_file'] = backup_file
        else:
            os.unlink(backup_file)

    if cron_file:
        res_args['cron_file'] = cron_file

    module.exit_json(**res_args)

    # --- should never get here
    module.exit_json(msg="Unable to execute cron task.")