Blame geo-replication/syncdaemon/subcmds.py

Packit Service e080da
# -*- coding: utf-8 -*-
Packit Service e080da
#
Packit Service e080da
#  Copyright (c) 2016 Red Hat, Inc. <http://www.redhat.com>
Packit Service e080da
#  This file is part of GlusterFS.
Packit Service e080da
#
Packit Service e080da
#  This file is licensed to you under your choice of the GNU Lesser
Packit Service e080da
#  General Public License, version 3 or any later version (LGPLv3 or
Packit Service e080da
#  later), or the GNU General Public License, version 2 (GPLv2), in all
Packit Service e080da
#  cases as published by the Free Software Foundation.
Packit Service e080da
#
Packit Service e080da
Packit Service e080da
from __future__ import print_function
Packit Service e080da
from syncdutils import lf
Packit Service e080da
import logging
Packit Service e080da
import gsyncdconfig as gconf
Packit Service e080da
Packit Service e080da
Packit Service e080da
ERROR_CONFIG_INVALID = 2
Packit Service e080da
ERROR_CONFIG_INVALID_VALUE = 3
Packit Service e080da
ERROR_CONFIG_NOT_CONFIGURABLE = 4
Packit Service e080da
Packit Service e080da
Packit Service e080da
def subcmd_monitor_status(args):
Packit Service e080da
    from gsyncdstatus import set_monitor_status
Packit Service e080da
    from rconf import rconf
Packit Service e080da
Packit Service e080da
    set_monitor_status(gconf.get("state-file"), args.status)
Packit Service e080da
    rconf.log_exit = False
Packit Service e080da
    logging.info(lf("Monitor Status Change", status=args.status))
Packit Service e080da
Packit Service e080da
Packit Service e080da
def subcmd_status(args):
Packit Service e080da
    from gsyncdstatus import GeorepStatus
Packit Service e080da
Packit Service e080da
    master_name = args.master.replace(":", "")
Packit Service e080da
    slave_data = args.slave.replace("ssh://", "")
Packit Service e080da
Packit Service e080da
    brick_status = GeorepStatus(gconf.get("state-file"),
Packit Service e080da
                                "",
Packit Service e080da
                                args.local_path,
Packit Service e080da
                                "",
Packit Service e080da
                                master_name,
Packit Service e080da
                                slave_data,
Packit Service e080da
                                gconf.get("pid-file"))
Packit Service e080da
    checkpoint_time = gconf.get("checkpoint", 0)
Packit Service e080da
    brick_status.print_status(checkpoint_time=checkpoint_time,
Packit Service e080da
                              json_output=args.json)
Packit Service e080da
Packit Service e080da
Packit Service e080da
def subcmd_monitor(args):
Packit Service e080da
    import monitor
Packit Service e080da
    from resource import GLUSTER, SSH, Popen
Packit Service e080da
    go_daemon = False if args.debug else True
Packit Service e080da
Packit Service e080da
    monitor.startup(go_daemon)
Packit Service e080da
    Popen.init_errhandler()
Packit Service e080da
    local = GLUSTER("localhost", args.master)
Packit Service e080da
    slavehost, slavevol = args.slave.split("::")
Packit Service e080da
    remote = SSH(slavehost, slavevol)
Packit Service e080da
    return monitor.monitor(local, remote)
Packit Service e080da
Packit Service e080da
Packit Service e080da
def subcmd_verify_spawning(args):
Packit Service e080da
    logging.info("Able to spawn gsyncd.py")
Packit Service e080da
Packit Service e080da
Packit Service e080da
def subcmd_worker(args):
Packit Service e080da
    import os
Packit Service e080da
    import fcntl
Packit Service e080da
Packit Service e080da
    from resource import GLUSTER, SSH, Popen
Packit Service e080da
Packit Service e080da
    Popen.init_errhandler()
Packit Service e080da
    fcntl.fcntl(args.feedback_fd, fcntl.F_SETFD, fcntl.FD_CLOEXEC)
Packit Service e080da
    local = GLUSTER("localhost", args.master)
Packit Service a90fdc
    slave_url, slavevol = args.slave.split("::")
Packit Service a90fdc
    if "@" not in slave_url:
Packit Service a90fdc
        slavehost = args.resource_remote
Packit Service a90fdc
    else:
Packit Service a90fdc
        slavehost = "%s@%s" % (slave_url.split("@")[0], args.resource_remote)
Packit Service e080da
    remote = SSH(slavehost, slavevol)
Packit Service e080da
    remote.connect_remote()
Packit Service e080da
    local.connect()
Packit Service e080da
    logging.info("Worker spawn successful. Acknowledging back to monitor")
Packit Service e080da
    os.close(args.feedback_fd)
Packit Service e080da
    local.service_loop(remote)
Packit Service e080da
Packit Service e080da
Packit Service e080da
def subcmd_slave(args):
Packit Service e080da
    from resource import GLUSTER, Popen
Packit Service e080da
Packit Service e080da
    Popen.init_errhandler()
Packit Service e080da
    slavevol = args.slave.split("::")[-1]
Packit Service e080da
    local = GLUSTER("localhost", slavevol)
Packit Service e080da
Packit Service e080da
    local.connect()
Packit Service e080da
    local.service_loop()
Packit Service e080da
Packit Service e080da
Packit Service e080da
def subcmd_agent(args):
Packit Service e080da
    import os
Packit Service e080da
    from changelogagent import agent, Changelog
Packit Service e080da
    from syncdutils import lf
Packit Service e080da
Packit Service e080da
    os.setsid()
Packit Service e080da
    logging.debug(lf("RPC FD",
Packit Service e080da
                     rpc_fd=repr(args.rpc_fd)))
Packit Service e080da
    return agent(Changelog(), args.rpc_fd)
Packit Service e080da
Packit Service e080da
Packit Service e080da
def subcmd_voluuidget(args):
Packit Service e080da
    from subprocess import Popen, PIPE
Packit Service e080da
    import xml.etree.ElementTree as XET
Packit Service e080da
Packit Service e080da
    ParseError = XET.ParseError if hasattr(XET, 'ParseError') else SyntaxError
Packit Service e080da
Packit Service a90fdc
    cmd = ['gluster', '--xml', '--remote-host=' + args.host,
Packit Service a90fdc
           'volume', 'info', args.volname]
Packit Service a90fdc
Packit Service a90fdc
    if args.inet6:
Packit Service a90fdc
        cmd.append("--inet6")
Packit Service a90fdc
Packit Service a90fdc
    po = Popen(cmd, bufsize=0,
Packit Service e080da
               stdin=None, stdout=PIPE, stderr=PIPE,
Packit Service e080da
               universal_newlines=True)
Packit Service e080da
Packit Service e080da
    vix, err = po.communicate()
Packit Service e080da
    if po.returncode != 0:
Packit Service e080da
        logging.info(lf("Volume info failed, unable to get "
Packit Service e080da
                        "volume uuid of slavevol, "
Packit Service e080da
                        "returning empty string",
Packit Service e080da
                        slavevol=args.volname,
Packit Service e080da
                        slavehost=args.host,
Packit Service e080da
                        error=po.returncode))
Packit Service e080da
        return ""
Packit Service e080da
    vi = XET.fromstring(vix)
Packit Service e080da
    if vi.find('opRet').text != '0':
Packit Service e080da
        logging.info(lf("Unable to get volume uuid of slavevol, "
Packit Service e080da
                        "returning empty string",
Packit Service e080da
                        slavevol=args.volname,
Packit Service e080da
                        slavehost=args.host,
Packit Service e080da
                        error=vi.find('opErrstr').text))
Packit Service e080da
        return ""
Packit Service e080da
Packit Service e080da
    try:
Packit Service e080da
        voluuid = vi.find("volInfo/volumes/volume/id").text
Packit Service e080da
    except (ParseError, AttributeError, ValueError) as e:
Packit Service e080da
        logging.info(lf("Parsing failed to volume uuid of slavevol, "
Packit Service e080da
                        "returning empty string",
Packit Service e080da
                        slavevol=args.volname,
Packit Service e080da
                        slavehost=args.host,
Packit Service e080da
                        error=e))
Packit Service e080da
        voluuid = ""
Packit Service e080da
Packit Service e080da
    print(voluuid)
Packit Service e080da
Packit Service e080da
Packit Service e080da
def _unlink(path):
Packit Service e080da
    import os
Packit Service e080da
    from errno import ENOENT
Packit Service e080da
    from syncdutils import GsyncdError
Packit Service e080da
    import sys
Packit Service e080da
Packit Service e080da
    try:
Packit Service e080da
        os.unlink(path)
Packit Service e080da
    except (OSError, IOError):
Packit Service e080da
        if sys.exc_info()[1].errno == ENOENT:
Packit Service e080da
            pass
Packit Service e080da
        else:
Packit Service e080da
            raise GsyncdError('Unlink error: %s' % path)
Packit Service e080da
Packit Service e080da
Packit Service e080da
def subcmd_delete(args):
Packit Service e080da
    import logging
Packit Service e080da
    import shutil
Packit Service e080da
    import glob
Packit Service e080da
    import sys
Packit Service e080da
    from errno import ENOENT, ENODATA
Packit Service e080da
    import struct
Packit Service e080da
Packit Service e080da
    from syncdutils import GsyncdError, Xattr, errno_wrap
Packit Service e080da
    import gsyncdconfig as gconf
Packit Service e080da
Packit Service e080da
    logging.info('geo-replication delete')
Packit Service e080da
    # remove the stime xattr from all the brick paths so that
Packit Service e080da
    # a re-create of a session will start sync all over again
Packit Service e080da
    stime_xattr_prefix = gconf.get('stime-xattr-prefix', None)
Packit Service e080da
Packit Service e080da
    # Delete pid file, status file, socket file
Packit Service e080da
    cleanup_paths = []
Packit Service e080da
    cleanup_paths.append(gconf.get("pid-file"))
Packit Service e080da
Packit Service e080da
    # Cleanup Session dir
Packit Service e080da
    try:
Packit Service e080da
        shutil.rmtree(gconf.get("georep-session-working-dir"))
Packit Service e080da
    except (IOError, OSError):
Packit Service e080da
        if sys.exc_info()[1].errno == ENOENT:
Packit Service e080da
            pass
Packit Service e080da
        else:
Packit Service e080da
            raise GsyncdError(
Packit Service e080da
                'Error while removing working dir: %s' %
Packit Service e080da
                gconf.get("georep-session-working-dir"))
Packit Service e080da
Packit Service e080da
    # Cleanup changelog working dirs
Packit Service e080da
    try:
Packit Service e080da
        shutil.rmtree(gconf.get("working-dir"))
Packit Service e080da
    except (IOError, OSError):
Packit Service e080da
        if sys.exc_info()[1].errno == ENOENT:
Packit Service e080da
            pass
Packit Service e080da
        else:
Packit Service e080da
            raise GsyncdError(
Packit Service e080da
                'Error while removing working dir: %s' %
Packit Service e080da
                gconf.get("working-dir"))
Packit Service e080da
Packit Service e080da
    for path in cleanup_paths:
Packit Service e080da
        # To delete temp files
Packit Service e080da
        for f in glob.glob(path + "*"):
Packit Service e080da
            _unlink(f)
Packit Service e080da
Packit Service e080da
    if args.reset_sync_time and stime_xattr_prefix:
Packit Service e080da
        for p in args.paths:
Packit Service e080da
            if p != "":
Packit Service e080da
                # set stime to (0,0) to trigger full volume content resync
Packit Service e080da
                # to slave on session recreation
Packit Service e080da
                # look at master.py::Xcrawl   hint: zero_zero
Packit Service e080da
                errno_wrap(Xattr.lsetxattr,
Packit Service e080da
                           (p, stime_xattr_prefix + ".stime",
Packit Service e080da
                            struct.pack("!II", 0, 0)),
Packit Service e080da
                           [ENOENT, ENODATA])
Packit Service e080da
                errno_wrap(Xattr.lremovexattr,
Packit Service e080da
                           (p, stime_xattr_prefix + ".entry_stime"),
Packit Service e080da
                           [ENOENT, ENODATA])
Packit Service e080da
Packit Service e080da
    return
Packit Service e080da
Packit Service e080da
Packit Service e080da
def print_config(name, value, only_value=False, use_underscore=False):
Packit Service e080da
    val = value
Packit Service e080da
    if isinstance(value, bool):
Packit Service e080da
        val = str(value).lower()
Packit Service e080da
Packit Service e080da
    if only_value:
Packit Service e080da
        print(val)
Packit Service e080da
    else:
Packit Service e080da
        if use_underscore:
Packit Service e080da
            name = name.replace("-", "_")
Packit Service e080da
Packit Service e080da
        print(("%s:%s" % (name, val)))
Packit Service e080da
Packit Service e080da
Packit Service e080da
def config_name_format(val):
Packit Service e080da
    return val.replace("_", "-")
Packit Service e080da
Packit Service e080da
Packit Service e080da
def subcmd_config_get(args):
Packit Service e080da
    import sys
Packit Service e080da
    import json
Packit Service e080da
Packit Service e080da
    all_config = gconf.getall(show_defaults=args.show_defaults,
Packit Service e080da
                              show_non_configurable=True)
Packit Service e080da
    if args.name is not None:
Packit Service e080da
        val = all_config.get(config_name_format(args.name), None)
Packit Service e080da
        if val is None:
Packit Service e080da
            sys.stderr.write("Invalid config name \"%s\"\n" % args.name)
Packit Service e080da
            sys.exit(ERROR_CONFIG_INVALID)
Packit Service e080da
Packit Service e080da
        print_config(args.name, val["value"], only_value=args.only_value,
Packit Service e080da
                     use_underscore=args.use_underscore)
Packit Service e080da
        return
Packit Service e080da
Packit Service e080da
    if args.json:
Packit Service e080da
        out = []
Packit Service e080da
        # Convert all values as string
Packit Service e080da
        for k in sorted(all_config):
Packit Service e080da
            v = all_config[k]
Packit Service e080da
            out.append({
Packit Service e080da
                "name": k,
Packit Service e080da
                "value": str(v["value"]),
Packit Service e080da
                "default": str(v["default"]),
Packit Service e080da
                "configurable": v["configurable"],
Packit Service e080da
                "modified": v["modified"]
Packit Service e080da
            })
Packit Service e080da
Packit Service e080da
        print((json.dumps(out)))
Packit Service e080da
        return
Packit Service e080da
Packit Service e080da
    for k in sorted(all_config):
Packit Service e080da
        print_config(k, all_config[k]["value"],
Packit Service e080da
                     use_underscore=args.use_underscore)
Packit Service e080da
Packit Service e080da
Packit Service e080da
def subcmd_config_check(args):
Packit Service e080da
    import sys
Packit Service e080da
Packit Service e080da
    try:
Packit Service e080da
        gconf.check(config_name_format(args.name), value=args.value,
Packit Service e080da
                    with_conffile=False)
Packit Service e080da
    except gconf.GconfNotConfigurable:
Packit Service e080da
        cnf_val = gconf.get(config_name_format(args.name), None)
Packit Service e080da
        if cnf_val is None:
Packit Service e080da
            sys.stderr.write("Invalid config name \"%s\"\n" % args.name)
Packit Service e080da
            sys.exit(ERROR_CONFIG_INVALID)
Packit Service e080da
Packit Service e080da
        # Not configurable
Packit Service e080da
        sys.stderr.write("Not configurable \"%s\"\n" % args.name)
Packit Service e080da
        sys.exit(ERROR_CONFIG_NOT_CONFIGURABLE)
Packit Service e080da
    except gconf.GconfInvalidValue:
Packit Service e080da
        sys.stderr.write("Invalid config value \"%s=%s\"\n" % (args.name,
Packit Service e080da
                                                               args.value))
Packit Service e080da
        sys.exit(ERROR_CONFIG_INVALID_VALUE)
Packit Service e080da
Packit Service e080da
Packit Service e080da
def subcmd_config_set(args):
Packit Service e080da
    import sys
Packit Service e080da
Packit Service e080da
    try:
Packit Service e080da
        gconf.setconfig(config_name_format(args.name), args.value)
Packit Service e080da
    except gconf.GconfNotConfigurable:
Packit Service e080da
        cnf_val = gconf.get(config_name_format(args.name), None)
Packit Service e080da
        if cnf_val is None:
Packit Service e080da
            sys.stderr.write("Invalid config name \"%s\"\n" % args.name)
Packit Service e080da
            sys.exit(ERROR_CONFIG_INVALID)
Packit Service e080da
Packit Service e080da
        # Not configurable
Packit Service e080da
        sys.stderr.write("Not configurable \"%s\"\n" % args.name)
Packit Service e080da
        sys.exit(ERROR_CONFIG_NOT_CONFIGURABLE)
Packit Service e080da
    except gconf.GconfInvalidValue:
Packit Service e080da
        sys.stderr.write("Invalid config value \"%s=%s\"\n" % (args.name,
Packit Service e080da
                                                               args.value))
Packit Service e080da
        sys.exit(ERROR_CONFIG_INVALID_VALUE)
Packit Service e080da
Packit Service e080da
Packit Service e080da
def subcmd_config_reset(args):
Packit Service e080da
    import sys
Packit Service e080da
Packit Service e080da
    try:
Packit Service e080da
        gconf.resetconfig(config_name_format(args.name))
Packit Service e080da
    except gconf.GconfNotConfigurable:
Packit Service e080da
        cnf_val = gconf.get(config_name_format(args.name), None)
Packit Service e080da
        if cnf_val is None:
Packit Service e080da
            sys.stderr.write("Invalid config name \"%s\"\n" % args.name)
Packit Service e080da
            sys.exit(ERROR_CONFIG_INVALID)
Packit Service e080da
Packit Service e080da
        # Not configurable
Packit Service e080da
        sys.stderr.write("Not configurable \"%s\"\n" % args.name)
Packit Service e080da
        sys.exit(ERROR_CONFIG_NOT_CONFIGURABLE)