Example #1
0
def diff(params, cache_only=None):
    def is_utf8(in_string):
        """Returns true if input is a valid UTF-8 string, False otherwise."""
        if isinstance(in_string, UnicodeType):
            return True
        elif isinstance(in_string, StringType):
            if PY3:
                return True
            try:
                in_string.decode('utf-8')
                return True
            except UnicodeDecodeError:
                return False
        return False

    if cache_only:
        return (0, "no-ops for caching", {})

    action_type = 'configfiles.diff'
    if not _local_permission_check(action_type):
        log_to_file(0, "permissions error: " + str(action_type))
        return _perm_error(action_type)

    _init()
    files = params.get('files') or []
    fp = file_utils.FileProcessor()
    missing_files = []
    diffs = {}
    exists = hasattr(os.path, 'lexists') and os.path.lexists or os.path.exists
    for file in files:
        path = file['path']
        if not exists(path):
            missing_files.append(path)
            continue

        diff = fp.diff(file)
        if diff:
            diffs[path] = diff

    extras = {}
    if missing_files:
        extras['missing_files'] = missing_files

    if diffs:
        for file in diffs.keys():
            if not is_utf8(diffs[file]):
                diffs[file] = "%s: binary files differ" % file
        extras['diffs'] = diffs

    log_to_file(
        0, "Files successfully compared: %s %s" %
        (format_file_string(files, create_key_list()), str(extras)))
    return 0, "Files successfully compared", extras
Example #2
0
def diff(params, cache_only=None):
    def is_utf8(in_string):
        """Returns true if input is a valid UTF-8 string, False otherwise."""
        if isinstance(in_string, UnicodeType):
            return True
        elif isinstance(in_string, StringType):
            try:
                in_string.decode('utf-8')
                return True
            except UnicodeDecodeError:
                return False
        return False

    if cache_only:
        return (0, "no-ops for caching", {})

    action_type = 'configfiles.diff'
    if not _local_permission_check(action_type):
        log_to_file(0, "permissions error: " + str(action_type))
        return _perm_error(action_type)

    _init()
    files = params.get('files') or []
    fp = file_utils.FileProcessor()
    missing_files = []
    diffs = {}
    exists = hasattr(os.path, 'lexists') and os.path.lexists or os.path.exists
    for file in files:
        path = file['path']
        if not exists(path):
            missing_files.append(path)
            continue

        diff = fp.diff(file)
        if diff:
            diffs[path] = diff

    extras = {}
    if missing_files:
        extras['missing_files'] = missing_files

    if diffs:
        for file in diffs.keys():
            if not is_utf8(diffs[file]):
                diffs[file] = "%s: binary files differ" % file
        extras['diffs'] = diffs

    log_to_file(0, "Files successfully diffed: %s %s" % (format_file_string(files, create_key_list()), str(extras)))
    return 0, "Files successfully diffed", extras
Example #3
0
def mtime_upload(action_id, params, cache_only=None):
    if cache_only:
        return (0, "no-ops for caching", {})

    action_type = 'configfiles.mtime_upload'
    if not _local_permission_check(action_type):
        log_to_file(0, "permissions error: " + str(action_type))
        return _perm_error(action_type)

    _init()

    file_matches = []
    now = time.time()
    upload_contents = None
    ignore_dirs = {'/proc': None, '/dev': None}

    if params['info']['import_contents'] == 'Y':
        upload_contents = 1

    for to_ignore in params['ignore']:
        ignore_dirs[utils.normalize_path(to_ignore)] = 1

    for search_path in params['search']:
        for dirname, dirs, names in os.walk(utils.normalize_path(search_path)):
            _visit_dir(
                {
                    'matches': file_matches,
                    'info': params['info'],
                    'ignore': ignore_dirs,
                    'now': now,
                }, dirname, names)

    if not file_matches:
        return 0, "No files found", {}

    r = rpc_cli_repository.ClientRepository()
    result = r.put_files(action_id,
                         file_matches,
                         upload_contents=upload_contents)

    formatted_result = format_result(result, file_matches)
    log_to_file(0, formatted_result)
    return formatted_result
Example #4
0
def upload(action_id, params, cache_only=None):
    if cache_only:
        return (0, "no-ops for caching", {})

    action_type = 'configfiles.upload'
    if not _local_permission_check(action_type):
        log_to_file(0, "permissions error: " + str(action_type))
        return _perm_error(action_type)

    _init()

    files = params or []

    r = rpc_cli_repository.ClientRepository()
    result = r.put_files(action_id, files)

    formatted_result = format_result(result, files)
    log_to_file(0, formatted_result)

    return formatted_result
Example #5
0
def upload(action_id, params, cache_only=None):
    if cache_only:
        return (0, "no-ops for caching", {})

    action_type = 'configfiles.upload'
    if not _local_permission_check(action_type):
        log_to_file(0, "permissions error: " + str(action_type))
        return _perm_error(action_type)

    _init()

    files = params or []

    r = rpc_cli_repository.ClientRepository()
    result = r.put_files(action_id, files)

    formatted_result = format_result(result, files)
    log_to_file(0, formatted_result)

    return formatted_result
Example #6
0
def deploy(params, topdir=None, cache_only=None):
    if cache_only:
        return (0, "no-ops for caching", {})

    action_type = 'configfiles.deploy'
    if not _local_permission_check(action_type):
        log_to_file(0, "permissions error: " + str(action_type))
        return _perm_error(action_type)

    _init()
    files = params.get('files') or []
    dep_trans = DeployTransaction(transaction_root=topdir, auto_rollback=0)

    for file in files:
        dep_trans.add(file)

    try:
        dep_trans.deploy()
    #5/3/05 wregglej - 135415 Adding stuff for missing user info
    except cfg_exceptions.UserNotFound, e:
            try:
                dep_trans.rollback()
            except FailedRollback:
                log_to_file(0, "Failed deployment and rollback, information on user '%s' could not be found" % (e[0], ))
                return (44, "Failed deployment and rollback, information on user '%s' could not be found" % (e[0], ), {})
            #5/3/05 wregglej - 136415 Adding some more exceptions to handle
            except cfg_exceptions.UserNotFound, f:
                log_to_file(0, "Failed deployment and rollback, information on user '%s' could not be found" % (f[0], ))
                return (50, "Failed deployment and rollback, information on user '%s' could not be found" % (f[0], ), {})
Example #7
0
def mtime_upload(action_id, params, cache_only=None):
    if cache_only:
        return (0, "no-ops for caching", {})

    action_type = 'configfiles.mtime_upload'
    if not _local_permission_check(action_type):
        log_to_file(0, "permissions error: " + str(action_type))
        return _perm_error(action_type)

    _init()

    file_matches = []
    now = time.time()
    upload_contents = None
    ignore_dirs = {'/proc':None, '/dev':None}

    if params['info']['import_contents'] == 'Y':
        upload_contents = 1

    for to_ignore in params['ignore']:
        ignore_dirs[utils.normalize_path(to_ignore)] = 1

    for search_path in params['search']:
        for dirname, dirs, names in os.walk(utils.normalize_path(search_path)):
             _visit_dir({
                'matches' : file_matches,
                'info' : params['info'],
                'ignore' : ignore_dirs,
                'now' : now,
                }, dirname, names)

    if not file_matches:
        return 0, "No files found", {}

    r = rpc_cli_repository.ClientRepository()
    result = r.put_files(action_id, file_matches, upload_contents=upload_contents)

    formatted_result = format_result(result, file_matches)
    log_to_file(0, formatted_result)
    return formatted_result
Example #8
0
def deploy(params, topdir=None, cache_only=None):
    if cache_only:
        return (0, "no-ops for caching", {})

    action_type = 'configfiles.deploy'
    if not _local_permission_check(action_type):
        log_to_file(0, "permissions error: " + str(action_type))
        return _perm_error(action_type)

    _init()
    files = params.get('files') or []
    dep_trans = DeployTransaction(transaction_root=topdir, auto_rollback=0)

    for file in files:
        dep_trans.add(file)

    try:
        dep_trans.deploy()
    #5/3/05 wregglej - 135415 Adding stuff for missing user info
    except cfg_exceptions.UserNotFound, e:
            try:
                dep_trans.rollback()
            except FailedRollback:
                log_to_file(0, "Failed deployment and rollback, information on user '%s' could not be found" % (e[0], ))
                return (44, "Failed deployment and rollback, information on user '%s' could not be found" % (e[0], ), {})
            #5/3/05 wregglej - 136415 Adding some more exceptions to handle
            except cfg_exceptions.UserNotFound, f:
                log_to_file(0, "Failed deployment and rollback, information on user '%s' could not be found" % (f[0], ))
                return (50, "Failed deployment and rollback, information on user '%s' could not be found" % (f[0], ), {})
Example #9
0
def diff(params, cache_only=None):
    if cache_only:
        return (0, "no-ops for caching", {})

    action_type = 'configfiles.diff'
    if not _local_permission_check(action_type):
        log_to_file(0, "permissions error: " + str(action_type))
        return _perm_error(action_type)

    _init()
    files = params.get('files') or []
    fp = file_utils.FileProcessor()
    missing_files = []
    diffs = {}
    exists = hasattr(os.path, 'lexists') and os.path.lexists or os.path.exists
    for file in files:
        path = file['path']
        if not exists(path):
            missing_files.append(path)
            continue
        if os.path.isdir(path):
            # We dont support dir diffs, ignore
            continue

        diff = fp.diff(file)
        diffs[path] = diff

    extras = {}
    if missing_files:
        extras['missing_files'] = missing_files
    
    if diffs:
        extras['diffs'] = diffs

    log_to_file(0, "Files successfully diffed: %s %s" % (format_file_string(files, create_key_list()), str(extras)))
    return 0, "Files successfully diffed", extras
Example #10
0
    os.close(pipe_read)

    # wait for the child to complete
    (somepid, exit_status) = os.waitpid(child_pid, 0)
    process_end = time.time()

    # Copy the output from the temporary file
    out_stream.seek(0, 0)
    extras['output'] = out_stream.read()
    out_stream.close()

    # Log script-output locally, unless we're asked not to
    if log_output:
        set_logfile(logfile_name)
        log_to_file(0, extras['output'])

    # since output can contain chars that won't make xmlrpc very happy,
    # base64 encode it...
    extras['base64enc'] = 1
    extras['output'] = base64.encodestring(extras['output'])

    extras['return_code'] = exit_status

    # calculate start and end times in db's timespace
    extras['process_start'] = db_now + (process_start - now)
    extras['process_end'] = db_now + (process_end - now)

    for key in ('process_start', 'process_end'):
        extras[key] = time.strftime("%Y-%m-%d %H:%M:%S",
                                    time.localtime(extras[key]))
Example #11
0
             "Failed deployment and rollback, information on user '%s' could not be found"
             % (e[0], ), {})
     #5/3/05 wregglej - 136415 Adding some more exceptions to handle
     except cfg_exceptions.UserNotFound, f:
         log_to_file(
             0,
             "Failed deployment and rollback, information on user '%s' could not be found"
             % (f[0], ))
         return (
             50,
             "Failed deployment and rollback, information on user '%s' could not be found"
             % (f[0], ), {})
     #5/5/05 wregglej - 136415 Adding exception handling for unknown group,
     except cfg_exceptions.GroupNotFound, f:
         log_to_file(
             0,
             "Failed deployment and rollback, group '%s' could not be found"
             % (f[0], ))
         return (
             51,
             "Failed deployment and rollback, group '%s' could not be found"
             % (f[0], ), {})
     else:
         log_to_file(
             0,
             "Failed deployment and rollback, information on user '%s' could not be found"
             % (e[0], ))
         return (
             50,
             "Failed deployment and rollback, information on user '%s' could not be found"
             % (e[0], ), {})
 except cfg_exceptions.GroupNotFound, e:
Example #12
0
 try:
     dep_trans.deploy()
 #5/3/05 wregglej - 135415 Adding stuff for missing user info
 except cfg_exceptions.UserNotFound, e:
         try:
             dep_trans.rollback()
         except FailedRollback:
             log_to_file(0, "Failed deployment and rollback, information on user '%s' could not be found" % (e[0], ))
             return (44, "Failed deployment and rollback, information on user '%s' could not be found" % (e[0], ), {})
         #5/3/05 wregglej - 136415 Adding some more exceptions to handle
         except cfg_exceptions.UserNotFound, f:
             log_to_file(0, "Failed deployment and rollback, information on user '%s' could not be found" % (f[0], ))
             return (50, "Failed deployment and rollback, information on user '%s' could not be found" % (f[0], ), {})
         #5/5/05 wregglej - 136415 Adding exception handling for unknown group,
         except cfg_exceptions.GroupNotFound, f:
             log_to_file(0, "Failed deployment and rollback, group '%s' could not be found" % (f[0],))
             return (51, "Failed deployment and rollback, group '%s' could not be found" % (f[0],), {})
         else:
             log_to_file(0, "Failed deployment and rollback, information on user '%s' could not be found" % (e[0], ))
             return (50, "Failed deployment and rollback, information on user '%s' could not be found" % (e[0], ), {})
 except cfg_exceptions.GroupNotFound, e:
         try:
             dep_trans.rollback()
         except FailedRollback:
             log_to_file(0, "Failed deployment and rollback, information on user '%s' could not be found" % (e[0], ))
             return (44, "Failed deployment and rollback, information on user '%s' could not be found" % (e[0], ), {})
         #5/3/05 wregglej - 136415 Adding some more exceptions to handle
         except cfg_exceptions.UserNotFound, f:
             log_to_file(0, "Failed deployment and rollback, information on user '%s' could not be found" % (f[0], ) )
             return (50, "Failed deployment and rollback, information on user '%s' could not be found" % (f[0], ), {})
         #5/5/05 wregglej - 136415 Adding exception handling for unknown group,
Example #13
0
def run(action_id, params, cache_only=None):

    cfg = config.initUp2dateConfig()
    local_config.init('rhncfg-client', defaults=dict(cfg.items()))

    tempfile.tempdir = local_config.get('script_tmp_dir')

    logfile_name = local_config.get('script_log_file')
    log_output = local_config.get('script_log_file_enable')

    if log_output:
        # If we're going to log, make sure we can create the logfile
        _create_path(logfile_name)

    if cache_only:
        return (0, "no-ops for caching", {})

    action_type = 'script.run'
    if not _local_permission_check(action_type):
        return _perm_error(action_type)

    extras = {'output': ''}
    script = params.get('script')
    if not script:
        return (1, "No script to execute", {})

    username = params.get('username')
    groupname = params.get('groupname')

    if not username:
        return (1, "No username given to execute script as", {})

    if not groupname:
        return (1, "No groupname given to execute script as", {})

    timeout = params.get('timeout')

    if timeout:
        try:
            timeout = int(timeout)
        except ValueError:
            return (1, "Invalid timeout value", {})
    else:
        timeout = None

    db_now = params.get('now')
    if not db_now:
        return (1, "'now' argument missing", {})
    db_now = time.mktime(time.strptime(db_now, "%Y-%m-%d %H:%M:%S"))

    now = time.time()
    process_start = None
    process_end = None

    child_pid = None

    # determine uid/ugid for script ownership, uid also used for setuid...
    try:
        user_record = pwd.getpwnam(username)
    except KeyError:
        return 1, "No such user %s" % username, extras

    uid = user_record[2]
    ugid = user_record[3]

    # create the script on disk
    try:
        script_path = _create_script_file(script, uid=uid, gid=ugid)
    except OSError:
        e = sys.exc_info()[1]
        return 1, "Problem creating script file:  %s" % e, extras

    # determine gid to run script as
    try:
        group_record = grp.getgrnam(groupname)
    except KeyError:
        return 1, "No such group %s" % groupname, extras

    run_as_gid = group_record[2]

    # create some pipes to communicate w/ the child process
    (pipe_read, pipe_write) = os.pipe()

    process_start = time.time()
    child_pid = os.fork()

    if not child_pid:
        # Parent doesn't write to child, so close that part
        os.close(pipe_read)

        # Redirect both stdout and stderr to the pipe
        os.dup2(pipe_write, sys.stdout.fileno())
        os.dup2(pipe_write, sys.stderr.fileno())

        # Close unnecessary file descriptors (including pipe since it's duped)
        for i in range(3, MAXFD):
            try:
                os.close(i)
            except:
                pass

        # all scripts initial working directory will be /
        # puts burden on script writer to ensure cwd is correct within the
        # script
        os.chdir('/')

        # the child process gets the desired uid/gid
        os.setgid(run_as_gid)
        groups = [
            g.gr_gid for g in grp.getgrall()
            if username in g.gr_mem or username in g.gr_name
        ]
        os.setgroups(groups)
        os.setuid(uid)

        # give this its own process group (which happens to be equal to its
        # pid)
        os.setpgrp()

        # Finally, exec the script
        try:
            os.umask(int("022", 8))
            os.execv(script_path, [
                script_path,
            ])
        finally:
            # This code can be reached only when script_path can not be
            # executed as otherwise execv never returns.
            # (The umask syscall always succeeds.)
            os._exit(1)

    # Parent doesn't write to child, so close that part
    os.close(pipe_write)

    output = None
    timed_out = None

    out_stream = tempfile.TemporaryFile()

    while 1:
        select_wait = None

        if timeout:
            elapsed = time.time() - process_start

            if elapsed >= timeout:
                timed_out = 1
                # Send TERM to all processes in the child's process group
                # Send KILL after that, just to make sure the child died
                os.kill(-child_pid, signal.SIGTERM)
                time.sleep(2)
                os.kill(-child_pid, signal.SIGKILL)
                break

            select_wait = timeout - elapsed

        # XXX try-except here for interrupted system calls
        input_fds, output_fds, error_fds = select.select([pipe_read], [], [],
                                                         select_wait)

        if error_fds:
            # when would this happen?
            os.close(pipe_read)
            return 1, "Fatal exceptional case", extras

        if not (pipe_read in input_fds):
            # Read timed out, should be caught in the next loop
            continue

        output = os.read(pipe_read, 4096)
        if not output:
            # End of file from the child
            break

        out_stream.write(output)

    os.close(pipe_read)

    # wait for the child to complete
    (somepid, exit_status) = os.waitpid(child_pid, 0)
    process_end = time.time()

    # Copy the output from the temporary file
    out_stream.seek(0, 0)
    extras['output'] = out_stream.read()
    out_stream.close()

    # Log script-output locally, unless we're asked not to
    if log_output:
        set_logfile(logfile_name)
        log_to_file(0, extras['output'])

    # since output can contain chars that won't make xmlrpc very happy,
    # base64 encode it...
    extras['base64enc'] = 1
    extras['output'] = base64.encodestring(extras['output'])

    extras['return_code'] = exit_status

    # calculate start and end times in db's timespace
    extras['process_start'] = db_now + (process_start - now)
    extras['process_end'] = db_now + (process_end - now)

    for key in ('process_start', 'process_end'):
        extras[key] = time.strftime("%Y-%m-%d %H:%M:%S",
                                    time.localtime(extras[key]))

    # clean up the script
    os.unlink(script_path)

    if timed_out:
        return 1, "Script killed, timeout of %s seconds exceeded" % timeout, extras

    if exit_status == 0:
        return 0, "Script executed", extras

    return 1, "Script failed", extras
Example #14
0
    os.close(pipe_read)

    # wait for the child to complete
    (somepid, exit_status) = os.waitpid(child_pid, 0)
    process_end = time.time()

    # Copy the output from the temporary file
    out_stream.seek(0, 0)
    extras['output'] = out_stream.read()
    out_stream.close()

    # Log script-output locally, unless we're asked not to
    if log_output :
        set_logfile(logfile_name)
        log_to_file(0, extras['output'])

    # since output can contain chars that won't make xmlrpc very happy,
    # base64 encode it...
    extras['base64enc'] = 1
    extras['output'] = base64.encodestring(extras['output'])

    extras['return_code'] = exit_status

    # calculate start and end times in db's timespace
    extras['process_start'] = db_now + (process_start - now)
    extras['process_end'] = db_now + (process_end - now)

    for key in ('process_start', 'process_end'):
        extras[key] = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(extras[key]))
Example #15
0
def deploy(params, topdir=None, cache_only=None):
    if cache_only:
        return (0, "no-ops for caching", {})

    action_type = 'configfiles.deploy'
    if not _local_permission_check(action_type):
        log_to_file(0, "permissions error: " + str(action_type))
        return _perm_error(action_type)

    _init()
    files = params.get('files') or []
    dep_trans = DeployTransaction(transaction_root=topdir, auto_rollback=0)

    for file in files:
        dep_trans.add(file)

    try:
        dep_trans.deploy()
    #5/3/05 wregglej - 135415 Adding stuff for missing user info
    except cfg_exceptions.UserNotFound:
            e = sys.exc_info()[1]
            try:
                dep_trans.rollback()
            except FailedRollback:
                log_to_file(0, "Failed deployment and rollback, information on user '%s' could not be found" % (e[0], ))
                return (44, "Failed deployment and rollback, information on user '%s' could not be found" % (e[0], ), {})
            #5/3/05 wregglej - 136415 Adding some more exceptions to handle
            except cfg_exceptions.UserNotFound:
                f = sys.exc_info()[1]
                log_to_file(0, "Failed deployment and rollback, information on user '%s' could not be found" % (f[0], ))
                return (50, "Failed deployment and rollback, information on user '%s' could not be found" % (f[0], ), {})
            #5/5/05 wregglej - 136415 Adding exception handling for unknown group,
            except cfg_exceptions.GroupNotFound:
                f = sys.exc_info()[1]
                log_to_file(0, "Failed deployment and rollback, group '%s' could not be found" % (f[0],))
                return (51, "Failed deployment and rollback, group '%s' could not be found" % (f[0],), {})
            else:
                log_to_file(0, "Failed deployment and rollback, information on user '%s' could not be found" % (e[0], ))
                return (50, "Failed deployment and rollback, information on user '%s' could not be found" % (e[0], ), {})
    except cfg_exceptions.GroupNotFound:
            e = sys.exc_info()[1]
            try:
                dep_trans.rollback()
            except FailedRollback:
                log_to_file(0, "Failed deployment and rollback, information on user '%s' could not be found" % (e[0], ))
                return (44, "Failed deployment and rollback, information on user '%s' could not be found" % (e[0], ), {})
            #5/3/05 wregglej - 136415 Adding some more exceptions to handle
            except cfg_exceptions.UserNotFound:
                f = sys.exc_info()[1]
                log_to_file(0, "Failed deployment and rollback, information on user '%s' could not be found" % (f[0], ) )
                return (50, "Failed deployment and rollback, information on user '%s' could not be found" % (f[0], ), {})
            #5/5/05 wregglej - 136415 Adding exception handling for unknown group,
            except cfg_exceptions.GroupNotFound:
                f = sys.exc_info()[1]
                log_to_file(0, "Failed deployment and rollback, group '%s' could not be found" % (f[0],))
                return (51, "Failed deployment and rollback, group '%s' could not be found" % (f[0],), {})
            else:
                log_to_file(0, "Failed deployment and rollback, group '%s' could not be found" % (e[0], ))
                return (51, "Failed deployment and rollback, group '%s' could not be found" % (e[0], ), {})
    except cfg_exceptions.FileEntryIsDirectory:
            e = sys.exc_info()[1]
            try:
                dep_trans.rollback()
            except FailedRollback:
                log_to_file(0, "Failed deployment and rollback, %s already exists as a directory" % (e[0], ))
                return (44, "Failed deployment and rollback, %s already exists as a directory" % (e[0], ), {})
            #5/3/05 wregglej - 136415 Adding some more exceptions to handle
            except cfg_exceptions.UserNotFound:
                f = sys.exc_info()[1]
                log_to_file(0, "Failed deployment and rollback, information on user '%s' could not be found" % (f[0], ))
                return (50, "Failed deployment and rollback, information on user '%s' could not be found" % (f[0], ), {})
            #5/5/05 wregglej - 136415 Adding exception handling for unknown group,
            except cfg_exceptions.GroupNotFound:
                f = sys.exc_info()[1]
                log_to_file(0, "Failed deployment and rollback, group '%s' could not be found" % (f[0],))
                return (51, "Failed deployment and rollback, group '%s' could not be found" % (f[0],), {})
            else:
                log_to_file(0, "Failed deployment, %s already exists as a directory" % (e[0], ))
                return (45, "Failed deployment, %s already exists as a directory" % (e[0], ), {})
    except cfg_exceptions.DirectoryEntryIsFile:
            e = sys.exc_info()[1]
            try:
                dep_trans.rollback()
            except FailedRollback:
                log_to_file(0, "Failed deployment and rollback, %s already exists as a file" % (e[0], ))
                return (46, "Failed deployment and rollback, %s already exists as a file" % (e[0], ), {})
            #5/3/05 wregglej - 136415 Adding exceptions for missing user
            except cfg_exceptions.UserNotFound:
                f = sys.exc_info()[1]
                log_to_file(0, "Failed deployment and rollback, information on user '%s' could not be found" % (f[0], ))
                return (50, "Failed deployment and rollback, information on user '%s' could not be found" % (f[0], ), {})
            #5/5/05 wregglej - 136415 Adding exception handling for unknown group,
            except cfg_exceptions.GroupNotFound:
                f = sys.exc_info()[1]
                log_to_file(0, "Failed deployment and rollback, group '%s' could not be found" % (f[0],))
                return (51, "Failed deployment and rollback, group '%s' could not be found" % (f[0],), {})
            else:
                log_to_file(0, "Failed deployment, %s already exists as a file" % (e[0], ))
                return (47, "Failed deployment, %s already exists as a file" % (e[0], ), {})

    except Exception:
        e = sys.exc_info()[1]
        print(e)
        try:
            dep_trans.rollback()
        except FailedRollback:
            e2 = sys.exc_info()[1]
            log_to_file(0, "Failed deployment, failed rollback:  %s" % e2)
            return (48, "Failed deployment, failed rollback:  %s" % e2, {})
        #5/3/05 wregglej - 135415 Add exception handling for missing user.
        except cfg_exceptions.UserNotFound:
            f = sys.exc_info()[1]
            log_to_file(0, "Failed deployment and rollback, information on user '%s' could not be found" % (f[0]))
            return (50, "Failed deployment and rollback, information on user '%s' could not be found" % (f[0]), {})
        #5/5/05 wregglej - 136415 Adding exception handling for unknown group,
        except cfg_exceptions.GroupNotFound:
            f = sys.exc_info()[1]
            log_to_file(0, "Failed deployment and rollback, group '%s' could not be found" % (f[0],))
            return (51, "Failed deployment and rollback, group '%s' could not be found" % (f[0],), {})
        else:
            log_to_file(0, "Failed deployment, rolled back:  %s" % e)
            return (49, "Failed deployment, rolled back:  %s" % e, {})

    extras = {}
    log_to_file(0, "Files successfully deployed: %s %s" % (format_file_string(files, create_key_list()), str(extras)))
    return 0, "Files successfully deployed", extras
Example #16
0
def deploy(params, topdir=None, cache_only=None):
    if cache_only:
        return (0, "no-ops for caching", {})

    action_type = 'configfiles.deploy'
    if not _local_permission_check(action_type):
        log_to_file(0, "permissions error: " + str(action_type))
        return _perm_error(action_type)

    _init()
    files = params.get('files') or []
    dep_trans = DeployTransaction(transaction_root=topdir, auto_rollback=0)

    for file in files:
        dep_trans.add(file)

    try:
        dep_trans.deploy()
    #5/3/05 wregglej - 135415 Adding stuff for missing user info
    except cfg_exceptions.UserNotFound:
        e = sys.exc_info()[1]
        try:
            dep_trans.rollback()
        except FailedRollback:
            log_to_file(
                0,
                "Failed deployment and rollback, information on user '%s' could not be found"
                % (e[0], ))
            return (
                44,
                "Failed deployment and rollback, information on user '%s' could not be found"
                % (e[0], ), {})
        #5/3/05 wregglej - 136415 Adding some more exceptions to handle
        except cfg_exceptions.UserNotFound:
            f = sys.exc_info()[1]
            log_to_file(
                0,
                "Failed deployment and rollback, information on user '%s' could not be found"
                % (f[0], ))
            return (
                50,
                "Failed deployment and rollback, information on user '%s' could not be found"
                % (f[0], ), {})
        #5/5/05 wregglej - 136415 Adding exception handling for unknown group,
        except cfg_exceptions.GroupNotFound:
            f = sys.exc_info()[1]
            log_to_file(
                0,
                "Failed deployment and rollback, group '%s' could not be found"
                % (f[0], ))
            return (
                51,
                "Failed deployment and rollback, group '%s' could not be found"
                % (f[0], ), {})
        else:
            log_to_file(
                0,
                "Failed deployment and rollback, information on user '%s' could not be found"
                % (e[0], ))
            return (
                50,
                "Failed deployment and rollback, information on user '%s' could not be found"
                % (e[0], ), {})
    except cfg_exceptions.GroupNotFound:
        e = sys.exc_info()[1]
        try:
            dep_trans.rollback()
        except FailedRollback:
            log_to_file(
                0,
                "Failed deployment and rollback, information on user '%s' could not be found"
                % (e[0], ))
            return (
                44,
                "Failed deployment and rollback, information on user '%s' could not be found"
                % (e[0], ), {})
        #5/3/05 wregglej - 136415 Adding some more exceptions to handle
        except cfg_exceptions.UserNotFound:
            f = sys.exc_info()[1]
            log_to_file(
                0,
                "Failed deployment and rollback, information on user '%s' could not be found"
                % (f[0], ))
            return (
                50,
                "Failed deployment and rollback, information on user '%s' could not be found"
                % (f[0], ), {})
        #5/5/05 wregglej - 136415 Adding exception handling for unknown group,
        except cfg_exceptions.GroupNotFound:
            f = sys.exc_info()[1]
            log_to_file(
                0,
                "Failed deployment and rollback, group '%s' could not be found"
                % (f[0], ))
            return (
                51,
                "Failed deployment and rollback, group '%s' could not be found"
                % (f[0], ), {})
        else:
            log_to_file(
                0,
                "Failed deployment and rollback, group '%s' could not be found"
                % (e[0], ))
            return (
                51,
                "Failed deployment and rollback, group '%s' could not be found"
                % (e[0], ), {})
    except cfg_exceptions.FileEntryIsDirectory:
        e = sys.exc_info()[1]
        try:
            dep_trans.rollback()
        except FailedRollback:
            log_to_file(
                0,
                "Failed deployment and rollback, %s already exists as a directory"
                % (e[0], ))
            return (
                44,
                "Failed deployment and rollback, %s already exists as a directory"
                % (e[0], ), {})
        #5/3/05 wregglej - 136415 Adding some more exceptions to handle
        except cfg_exceptions.UserNotFound:
            f = sys.exc_info()[1]
            log_to_file(
                0,
                "Failed deployment and rollback, information on user '%s' could not be found"
                % (f[0], ))
            return (
                50,
                "Failed deployment and rollback, information on user '%s' could not be found"
                % (f[0], ), {})
        #5/5/05 wregglej - 136415 Adding exception handling for unknown group,
        except cfg_exceptions.GroupNotFound:
            f = sys.exc_info()[1]
            log_to_file(
                0,
                "Failed deployment and rollback, group '%s' could not be found"
                % (f[0], ))
            return (
                51,
                "Failed deployment and rollback, group '%s' could not be found"
                % (f[0], ), {})
        else:
            log_to_file(
                0, "Failed deployment, %s already exists as a directory" %
                (e[0], ))
            return (45, "Failed deployment, %s already exists as a directory" %
                    (e[0], ), {})
    except cfg_exceptions.DirectoryEntryIsFile:
        e = sys.exc_info()[1]
        try:
            dep_trans.rollback()
        except FailedRollback:
            log_to_file(
                0,
                "Failed deployment and rollback, %s already exists as a file" %
                (e[0], ))
            return (
                46,
                "Failed deployment and rollback, %s already exists as a file" %
                (e[0], ), {})
        #5/3/05 wregglej - 136415 Adding exceptions for missing user
        except cfg_exceptions.UserNotFound:
            f = sys.exc_info()[1]
            log_to_file(
                0,
                "Failed deployment and rollback, information on user '%s' could not be found"
                % (f[0], ))
            return (
                50,
                "Failed deployment and rollback, information on user '%s' could not be found"
                % (f[0], ), {})
        #5/5/05 wregglej - 136415 Adding exception handling for unknown group,
        except cfg_exceptions.GroupNotFound:
            f = sys.exc_info()[1]
            log_to_file(
                0,
                "Failed deployment and rollback, group '%s' could not be found"
                % (f[0], ))
            return (
                51,
                "Failed deployment and rollback, group '%s' could not be found"
                % (f[0], ), {})
        else:
            log_to_file(
                0, "Failed deployment, %s already exists as a file" % (e[0], ))
            return (47, "Failed deployment, %s already exists as a file" %
                    (e[0], ), {})

    except Exception:
        e = sys.exc_info()[1]
        print(e)
        try:
            dep_trans.rollback()
        except FailedRollback:
            e2 = sys.exc_info()[1]
            log_to_file(0, "Failed deployment, failed rollback:  %s" % e2)
            return (48, "Failed deployment, failed rollback:  %s" % e2, {})
        #5/3/05 wregglej - 135415 Add exception handling for missing user.
        except cfg_exceptions.UserNotFound:
            f = sys.exc_info()[1]
            log_to_file(
                0,
                "Failed deployment and rollback, information on user '%s' could not be found"
                % (f[0]))
            return (
                50,
                "Failed deployment and rollback, information on user '%s' could not be found"
                % (f[0]), {})
        #5/5/05 wregglej - 136415 Adding exception handling for unknown group,
        except cfg_exceptions.GroupNotFound:
            f = sys.exc_info()[1]
            log_to_file(
                0,
                "Failed deployment and rollback, group '%s' could not be found"
                % (f[0], ))
            return (
                51,
                "Failed deployment and rollback, group '%s' could not be found"
                % (f[0], ), {})
        else:
            log_to_file(0, "Failed deployment, rolled back:  %s" % e)
            return (49, "Failed deployment, rolled back:  %s" % e, {})

    extras = {}
    log_to_file(
        0, "Files successfully deployed: %s %s" %
        (format_file_string(files, create_key_list()), str(extras)))
    return 0, "Files successfully deployed", extras
Example #17
0
def run(action_id, params, cache_only=None):

    cfg = config.initUp2dateConfig()
    local_config.init('rhncfg-client', defaults=dict(cfg.items()))

    tempfile.tempdir = local_config.get('script_tmp_dir')

    logfile_name = local_config.get('script_log_file')
    log_output = local_config.get('script_log_file_enable')

    if log_output:
        # If we're going to log, make sure we can create the logfile
        _create_path(logfile_name)

    if cache_only:
        return (0, "no-ops for caching", {})

    action_type = 'script.run'
    if not _local_permission_check(action_type):
        return _perm_error(action_type)


    extras = {'output':''}
    script = params.get('script')
    if not script:
        return (1, "No script to execute", {})

    username = params.get('username')
    groupname = params.get('groupname')

    if not username:
        return (1, "No username given to execute script as", {})

    if not groupname:
        return (1, "No groupname given to execute script as", {})

    timeout = params.get('timeout')

    if timeout:
        try:
            timeout = int(timeout)
        except ValueError:
            return (1, "Invalid timeout value", {})
    else:
        timeout = None

    db_now = params.get('now')
    if not db_now:
        return (1, "'now' argument missing", {})
    db_now = time.mktime(time.strptime(db_now, "%Y-%m-%d %H:%M:%S"))

    now = time.time()
    process_start = None
    process_end = None

    child_pid = None

    # determine uid/ugid for script ownership, uid also used for setuid...
    try:
        user_record = pwd.getpwnam(username)
    except KeyError:
        return 1, "No such user %s" % username, extras

    uid = user_record[2]
    ugid = user_record[3]


    # create the script on disk
    try:
        script_path = _create_script_file(script, uid=uid, gid=ugid)
    except OSError:
        e = sys.exc_info()[1]
        return 1, "Problem creating script file:  %s" % e, extras

    # determine gid to run script as
    try:
        group_record = grp.getgrnam(groupname)
    except KeyError:
        return 1, "No such group %s" % groupname, extras

    run_as_gid = group_record[2]


    # create some pipes to communicate w/ the child process
    (pipe_read, pipe_write) = os.pipe()

    process_start = time.time()
    child_pid = os.fork()

    if not child_pid:
        # Parent doesn't write to child, so close that part
        os.close(pipe_read)

        # Redirect both stdout and stderr to the pipe
        os.dup2(pipe_write, sys.stdout.fileno())
        os.dup2(pipe_write, sys.stderr.fileno())

        # Close unnecessary file descriptors (including pipe since it's duped)
        for i in range(3, MAXFD):
            try:
                os.close(i)
            except:
                pass

        # all scripts initial working directory will be /
        # puts burden on script writer to ensure cwd is correct within the
        # script
        os.chdir('/')

        # the child process gets the desired uid/gid
        os.setgid(run_as_gid)
        groups=[g.gr_gid for g in grp.getgrall() if username in g.gr_mem or username in g.gr_name]
        os.setgroups(groups)
        os.setuid(uid)

        # give this its own process group (which happens to be equal to its
        # pid)
        os.setpgrp()

        clean_env = {"PATH": "/sbin:/bin:/usr/sbin:/usr/bin", "TERM": "xterm"}
        # Finally, exec the script
        try:
            os.umask(int("022", 8))
            os.execve(script_path, [script_path, ], clean_env)
        finally:
            # This code can be reached only when script_path can not be
            # executed as otherwise execv never returns.
            # (The umask syscall always succeeds.)
            os._exit(1)

    # Parent doesn't write to child, so close that part
    os.close(pipe_write)

    output = None
    timed_out = None

    out_stream = open('/var/lib/up2date/action.%s' % str(action_id), 'ab+', 0)

    while 1:
        select_wait = None

        if timeout:
            elapsed = time.time() - process_start

            if elapsed >= timeout:
                timed_out = 1
                # Send TERM to all processes in the child's process group
                # Send KILL after that, just to make sure the child died
                os.kill(-child_pid, signal.SIGTERM)
                time.sleep(2)
                os.kill(-child_pid, signal.SIGKILL)
                break

            select_wait = timeout - elapsed

        try:
            input_fds, output_fds, error_fds = select.select([pipe_read], [], [], select_wait)
        except select.error:
            return 255, "Termination signal occurred during execution.", {}

        if error_fds:
            # when would this happen?
            os.close(pipe_read)
            return 1, "Fatal exceptional case", extras

        if not (pipe_read in input_fds):
            # Read timed out, should be caught in the next loop
            continue

        output = os.read(pipe_read, 4096)
        if not output:
            # End of file from the child
            break

        out_stream.write(output)

    os.close(pipe_read)

    # wait for the child to complete
    (somepid, exit_status) = os.waitpid(child_pid, 0)
    process_end = time.time()

    # Copy the output from the temporary file
    out_stream.seek(0, 0)
    extras['output'] = out_stream.read()
    out_stream.close()

    # Log script-output locally, unless we're asked not to
    if log_output :
        set_logfile(logfile_name)
        log_to_file(0, extras['output'])

    # since output can contain chars that won't make xmlrpc very happy,
    # base64 encode it...
    extras['base64enc'] = 1
    extras['output'] = base64.encodestring(extras['output'])

    extras['return_code'] = exit_status

    # calculate start and end times in db's timespace
    extras['process_start'] = db_now + (process_start - now)
    extras['process_end'] = db_now + (process_end - now)

    for key in ('process_start', 'process_end'):
        extras[key] = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(extras[key]))

    # clean up the script
    os.unlink(script_path)

    if timed_out:
        return 1, "Script killed, timeout of %s seconds exceeded" % timeout, extras

    if exit_status == 0:
        return 0, "Script executed", extras

    return 1, "Script failed", extras