def exec_cmd(self, cmd, as_admin=0, admin_password=None, output_handler=None, read_size=128, get_channel_cb=None): output = None retcode = None self.mtx.acquire() dprint_ex(3, "cmd = ", cmd, ", sudo = ", as_admin) try: (output, retcode) = WbAdminSSH.exec_cmd(self, cmd, as_admin=as_admin, admin_password=admin_password, output_handler=output_handler, read_size=read_size, get_channel_cb=get_channel_cb) dprint_ex(3, "Done cmd = ", cmd) finally: self.mtx.release() return (output, retcode)
def __init__(self, server_instance_settings): AppView.__init__(self, False, "admin", True) server_profile = ServerProfile(server_instance_settings, False) self.ctrl_be = wb_admin_control.WbAdminControl(server_profile, connect_sql=True) self.ctrl_be.init() version = self.ctrl_be.get_server_version() if type(version) is tuple: valid_versions = ((4, 0), (4, 1), (5, 0), (5, 1), (5, 2), (5, 4), (5, 5), (5, 6), (6, 0)) if version[:2] not in valid_versions: print version, "UNSUPPORTED" else: dprint_ex("Server version %s is supported" % str(version)) self.on_close(wb_admin_utils.weakcb(self, "handle_on_close")) # Create sections and add them to the admin page. self.configuration = wb_admin_main.WbAdminMainView( server_profile, self.ctrl_be, self.monitor) self.add(self.configuration, True, True)
def reader(self, ssh_session): what = None out = "" timeouts = 12 while self.running[0]: # running is passed in list via "refernce" try: ch = ssh_session.recv(1) timeouts = 12 if ch == "C": what = self.parse_cpu elif ch == "M": what = self.parse_mem elif ch == "\r" or ch == "\n": if what is not None: what(out) what = None out = "" elif ch in "0123456789. ": out += ch elif ch == ",": out += "." else: what = None out = "" except socket.timeout: timeouts -= 1 if timeouts <= 0: ssh_session.close() raise Exception("Can't read from remote Windows script") dprint_ex(1, "Leaving monitor thread which polls remote windows")
def run_version_select_form(version): form = Form(Form.main_form()) top_vbox = newBox(False) top_vbox.set_padding(16) top_vbox.set_spacing(16) info_hbox = newBox(True) info_hbox.set_spacing(16) img_box = newImageBox() img_box.set_image("warning_icon.png") right_vbox = newBox(False) right_vbox.set_spacing(12) warn_label = newLabel("Server version %s is not supported by Workbench\nconfiguration file management tool." % ".".join(map(lambda x: str(x), version))) right_vbox.add(warn_label, False, False) warn_label = newLabel("Although, you can select different server version\nfor the tool to use. Suggested version " "is given\nbelow. You can either pick version or type one." ) right_vbox.add(warn_label, False, False) warn_label = newLabel("Valid version formats are X.Y.ZZ or X.Y.\nAll other variants will resort to default - 5.1.") right_vbox.add(warn_label, False, False) if (type(version) is not tuple): version = (5,1) dprint_ex(1, "Given version is not a valid tuple object") try: version_maj = int(version[0]) + int(version[1]) / 10.0 except (ValueError, IndexError), e: version_maj = 5.1
def shutdown_event(self): self.poll_control = self.skip_poll if self.dbconn: self.dbconn.disconnect() self.dbconn = None self.poll_control = self.stopped dprint_ex(3, "SqlDataSource shutdown. poll_control =", self.poll_control)
def poll(self): if self.running[0] is False: self.ch.stdin.write("exit\r\n") self.ch.stdin.flush() return self.ch.stdin.write("cpu\r\n") self.ch.stdin.flush() self.ch.stdin.write("mem\r\n") self.ch.stdin.flush() value = self.get_mem() try: value = float(value) except ValueError: dprint_ex(3, "Can not convert mem value", value, " to float") value = None if value is not None: self.mem_widget[0].set_value(value) self.ctrl_be.uitask(self.mem_widget[0].set_description, "Mem: " + str(int(value)) + "%") value = self.get_cpu() try: value = float(value) except ValueError: value = None if value is not None: self.cpu_widget[0].set_value(value/100) self.ctrl_be.uitask(self.cpu_widget[0].set_description ,"CPU: " + str(int(value)) + "%")
def server_stopped_event(self): dprint_ex(1, "Handling stop event") if len(self.tabs) > 0 and hasattr(self.tabs[0], "print_output"): self.ctrl_be.uitask(self.tabs[0].print_output, "Server is stopped") self.notify_server_status_change("stopped") self.refresh_tasks_sleep_time = 3 dprint_ex(1, "Done handling stop event")
def refresh_tasks_thread(self): dprint_ex(2, "Entering refresh tasks thread") while not self.closing: status = "unknown" try: status = self.ctrl_be.is_server_running(verbose=0) except Exception, exc: import traceback traceback.print_exc() print "exception getting server status: %s" % exc control_event = None if self.last_server_status != status: if status == "running": control_event = "server_started" elif status == "stopped": control_event = "server_stopped" if control_event: self.ctrl_be.event_from_main(control_event) dprint_ex(3, "server running", status, ", self.closing =", self.closing) self.last_server_status = status time.sleep(self.refresh_tasks_sleep_time)
def server_started_event(self): dprint_ex(1, "Handling start event") if len(self.tabs) > 0 and hasattr(self.tabs[0], 'print_output'): self.ctrl_be.uitask(self.tabs[0].print_output, "Server is running") self.notify_server_status_change("running") self.refresh_tasks_sleep_time = 2 dprint_ex(1, "Done handling start event")
def poll_sources(self): while self.running[0] and self.ctrl_be.running: #sleep here for cmd in self.sources: cmd.poll() time.sleep(self.interval) dprint_ex(1, "exiting monitor thread...")
def read_from_script(self): line = "" while self.running[0]: c = self.ch.stdout.read(1) if c == ",": c = "." if c == "": break line += c if c == "\n": line = line.strip(" \r\t\n%") if len(line) == 0: print "Read empty string from script" # TODO: Probably need another way of informing. TBD else: if line[0] == 'C': self.mtx.acquire() self.cpu = line[2:] self.mtx.release() elif line[0] == 'M': self.mtx.acquire() self.mem = line[2:] self.mtx.release() line = "" dprint_ex(4, "WinLocalStats: line-", line, ", cpu-", self.cpu, ", mem", self.mem)
def poll(self): dprint_ex(5, "SqlDataSource poll. poll_control =", self.poll_control) if self.poll_control == self.polling and self.dbconn: result = None try: result = self.dbconn.executeQuery( self.sql) #ctrl_be from DataSource except QueryError, e: result = None if e.is_connection_error(): self.dbconn.disconnect() if e.is_error_recoverable(): self.dbconn = self.ctrl_be.get_new_sql_connection( False) if result is not None: while result.nextRow(): name = result.stringByName("Variable_name") if name in self.rev_sources: rev_src = self.rev_sources[name] value = float(result.stringByName("Value")) # rev_src contains list of sources and index of current variable in the sources for (src, i) in rev_src: src.set_var(i, value) res = src.calculate()
def get_password_for( self, service_type ): # Raises OperationCancelledError if user cancels pwd dlg. force_reset = False if self.pwd_store.has_key(service_type): if self.pwd_store[service_type] is None: force_reset = True else: return self.pwd_store[service_type] details = self.get_password_parameters(service_type) if not details: # No password needed for this service_type return None # special case for UAC used in windows if details == "UAC": return "UAC" title, service, account = details dprint_ex( 2, "request password for %s => %s, %s, %s" % (service_type, title, service, account)) accepted, password = mforms.Utilities.find_or_ask_for_password( title, service, account, force_reset) if accepted: if not password: password = "" self.pwd_store[service_type] = password return password else: raise OperationCancelledError("Password input cancelled")
def get_password_for(self, service_type): # Raises OperationCancelledError if user cancels pwd dlg. force_reset = False if self.pwd_store.has_key(service_type): if self.pwd_store[service_type] is None: force_reset = True else: return self.pwd_store[service_type] details = self.get_password_parameters(service_type) if not details: # No password needed for this service_type return None # special case for UAC used in windows if details == "UAC": return "UAC" title, service, account = details dprint_ex(2, "request password for %s => %s, %s, %s" % (service_type, title, service, account)) accepted, password = mforms.Utilities.find_or_ask_for_password(title, service, account, force_reset) if accepted: if not password: password = "" self.pwd_store[service_type] = password return password else: raise OperationCancelledError("Password input cancelled")
def create_ui(self): self.loading = True self.cfg_be = wb_admin_config_file_be.WbAdminConfigFileBE(self.server_profile, self.ctrl_be) sys_config_path = self.server_profile.config_file_path if sys_config_path is None: sys_config_path = "" self.file_name_ctrl.set_value(sys_config_path) self.section_ctrl.add_changed_callback(self.clear_and_load) try: self.myopts = self.cfg_be.get_possible_options() option_stats = self.cfg_be.get_option_set_stats() dprint_ex(1, "Options stats: '%s'" % str(option_stats)) if option_stats and type(option_stats) is dict: added = option_stats.get("added", None) if added is not None and added < 10: user_selected_version = run_version_select_form(option_stats["version"]) self.server_profile.set_server_version(".".join(map(lambda x: str(x), user_selected_version))) self.cfg_be.reload_possible_options() self.myopts = self.cfg_be.get_possible_options() option_stats = self.cfg_be.get_option_set_stats() dprint_ex(1, "Options stats after version correction: '%s'" % str(option_stats)) except KeyError: Utilities.show_error("Error", "Wrong version '" + self.version + "'given to admin plugin", "Close", None, None) self.load_options_from_cfg() #build ordered list of pages. Initially only skeleton pages are created, means only names. # Values into pages will be load as soon as page is switched to. self.pages = {} for page_name, page_content in self.myopts.iteritems(): self.pages[int(page_content['position'])] = Page(page_name, page_content) # False means page not created # page key is its position in UI. As we can have pages positions set like (1,2,4,5) # the position set needs to be sorted so pages appear in specified order page_positions = self.pages.keys() page_positions.sort() # Create dummy pages according to assigned position for page_pos in page_positions: page = self.pages[page_pos] page.panel = newScrollPanel(mforms.ScrollPanelNoFlags) self.tab_view.add_page(page.panel, page.page_name) if debug_level > 0: # Create file page page = Page("File", None) page.panel = newTextBox(mforms.BothScrollBars) page.set_update_cb(self.update_file_content_tab) self.pages[max(self.pages.keys()) + 1] = page self.tab_view.add_page(page.panel, page.page_name) # Create first page, so we display something from start self.create_page(1) self.loading = True # create_page resets loading flag self.tab_view.add_tab_changed_callback(self.tab_changed) self.loading = False
def shutdown(self): dprint_ex(2, " closing") self.closing = True for tab in self.tabs: if hasattr(tab, "shutdown"): res = tab.shutdown() if res is False: # It has to explicitely return False to cancel shutdown self.closing = False
def server_started_event(self): self.poll_control = self.started if self.dbconn: self.dbconn.disconnect() self.dbconn = None self.dbconn = self.ctrl_be.get_new_sql_connection(True) self.poll_control = self.polling dprint_ex(3, "SqlDataSource server started. poll_control =", self.poll_control)
def connection_selected(self): dprint_ex(4, "Enter") if not self.connection_list.get_selected_node(): self.kill_button.set_enabled(False) self.killq_button.set_enabled(False) else: self.kill_button.set_enabled(True) self.killq_button.set_enabled(True) dprint_ex(4, "Leave")
def local_run_cmd_windows(command, as_admin=False, admin_password=None, sudo_prefix=None, output_handler=None): # wrap cmd command = "cmd.exe /C " + command out_str = "" retcode = 1 if as_admin: try: from ctypes import c_int, WINFUNCTYPE, windll from ctypes.wintypes import HWND, LPCSTR, UINT prototype = WINFUNCTYPE(c_int, HWND, LPCSTR, LPCSTR, LPCSTR, LPCSTR, UINT) scriptparts = command.partition(" ") cmdname = scriptparts[0] cmdparams = scriptparts[2] paramflags = (1, "hwnd", 0), (1, "operation", "runas"), ( 1, "file", cmdname), (1, "params", cmdparams), (1, "dir", None), (1, "showcmd", 0) SHellExecute = prototype(("ShellExecuteA", windll.shell32), paramflags) ret = SHellExecute() # > 32 is OK, < 32 is error code retcode = 1 if ret > 32: retcode = 0 else: if ret == 0: dprint_ex(1, "Out of memory executing %s" % command) else: dprint_ex(1, "Error %i executing %s" % (ret, command)) return retcode except: import traceback traceback.print_exc() else: try: stdin, stdout, stderr = os.popen3(command) out = stdout.read() if not out: out = "" err = stderr.read() if not err: err = "" out_str = out + err retcode = stdout.close( ) # this doesn't really work, it will return None stderr.close() stdin.close() except Exception, exc: import traceback traceback.print_exc() retcode = 1 out_str = "Internal error: %s" % exc
def real_update_ui(self, server_status): dprint_ex(3, "server_status on enter is %s" % str(server_status)) if not self.server_profile.admin_enabled: return self.is_server_running_prev_check = server_status if self._ctrl_be.target_version and self._ctrl_be.target_version.is_supported_mysql_version_at_least(5, 7, 5): self.offline_mode_btn.show(True) else: self.offline_mode_btn.show(False) if server_status in ("running", "starting", "offline"): if server_status == "starting": self.long_status_msg.set_text("The database server is starting...") self.start_stop_btn.set_enabled(False) self.short_status_msg.set_color("#DDCC00") self.offline_mode_btn.set_text("Bring Offline") self.offline_mode_btn.set_enabled(False) elif server_status == "offline": self.offline_mode_btn.set_text("Bring Online") self.offline_mode_btn.set_enabled(True) server_status = "offline" self.short_status_msg.set_color("#0000B0") self.long_status_msg.set_text("The database server is in offline mode. To put it back into online mode, use the \"Online mode\" button") else: self.offline_mode_btn.set_enabled(True) self.offline_mode_btn.set_text("Bring Offline") self.start_stop_btn.set_enabled(True) self.short_status_msg.set_color("#00B000") self.long_status_msg.set_text("The database server is started and ready for client connections. To shut the server down, use the \"Stop Server\" button") self.short_status_msg.set_text(server_status) self.start_stop_btn.set_text("Stop Server") elif server_status in ("stopped", "stopping"): if server_status == "stopping": self.long_status_msg.set_text("The database server is stopping...") self.start_stop_btn.set_enabled(False) self.offline_mode_btn.set_enabled(False) self.short_status_msg.set_color("#DDCC00") else: self.start_stop_btn.set_enabled(True) self.offline_mode_btn.set_enabled(False) self.short_status_msg.set_color("#B00000") self.long_status_msg.set_text("The database server is stopped. To start the Server, use the \"Start Server\" button") self.short_status_msg.set_text(server_status) self.start_stop_btn.set_text("Start Server") else: self.long_status_msg.set_text("The state of the database server could not be determined. Please verify server profile settings.") self.short_status_msg.set_text("unknown") self.short_status_msg.set_color("#FF0000") self.start_stop_btn.set_text("Start Server") self.start_stop_btn.set_enabled(False) self.relayout() dprint_ex(3, "Leave")
def update_ui(self, server_status): dprint_ex(3, "server_status on enter is %s" % str(server_status)) if not self.server_profile.admin_enabled: return self.is_server_running_prev_check = server_status if self.ctrl_be.target_version and self.ctrl_be.target_version.is_supported_mysql_version_at_least(5, 7, 5): self.offline_mode_btn.show(True) else: self.offline_mode_btn.show(False) if server_status in ("running", "starting", "offline"): if server_status == "starting": self.long_status_msg.set_text("The database server is starting...") self.start_stop_btn.set_enabled(False) self.short_status_msg.set_color("#DDCC00") self.offline_mode_btn.set_text("Bring Offline") self.offline_mode_btn.set_enabled(False) elif server_status == "offline": self.offline_mode_btn.set_text("Bring Online") self.offline_mode_btn.set_enabled(True) server_status = "offline" self.short_status_msg.set_color("#0000B0") self.long_status_msg.set_text("The database server is in offline mode. To put it back into online mode, use the \"Online mode\" button") else: self.offline_mode_btn.set_enabled(True) self.offline_mode_btn.set_text("Bring Offline") self.start_stop_btn.set_enabled(True) self.short_status_msg.set_color("#00B000") self.long_status_msg.set_text("The database server is started and ready for client connections. To shut the server down, use the \"Stop Server\" button") self.short_status_msg.set_text(server_status) self.start_stop_btn.set_text("Stop Server") elif server_status in ("stopped", "stopping"): if server_status == "stopping": self.long_status_msg.set_text("The database server is stopping...") self.start_stop_btn.set_enabled(False) self.offline_mode_btn.set_enabled(False) self.short_status_msg.set_color("#DDCC00") else: self.start_stop_btn.set_enabled(True) self.offline_mode_btn.set_enabled(False) self.short_status_msg.set_color("#B00000") self.long_status_msg.set_text("The database server is stopped. To start the Server, use the \"Start Server\" button") self.short_status_msg.set_text(server_status) self.start_stop_btn.set_text("Start Server") else: self.long_status_msg.set_text("The state of the database server could not be determined. Please verify server profile settings.") self.short_status_msg.set_text("unknown") self.short_status_msg.set_color("#FF0000") self.start_stop_btn.set_text("Start Server") self.start_stop_btn.set_enabled(False) self.relayout() dprint_ex(3, "Leave")
def __init__(self, sql, mon_be): DataSource.__init__(self, "sql_source", mon_be, None) self.sql = sql self.mon_be = mon_be self.sources = {} self.rev_sources = {} self.dbconn = None self.ctrl_be.add_me_for_event("server_started", self) self.ctrl_be.add_me_for_event("server_stopped", self) self.ctrl_be.add_me_for_event("shutdown", self) self.poll_control = self.stopped dprint_ex(3, "SqlDataSource created. poll_control =", self.poll_control)
def fetch_windows_shell_info(self): # get some info from the remote shell result, code = self.get_cmd_output("chcp.com") if code == 0: result = result.strip(" .\r\n").split() if len(result) > 0: self.cmd_output_encoding = "cp" + result[-1] else: print "WARNING: Unable to determine codepage from shell: %s" % result result, code = self.get_cmd_output("echo %PROCESSOR_ARCHITECTURE%") if result: result = result.strip() ProgramFilesVar = None x86var = None if result != "x86": #we are on x64 win in x64 mode x86var = WIN_PROGRAM_FILES_X86_VAR ProgramFilesVar = WIN_PROGRAM_FILES_VAR else: result, code = self.get_cmd_output("echo %PROCESSOR_ARCHITEW6432%") if result: result = result.strip() if result == "%PROCESSOR_ARCHITEW6432%": #we are on win 32 x86var = WIN_PROGRAM_FILES_VAR ProgramFilesVar = WIN_PROGRAM_FILES_VAR else: #32bit app on x64 win x86var = WIN_PROGRAM_FILES_VAR ProgramFilesVar = WIN_PROGRAM_FILES_X64_VAR result, code = self.get_cmd_output("echo " + ProgramFilesVar) if code == 0: self.target_shell_variables["%ProgramFiles%"] = result.strip( "\r\n") if ProgramFilesVar != "%ProgramFiles%": self.target_shell_variables[ProgramFilesVar] = result.strip( "\r\n") else: print "WARNING: Unable to fetch ProgramFiles value in Windows machine: %s" % result # this one only exists in 64bit windows result, code = self.get_cmd_output("echo " + x86var) if code == 0: self.target_shell_variables["%ProgramFiles(x86)%"] = result.strip( "\r\n") else: print "WARNING: Unable to fetch ProgramFiles(x86) value in local Windows machine: %s" % result dprint_ex( 1, "Encoding: %s, Shell Variables: %s" % (self.cmd_output_encoding, self.target_shell_variables))
def parse_mem(self, text): text = text.strip(" \r\t\n") value = None try: value = float(text) except ValueError: value = None if value is not None: self.mtx.acquire() try: self.mem = value finally: self.mtx.release() dprint_ex(4, "Got mem stat value from remote script -", value)
def local_run_cmd_windows(command, as_admin=False, admin_password=None, sudo_prefix=None, output_handler=None): # wrap cmd command = "cmd.exe /C " + command out_str ="" retcode = 1 if as_admin: try: from ctypes import c_int, WINFUNCTYPE, windll from ctypes.wintypes import HWND, LPCSTR, UINT prototype = WINFUNCTYPE(c_int, HWND, LPCSTR, LPCSTR, LPCSTR, LPCSTR, UINT) scriptparts = command.partition(" ") cmdname = scriptparts[0] cmdparams = scriptparts[2] paramflags = (1, "hwnd", 0), (1, "operation", "runas"), (1, "file", cmdname), (1, "params", cmdparams), (1, "dir", None), (1, "showcmd", 0) SHellExecute = prototype(("ShellExecuteA", windll.shell32), paramflags) ret = SHellExecute() # > 32 is OK, < 32 is error code retcode = 1 if ret > 32: retcode = 0 else: if ret == 0: dprint_ex(1, "Out of memory executing %s" % command) else: dprint_ex(1, "Error %i executing %s" % (ret, command)) return retcode except: import traceback traceback.print_exc() else: try: stdin, stdout, stderr = os.popen3(command) out = stdout.read() if not out: out = "" err = stderr.read() if not err: err = "" out_str = out + err retcode = stdout.close() # this doesn't really work, it will return None stderr.close() stdin.close() except Exception, exc: import traceback traceback.print_exc() retcode = 1 out_str = "Internal error: %s"%exc
def fetch_windows_shell_info(self): # get some info from the remote shell result, code = self.get_cmd_output("chcp.com") if code == 0: result = result.strip(" .\r\n").split() if len(result) > 0: self.cmd_output_encoding = "cp" + result[-1] else: print "WARNING: Unable to determine codepage from shell: %s"%result result, code = self.get_cmd_output("echo %PROCESSOR_ARCHITECTURE%") if result: result = result.strip() ProgramFilesVar = None x86var = None if result != "x86":#we are on x64 win in x64 mode x86var = WIN_PROGRAM_FILES_X86_VAR ProgramFilesVar = WIN_PROGRAM_FILES_VAR else: result, code = self.get_cmd_output("echo %PROCESSOR_ARCHITEW6432%") if result: result = result.strip() if result == "%PROCESSOR_ARCHITEW6432%":#we are on win 32 x86var = WIN_PROGRAM_FILES_VAR ProgramFilesVar = WIN_PROGRAM_FILES_VAR else:#32bit app on x64 win x86var = WIN_PROGRAM_FILES_VAR ProgramFilesVar = WIN_PROGRAM_FILES_X64_VAR result, code = self.get_cmd_output("echo "+ ProgramFilesVar) if code == 0: self.target_shell_variables["%ProgramFiles%"] = result.strip("\r\n") if ProgramFilesVar != "%ProgramFiles%": self.target_shell_variables[ProgramFilesVar] = result.strip("\r\n") else: print "WARNING: Unable to fetch ProgramFiles value in Windows machine: %s"%result # this one only exists in 64bit windows result, code = self.get_cmd_output("echo "+ x86var) if code == 0: self.target_shell_variables["%ProgramFiles(x86)%"] = result.strip("\r\n") else: print "WARNING: Unable to fetch ProgramFiles(x86) value in local Windows machine: %s"%result dprint_ex(1, "Encoding: %s, Shell Variables: %s" % (self.cmd_output_encoding, self.target_shell_variables))
def update_ui(self, server_status): dprint_ex(3, "server_status on enter is %s" % str(server_status)) if not self.server_profile.admin_enabled: return self.is_server_running_prev_check = server_status if server_status in ("running", "starting"): if server_status == "starting": self.long_status_msg.set_text( "The database server is starting...") self.start_stop_btn.set_enabled(False) self.short_status_msg.set_color("#DDCC00") else: self.start_stop_btn.set_enabled(True) self.short_status_msg.set_color("#00DD00") self.long_status_msg.set_text( "The database server is started and ready for client connections. To shut the Server down, use the \"Stop Server\" button" ) self.short_status_msg.set_text(server_status) self.start_stop_btn.set_text("Stop Server") elif server_status in ("stopped", "stopping"): if server_status == "stopping": self.long_status_msg.set_text( "The database server is stopping...") self.start_stop_btn.set_enabled(False) self.short_status_msg.set_color("#DDCC00") else: self.start_stop_btn.set_enabled(True) self.short_status_msg.set_color("#DD0000") self.long_status_msg.set_text( "The database server is stopped. To start the Server, use the \"Start Server\" button" ) self.short_status_msg.set_text(server_status) self.start_stop_btn.set_text("Start Server") else: self.long_status_msg.set_text( "The state of the database server could not be determined, please verify server profile settings." ) self.short_status_msg.set_text("unknown") self.short_status_msg.set_color("#FF0000") self.start_stop_btn.set_text("Start Server") self.start_stop_btn.set_enabled(False) dprint_ex(3, "Leave")
def exec_cmd(self, cmd, as_admin = 0, admin_password = None, output_handler = None, read_size = 128, get_channel_cb = None): output = None retcode = None self.mtx.acquire() dprint_ex(3, "cmd = ", cmd, ", sudo = ", as_admin) try: (output, retcode) = WbAdminSSH.exec_cmd(self, cmd, as_admin=as_admin, admin_password=admin_password, output_handler=output_handler, read_size = read_size, get_channel_cb = get_channel_cb) dprint_ex(3, "Done cmd = ", cmd) finally: self.mtx.release() return (output, retcode)
def is_dir_writable(self, path): ret = False try: dirlist = os.listdir(path) filename = '~wba_write_test' cnt = 1 while True: if filename + str(cnt) not in dirlist: break cnt += 1 filename = os.path.join(path, filename + str(cnt)) fp = open(filename, 'w') fp.close() os.remove(filename) ret = True except (IOError, OSError), e: ret = False dprint_ex(1, "code=",e.errno)
def is_dir_writable(self, path): ret = False try: dirlist = os.listdir(path) filename = '~wba_write_test' cnt = 1 while True: if filename + str(cnt) not in dirlist: break cnt += 1 filename = os.path.join(path, filename + str(cnt)) fp = open(filename, 'w') fp.close() os.remove(filename) ret = True except (IOError, OSError), e: ret = False dprint_ex(1, "code=", e.errno)
def __init__(self, ctrl_be, server_profile, main_view, editor): mforms.AppView.__init__(self, False, "administrator", False) self.editor = editor self.owner = main_view self.tabs = [] self.name2page = {} self.config_ui = None self.closing = False self.tabview = newTabView(True) self.ctrl_be = ctrl_be self.old_active_tab = None self.server_profile = server_profile self.refresh_tasks_sleep_time = 2 # if we're in the Mac, we need to set the background color of the main view of the tab to white, # so that MTabSwitcher will take the cue and set the tab color to white too if self.server_profile.host_os == wbaOS.darwin: self.set_back_color("#ffffff") # Setup self self.set_managed() self.set_release_on_add() self.on_close(wb_admin_utils.weakcb(self, "handle_on_close")) self.ctrl_be.add_me_for_event("server_started", self) self.ctrl_be.add_me_for_event("server_stopped", self) self.add(self.tabview, True, True) Utilities.add_timeout(0.5, weakcb(self, "timeout")) self.timeout_thread = threading.Thread(target = self.refresh_tasks_thread) self.timeout_thread.setDaemon(True) self.timeout_thread.start() self.tabview.add_tab_changed_callback(self.tab_changed) self.timeout() # will call self.connect_mysql() and check if mysql is running self.ctrl_be.continue_events() # Process events which are queue during init dprint_ex(1, "WBA init complete")
def connection_selected(self): dprint_ex(4, "Enter") sel = self.connection_list.get_selection() if not sel: self.kill_button.set_enabled(False) self.killq_button.set_enabled(False) else: self.kill_button.set_enabled(True) self.killq_button.set_enabled(True) if self._showing_extras: if sel and len(sel) == 1: self.connection_details.update(sel[0]) else: self.connection_details.update(None) tab = self.extra_info_tab.get_active_tab() if tab == self.mdl_locks_page: self.refresh_mdl_list() elif tab == self.attributes_page: self.refresh_attr_list() dprint_ex(4, "Leave")
def __init__(self, server_instance_settings): AppView.__init__(self, False, "admin", True) server_profile = ServerProfile(server_instance_settings, False) self.ctrl_be = wb_admin_control.WbAdminControl(server_profile, connect_sql=True) self.ctrl_be.init() version = self.ctrl_be.get_server_version() if type(version) is tuple: valid_versions = ((4, 0), (4, 1), (5, 0), (5, 1), (5, 2), (5, 4), (5, 5), (5, 6), (6, 0)) if version[:2] not in valid_versions: print version, "UNSUPPORTED" else: dprint_ex("Server version %s is supported" % str(version)) self.on_close(wb_admin_utils.weakcb(self, "handle_on_close")) # Create sections and add them to the admin page. self.configuration = wb_admin_main.WbAdminMainView(server_profile, self.ctrl_be, self.monitor) self.add(self.configuration, True, True)
def run_version_select_form(version): form = Form(Form.main_form()) top_vbox = newBox(False) top_vbox.set_padding(16) top_vbox.set_spacing(16) info_hbox = newBox(True) info_hbox.set_spacing(16) img_box = newImageBox() img_box.set_image("warning_icon.png") right_vbox = newBox(False) right_vbox.set_spacing(12) warn_label = newLabel( "Server version %s is not supported by Workbench\nconfiguration file management tool." % ".".join(map(lambda x: str(x), version))) right_vbox.add(warn_label, False, False) warn_label = newLabel( "Although, you can select different server version\nfor the tool to use. Suggested version " "is given\nbelow. You can either pick version or type one.") right_vbox.add(warn_label, False, False) warn_label = newLabel( "Valid version formats are X.Y.ZZ or X.Y.\nAll other variants will resort to default - 5.1." ) right_vbox.add(warn_label, False, False) if (type(version) is not tuple): version = (5, 1) dprint_ex(1, "Given version is not a valid tuple object") try: version_maj = int(version[0]) + int(version[1]) / 10.0 except (ValueError, IndexError), e: version_maj = 5.1
def poll(self): dprint_ex(5, "SqlDataSource poll. poll_control =", self.poll_control) if self.poll_control == self.polling and self.dbconn: result = None try: result = self.dbconn.executeQuery(self.sql) #ctrl_be from DataSource except QueryError, e: result = None if e.is_connection_error(): self.dbconn.disconnect() if e.is_error_recoverable(): self.dbconn = self.ctrl_be.get_new_sql_connection(False) if result is not None: while result.nextRow(): name = result.stringByName("Variable_name") if name in self.rev_sources: rev_src = self.rev_sources[name] value = float(result.stringByName("Value")) # rev_src contains list of sources and index of current variable in the sources for (src, i) in rev_src: src.set_var(i, value) res = src.calculate()
def update_ui(self, server_status): dprint_ex(2, "Enter. server_status =", server_status) if not self.server_profile.admin_enabled: return self.is_server_running_prev_check = server_status if server_status in ("running", "starting"): if server_status == "starting": self.long_status_msg.set_text("The database server is starting...") self.start_stop_btn.set_enabled(False) self.short_status_msg.set_color("#DDCC00") else: self.start_stop_btn.set_enabled(True) self.short_status_msg.set_color("#00DD00") self.long_status_msg.set_text("The database server is started and ready for client connections. To shut the Server down, use the \"Stop Server\" button") self.short_status_msg.set_text(server_status) self.start_stop_btn.set_text("Stop Server") elif server_status in ("stopped", "stopping"): if server_status == "stopping": self.long_status_msg.set_text("The database server is stopping...") self.start_stop_btn.set_enabled(False) self.short_status_msg.set_color("#DDCC00") else: self.start_stop_btn.set_enabled(True) self.short_status_msg.set_color("#DD0000") self.long_status_msg.set_text("The database server is stopped. To start the Server, use the \"Start Server\" button") self.short_status_msg.set_text(server_status) self.start_stop_btn.set_text("Start Server") else: self.long_status_msg.set_text("The state of the database server could not be determined, please verify server profile settings.") self.short_status_msg.set_text("unknown") self.short_status_msg.set_color("#FF0000") self.start_stop_btn.set_text("Start Server") self.start_stop_btn.set_enabled(False) dprint_ex(2, "Leave")
def save_file_content_and_backup(self, filename, content, backup_extension, as_admin = False, admin_password = None): dprint_ex(1, "Saving file %s with backup (sudo=%s)" % (filename, as_admin)) if as_admin: tmp_name = self.tempdir+"\\wbfilesavetmp" tmp = open(tmp_name, "w+b") try: dprint_ex(1, "Writing file contents to tmp file %s" % tmp_name) tmp.write(content) tmp.close() if backup_extension and os.path.exists(filename): #dprint_ex(1, "Creating backup of %s to %s" % (filename, filename+backup_extension)) #self._copy_file(source = filename, dest = filename + backup_extension, # as_admin = as_admin, admin_password = admin_password) # Create backup and copy over file to final destination in a single command # This is done because running copy twice, would bring up the UAC dialog twice script = "copy /Y %s %s && copy /Y %s %s" % (quote_path_win(filename), quote_path_win(filename + backup_extension), quote_path_win(tmp_name), quote_path_win(filename)) dprint_ex(1, "Creating backup and commiting tmp file: %s" % script) output = [] res = self.process_ops.exec_cmd(script, as_admin = True, admin_password = admin_password, output_handler = lambda line, l= output: l.append(line) ) if res != 0: output = "\n".join(output) raise RuntimeError("Error while executing '%s'. Output = '%s'"%(script, output)) else: dprint_ex(1, "Copying over tmp file to final filename using sudo: %s -> %s" % (tmp_name, filename)) self._copy_file(source = tmp_name, dest = filename, as_admin = as_admin, admin_password = admin_password) dprint_ex(1, "Delete tmp file %s" % tmp_name) # delete tmp file ## BIZARRE STUFF GOING ON HERE # commenting out the following line, will make something in committing config file change fail # even tho the copies happen before this line.. wtf # os.remove(tmp_name) dprint_ex(1, "Done.") except Exception, exc: dprint_ex(1, str(exc)) if tmp: tmp.close() raise
def save_file_content_and_backup(self, filename, content, backup_extension, as_admin=False, admin_password=None): dprint_ex( 1, "Saving file %s with backup (sudo=%s)" % (filename, as_admin)) if as_admin: tmp_name = self.tempdir + "\\wbfilesavetmp" tmp = open(tmp_name, "w+b") try: dprint_ex(1, "Writing file contents to tmp file %s" % tmp_name) tmp.write(content) tmp.close() if backup_extension and os.path.exists(filename): #dprint_ex(1, "Creating backup of %s to %s" % (filename, filename+backup_extension)) #self._copy_file(source = filename, dest = filename + backup_extension, # as_admin = as_admin, admin_password = admin_password) # Create backup and copy over file to final destination in a single command # This is done because running copy twice, would bring up the UAC dialog twice script = "copy /Y %s %s && copy /Y %s %s" % ( quote_path_win(filename), quote_path_win(filename + backup_extension), quote_path_win(tmp_name), quote_path_win(filename)) dprint_ex( 1, "Creating backup and commiting tmp file: %s" % script) output = [] res = self.process_ops.exec_cmd( script, as_admin=True, admin_password=admin_password, output_handler=lambda line, l=output: l.append(line)) if res != 0: output = "\n".join(output) raise RuntimeError( "Error while executing '%s'. Output = '%s'" % (script, output)) else: dprint_ex( 1, "Copying over tmp file to final filename using sudo: %s -> %s" % (tmp_name, filename)) self._copy_file(source=tmp_name, dest=filename, as_admin=as_admin, admin_password=admin_password) dprint_ex(1, "Delete tmp file %s" % tmp_name) # delete tmp file ## BIZARRE STUFF GOING ON HERE # commenting out the following line, will make something in committing config file change fail # even tho the copies happen before this line.. wtf # os.remove(tmp_name) dprint_ex(1, "Done.") except Exception, exc: dprint_ex(1, str(exc)) if tmp: tmp.close() raise
def save_file_content_and_backup(self, filename, content, backup_extension, as_admin=False, admin_password=None): dprint_ex( 1, "Saving file %s with backup (sudo=%s)" % (filename, as_admin)) if as_admin: # The delete argument is only available starting from py 2.6 (NamedTemporaryFile deletes files on close in all cases, unless you pass delete=False) tmp = tempfile.NamedTemporaryFile(dir=self.tempdir) tmp_name = tmp.name try: dprint_ex(1, "Writing file contents to tmp file %s" % tmp_name) tmp.write(content) tmp.flush() if backup_extension and os.path.exists(filename): dprint_ex( 1, "Creating backup of %s to %s" % (filename, filename + backup_extension)) self._copy_file(source=filename, dest=filename + backup_extension, as_admin=as_admin, admin_password=admin_password) dprint_ex( 1, "Copying over tmp file to final filename using sudo: %s -> %s" % (tmp_name, filename)) self._copy_file(source=tmp_name, dest=filename, as_admin=as_admin, admin_password=admin_password) dprint_ex(1, "Done") tmp.close() except Exception, exc: dprint_ex(1, str(exc)) if tmp: tmp.close() raise
def __del__(self): dprint_ex(2, "Closing SSH connection") self.close()
def save_file_content_and_backup(self, path, content, backup_extension, as_admin = False, admin_password = None): # Check if dir, where config file will be stored is writable dirname, filename = splitpath(path) if not as_admin and not self.is_dir_writable(dirname.strip(" \r\t\n")): raise PermissionDeniedError("Cannot write to directory %s" % dirname) if self.ssh is not None: ## Get home dir for using as tmpdir homedir, status = self.process_ops.get_cmd_output("echo ~") if type(homedir) is unicode: homedir = homedir.encode("utf8") if type(homedir) is str: homedir = homedir.strip(" \r\t\n") else: homedir = None dprint_ex(2, "Got home dir", homedir) if not homedir: raise Exception("Unable to get path for remote home directory") tmpfilename = homedir + "/.wba.temp" dprint_ex(1, "Remotely writing contents to temporary file %s" % tmpfilename) dprint_ex(3, content) self.ssh.set_contents(tmpfilename, content) if backup_extension: dprint_ex(1, "Backing up %s" % path) backup_cmd = "/bin/cp " + quote_path(path) + " " + quote_path(path+backup_extension) self.process_ops.exec_cmd(backup_cmd, as_admin, admin_password) copy_to_dest = "/bin/cp " + quote_path(tmpfilename) + " " + quote_path(path) delete_tmp = "/bin/rm " + quote_path(tmpfilename) dprint_ex(1, "Copying file to final destination: %s" % copy_to_dest) self.process_ops.exec_cmd(copy_to_dest, as_admin, admin_password) dprint_ex(1, "Deleting tmp file: %s" % delete_tmp) self.process_ops.exec_cmd(delete_tmp) else: raise Exception("No SSH session active, cannot save file remotely")
def local_run_cmd_linux(command, as_admin=False, admin_password=None, sudo_prefix=default_sudo_prefix, output_handler=None): # pexpect used only in linux import pexpect # wrap cmd if as_admin: command = wrap_for_sudo(command, sudo_prefix) script = command.strip(" ") if script is None or len(script) == 0: return None temp_file = tempfile.NamedTemporaryFile() script = script + " > " + temp_file.name + " 2>&1; echo CMDRESULT$? >> " + temp_file.name result = None if "'" in script: print "' found in script", script raise Exception( "WBA: Internal error, unexpected character in script to be executed" ) if not as_admin: result = pexpect.run("/bin/bash -c '" + script + "'", withexitstatus=True) else: child = pexpect.spawn("/bin/bash -c '" + script + "'") # script should already have sudo prefix try: child.expect('assword', timeout=10) if admin_password is not None: child.write(admin_password + '\n') else: child.write("\n") except pexpect.TIMEOUT: #though we are not able to get the expected output, the password is fed anyway if admin_password is not None: child.write(admin_password + '\n') else: child.write("\n") except pexpect.EOF: #Nothing we can do, client is terminatd for some reason, try to read anything available dprint_ex(2, "Pipe from sudo is closed.", script) text = "" if child.isalive(): should_quit_read_loop = False while not should_quit_read_loop and child.isalive(): try: current_text = child.read_nonblocking(256, 30) if current_text.find('EnterPasswordHere') >= 0: try: child.close() except: pass temp_file.close() raise InvalidPasswordError( "Incorrect password for sudo") else: text += current_text except pexpect.TIMEOUT: pass except pexpect.EOF: should_quit_read_loop = True else: #Try to read text = child.read() child.close() text = temp_file.read() temp_file.close() idx = text.rfind("CMDRESULT") if (idx != -1): retcode = int(text[idx + 9:].strip(" \r\t\n")) if output_handler: output_handler(text[0:idx]) result = retcode return result
def save_file_content_and_backup(self, path, content, backup_extension, as_admin=False, admin_password=None): # Check if dir, where config file will be stored is writable dirname, filename = splitpath(path) if not as_admin and not self.is_dir_writable(dirname.strip(" \r\t\n")): raise PermissionDeniedError("Cannot write to directory %s" % dirname) if self.ssh is not None: ## Get temp dir for using as tmpdir tmpdir, status = self.process_ops.get_cmd_output("echo %temp%") if type(tmpdir) is unicode: tmpdir = tmpdir.encode("utf8") if type(tmpdir) is str: tmpdir = tmpdir.strip(" \r\t\n") if tmpdir[1] == ":": tmpdir = tmpdir[2:] else: dprint_ex( 1, "Temp directory path '" + tmpdir + " is not in expected form. The expected for is something like 'C:\\Windows\\Temp'" ) tmpdir = None dprint_ex(2, "Got temp dir", tmpdir) else: tmpdir = None if not tmpdir: tmpdir = dirname tmpfilename = tmpdir + r"\workbench-temp-file.ini" dprint_ex( 1, "Remotely writing contents to temporary file %s" % tmpfilename) dprint_ex(1, content) self.ssh.set_contents(tmpfilename, content) if backup_extension: dprint_ex(1, "Backing up %s" % path) backup_cmd = "copy /y " + quote_path_win( path) + " " + quote_path_win(path + backup_extension) msg, code = self.process_ops.get_cmd_output(backup_cmd) if code != 0: print backup_cmd, "->", msg raise RuntimeError("Error backing up file: %s" % msg) copy_to_dest = "copy /y " + quote_path_win( tmpfilename) + " " + quote_path_win(path) delete_tmp = "del " + quote_path_win(tmpfilename) dprint_ex(1, "Copying file to final destination: %s" % copy_to_dest) msg, code = self.process_ops.get_cmd_output(copy_to_dest) if code != 0: print copy_to_dest, "->", msg raise RuntimeError( "Error copying temporary file over destination file: %s\n%s to %s" % (msg, tmpfilename, path)) dprint_ex(1, "Deleting tmp file: %s" % delete_tmp) msg, code = self.process_ops.get_cmd_output(delete_tmp) if code != 0: print "Could not delete temporary file %s: %s" % (tmpfilename, msg) else: raise Exception("No SSH session active, cannot save file remotely")
def save_file_content_and_backup(self, path, content, backup_extension, as_admin = False, admin_password = None): # Check if dir, where config file will be stored is writable dirname, filename = splitpath(path) if not as_admin and not self.is_dir_writable(dirname.strip(" \r\t\n")): raise PermissionDeniedError("Cannot write to directory %s" % dirname) if self.ssh is not None: ## Get temp dir for using as tmpdir tmpdir, status = self.process_ops.get_cmd_output("echo %temp%") if type(tmpdir) is unicode: tmpdir = tmpdir.encode("utf8") if type(tmpdir) is str: tmpdir = tmpdir.strip(" \r\t\n") if tmpdir[1] == ":": tmpdir = tmpdir[2:] else: dprint_ex(1,"Temp directory path '" + tmpdir + " is not in expected form. The expected for is something like 'C:\\Windows\\Temp'") tmpdir = None dprint_ex(2, "Got temp dir", tmpdir) else: tmpdir = None if not tmpdir: tmpdir = dirname tmpfilename = tmpdir + r"\workbench-temp-file.ini" dprint_ex(1, "Remotely writing contents to temporary file %s" % tmpfilename) dprint_ex(1, content) self.ssh.set_contents(tmpfilename, content) if backup_extension: dprint_ex(1, "Backing up %s" % path) backup_cmd = "copy /y " + quote_path_win(path) + " " + quote_path_win(path+backup_extension) msg, code = self.process_ops.get_cmd_output(backup_cmd) if code != 0: print backup_cmd, "->", msg raise RuntimeError("Error backing up file: %s" % msg) copy_to_dest = "copy /y " + quote_path_win(tmpfilename) + " " + quote_path_win(path) delete_tmp = "del " + quote_path_win(tmpfilename) dprint_ex(1, "Copying file to final destination: %s" % copy_to_dest) msg, code = self.process_ops.get_cmd_output(copy_to_dest) if code != 0: print copy_to_dest, "->", msg raise RuntimeError("Error copying temporary file over destination file: %s\n%s to %s" % (msg, tmpfilename, path)) dprint_ex(1, "Deleting tmp file: %s" % delete_tmp) msg, code = self.process_ops.get_cmd_output(delete_tmp) if code != 0: print "Could not delete temporary file %s: %s" % (tmpfilename, msg) else: raise Exception("No SSH session active, cannot save file remotely")