def load_hosts(self):
        """
        Will identify the host in the database that are applicable to a given host
        (Host in database can be defined with wildcard so it is not a straight comparison)
        """
        hosts = None

        # note the comparison of the host field is backwards than normal.
        # this in on purpose to allow identifying using SQL all the hosts in the grant definitions
        # that do match the host being queried.
        result = self.context.ctrl_be.exec_query("""SELECT host 
                                                    FROM mysql.user 
                                                    WHERE user = '******' AND '%s' LIKE host"""
                                                 % (self.user, self.host))
        if result:
            hosts = []
            while result.nextRow():
                hosts.append(result.stringByIndex(1))
        else:
            log_warning(
                'There are no grants defined for the user %s on hosts matching %s\n'
                % (self.user, self.host))

        self.applicant_hosts = hosts

        return hosts
Beispiel #2
0
def visualExplain(editor, result_panel):
    version = Version.fromgrt(editor.owner.serverVersion)

    statement = editor.currentStatement
    if statement:
        try:
            explain = editor.owner.executeQuery("EXPLAIN %s" % statement, 1)
        except Exception as e:
            log_warning("Could not execute EXPLAIN %s: %s\n" % (statement, e))
            explain = None

        json = None
        if explain and version.is_supported_mysql_version_at_least(5, 6):
            rset = editor.owner.executeQuery(
                "EXPLAIN FORMAT=JSON %s" % statement, 1)
            if rset and rset.goToFirstRow():
                json = rset.stringFieldValue(0)
                rset.reset_references()

        view = ExplainTab(version, statement, json,
                          explain if explain else None)
        dock = mforms.fromgrt(result_panel.dockingPoint)
        view.set_identifier("execution_plan")
        view.set_title("Execution\nPlan")
        dock.dock_view(view, "output_type-executionplan.png", 0)
        dock.select_view(view)

    return 0
    def load_privileges(self, host):

        # Clears any previously loaded privileges
        self._granted_privileges = {}

        if host in self.applicant_hosts:
            # If there are hosts it means there are privileges applicable for the user
            # On the indicated host
            result = self.context.ctrl_be.exec_query(
                "SHOW GRANTS FOR `%s`@`%s`" % (self.user, host))

            context = grt.modules.MySQLParserServices.createParserContext(
                self._character_sets, self._target_version,
                'STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION',
                1)

            if result:
                while result.nextRow():
                    statement = result.stringByIndex(1)
                    grant_data = None

                    try:
                        grant_data = grt.modules.MySQLParserServices.parseStatementDetails(
                            context, statement)
                        if not grant_data['error']:
                            # Gets the target scope for the privileges
                            target_string = grant_data['target']

                            target = None

                            # Search for an already existing target
                            for tgt in self._granted_privileges.keys():
                                if tgt.identical(target_string):
                                    target = tgt

                            # If not found, creates one
                            if not target:
                                target = PrivilegeTarget()
                                target.set_from_string(target_string)

                            # Gets the privilege list
                            priv_list = grant_data['privileges']

                            # Adds the privileges to the granted list
                            self.add_privileges(target, priv_list)
                        else:
                            log_error(
                                'An error occurred parsing GRANT statement: %s\n -> %s\n'
                                % (statement, grant_data['error']))
                    except Exception, exc:
                        log_error(
                            'An error occurred parsing GRANT statement: %s\n -> %s\n'
                            % (statement, exc))

            else:
                log_warning('There are no grants defined for %s@%s\n' %
                            (self.user, self.host))
    def refresh(self):
        self.tree.clear()
        for table in self.table_manager.table_names or []:
            try:
                rset = self.editor.executeManagementQuery(
                    self.show_query % {
                        'table': table.replace("`", "``"),
                        'schema': self.schema.replace("`", "``")
                    }, 0)
            except grt.DBError as err:
                log_warning("Error querying index info for %s.%s: %s\n" %
                            (self.schema, table, err[0]))
                continue
            ok = rset.goToFirstRow()
            while ok:
                if not self.filter or self.filter(rset):
                    node = self.tree.add_node()
                    node.set_icon_path(0, self.icon_path)
                    i = 0
                    for field_obj, ctype, caption, width, min_version in self.columns:
                        if min_version and not self.target_version.is_supported_mysql_version_at_least(
                                Version.fromstr(min_version)):
                            continue
                        format_func = None
                        field = None
                        try:
                            format_func = field_obj['format_func']
                            field = field_obj['field']
                        except:
                            field = field_obj

                        if ctype == mforms.IntegerColumnType:
                            if type(field) is int:
                                node.set_int(i, rset.intFieldValue(field) or 0)
                            else:
                                node.set_int(
                                    i,
                                    rset.intFieldValueByName(field) or 0)
                        else:
                            if type(field) is int:
                                node.set_string(
                                    i,
                                    rset.stringFieldValue(field) or ""
                                    if format_func is None else format_func(
                                        rset.stringFieldValue(field)))
                            else:
                                node.set_string(
                                    i,
                                    rset.stringFieldValueByName(field) or ""
                                    if format_func is None else format_func(
                                        rset.stringFieldValueByName(field)))
                        i += 1
                ok = rset.nextRow()
        self.refresh_row_count()
Beispiel #5
0
    def _connect_ssh(self):
        """Create the SSH client and set up the connection.
        
        Any exception coming from paramiko will be notified as an error
        that would cause the failure of the connection. Some of these are:
        
        paramiko.AuthenticationException   --- raised when authentication failed for some reason
        paramiko.PasswordRequiredException --- raised when a password is needed to unlock a private key file;
                                               this is a subclass of paramiko.AuthenticationException
        """
        try:

            config = paramiko.config.SSHConfig()
            config_file_path = self._get_ssh_config_path()
            if config_file_path:
                with open(config_file_path) as f:
                    config.parse(f)

            opts = config.lookup(self._server[0])
            ssh_known_hosts_file = None
            if "userknownhostsfile" in opts:
                ssh_known_hosts_file = opts["userknownhostsfile"]
            else:
                self._client.get_host_keys().clear()
                ssh_known_hosts_file = '~/.ssh/known_hosts'

                if platform.system().lower() == "windows":
                    ssh_known_hosts_file = '%s\ssh\known_hosts' % mforms.App.get(
                    ).get_user_data_folder()

            try:
                self._client.load_host_keys(
                    os.path.expanduser(ssh_known_hosts_file))
            except IOError, e:
                log_warning(
                    "IOError, probably caused by file %s not found, the message was: %s\n"
                    % (ssh_known_hosts_file, e))

            if "stricthostkeychecking" in opts and opts[
                    "stricthostkeychecking"].lower() == "no":
                self._client.set_missing_host_key_policy(WarningPolicy())
            else:
                self._client.set_missing_host_key_policy(
                    StoreIfConfirmedPolicy())

            has_key = bool(self._keyfile)
            self._client.connect(self._server[0],
                                 self._server[1],
                                 username=self._username,
                                 key_filename=self._keyfile,
                                 password=self._password,
                                 look_for_keys=has_key,
                                 allow_agent=has_key,
                                 timeout=SSH_CONNECTION_TIMEOUT)
Beispiel #6
0
 def handle_sql_disconnection(self, e):
     self.disconnect_sql()
     if e.is_error_recoverable():
         log_warning(
             "Error is recoverable. Reconnecting to MySQL server.\n")
         try:
             self.connect_sql()
             if self.is_sql_connected():
                 return True
         except MySQLError as er:
             log_warning("Auto-reconnection failed: %s\n" % er)
         return False
     return False
def ts_iso_to_local(ts, fmt):
    if ts[-1] == "Z":
        ts = ts[:-1]
    if "." in ts:  # strip the millisecond part
        ts, _, ms = ts.partition(".")
        ms = "." + ms
    else:
        ms = ""
    try:
        local_time = calendar.timegm(
            datetime.datetime.strptime(ts, "%Y-%m-%dT%H:%M:%S").timetuple())
        return time.strftime(fmt, time.localtime(local_time)) + ms
    except Exception as e:
        log_warning("Error parsing timestamp %s: %s\n" % (ts, e))
        return ts
    def load_privileges(self, host):
      
        # Clears any previously loaded privileges
        self._granted_privileges = {}
        
        if host in self.applicant_hosts:
            # If there are hosts it means there are privileges applicable for the user
            # On the indicated host
            result = self.context.ctrl_be.exec_query("SHOW GRANTS FOR `%s`@`%s`" % (self.user, host))
            
            context = grt.modules.MySQLParserServices.createParserContext(self._character_sets, self._target_version, 'STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION', 1)
            
            if result:
                while result.nextRow():
                    statement = result.stringByIndex(1)
                    grant_data = None
                    
                    try:
                        grant_data = grt.modules.MySQLParserServices.parseStatementDetails(context, statement)
                        if not grant_data['error']:
                            # Gets the target scope for the privileges
                            target_string = grant_data['target']
            
                            target = None
            
                            # Search for an already existing target
                            for tgt in self._granted_privileges.keys():
                                if tgt.identical(target_string):
                                    target = tgt
            
                            # If not found, creates one
                            if not target:
                                target = PrivilegeTarget()
                                target.set_from_string(target_string)
            
                            # Gets the privilege list
                            priv_list = grant_data['privileges']
            
                            # Adds the privileges to the granted list
                            self.add_privileges(target, priv_list)
                        else:
                            log_error('An error occurred parsing GRANT statement: %s\n -> %s\n' % (statement, grant_data['error']))
                    except Exception, exc:
                        log_error('An error occurred parsing GRANT statement: %s\n -> %s\n' % (statement, exc))

            else:
                log_warning('There are no grants defined for %s@%s\n' % (self.user, self.host))
    def _connect_ssh(self):
        """Create the SSH client and set up the connection.
        
        Any exception coming from paramiko will be notified as an error
        that would cause the failure of the connection. Some of these are:
        
        paramiko.AuthenticationException   --- raised when authentication failed for some reason
        paramiko.PasswordRequiredException --- raised when a password is needed to unlock a private key file;
                                               this is a subclass of paramiko.AuthenticationException
        """
        try:
            
            config = paramiko.config.SSHConfig()
            config_file_path = self._get_ssh_config_path()
            if config_file_path:
                with open(config_file_path) as f:
                    config.parse(f)
                
            opts = config.lookup(self._server[0])
            ssh_known_hosts_file = None
            if "userknownhostsfile" in opts:
                ssh_known_hosts_file = opts["userknownhostsfile"]
            else:
                self._client.get_host_keys().clear()
                ssh_known_hosts_file = '~/.ssh/known_hosts'
                
                if platform.system().lower() == "windows":
                    ssh_known_hosts_file = '%s\ssh\known_hosts' % mforms.App.get().get_user_data_folder()

            try:
                self._client.load_host_keys(os.path.expanduser(ssh_known_hosts_file))
            except IOError, e:
                log_warning("IOError, probably caused by file %s not found, the message was: %s\n" % (ssh_known_hosts_file, e))

            if "stricthostkeychecking" in opts and opts["stricthostkeychecking"].lower() == "no":
                self._client.set_missing_host_key_policy(WarningPolicy())
            else:
                self._client.set_missing_host_key_policy(StoreIfConfirmedPolicy())
                
            has_key = bool(self._keyfile)
            self._client.connect(self._server[0], self._server[1], username=self._username,
                                 key_filename=self._keyfile, password=self._password,
                                 look_for_keys=has_key, allow_agent=has_key, timeout=SSH_CONNECTION_TIMEOUT)
Beispiel #10
0
    def exec_query_multi_result(self, q, auto_reconnect=True):
        ret = None
        if self.sql is not None:
            try:
                ret = self.sql.exec_query_multi_result(q)
            except QueryError as e:
                log_warning("Error executing query multi result %s: %s\n" %
                            (q, strip_password(str(e))))
                if auto_reconnect and e.is_connection_error():
                    log_warning(
                        "exec_query_multi_result: Loss of connection to mysql server was detected.\n"
                    )
                    self.handle_sql_disconnection(e)
                else:  # if exception is not handled, give a chance to the caller do it
                    raise e
        else:
            log_debug("sql connection is down\n")

        return ret
Beispiel #11
0
    def exec_sql(self, q, auto_reconnect=True):
        if self.sql is not None:
            try:
                ret = self.sql.execute(q)
                cnt = self.sql.updateCount()
                return ret, cnt
            except QueryError as e:
                log_warning("Error executing SQL %s: %s\n" %
                            (strip_password(q), strip_password(str(e))))
                if auto_reconnect and e.is_connection_error():
                    log_warning(
                        "exec_sql: Loss of connection to mysql server was detected.\n"
                    )
                    self.handle_sql_disconnection(e)
                else:
                    raise e
        else:
            log_debug("sql connection is down\n")

        return None, -1
Beispiel #12
0
 def wait_connection(self, port):
     tunnel = self.tunnel_by_port.get(port)
     if not tunnel:
         return 'Could not find a tunnel for port %d' % port
     error = None
     close_tunnel = False
     tunnel.port_is_set.wait()
     if tunnel.isAlive():
         while True:
             # Process any message in queue. Every retrieved message is printed.
             # If an error is detected in the queue, exit returning its message:
             try:
                 msg_type, msg = tunnel.q.get_nowait()
             except queue.Empty:
                 continue
             else:
                 if msg_type == 'KEY_ERROR':
                     if mforms.Utilities.show_message("SSH Server Fingerprint Missing", msg['msg'], "Continue", "Cancel", "") == mforms.ResultOk:
                         msg['obj'].client._host_keys.add(msg['obj'].hostname, msg['obj'].key.get_name(), msg['obj'].key)
                         if msg['obj'].client._host_keys_filename is not None:
                             try:
                                 if os.path.isdir(os.path.dirname(msg['obj'].client._host_keys_filename)) == False:
                                     log_warning("Host_keys directory is missing, recreating it\n")
                                     os.makedirs(os.path.dirname(msg['obj'].client._host_keys_filename))
                                 if os.path.exists(msg['obj'].client._host_keys_filename) == False:
                                     log_warning("Host_keys file is missing, recreating it\n")
                                     open(msg['obj'].client._host_keys_filename, 'a').close()
                                 msg['obj'].client.save_host_keys(msg['obj'].client._host_keys_filename)
                                 log_warning("Successfully saved host_keys file.\n")
                             except IOError as e:
                                 error = str(e)
                                 break;
                         error = "Server key has been stored"
                     else:
                         error = "User cancelled"
                     close_tunnel = True
                     break # Exit returning the error message
                 elif msg_type == 'IO_ERROR':
                     error = msg
                     break # Exit returning the error message
                 else:
                     time.sleep(0.3)
                 _msg = msg
                 if type(msg) is tuple:
                     msg = '\n' + ''.join(traceback.format_exception(*msg))
                     _msg = str(_msg[1])
                 log_debug("%s: %s\n" % (msg_type, msg))
                 if msg_type == 'ERROR':
                     error = _msg
                     break  # Exit returning the error message
             
             if (not tunnel.is_connecting() or not tunnel.isAlive()) and tunnel.q.empty():  
                 break
             time.sleep(0.3)
     log_debug("returning from wait_connection(%s): %s\n" % (port, error))
     # we need to close tunnel so it get opened again, without it we may have problems later
     if close_tunnel:
         tunnel.close()
         del self.tunnel_by_port[port]
     return error
def download_server_install_script(ctrl_be):
    server_helper = ctrl_be.server_helper
    profile = server_helper.profile
    install_script_path = server_helper.join_paths(profile.basedir, "share", "mysql_sys_schema.sql")

    try:

        if not server_helper.file_exists(install_script_path):
            log_warning("The server does not supply the sys schema install script\n")
            return None
          
        if not server_helper.check_file_readable(install_script_path):
            log_warning("The server supplies the sys schema install script, but it's not readable\n")
            return None

        install_script_content = server_helper.get_file_content(install_script_path)

    except Exception:
        import traceback
        log_error("There was an exception when making validations:\n%s\n" % traceback.format_exc())
        return None

    # Import the file to the local user space
    local_install_script_path = os.path.join(mforms.App.get().get_user_data_folder(), "install_sys_script.sql")
    f = open(local_install_script_path, "w")
    
    for line in install_script_content.split('\n'):
        content = ""
        if line.startswith("CREATE DEFINER='root'@'localhost'"):
            # Set delimiters for functions/procedures/triggers, so that we can run them on the server properly
            delimiter = delimiter = grt.root.wb.options.options['SqlDelimiter']
            line = re.sub(r'(.*);', r'\1' + delimiter, line)
            content = "\nDELIMITER " + delimiter + "\n%s\nDELIMITER ;\n" % line
        else:
            content = line
        f.write("%s\n" % content)
    f.close()
    
    return local_install_script_path
    def load_hosts(self):
        """
        Will identify the host in the database that are applicable to a given host
        (Host in database can be defined with wildcard so it is not a straight comparison)
        """
        hosts = None

        # note the comparison of the host field is backwards than normal.
        # this in on purpose to allow identifying using SQL all the hosts in the grant definitions
        # that do match the host being queried.
        result = self.context.ctrl_be.exec_query("""SELECT host 
                                                    FROM mysql.user 
                                                    WHERE user = '******' AND '%s' LIKE host""" % (self.user, self.host))
        if result:
            hosts = []
            while result.nextRow():
                hosts.append(result.stringByIndex(1))
        else:
            log_warning('There are no grants defined for the user %s on hosts matching %s\n' % (self.user, self.host))

        self.applicant_hosts = hosts

        return hosts
    def refresh(self):
        self.tree.clear()
        for table in self.table_manager.table_names or []:
            try:
                rset = self.editor.executeManagementQuery(self.show_query % {'table' : table.replace("`", "``"), 'schema' : self.schema.replace("`", "``")}, 0)
            except grt.DBError, err:
                log_warning("Error querying index info for %s.%s: %s\n" % (self.schema, table, err[0]))
                continue
            ok = rset.goToFirstRow()
            while ok:
                if not self.filter or self.filter(rset):
                    node = self.tree.add_node()
                    node.set_icon_path(0, self.icon_path)
                    i = 0
                    for field_obj, ctype, caption, width, min_version in self.columns:
                        if min_version and not self.target_version.is_supported_mysql_version_at_least(Version.fromstr(min_version)):
                            continue
                        format_func = None
                        field = None
                        try:
                            format_func = field_obj['format_func']
                            field = field_obj['field']
                        except:
                            field = field_obj

                        if ctype == mforms.IntegerColumnType:
                            if type(field) is int:
                                node.set_int(i, rset.intFieldValue(field) or 0)
                            else:
                                node.set_int(i, rset.intFieldValueByName(field) or 0)
                        else:
                            if type(field) is int:
                                node.set_string(i, rset.stringFieldValue(field) or "" if format_func is None else format_func(rset.stringFieldValue(field)))
                            else:
                                node.set_string(i, rset.stringFieldValueByName(field) or "" if format_func is None else format_func(rset.stringFieldValueByName(field)))
                        i += 1
                ok = rset.nextRow()
 def wait_connection(self, port):
     tunnel = self.tunnel_by_port.get(port)
     if not tunnel:
         return 'Could not find a tunnel for port %d' % port
     error = None
     tunnel.port_is_set.wait()
     if tunnel.isAlive():
         while True:
             # Process any message in queue. Every retrieved message is printed.
             # If an error is detected in the queue, exit returning its message:
             try:
                 msg_type, msg = tunnel.q.get_nowait()
             except Queue.Empty:
                 continue
             else:
                 if msg_type == 'KEY_ERROR':
                     if mforms.Utilities.show_message("SSH Server Fingerprint Missing", msg['msg'], "Continue", "Cancel", "") == mforms.ResultOk:
                         msg['obj'].client._host_keys.add(msg['obj'].hostname, msg['obj'].key.get_name(), msg['obj'].key)
                         if msg['obj'].client._host_keys_filename is not None:
                             try:
                                 if os.path.isdir(os.path.dirname(msg['obj'].client._host_keys_filename)) == False:
                                     log_warning("Host_keys directory is missing, recreating it\n")
                                     os.makedirs(os.path.dirname(msg['obj'].client._host_keys_filename))
                                 if os.path.exists(msg['obj'].client._host_keys_filename) == False:
                                     log_warning("Host_keys file is missing, recreating it\n")
                                     open(msg['obj'].client._host_keys_filename, 'a').close()
                                 msg['obj'].client.save_host_keys(msg['obj'].client._host_keys_filename)
                                 log_warning("Successfully saved host_keys file.\n")
                             except IOError, e:
                                 error = str(e)
                                 break;
                         error = "Server key has been stored"
                     else:
                         error = "User cancelled"
                     break # Exit returning the error message
                 elif msg_type == 'IO_ERROR':
                     error = msg
                     break # Exit returning the error message
                 else:
                     time.sleep(0.3)
                 _msg = msg
                 if type(msg) is tuple:
                     msg = '\n' + ''.join(traceback.format_exception(*msg))
                     _msg = str(_msg[1])
                 log_debug("%s: %s\n" % (msg_type, msg))
                 if msg_type == 'ERROR':
                     error = _msg
                     break  # Exit returning the error message
Beispiel #17
0
 def _confirm_server_fingerprint(self, host, port, fingerprint_exception):
     msg = {
         'msg':
         "The authenticity of host '%(0)s (%(0)s)' can't be established.\n%(1)s key fingerprint is %(2)s\nAre you sure you want to continue connecting?"
         % {
             '0': "%s:%s" % (host, port),
             '1': fingerprint_exception.key.get_name(),
             '2': fingerprint_exception.fingerprint
         },
         'obj': fingerprint_exception
     }
     if mforms.Utilities.show_message("SSH Server Fingerprint Missing",
                                      msg['msg'], "Continue", "Cancel",
                                      "") == mforms.ResultOk:
         msg['obj'].client._host_keys.add(msg['obj'].hostname,
                                          msg['obj'].key.get_name(),
                                          msg['obj'].key)
         if msg['obj'].client._host_keys_filename is not None:
             try:
                 if os.path.isdir(
                         os.path.dirname(msg['obj'].client.
                                         _host_keys_filename)) == False:
                     log_warning(
                         "Host_keys directory is missing, recreating it\n")
                     os.makedirs(
                         os.path.dirname(
                             msg['obj'].client._host_keys_filename))
                 if os.path.exists(
                         msg['obj'].client._host_keys_filename) == False:
                     log_warning(
                         "Host_keys file is missing, recreating it\n")
                     open(msg['obj'].client._host_keys_filename,
                          'a').close()
                 msg['obj'].client.save_host_keys(
                     msg['obj'].client._host_keys_filename)
                 log_warning("Successfully saved host_keys file.\n")
                 return True
             except IOError as e:
                 error = str(e)
                 raise e
     else:
         return False
Beispiel #18
0
 def missing_host_key(self, client, hostname, key):
     import binascii
     log_warning('WARNING: Unknown %s host key for %s: %s\n' %
                 (key.get_name(), hostname,
                  binascii.hexlify(key.get_fingerprint())))
Beispiel #19
0
            import traceback
            log_debug2("Backtrace was: " % traceback.format_stack())
            return "ERROR " + str(exc)

        os_info = test_ssh_connection.detect_operating_system_version()
        if os_info:
            os_type, os_name, os_variant, os_version = os_info
            log_info("Instance test: detected remote OS: %s (%s), %s, %s\n" %
                     (os_info))

            # check if the admin access error was because of wrong OS set
            if os_type != profile.target_os:
                return "ERROR Wrong Remote OS configured for connection. Set to %s, but was detected as %s" % (
                    profile.target_os, os_type)
        else:
            log_warning(
                "Instance test: could not determine OS version information\n")

            return "ERROR Could not determine remote OS details"

        return "OK"

    elif what == "disconnect":
        if test_ssh_connection:
            test_ssh_connection = None
        return "OK"

    elif what == "check_privileges":
        return "ERROR"

    elif what in ("find_config_file", "check_config_path",
                  "check_config_section"):
Beispiel #20
0
def testInstanceSettingByName(what, connection, server_instance):
    global test_ssh_connection
    log_debug("Test %s in %s\n" % (what, connection.name))

    profile = ServerProfile(connection, server_instance)
    if what == "connect_to_host":
        if test_ssh_connection:
            test_ssh_connection = None

        log_info("Instance test: Connecting to %s\n" % profile.ssh_hostname)

        try:
            test_ssh_connection = wb_admin_control.WbAdminControl(
                profile, None, connect_sql=False, test_only=True)
            test_ssh_connection.init()

            grt.send_info("connected.")
        except Exception as exc:
            log_error("Exception: %s\n" % str(exc))
            import traceback
            log_debug2("Backtrace was: ", traceback.format_stack())
            return "ERROR " + str(exc)
        except:
            return "ERROR"

        try:
            test_ssh_connection.acquire_admin_access()
        except Exception as exc:

            log_error("Exception: %s\n" % str(exc))
            import traceback
            log_debug2("Backtrace was: " % traceback.format_stack())
            return "ERROR " + str(exc)

        os_info = test_ssh_connection.detect_operating_system_version()
        if os_info:
            os_type, os_name, os_variant, os_version = os_info
            log_info("Instance test: detected remote OS: %s (%s), %s, %s\n" %
                     (os_info))

            # check if the admin access error was because of wrong OS set
            if os_type != profile.target_os:
                return "ERROR Wrong Remote OS configured for connection. Set to %s, but was detected as %s" % (
                    profile.target_os, os_type)
        else:
            log_warning(
                "Instance test: could not determine OS version information\n")

            return "ERROR Could not determine remote OS details"

        return "OK"

    elif what == "disconnect":
        if test_ssh_connection:
            test_ssh_connection = None
        return "OK"

    elif what == "check_privileges":
        return "ERROR"

    elif what in ("find_config_file", "check_config_path",
                  "check_config_section"):
        config_file = profile.config_file_path
        print("Check if %s exists in remote host" % config_file)
        try:
            if not test_ssh_connection.ssh.fileExists(config_file):
                return "ERROR File %s doesn't exist" % config_file
            else:
                print("File was found in expected location")
        except IOError:
            return 'ERROR Could not verify the existence of the file %s' % config_file

        if what == "check_config_path":
            return "OK"

        section = profile.config_file_section
        cfg_file_content = ""
        print("Check if %s section exists in %s" % (section, config_file))
        try:
            #local_file = test_ssh_connection.fetch_file(config_file)
            cfg_file_content = test_ssh_connection.server_helper.get_file_content(
                path=config_file)
        except Exception as exc:
            import traceback
            traceback.print_exc()
            return "ERROR " + str(exc)

        if ("[" + section + "]") in cfg_file_content:
            return "OK"
        return "ERROR Couldn't find section %s in the remote config file %s" % (
            section, config_file)

    elif what in ("find_config_file/local", "check_config_path/local",
                  "check_config_section/local"):
        config_file = profile.config_file_path
        config_file = wb_admin_control.WbAdminControl(
            profile, None,
            connect_sql=False).expand_path_variables(config_file)
        print("Check if %s can be accessed" % config_file)
        if os.path.exists(config_file):
            print("File was found at the expected location")
        else:
            return "ERROR File %s doesn't exist" % config_file

        if what == "check_config_path/local":
            return "OK"

        section = profile.config_file_section
        print("Check if section for instance %s exists in %s" %
              (section, config_file))
        if check_if_config_file_has_section(open(config_file, "r"), section):
            print("[%s] section found in configuration file" % section)
            return "OK"
        return "ERROR Couldn't find section [%s] in the config file %s" % (
            section, config_file)

    elif what == "find_error_files":
        return "ERROR"

    elif what == "check_admin_commands":
        path = profile.start_server_cmd
        cmd_start = None
        if path.startswith("/"):
            cmd_start = path.split()[0]
            if not test_ssh_connection.ssh.fileExists(cmd_start):
                return "ERROR %s is invalid" % path

        path = profile.stop_server_cmd
        if path.startswith("/"):
            cmd = path.split()[0]
            if cmd != cmd_start and not test_ssh_connection.ssh.fileExists(
                    cmd):
                return "ERROR %s is invalid" % path

        return "OK"

    elif what == "check_admin_commands/local":
        path = profile.start_server_cmd
        cmd_start = None
        if path.startswith("/"):
            cmd_start = path.split()[0]
            if not os.path.exists(cmd_start):
                return "ERROR %s is invalid" % path

        path = profile.stop_server_cmd
        if path.startswith("/"):
            cmd = path.split()[0]
            if cmd != cmd_start and not os.path.exists(cmd):
                return "ERROR %s is invalid" % path

        return "OK"

    return "ERROR bad command"
Beispiel #21
0
    def acquire_admin_access(self):
        """Make sure we have access to the instance for admin (for config file, start/stop etc)"""
        if self.server_control or not self.server_profile.admin_enabled:
            return

        if self.server_profile.uses_ssh:
            if self.editor is not None:
                if self.editor.sshConnection.isConnected() == 0:
                    if self.editor.sshConnection.connect() != 0:
                        raise OperationCancelledError(
                            "Could not connect to SSH server")
                self.sshBridge = self.editor.sshConnection
                self.server_helper = ServerManagementHelper(
                    self.server_profile, self.sshBridge)
            else:
                ssh = grt.modules.Workbench.createSSHSession(
                    self.server_profile.get_settings_object())
                if ssh.connect() != 0:
                    raise OperationCancelledError(
                        "Could not connect to SSH server")
                self.sshBridge = ssh
                self.server_helper = ServerManagementHelper(
                    self.server_profile, self.sshBridge)
        else:
            self.server_helper = ServerManagementHelper(
                self.server_profile, None)

        if self.server_helper:
            self.server_profile.expanded_config_file_path = self.server_helper.shell.expand_path_variables(
                self.server_profile.config_file_path)
            self.query_server_installation_info()

        # detect the exact type of OS we're managing
        os_info = self.detect_operating_system_version()
        if os_info:
            os_type, os_name, os_variant, os_version = os_info
            log_debug(
                "Target OS detection returned: os_type=%s, os_name=%s, os_variant=%s, os_version=%s\n"
                % (os_type, os_name, os_variant, os_version))
            self.server_profile.set_os_version_info(os_type or "", os_name
                                                    or "", os_variant or "",
                                                    os_version or "")
        else:
            log_warning("Could not detect target OS details\n")
        # init server control instance appropriate for what we're connecting to
        if self.server_profile.uses_wmi:
            self.server_control = ServerControlWMI(self.server_profile,
                                                   self.server_helper,
                                                   self.password_handler)
        elif self.server_profile.uses_ssh or self.server_profile.is_local:
            self.server_control = ServerControlShell(self.server_profile,
                                                     self.server_helper,
                                                     self.password_handler)
        else:
            log_error(
                """Unknown management method selected. Server Profile is possibly inconsistent
uses_ssh: %i uses_wmi: %i\n""" %
                (self.server_profile.uses_ssh, self.server_profile.uses_wmi))
            raise Exception(
                "Unknown management method selected. Server Profile is possibly inconsistent"
            )

        # Sets the default logging callback
        if self.server_control:
            self.log_cb = self.server_control.info
            self.end_line = ""
Beispiel #22
0
    def _connect_ssh(self):
        """Create the SSH client and set up the connection.
        
        Any exception coming from paramiko will be notified as an error
        that would cause the failure of the connection. Some of these are:
        
        paramiko.AuthenticationException   --- raised when authentication failed for some reason
        paramiko.PasswordRequiredException --- raised when a password is needed to unlock a private key file;
                                               this is a subclass of paramiko.AuthenticationException
        """
        try:
            
            config = paramiko.config.SSHConfig()
            config_file_path = self._get_ssh_config_path()
            if config_file_path:
                with open(config_file_path) as f:
                    config.parse(f)
                
            opts = config.lookup(self._server[0])
            ssh_known_hosts_file = None
            if "userknownhostsfile" in opts:
                ssh_known_hosts_file = opts["userknownhostsfile"]
            else:
                self._client.get_host_keys().clear()
                ssh_known_hosts_file = '~/.ssh/known_hosts'
                
                if platform.system().lower() == "windows":
                    ssh_known_hosts_file = '%s\ssh\known_hosts' % mforms.App.get().get_user_data_folder()

            try:
                self._client.load_host_keys(os.path.expanduser(ssh_known_hosts_file))
            except IOError as e:
                log_warning("IOError, probably caused by file %s not found, the message was: %s\n" % (ssh_known_hosts_file, e))

            if "stricthostkeychecking" in opts and opts["stricthostkeychecking"].lower() == "no":
                self._client.set_missing_host_key_policy(WarningPolicy())
            else:
                self._client.set_missing_host_key_policy(StoreIfConfirmedPolicy())
                
            has_key = bool(self._keyfile)
            self._client.connect(self._server[0], self._server[1], username=self._username,
                                 key_filename=self._keyfile, password=self._password,
                                 look_for_keys=has_key, allow_agent=has_key, timeout=SSH_CONNECTION_TIMEOUT)
        except paramiko.BadHostKeyException as exc:
            self.notify_exception_error('ERROR',format_bad_host_exception(exc, '%s\ssh\known_hosts' % mforms.App.get().get_user_data_folder() if platform.system().lower() == "windows" else "~/.ssh/known_hosts file"))
            return False
        except paramiko.BadAuthenticationType as exc:
            self.notify_exception_error('ERROR', "Bad authentication type, the server is not accepting this type of authentication.\nAllowed ones are:\n %s" % exc.allowed_types, sys.exc_info());
            return False
        except paramiko.AuthenticationException as exc:
            self.notify_exception_error('ERROR', "Authentication failed, please check credentials.\nPlease refer to logs for details", sys.exc_info())
            return False
        except socket.gaierror as exc:
            self.notify_exception_error('ERROR', "Error connecting to SSH server: %s\nPlease refer to logs for details." % str(exc))
            return False
        except paramiko.ChannelException as exc:
            self.notify_exception_error('ERROR', "Error connecting SSH channel.\nPlease refer to logs for details: %s" % str(exc), sys.exc_info())
            return False
        except SSHFingerprintNewError as exc:
            self.notify_exception_error('KEY_ERROR', { 'msg': "The authenticity of host '%(0)s (%(0)s)' can't be established.\n%(1)s key fingerprint is %(2)s\nAre you sure you want to continue connecting?"  % {'0': "%s:%s" % (self._server[0], self._server[1]), '1': exc.key.get_name(), '2': exc.fingerprint}, 'obj': exc})
            return False
        except IOError as exc:
            #Io should be report to the user, so maybe he will be able to fix this issue
            self.notify_exception_error('IO_ERROR', "IO Error: %s.\n Please refer to logs for details." % str(exc), sys.exc_info())
            return False

        except Exception as exc:
            self.notify_exception_error('ERROR', "Authentication error, unhandled exception caught in tunnel manager, please refer to logs for details", sys.exc_info())
            return False
        else:
            log_debug("connect_ssh2 OK\n")
            return True
    def analyze_file(self):
        self.reset_column_fix()
        with open(self._filepath, 'rb') as csvfile:
            if self.dialect is None:
                csvsample = []
                for i in range(0, 2):  #read two lines as a sample
                    line = csvfile.readline()
                    if len(line) > 0:
                        csvsample.append(line)

                csvsample_len = len(csvsample)
                csvsample = "".join(csvsample)
                self.dialect = csv.Sniffer().sniff(csvsample)
                self.has_header = csv.Sniffer().has_header(csvsample)
                if self.has_header and csvsample_len == 1:
                    self.has_header = False

                csvfile.seek(0)
                self.options['filedseparator'][
                    'value'] = self.dialect.delimiter
                self.options['lineseparator'][
                    'value'] = self.dialect.lineterminator
                self.options['encolsestring']['value'] = self.dialect.quotechar
            else:
                self.dialect.delimiter = self.options['filedseparator'][
                    'value']
                self.dialect.lineterminator = self.options['lineseparator'][
                    'value']
                self.dialect.quotechar = self.options['encolsestring']['value']

                csvfile.seek(0)

            try:
                reader = UniReader(csvfile,
                                   self.dialect,
                                   encoding=self._encoding)
                self._columns = []
                row_line = None
                try:
                    row_line = reader.next()
                except StopIteration, e:
                    pass

                if row_line:
                    for col_value in row_line:
                        self._columns.append({
                            'name':
                            self.fix_column_name(col_value),
                            'type':
                            'text',
                            'is_string':
                            True,
                            'is_geometry':
                            False,
                            'is_bignumber':
                            False,
                            'is_number':
                            False,
                            'is_date_or_time':
                            False,
                            'is_bin':
                            False,
                            'is_float':
                            False,
                            'is_json':
                            False,
                            'value': []
                        })

                    ii = -1
                    for ii, row in enumerate(
                            reader):  #we will read only first few rows
                        if ii < 5:
                            for j, col_value in enumerate(row):
                                try:
                                    json_value = json.loads(col_value)
                                    self._columns[j]['is_string'] = False
                                    self._columns[j]['is_json'] = True
                                    self._columns[j]['value'].append(
                                        json_value)
                                except Exception as e:
                                    self._columns[j]['value'].append(col_value)
                        else:
                            break

                    # We hit here an edge case, enumerate didn't run but row_line contains something,
                    # we will assume this means that there's just one line
                    if ii == -1 and len(row_line) > 0:
                        ii = 1

                    if not self.has_header and ii == 1:  # This means there were one line which was consumed as a header we need to copy it to use as values
                        log_warning(
                            "File: %s, probably has got only one line, using it as a header and data\n"
                            % self._filepath)
                        for j, col_value in enumerate(row_line):
                            try:
                                json_value = json.loads(col_value)
                                self._columns[j]['is_string'] = False
                                self._columns[j]['is_json'] = True
                                self._columns[j]['value'].append(json_value)
                            except Exception as e:
                                self._columns[j]['value'].append(col_value)

                    for col in self._columns:
                        # Means the file is missing some data or is mallformed
                        if len(col['value']) == 0:
                            log_error(
                                "Error analyzing file, we have no values.")
                            return False

                        gtype = self.guess_type(col['value'])
                        if gtype not in self._type_map:
                            raise Exception("Unhandled type: %s in %s" %
                                            (gtype, self._type_map))
                        else:
                            col['type'] = gtype
                            for attrib in col:
                                if attrib.startswith("is_"):
                                    if attrib == self._type_map[gtype]:
                                        col[attrib] = True
                                    else:
                                        col[attrib] = False
            except (UnicodeError, UnicodeDecodeError), e:
                import traceback
                log_error(
                    "Error analyzing file, probably encoding issue: %s\n Traceback is: %s"
                    % (e, traceback.format_exc()))
                self._last_analyze = False
                return False
    def analyze_file(self):
        with open(self._filepath, 'rb') as csvfile:
            if self.dialect is None:
                csvsample = []
                for i in range(0,2): #read two lines as a sample
                    line = csvfile.readline()
                    if len(line) > 0:
                        csvsample.append(line)
                
                csvsample_len = len(csvsample)
                csvsample = "".join(csvsample)
                self.dialect = csv.Sniffer().sniff(csvsample)
                self.has_header = csv.Sniffer().has_header(csvsample)
                if self.has_header and csvsample_len == 1:
                    self.has_header = False
                    
                csvfile.seek(0)
                self.options['filedseparator']['value'] = self.dialect.delimiter 
                self.options['lineseparator']['value'] = self.dialect.lineterminator 
                self.options['encolsestring']['value'] = self.dialect.quotechar 
            else:
                self.dialect.delimiter = self.options['filedseparator']['value']
                self.dialect.lineterminator = self.options['lineseparator']['value']
                self.dialect.quotechar = self.options['encolsestring']['value']
                csvfile.seek(0)
                
            try:
                reader = UniReader(csvfile, self.dialect, encoding=self._encoding)
                self._columns = []
                row_line = None
                try:
                    row_line = reader.next()
                except StopIteration, e:
                    pass
                
                
                if row_line:
                    for col_value in row_line:
                        self._columns.append({'name': col_value, 'type': 'text', 'is_string': True, 'is_geometry': False, 'is_bignumber': False, 'is_number': False, 'is_date_or_time': False, 'is_bin': False, 'is_float':False, 'is_json':False,'value': []})
                        
                    for i, row in enumerate(reader): #we will read only first few rows
                        if i < 5:
                            for j, col_value in enumerate(row):
                                try:
                                    json_value = json.loads(col_value)
                                    self._columns[j]['is_string'] = False
                                    self._columns[j]['is_json'] = True
                                    self._columns[j]['value'].append(json_value)
                                except Exception as e:
                                    self._columns[j]['value'].append(col_value)
                        else:
                            break
                        
                    if not self.has_header and i == 1: # This means there were one line which was consumed as a header we need to copy it to use as values
                        log_warning("File: %s, probably has got only one line, using it as a header and data\n" % self._filepath)
                        for j, col_value in enumerate(row_line):
                            try:
                                json_value = json.loads(col_value)
                                self._columns[j]['is_string'] = False
                                self._columns[j]['is_json'] = True
                                self._columns[j]['value'].append(json_value)
                            except Exception as e:
                                self._columns[j]['value'].append(col_value)

                    for col in self._columns:
                        # Means the file is missing some data or is mallformed
                        if len(col['value']) == 0:
                            return False

                        gtype = self.guess_type(col['value'])
                        if gtype not in self._type_map:
                            raise Exception("Unhandled type: %s in %s" % (gtype, self._type_map))
                        else:
                            col['type'] = gtype
                            for attrib in col:
                                if attrib.startswith("is_"):
                                    if attrib == self._type_map[gtype]:
                                        col[attrib] = True
                                    else:
                                        col[attrib] = False
            except (UnicodeError, UnicodeDecodeError), e:
                import traceback
                log_error("Error analyzing file, probably encoding issue: %s\n Traceback is: %s" % (e, traceback.format_exc()))
                self._last_analyze = False
                return False
 def missing_host_key(self, client, hostname, key):
     import binascii
     log_warning('WARNING: Unknown %s host key for %s: %s\n' % (key.get_name(), hostname, binascii.hexlify(key.get_fingerprint())))
Beispiel #26
0
        except Exception, exc:
            log_error("Exception: %s" % exc.message)
            import traceback
            log_debug2("Backtrace was: " % traceback.format_stack())
            return "ERROR "+str(exc)

        os_info = test_ssh_connection.detect_operating_system_version()
        if os_info:
            os_type, os_name, os_variant, os_version = os_info
            log_info("Instance test: detected remote OS: %s (%s), %s, %s\n" % (os_info))

            # check if the admin access error was because of wrong OS set
            if os_type != profile.target_os:
                return "ERROR Wrong Remote OS configured for connection. Set to %s, but was detected as %s" % (profile.target_os, os_type)
        else:
            log_warning("Instance test: could not determine OS version information\n")

            return "ERROR Could not determine remote OS details"

        return "OK"

    elif what == "disconnect":
        if test_ssh_connection:
            test_ssh_connection = None
        return "OK"

    elif what == "check_privileges":
        return "ERROR"

    elif what in ("find_config_file", "check_config_path", "check_config_section"):
        config_file = profile.config_file_path
Beispiel #27
0
    def detect_operating_system_version(self):
        """Try to detect OS information in the remote server, via SSH connection.
            
        The information returned is (os_type, os_name, os_variant, os_version)
            
            
            os_type: one of the main types of OS supported (one of wbaOS.windows, wbaOS.linux, wbaOS.darwin)
            os_name: the exact name of the OS (for example Windows, Linux, macOS, Solaris)
            os_variant: the variant of the OS, especially for Linux distributions (for example Ubuntu, Fedora etc.)
            os_version: the version of the OS (for example 19.10)
        """
        if self.is_ssh_connected() or self.server_profile.is_local:
            o = io.StringIO()
            # check if windows
            rc = self.server_helper.execute_command('ver',
                                                    output_handler=o.write)
            if rc == 0 and o.getvalue().strip().startswith(
                    "Microsoft Windows"):
                os_type = wbaOS.windows
                os_name = "Windows"
                os_variant = "Windows"
                os_version = o.getvalue().strip()

                o = io.StringIO()
                rc = self.server_helper.execute_command(
                    'reg query "HKLM\Software\Microsoft\Windows NT\CurrentVersion" /v "ProductName"',
                    output_handler=o.write)
                if rc == 0:
                    os_name = " ".join(
                        o.getvalue().strip().split("\n")[-1].split()[2:])
                return os_type, os_name, os_variant, os_version
            else:
                os_type, os_name, os_variant, os_version = (None, None, None,
                                                            None)

                o = io.StringIO()
                if self.server_helper.execute_command(
                        "uname", output_handler=o.write) == 0:
                    ostype = o.getvalue().strip()
                    log_debug("uname in remote system returned %s\n" % ostype)
                    if ostype == "Darwin":
                        os_type = wbaOS.darwin
                        o = io.StringIO()
                        if self.server_helper.execute_command(
                                "sw_vers", output_handler=o.write) == 0:
                            for line in o.getvalue().strip().split("\n"):
                                line = line.strip()
                                if line:
                                    k, v = line.split(":", 1)
                                    if k == "ProductName":
                                        os_name = v.strip()
                                        os_variant = v.strip()
                                    elif k == "ProductVersion":
                                        os_version = v.strip()
                    else:
                        os_type = wbaOS.linux

                        o = io.StringIO()
                        if self.server_helper.execute_command(
                                "lsb_release -a", output_handler=o.write) == 0:
                            os_name = "Linux"
                            for line in o.getvalue().strip().split("\n"):
                                line = line.strip()
                                if line:
                                    k, sep, v = line.partition(":")
                                    if k == "Distributor ID":
                                        os_variant = v.strip()
                                    elif k == "Release":
                                        os_version = v.strip()
                        else:
                            log_warning(
                                "lsb_release utility not found in target server. Consider installing its package if possible\n"
                            )
                            # some distros don't install lsb things by default
                            try:
                                info = self.server_helper.get_file_content(
                                    "/etc/fedora-release")
                                if info:
                                    os_name = "Linux"
                                    os_variant = "Fedora"
                                    os_version = info[info.find("release") +
                                                      1:].split()[0].strip()
                            except (IOError, OSError):
                                pass
                            try:
                                info = self.server_helper.get_file_content(
                                    "/etc/debian_version")
                                if info:
                                    os_name = "Linux"
                                    os_variant = "Debian"
                                    os_version = info.strip()
                            except (IOError, OSError):
                                pass
                            try:
                                info = self.server_helper.get_file_content(
                                    "/etc/oracle-release")
                                if info:
                                    os_name = "Linux"
                                    os_variant = "Oracle Linux"
                                    os_version = info[info.find("release") +
                                                      1:].split()[0].strip()
                            except (IOError, OSError):
                                pass
                    return os_type, os_name, os_variant, os_version
                else:
                    log_error(
                        "Could not execute uname command on remote server, system type is unknown\n"
                    )
        return None