Example #1
0
def report_show_slave_status():
    """
    Reports slave status to TwinDB dispatcher
    :return: nothing
    """
    agent_config = twindb_agent.config.AgentConfig.get_config()
    log = logging.getLogger("twindb_remote")
    log.debug("Reporting SHOW SLAVE STATUS for server_id = %s" %
              agent_config.server_id)

    server_config = get_config()
    if not server_config:
        log.error("Failed to get server config from dispatcher")
        return
    mysql = twindb_agent.twindb_mysql.MySQL(
        mysql_user=server_config["mysql_user"],
        mysql_password=server_config["mysql_password"])
    ss = mysql.get_slave_status()
    data = {
        "type": "report_sss",
        "params": {
            "server_id": agent_config.server_id,
            "mysql_server_id": ss["mysql_server_id"],
            "mysql_master_server_id": ss["mysql_master_server_id"],
            "mysql_master_host": ss["mysql_master_host"],
            "mysql_seconds_behind_master": ss["mysql_seconds_behind_master"],
            "mysql_slave_io_running": ss["mysql_slave_io_running"],
            "mysql_slave_sql_running": ss["mysql_slave_sql_running"],
        }
    }
    api = twindb_agent.api.TwinDBAPI()
    api.call(data)
    if not api.success:
        log.error("Could not report replication status to the dispatcher")
    return
Example #2
0
def report_show_slave_status():
    """
    Reports slave status to TwinDB dispatcher
    :return: nothing
    """
    agent_config = twindb_agent.config.AgentConfig.get_config()
    log = logging.getLogger("twindb_remote")
    log.debug("Reporting SHOW SLAVE STATUS for server_id = %s" % agent_config.server_id)

    server_config = get_config()
    if not server_config:
        log.error("Failed to get server config from dispatcher")
        return
    mysql = twindb_agent.twindb_mysql.MySQL(mysql_user=server_config["mysql_user"],
                                            mysql_password=server_config["mysql_password"])
    ss = mysql.get_slave_status()
    data = {
        "type": "report_sss",
        "params": {
            "server_id": agent_config.server_id,
            "mysql_server_id": ss["mysql_server_id"],
            "mysql_master_server_id": ss["mysql_master_server_id"],
            "mysql_master_host": ss["mysql_master_host"],
            "mysql_seconds_behind_master": ss["mysql_seconds_behind_master"],
            "mysql_slave_io_running": ss["mysql_slave_io_running"],
            "mysql_slave_sql_running": ss["mysql_slave_sql_running"],
        }
    }
    api = twindb_agent.api.TwinDBAPI()
    api.call(data)
    if not api.success:
        log.error("Could not report replication status to the dispatcher")
    return
Example #3
0
 def record_backup(name, size, backup_lsn=None):
     """
     Saves details about backup copy in TwinDB dispatcher
     :param name: name of backup
     :param size: size of the backup in bytes
     :param backup_lsn: last LSN if it was incremental backup
     :return: JSON string with status of the request i.e. { "success": True } or None if error happened
     """
     log.info("Saving information about backup:", log_params)
     log.info("File name : %s" % name, log_params)
     log.info("Volume id : %d" % int(job_order["params"]["volume_id"]), log_params)
     log.info("Size      : %d (%s)" % (int(size), twindb_agent.utils.h_size(size)), log_params)
     log.info("Ancestor  : %d" % int(job_order["params"]["ancestor"]), log_params)
     data = {
         "type": "update_backup_data",
         "params": {
             "job_id": job_order["job_id"],
             "name": name,
             "volume_id": job_order["params"]["volume_id"],
             "size": size,
             "lsn": backup_lsn,
             "ancestor": job_order["params"]["ancestor"]
         }
     }
     log.debug("Saving a record %s" % data, log_params)
     api = twindb_agent.api.TwinDBAPI(logger_name=logger_name)
     api.call(data)
     if api.success:
         log.info("Saved backup copy details", log_params)
         return True
     else:
         log.error("Failed to save backup copy details")
         return False
Example #4
0
def report_agent_privileges():
    """
    Reports what privileges are given to the agent
    :return: nothing
    """
    agent_config = twindb_agent.config.AgentConfig.get_config()
    log = logging.getLogger("twindb_remote")
    log.debug("Reporting agent privileges for server_id = %s" %
              agent_config.server_id)

    server_config = get_config()
    if not server_config:
        log.error("Failed to get server config from dispatcher")
        return
    mysql = twindb_agent.twindb_mysql.MySQL(
        mysql_user=server_config["mysql_user"],
        mysql_password=server_config["mysql_password"])

    con = mysql.get_mysql_connection()
    cursor = con.cursor()
    query = "SELECT PRIVILEGE_TYPE FROM information_schema.USER_PRIVILEGES"
    log.debug("Sending query : %s" % query)
    cursor.execute(query)

    privileges = {
        "Reload_priv": "N",
        "Lock_tables_priv": "N",
        "Repl_client_priv": "N",
        "Super_priv": "N",
        "Create_tablespace_priv": "N"
    }
    for (priv, ) in cursor:
        if priv == "RELOAD":
            privileges["Reload_priv"] = "Y"
        elif priv == "LOCK TABLES":
            privileges["Lock_tables_priv"] = "Y"
        elif priv == "REPLICATION CLIENT":
            privileges["Repl_client_priv"] = "Y"
        elif priv == "SUPER":
            privileges["Super_priv"] = "Y"
        elif priv == "CREATE TABLESPACE":
            privileges["Create_tablespace_priv"] = "Y"
    data = {
        "type": "report_agent_privileges",
        "params": {
            "Reload_priv": privileges["Reload_priv"],
            "Lock_tables_priv": privileges["Lock_tables_priv"],
            "Repl_client_priv": privileges["Repl_client_priv"],
            "Super_priv": privileges["Super_priv"],
            "Create_tablespace_priv": privileges["Create_tablespace_priv"]
        }
    }
    api = twindb_agent.api.TwinDBAPI()
    api.call(data)
    if not api.success:
        log.error("Could not report agent permissions to the dispatcher")
    return
Example #5
0
def report_agent_privileges():
    """
    Reports what privileges are given to the agent
    :return: nothing
    """
    agent_config = twindb_agent.config.AgentConfig.get_config()
    log = logging.getLogger("twindb_remote")
    log.debug("Reporting agent privileges for server_id = %s" % agent_config.server_id)

    server_config = get_config()
    if not server_config:
        log.error("Failed to get server config from dispatcher")
        return
    mysql = twindb_agent.twindb_mysql.MySQL(mysql_user=server_config["mysql_user"],
                                            mysql_password=server_config["mysql_password"])

    con = mysql.get_mysql_connection()
    cursor = con.cursor()
    query = "SELECT PRIVILEGE_TYPE FROM information_schema.USER_PRIVILEGES"
    log.debug("Sending query : %s" % query)
    cursor.execute(query)

    privileges = {
        "Reload_priv": "N",
        "Lock_tables_priv": "N",
        "Repl_client_priv": "N",
        "Super_priv": "N",
        "Create_tablespace_priv": "N"
    }
    for (priv,) in cursor:
        if priv == "RELOAD":
            privileges["Reload_priv"] = "Y"
        elif priv == "LOCK TABLES":
            privileges["Lock_tables_priv"] = "Y"
        elif priv == "REPLICATION CLIENT":
            privileges["Repl_client_priv"] = "Y"
        elif priv == "SUPER":
            privileges["Super_priv"] = "Y"
        elif priv == "CREATE TABLESPACE":
            privileges["Create_tablespace_priv"] = "Y"
    data = {
        "type": "report_agent_privileges",
        "params": {
            "Reload_priv": privileges["Reload_priv"],
            "Lock_tables_priv": privileges["Lock_tables_priv"],
            "Repl_client_priv": privileges["Repl_client_priv"],
            "Super_priv": privileges["Super_priv"],
            "Create_tablespace_priv": privileges["Create_tablespace_priv"]
        }
    }
    api = twindb_agent.api.TwinDBAPI()
    api.call(data)
    if not api.success:
        log.error("Could not report agent permissions to the dispatcher")
    return
Example #6
0
def schedule_backup():
    """
    Asks dispatcher to schedule a job for this server
    """
    log = logging.getLogger("twindb_console")
    data = {"type": "schedule_backup", "params": {}}
    api = twindb_agent.api.TwinDBAPI(logger_name="twindb_console")
    api.call(data)
    if api.success:
        log.info("A backup job is successfully registered")
        return True
    else:
        log.error("Failed to schedule a backup job")
        return False
Example #7
0
def commit_registration():
    """
    Confirms that agent successfully created local MySQL user.
    :return:
    """
    log = logging.getLogger("twindb_console")
    data = {"type": "confirm_registration", "params": {}}
    api = twindb_agent.api.TwinDBAPI()
    api.call(data)
    if api.success:
        log.info("Successfully confirmed agent registration")
        return True
    else:
        log.error("Failer to config agent registration")
        return False
Example #8
0
    def get_backups_chain(self):
        """
        Gets a chain of parents of the given backup_copy_id
        :return: list of dictionaries with backup copy params:
            {
            "backup_copy_id": 188,
            "name": "server_id_479a41b3-d22d-41a8-b7d3-4e40302622f6_2015-04-06T15:10:46.050984.tar.gp",
            "ip": "127.0.0.1",
            full: True
            },
            {...}
        """
        log = self.logger
        log_params = self.log_params
        backup_copy_id = self.job_order["params"]["backup_copy_id"]
        log.debug("Getting backups chain for backup_copy_id %d" % backup_copy_id, log_params)

        data = {
            "type": "get_backups_chain",
            "params": {
                "backup_copy_id": backup_copy_id
            }
        }
        api = twindb_agent.api.TwinDBAPI()
        backups_chain = api.call(data)
        return backups_chain
Example #9
0
    def get_backups_chain(self):
        """
        Gets a chain of parents of the given backup_copy_id
        :return: list of dictionaries with backup copy params:
            {
            "backup_copy_id": 188,
            "name": "server_id_479a41b3-d22d-41a8-b7d3-4e40302622f6_2015-04-06T15:10:46.050984.tar.gp",
            "ip": "127.0.0.1",
            full: True
            },
            {...}
        """
        log = self.logger
        log_params = self.log_params
        backup_copy_id = self.job_order["params"]["backup_copy_id"]
        log.debug("Getting backups chain for backup_copy_id %d" % backup_copy_id, log_params)

        data = {
            "type": "get_backups_chain",
            "params": {
                "backup_copy_id": backup_copy_id
            }
        }
        api = twindb_agent.api.TwinDBAPI()
        backups_chain = api.call(data)
        return backups_chain
Example #10
0
def schedule_backup():
    """
    Asks dispatcher to schedule a job for this server
    """
    log = logging.getLogger("twindb_console")
    data = {
        "type": "schedule_backup",
        "params": {}
    }
    api = twindb_agent.api.TwinDBAPI(logger_name="twindb_console")
    api.call(data)
    if api.success:
        log.info("A backup job is successfully registered")
        return True
    else:
        log.error("Failed to schedule a backup job")
        return False
Example #11
0
def commit_registration():
    """
    Confirms that agent successfully created local MySQL user.
    :return:
    """
    log = logging.getLogger("twindb_console")
    data = {
        "type": "confirm_registration",
        "params": {}
    }
    api = twindb_agent.api.TwinDBAPI()
    api.call(data)
    if api.success:
        log.info("Successfully confirmed agent registration")
        return True
    else:
        log.error("Failer to config agent registration")
        return False
Example #12
0
def log_job_notify(params):
    """
    Notifies a job event to TwinDB dispatcher
    :param params: { event: "start_job", job_id: job_id } or
             { event: "stop_job", job_id: job_id, ret_code: ret }
    :return: True of False if error happened
    """
    log = logging.getLogger("twindb_remote")
    log.info("Sending event notification %s" % params["event"])
    data = {"type": "notify", "params": params}
    job_id = int(params["job_id"])
    api = twindb_agent.api.TwinDBAPI()
    api.call(data)
    if api.success:
        log.debug("Dispatcher acknowledged job_id = %d notification" % job_id)
        return True
    else:
        log.error("Dispatcher didn't acknowledge job_id = %d notification" %
                  job_id)
        return False
Example #13
0
def unregister(delete_backups=False):
    """
    Unregisters this server in TwinDB dispatcher
    Returns
      True    - if server was successfully unregistered
      False   - if error happened
    """
    log = logging.getLogger("twindb_console")

    data = {
        "type": "unregister",
        "params": {
            "delete_backups": delete_backups,
        }
    }
    api = twindb_agent.api.TwinDBAPI(logger_name="twindb_console")
    api.call(data)
    if api.success:
        log.info("The server is successfully unregistered")
    else:
        log.error("Failed to unregister the agent")
    return
Example #14
0
def unregister(delete_backups=False):
    """
    Unregisters this server in TwinDB dispatcher
    Returns
      True    - if server was successfully unregistered
      False   - if error happened
    """
    log = logging.getLogger("twindb_console")

    data = {
        "type": "unregister",
        "params": {
            "delete_backups": delete_backups,
        }
    }
    api = twindb_agent.api.TwinDBAPI(logger_name="twindb_console")
    api.call(data)
    if api.success:
        log.info("The server is successfully unregistered")
    else:
        log.error("Failed to unregister the agent")
    return
Example #15
0
def log_job_notify(params):
    """
    Notifies a job event to TwinDB dispatcher
    :param params: { event: "start_job", job_id: job_id } or
             { event: "stop_job", job_id: job_id, ret_code: ret }
    :return: True of False if error happened
    """
    log = logging.getLogger("twindb_remote")
    log.info("Sending event notification %s" % params["event"])
    data = {
        "type": "notify",
        "params": params
    }
    job_id = int(params["job_id"])
    api = twindb_agent.api.TwinDBAPI()
    api.call(data)
    if api.success:
        log.debug("Dispatcher acknowledged job_id = %d notification" % job_id)
        return True
    else:
        log.error("Dispatcher didn't acknowledge job_id = %d notification" % job_id)
        return False
Example #16
0
def get_job():
    """
    Gets job order from TwinDB dispatcher
    :return: Job order in python dictionary or None if error happened
    """
    agent_config = twindb_agent.config.AgentConfig.get_config()
    log = logging.getLogger("twindb_remote")
    log.debug("Getting job for server_id = %s" % agent_config.server_id)

    api = twindb_agent.api.TwinDBAPI()
    data = {"type": "get_job", "params": {}}
    job_order = api.call(data)
    return job_order
Example #17
0
 def record_backup(name, size, backup_lsn=None):
     """
     Saves details about backup copy in TwinDB dispatcher
     :param name: name of backup
     :param size: size of the backup in bytes
     :param backup_lsn: last LSN if it was incremental backup
     :return: JSON string with status of the request i.e. { "success": True } or None if error happened
     """
     log.info("Saving information about backup:", log_params)
     log.info("File name : %s" % name, log_params)
     log.info("Volume id : %d" % int(job_order["params"]["volume_id"]),
              log_params)
     log.info(
         "Size      : %d (%s)" %
         (int(size), twindb_agent.utils.h_size(size)), log_params)
     log.info("Ancestor  : %d" % int(job_order["params"]["ancestor"]),
              log_params)
     data = {
         "type": "update_backup_data",
         "params": {
             "job_id": job_order["job_id"],
             "name": name,
             "volume_id": job_order["params"]["volume_id"],
             "size": size,
             "lsn": backup_lsn,
             "ancestor": job_order["params"]["ancestor"]
         }
     }
     log.debug("Saving a record %s" % data, log_params)
     api = twindb_agent.api.TwinDBAPI(logger_name=logger_name)
     api.call(data)
     if api.success:
         log.info("Saved backup copy details", log_params)
         return True
     else:
         log.error("Failed to save backup copy details")
         return False
Example #18
0
def get_job():
    """
    Gets job order from TwinDB dispatcher
    :return: Job order in python dictionary or None if error happened
    """
    agent_config = twindb_agent.config.AgentConfig.get_config()
    log = logging.getLogger("twindb_remote")
    log.debug("Getting job for server_id = %s" % agent_config.server_id)

    api = twindb_agent.api.TwinDBAPI()
    data = {
        "type": "get_job",
        "params": {}
    }
    job_order = api.call(data)
    return job_order
Example #19
0
def is_registered():
    """
    Checks whether the server is registered or not
    :return: True if registered, False if not so much
    """
    agent_config = twindb_agent.config.AgentConfig.get_config()
    log = logging.getLogger("twindb_console")
    log.debug("Getting registration status for server_id = %s" %
              agent_config.server_id)

    twindb_email = "*****@*****.**" % agent_config.server_id
    log.debug("Reading GPG public key of %s." % twindb_email)

    # Reading the GPG key
    gpg_cmd = [
        "gpg", "--homedir", agent_config.gpg_homedir, "--armor", "--export",
        twindb_email
    ]
    try:
        p = subprocess.Popen(gpg_cmd, stdout=subprocess.PIPE)
        enc_public_key = p.communicate()[0]
    except OSError as err:
        log.error("Failed to run command %r. %s" % (gpg_cmd, err))
        log.error("Failed to export GPG keys of %s from %s." %
                  (twindb_email, agent_config.gpg_homedir))
        sys.exit(2)

    # Call the TwinDB api to check for server registration
    data = {
        "type": "is_registered",
        "params": {
            "server_id": agent_config.server_id,
            "enc_public_key": enc_public_key
        }
    }
    api = twindb_agent.api.TwinDBAPI(logger_name="twindb_console")
    api_response = api.call(data)
    if api_response:
        if api_response["registered"]:
            return True
        else:
            return False
    else:
        # API call was unsuccessfull, consider the agent unregistered
        return False
Example #20
0
def get_config():
    """
    Gets backup config from TwinDB dispatcher
    :return: Backup config or None if error happened
    """
    agent_config = twindb_agent.config.AgentConfig.get_config()
    log = logging.getLogger("twindb_remote")
    log.debug("Getting config for server_id = %s" % agent_config.server_id)

    api = twindb_agent.api.TwinDBAPI()
    data = {
        "type": "get_config",
        "params": {
            "server_id": agent_config.server_id
        }
    }
    config = api.call(data)
    return config
Example #21
0
def get_config():
    """
    Gets backup config from TwinDB dispatcher
    :return: Backup config or None if error happened
    """
    agent_config = twindb_agent.config.AgentConfig.get_config()
    log = logging.getLogger("twindb_remote")
    log.debug("Getting config for server_id = %s" % agent_config.server_id)

    api = twindb_agent.api.TwinDBAPI()
    data = {
        "type": "get_config",
        "params": {
            "server_id": agent_config.server_id
        }
    }
    config = api.call(data)
    return config
Example #22
0
def is_registered():
    """
    Checks whether the server is registered or not
    :return: True if registered, False if not so much
    """
    agent_config = twindb_agent.config.AgentConfig.get_config()
    log = logging.getLogger("twindb_console")
    log.debug("Getting registration status for server_id = %s" % agent_config.server_id)

    twindb_email = "*****@*****.**" % agent_config.server_id
    log.debug("Reading GPG public key of %s." % twindb_email)

    # Reading the GPG key
    gpg_cmd = ["gpg", "--homedir", agent_config.gpg_homedir, "--armor", "--export", twindb_email]
    try:
        p = subprocess.Popen(gpg_cmd, stdout=subprocess.PIPE)
        enc_public_key = p.communicate()[0]
    except OSError as err:
        log.error("Failed to run command %r. %s" % (gpg_cmd, err))
        log.error("Failed to export GPG keys of %s from %s." % (twindb_email, agent_config.gpg_homedir))
        sys.exit(2)

    # Call the TwinDB api to check for server registration
    data = {
        "type": "is_registered",
        "params": {
            "server_id": agent_config.server_id,
            "enc_public_key": enc_public_key
        }
    }
    api = twindb_agent.api.TwinDBAPI(logger_name="twindb_console")
    api_response = api.call(data)
    if api_response:
        if api_response["registered"]:
            return True
        else:
            return False
    else:
        # API call was unsuccessfull, consider the agent unregistered
        return False
Example #23
0
def execute(job_order, logger_name="twindb_remote"):
    """
    Processes send_key job
    :return: nothing
    """
    agent_config = twindb_agent.config.AgentConfig.get_config()
    log = logging.getLogger(logger_name)

    # Get owner of the GPG key
    cmd_1 = ["gpg", "--list-packets"]
    try:
        gpg_pub_key = job_order["params"]["gpg_pub_key"]
        if gpg_pub_key:
            log.debug("Starting %r" % cmd_1)
            p1 = subprocess.Popen(cmd_1, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
            cout, cerr = p1.communicate(gpg_pub_key)
            keyid = "Unknown"
            for line in cout.split("\n"):
                if "keyid:" in line:
                    keyid = line.replace("keyid:", "").strip()
                    break
            log.debug("Requestor's public key id is %s" % keyid)
        else:
            log.error("Requestor public key is empty")
            return -1
    except OSError as err:
        log.error("Failed to run command %r: %s" % (cmd_1, err))
        return -1
    # Import public GPG key. It's a user public key sent by the dispatcher
    try:
        log.debug("Importing requestor's key %s" % keyid)
        cmd_1 = ["gpg", "--import"]
        p1 = subprocess.Popen(cmd_1, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        cout, cerr = p1.communicate(gpg_pub_key)
        if cout:
            log.info(cout)
        if cerr:
            log.error(cerr)
    except OSError as err:
        log.error("Failed to run command %r: %s" % (cmd_1, err))
        return -1
    # Get private key and encrypt it
    gpg_pub_key = job_order["params"]["gpg_pub_key"]
    if gpg_pub_key:
        log.debug("Exporting private key of server %s" % agent_config.server_id)
        cmd_1 = ["gpg", "--armor", "--export-secret-key", agent_config.server_id]
        cmd_2 = ["gpg", "--armor", "--encrypt", "--sign", "--batch", "-r", keyid,
                 "--local-user", agent_config.server_id,
                 "--trust-model", "always"]
        try:
            log.debug("Starting %r" % cmd_1)
            p1 = subprocess.Popen(cmd_1, stdout=subprocess.PIPE)
        except OSError as err:
            log.error("Failed to run command %r: %s" % (cmd_1, err))
            return -1
        try:
            log.debug("Starting %r" % cmd_2)
            p2 = subprocess.Popen(cmd_2, stdin=p1.stdout, stdout=subprocess.PIPE)
            cout, cerr = p2.communicate()
            enc_private_key = cout
            log.debug("Encrypted private key %s" % enc_private_key)
        except OSError as err:
            log.error("Failed to run command %r: %s" % (cmd_2, err))
            return -1
        # Now send the private key to dispatcher
        data = {
            "type": "send_key",
            "params": {
                "enc_private_key": enc_private_key,
                "job_id": job_order["job_id"]
            }
        }
        api = twindb_agent.api.TwinDBAPI()
        api.call(data)
        if api.success:
            return 0
        else:
            return -1
    else:
        log.error("The job order requested send_key, but no public key was provided")
        return -1
Example #24
0
def execute(job_order, logger_name="twindb_remote"):
    """
    Processes send_key job
    :return: nothing
    """
    agent_config = twindb_agent.config.AgentConfig.get_config()
    log = logging.getLogger(logger_name)

    # Get owner of the GPG key
    cmd_1 = ["gpg", "--list-packets"]
    try:
        gpg_pub_key = job_order["params"]["gpg_pub_key"]
        if gpg_pub_key:
            log.debug("Starting %r" % cmd_1)
            p1 = subprocess.Popen(cmd_1,
                                  stdin=subprocess.PIPE,
                                  stdout=subprocess.PIPE)
            cout, cerr = p1.communicate(gpg_pub_key)
            keyid = "Unknown"
            for line in cout.split("\n"):
                if "keyid:" in line:
                    keyid = line.replace("keyid:", "").strip()
                    break
            log.debug("Requestor's public key id is %s" % keyid)
        else:
            log.error("Requestor public key is empty")
            return -1
    except OSError as err:
        log.error("Failed to run command %r: %s" % (cmd_1, err))
        return -1
    # Import public GPG key. It's a user public key sent by the dispatcher
    try:
        log.debug("Importing requestor's key %s" % keyid)
        cmd_1 = ["gpg", "--import"]
        p1 = subprocess.Popen(cmd_1,
                              stdin=subprocess.PIPE,
                              stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE)
        cout, cerr = p1.communicate(gpg_pub_key)
        if cout:
            log.info(cout)
        if cerr:
            log.error(cerr)
    except OSError as err:
        log.error("Failed to run command %r: %s" % (cmd_1, err))
        return -1
    # Get private key and encrypt it
    gpg_pub_key = job_order["params"]["gpg_pub_key"]
    if gpg_pub_key:
        log.debug("Exporting private key of server %s" %
                  agent_config.server_id)
        cmd_1 = [
            "gpg", "--armor", "--export-secret-key", agent_config.server_id
        ]
        cmd_2 = [
            "gpg", "--armor", "--encrypt", "--sign", "--batch", "-r", keyid,
            "--local-user", agent_config.server_id, "--trust-model", "always"
        ]
        try:
            log.debug("Starting %r" % cmd_1)
            p1 = subprocess.Popen(cmd_1, stdout=subprocess.PIPE)
        except OSError as err:
            log.error("Failed to run command %r: %s" % (cmd_1, err))
            return -1
        try:
            log.debug("Starting %r" % cmd_2)
            p2 = subprocess.Popen(cmd_2,
                                  stdin=p1.stdout,
                                  stdout=subprocess.PIPE)
            cout, cerr = p2.communicate()
            enc_private_key = cout
            log.debug("Encrypted private key %s" % enc_private_key)
        except OSError as err:
            log.error("Failed to run command %r: %s" % (cmd_2, err))
            return -1
        # Now send the private key to dispatcher
        data = {
            "type": "send_key",
            "params": {
                "enc_private_key": enc_private_key,
                "job_id": job_order["job_id"]
            }
        }
        api = twindb_agent.api.TwinDBAPI()
        api.call(data)
        if api.success:
            return 0
        else:
            return -1
    else:
        log.error(
            "The job order requested send_key, but no public key was provided")
        return -1
Example #25
0
def register(code):
    """
    Register this server in TwinDB dispatcher. Exits if error happened
    :param code: string with a secret registration code
    :return: True - if server was successfully registered
    """
    agent_config = twindb_agent.config.AgentConfig.get_config()
    log = logging.getLogger("twindb_console")

    # Check that the agent can connect to local MySQL
    mysql = twindb_agent.twindb_mysql.MySQL(logger_name="twindb_console")
    conn = mysql.get_mysql_connection()
    if conn:
        cursor = conn.cursor()
        cursor.execute(
            "SELECT COUNT(*) FROM information_schema.user_privileges")
        row = cursor.fetchone()
        if row[0] == 0:
            log.error(
                "Local MySQL server is running with --skip-grant-tables option"
            )
            return False
        conn.close()
    else:
        if not (agent_config.mysql_user or agent_config.mysql_password):
            log.info(
                "Try to call the agent with -u and -p options to specify MySQL user and password"
            )
            log.info(
                "Another option is to specify MySQL user and password in /root/.my.cnf"
            )
        sys.exit(2)
    # Check early to see that the MySQL user passed to the agent has enough
    # privileges to create a separate MySQL user needed by TwinDB
    mysql_access_available, missing_mysql_privileges = mysql.has_mysql_access()
    if not mysql_access_available:
        log.error("The MySQL user %s does not have enough privileges" %
                  agent_config.mysql_user)
        if missing_mysql_privileges:
            log.error("Following privileges are missing: %s" %
                      ','.join(missing_mysql_privileges))
        return False

    log.info("Registering TwinDB agent with code %s" % code)
    name = os.uname()[1].strip()  # un[1] is a hostname

    twindb_email = "*****@*****.**" % agent_config.server_id

    # Read GPG public key
    cmd = [
        "gpg", "--homedir", agent_config.gpg_homedir, "--armor", "--export",
        twindb_email
    ]
    try:
        log.debug("Reading GPG public key of %s." % twindb_email)
        p1 = subprocess.Popen(cmd, stdout=subprocess.PIPE)
        enc_public_key = p1.communicate()[0]
    except OSError as err:
        log.error("Failed to run command %r. %s" % (cmd, err))
        log.error("Failed to export GPG keys of %s from %s." %
                  (twindb_email, agent_config.gpg_homedir))
        return False

    if not os.path.isfile(agent_config.ssh_private_key_file):
        try:
            log.info("Generating SSH keys pair.")
            subprocess.call([
                "ssh-keygen", "-N", "", "-f", agent_config.ssh_private_key_file
            ])
        except OSError as err:
            log.error("Failed to run command %r. %s" % (cmd, err))
            log.error("Failed to generate SSH keys.")
            return False
    try:
        log.info("Reading SSH public key from %s." %
                 agent_config.ssh_public_key_file)
        f = open(agent_config.ssh_public_key_file, 'r')
        ssh_public_key = f.read()
        f.close()
    except IOError as err:
        log.error("Failed to read from file %s. %s" %
                  (agent_config.ssh_public_key_file, err))
        log.error("Failed to read SSH keys.")
        return False

    # Read local ip addresses
    cmd = "ip addr"
    cmd += "| grep -w inet"
    cmd += "| awk '{ print $2}'"
    cmd += "| awk -F/ '{ print $1}'"
    cout = None
    log.debug("Getting list of local IP addresses")
    try:
        log.debug("Running: %s" % cmd)
        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
        cout, cerr = p.communicate()
        log.debug("STDOUT: %s" % cout)
        log.debug("STDERR: %s" % cerr)
    except OSError as err:
        log.error("Failed to run command %r. %s" % (cmd, err))
    local_ip = list()
    for row in cout.split("\n"):
        row = row.rstrip("\n")
        if row and row != "127.0.0.1":
            local_ip.append(row)
    ss = mysql.get_slave_status()
    data = {
        "type": "register",
        "params": {
            "reg_code": code,
            "name": name,
            "server_id": agent_config.server_id,
            "enc_public_key": enc_public_key,
            "ssh_public_key": ssh_public_key,
            "mysql_server_id": ss["mysql_server_id"],
            "mysql_master_server_id": ss["mysql_master_server_id"],
            "mysql_master_host": ss["mysql_master_host"],
            "mysql_seconds_behind_master": ss["mysql_seconds_behind_master"],
            "mysql_slave_io_running": ss["mysql_slave_io_running"],
            "mysql_slave_sql_running": ss["mysql_slave_sql_running"],
            "local_ip": local_ip
        }
    }
    api = twindb_agent.api.TwinDBAPI()
    api.call(data)
    if api.success:
        log.info("Received successful response to register an agent")
        if mysql.create_agent_user():
            log.info("Created MySQL user for TwinDB agent")
            return True
        else:
            log.error("Failed to created MySQL user for TwinDB agent")
            return False
    else:
        log.error("Failed to register agent")
        log.error(api.error)
        log.debug(api.debug)
Example #26
0
def register(code):
    """
    Register this server in TwinDB dispatcher. Exits if error happened
    :param code: string with a secret registration code
    :return: True - if server was successfully registered
    """
    agent_config = twindb_agent.config.AgentConfig.get_config()
    log = logging.getLogger("twindb_console")

    # Check that the agent can connect to local MySQL
    mysql = twindb_agent.twindb_mysql.MySQL(logger_name="twindb_console")
    conn = mysql.get_mysql_connection()
    if conn:
        cursor = conn.cursor()
        cursor.execute("SELECT COUNT(*) FROM information_schema.user_privileges")
        row = cursor.fetchone()
        if row[0] == 0:
            log.error("Local MySQL server is running with --skip-grant-tables option")
            return False
        conn.close()
    else:
        if not (agent_config.mysql_user or agent_config.mysql_password):
            log.info("Try to call the agent with -u and -p options to specify MySQL user and password")
            log.info("Another option is to specify MySQL user and password in /root/.my.cnf")
        sys.exit(2)
    # Check early to see that the MySQL user passed to the agent has enough
    # privileges to create a separate MySQL user needed by TwinDB
    mysql_access_available, missing_mysql_privileges = mysql.has_mysql_access()
    if not mysql_access_available:
        log.error("The MySQL user %s does not have enough privileges" % agent_config.mysql_user)
        if missing_mysql_privileges:
            log.error("Following privileges are missing: %s" % ','.join(missing_mysql_privileges))
        return False

    log.info("Registering TwinDB agent with code %s" % code)
    name = os.uname()[1].strip()  # un[1] is a hostname

    twindb_email = "*****@*****.**" % agent_config.server_id

    # Read GPG public key
    cmd = ["gpg", "--homedir", agent_config.gpg_homedir, "--armor", "--export", twindb_email]
    try:
        log.debug("Reading GPG public key of %s." % twindb_email)
        p1 = subprocess.Popen(cmd, stdout=subprocess.PIPE)
        enc_public_key = p1.communicate()[0]
    except OSError as err:
        log.error("Failed to run command %r. %s" % (cmd, err))
        log.error("Failed to export GPG keys of %s from %s." % (twindb_email, agent_config.gpg_homedir))
        return False

    if not os.path.isfile(agent_config.ssh_private_key_file):
        try:
            log.info("Generating SSH keys pair.")
            subprocess.call(["ssh-keygen", "-N", "", "-f", agent_config.ssh_private_key_file])
        except OSError as err:
            log.error("Failed to run command %r. %s" % (cmd, err))
            log.error("Failed to generate SSH keys.")
            return False
    try:
        log.info("Reading SSH public key from %s." % agent_config.ssh_public_key_file)
        f = open(agent_config.ssh_public_key_file, 'r')
        ssh_public_key = f.read()
        f.close()
    except IOError as err:
        log.error("Failed to read from file %s. %s" % (agent_config.ssh_public_key_file, err))
        log.error("Failed to read SSH keys.")
        return False

    # Read local ip addresses
    cmd = "ip addr"
    cmd += "| grep -w inet"
    cmd += "| awk '{ print $2}'"
    cmd += "| awk -F/ '{ print $1}'"
    cout = None
    log.debug("Getting list of local IP addresses")
    try:
        log.debug("Running: %s" % cmd)
        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
        cout, cerr = p.communicate()
        log.debug("STDOUT: %s" % cout)
        log.debug("STDERR: %s" % cerr)
    except OSError as err:
        log.error("Failed to run command %r. %s" % (cmd, err))
    local_ip = list()
    for row in cout.split("\n"):
        row = row.rstrip("\n")
        if row and row != "127.0.0.1":
            local_ip.append(row)
    ss = mysql.get_slave_status()
    data = {
        "type": "register",
        "params": {
            "reg_code": code,
            "name": name,
            "server_id": agent_config.server_id,
            "enc_public_key": enc_public_key,
            "ssh_public_key": ssh_public_key,
            "mysql_server_id": ss["mysql_server_id"],
            "mysql_master_server_id": ss["mysql_master_server_id"],
            "mysql_master_host": ss["mysql_master_host"],
            "mysql_seconds_behind_master": ss["mysql_seconds_behind_master"],
            "mysql_slave_io_running": ss["mysql_slave_io_running"],
            "mysql_slave_sql_running": ss["mysql_slave_sql_running"],
            "local_ip": local_ip
        }
    }
    api = twindb_agent.api.TwinDBAPI()
    api.call(data)
    if api.success:
        log.info("Received successful response to register an agent")
        if mysql.create_agent_user():
            log.info("Created MySQL user for TwinDB agent")
            return True
        else:
            log.error("Failed to created MySQL user for TwinDB agent")
            return False
    else:
        log.error("Failed to register agent")
        log.error(api.error)
        log.debug(api.debug)