예제 #1
0
    def __init__(self, server1, user, passwd=None, verbosity=0):
        """Constructor

        :param server1:    Server instance
        :type server1:     Server
        :param user:       MySQL user account name (user@host).
        :type user:        string
        :param passwd:     Password for the user. By default, None
                           (no password).
        :type passwd:      string
        :param verbosity:  Verbosity level to log extra information during
                           operations. By default, 0 (no extra information
                           logged).
        :type verbosity:   integer
        """

        self.server1 = server1
        self.sql_mode = ''
        self.user, self.host = parse_user_host(user)
        self.host = clean_IPv6(self.host)
        self.passwd = passwd
        self.verbosity = verbosity
        self.current_user = None
        self.grant_dict = None
        self.global_grant_dict = None
        self.grant_list = None
        self.global_grant_list = None
        self.query_options = {
            'fetch': False
        }
예제 #2
0
    def get_grants(self, globals_privs=False, as_dict=False, refresh=False):
        """Retrieve the grants for the current user

        :param globals_privs:  Include global privileges in clone (i.e. user@%)
        :type globals_privs:   boolean
        :param as_dict:        If True, instead of a list of plain grant
                               strings, return a dictionary with the grants.
        :type as_dict:         boolean
        :param refresh:        If True, reads grant privileges directly from
                               the server and updates cached values, otherwise
                               uses the cached values.
        :type refresh:         boolean

        :return: result set or None if no grants defined
        :rtype: List, dict or None
        """

        # only read values from server if needed
        if refresh or not self.grant_list or not self.global_grant_list:
            # Get the users' connection user@host if not retrieved
            if self.current_user is None:
                res = self.server1.exec_query("SELECT CURRENT_USER()")
                parts = res[0][0].split('@')
                # If we're connected as some other user, use the user@host
                # defined at instantiation
                if parts[0] != self.user:
                    host = clean_IPv6(self.host)
                    self.current_user = "******" % (self.user, host)
                else:
                    self.current_user = "******" % (parts[0], parts[1])
            grants = []
            try:
                res = self.server1.exec_query("SHOW GRANTS FOR "
                                              "{0}".format(self.current_user))
                for grant in res:
                    grants.append(grant)
            except GadgetQueryError:
                pass  # Error here is ok - no grants found.

            # Cache user grants
            self.grant_list = grants[:]
            self.sql_mode = self.server1.select_variable("SQL_MODE")
            self.grant_dict = User._get_grants_as_dict(self.grant_list,
                                                       self.verbosity,
                                                       self.sql_mode)
            # If current user is already using global host wildcard '%', there
            # is no need to run the show grants again.
            if globals_privs:
                if self.host != '%':
                    try:
                        res = self.server1.exec_query(
                            "SHOW GRANTS FOR '{0}'{1}".format(self.user,
                                                              "@'%'"))
                        for grant in res:
                            grants.append(grant)
                        self.global_grant_list = grants[:]
                        self.global_grant_dict = User._get_grants_as_dict(
                            self.global_grant_list, self.verbosity)
                    except GadgetQueryError:
                        # User has no global privs, return the just the ones
                        # for current host
                        self.global_grant_list = self.grant_list
                        self.global_grant_dict = self.grant_dict
                else:
                    # if host is % then we already have the global privs
                    self.global_grant_list = self.grant_list
                    self.global_grant_dict = self.grant_dict

        if globals_privs:
            if as_dict:
                return self.global_grant_dict
            else:
                return self.global_grant_list
        else:
            if as_dict:
                return self.grant_dict
            else:
                return self.grant_list
예제 #3
0
 def test_clean_IPv6(self):
     """Test clean_IPv6 function.
     """
     self.assertEqual(clean_IPv6("[2001:db8::ff00:42:8329]"),
                      "2001:db8::ff00:42:8329")
예제 #4
0
def resolve_gr_local_address(gr_host, server_host, server_port):
    """Resolves Group Replication local address (host, port).

    If a host is not found on gr_host, the returned host is the one given on
    server_host.
    If a port is not found on gr_host, the returned port is the one given on
    server_port plus 10000, unless the result is higher than 65535, in that
    case a random port number will be generated.

    :param gr_host:     Group replication host address in the format:
                        <host>[:<port>] (i.e., host or host and port separated
                        by ':').
    :type gr_host:      string
    :param server_host: The host where the MySQL server is running.
    :type server_host:  string
    :param server_port: The port that the MySQL server is using.
    :type server_port:  string

    :raise GadgetError:  If could not found a free port.

    :return: A tuple with host and port.
    :rtype:  tuple
    """
    # No info provided, use the server to generate it.
    if gr_host is None or gr_host == "":
        gr_host = server_host
        local_port = str(int(server_port) + 10000)

    # gr_host can have both elements; host and port, but be aware of IPv6
    elif len(gr_host.rsplit(":", 1)) == 2 and gr_host[-1] != "]":
        gr_host, local_port = gr_host.rsplit(":", 1)
        if not gr_host:
            gr_host = server_host
        if not local_port:
            local_port = str(int(server_port) + 10000)
        elif not local_port.isdigit():
            gr_host = "{0}:{1}".format(gr_host, local_port)
            local_port = str(int(server_port) + 10000)

    # Try to get the port only
    elif gr_host.isdigit():
        local_port = gr_host
        gr_host = server_host

    # Generate a local port based on the + 10000 rule.
    else:
        local_port = str(int(server_port) + 10000)

    # in case the gr_host is a IPv6 remove the square brackets '[ ]'
    gr_host = clean_IPv6(gr_host)

    # Generate a random port if out of range.
    if int(local_port) < 0 or int(local_port) > 65535:
        local_port = str(random.randint(10000, 65535))
        # gr_host is host address

    # verify the port is not in use.
    tries = 1
    port_found = False
    while tries < 5 and not port_found:
        tries += 1
        if not is_listening(server_host, int(local_port)):
            port_found = True
        else:
            local_port = str(random.randint(10000, 65535))

    if not port_found:
        raise GadgetError("Unable to find an available port on which the "
                          "member will expose itself to be contacted by the "
                          "other members of the group. Please try again to "
                          "attempt to use another random port or free port "
                          "{0}.".format(str(int(server_port) + 10000)))

    return gr_host, local_port
예제 #5
0
 def test_clean_IPv6(self):
     """Test clean_IPv6 function.
     """
     self.assertEqual(clean_IPv6("[2001:db8::ff00:42:8329]"),
                      "2001:db8::ff00:42:8329")
예제 #6
0
def resolve_gr_local_address(gr_host, server_host, server_port):
    """Resolves Group Replication local address (host, port).

    If a host is not found on gr_host, the returned host is the one given on
    server_host.
    If a port is not found on gr_host, the returned port is the one given on
    server_port * 10 + 1, unless the result is higher than 65535, in that case
    a random port number will be generated.

    :param gr_host:     Group replication host address in the format:
                        <host>[:<port>] (i.e., host or host and port separated
                        by ':').
    :type gr_host:      string
    :param server_host: The host where the MySQL server is running.
    :type server_host:  string
    :param server_port: The port that the MySQL server is using.
    :type server_port:  string

    :raise GadgetError:  If the local address port is not valid or not free.

    :return: A tuple with host and port.
    :rtype:  tuple
    """
    is_port_specified = False

    # No info provided, use the server to generate it.
    if gr_host is None or gr_host == "":
        gr_host = server_host
        local_port = str(int(server_port) * 10 + 1)

    # gr_host can have both elements; host and port, but be aware of IPv6
    elif len(gr_host.rsplit(":", 1)) == 2 and gr_host[-1] != "]":
        gr_host, local_port = gr_host.rsplit(":", 1)
        if not gr_host:
            gr_host = server_host
        if not local_port:
            local_port = str(int(server_port) * 10 + 1)
        elif (not local_port.isdigit()
              or int(local_port) <= 0 or int(local_port) > 65535):
            # Raise an error if the specified port part is invalid.
            raise GadgetError(
                _ERROR_INVALID_LOCAL_ADDRESS_PORT.format(local_port))

    # Try to get the port only
    elif gr_host.isdigit():
        local_port = gr_host
        gr_host = server_host
        # Raise an error if the specified port is invalid (out of range).
        if int(local_port) <= 0 or int(local_port) > 65535:
            raise GadgetError(
                _ERROR_INVALID_LOCAL_ADDRESS_PORT.format(local_port))

    # Generate a local port based on the * 10 + 1 rule.
    else:
        local_port = str(int(server_port) * 10 + 1)

    # in case the gr_host is a IPv6 remove the square brackets '[ ]'
    gr_host = clean_IPv6(gr_host)

    # Generate a random port if out of range.
    if int(local_port) <= 0 or int(local_port) > 65535:
        local_port = str(random.randint(10000, 65535))
        # gr_host is host address

    # verify the port is not in use.
    if is_listening(server_host, int(local_port)):
        raise GadgetError(
            _ERROR_LOCAL_ADDRESS_PORT_IN_USE.format(local_port))

    return gr_host, local_port