def on_merge(self, changes): # Handle button presses number_of_vm = "There are %s Virtual Machines running." \ % (virt.number_of_domains()) if "action.lock" in changes: self.logger.info("Locking screen") self._lock_dialog = LockDialog() self.application.ui.hotkeys_enabled(False) self.widgets.add(self._lock_dialog) return self._lock_dialog elif "action.unlock" in changes and "password" in changes: self.logger.info("UnLocking screen") pam = security.PAM() if pam.authenticate(os.getlogin(), changes["password"]): self._lock_dialog.close() self.application.ui.hotkeys_enabled(True) else: self.application.notice("The provided password was incorrect.") self.widgets["password"].text("") elif "action.logoff" in changes: self.logger.info("Logging off") self.application.quit() elif "action.restart" in changes: self.logger.info("Restarting") return ui.ConfirmationDialog( "confirm.reboot", "Confirm System Restart", number_of_vm + "\nThis will restart the system," "proceed?") elif "confirm.reboot.yes" in changes: self.logger.info("Confirm Restarting") self.dry_or(lambda: system.reboot()) elif "action.poweroff" in changes: self.logger.info("Shutting down") return ui.ConfirmationDialog( "confirm.shutdown", "Confirm System Poweroff", number_of_vm + "\nThis will shut down the system," "proceed?") elif "confirm.shutdown.yes" in changes: self.logger.info("Confirm Shutting down") self.dry_or(lambda: system.poweroff()) elif "action.hostkey" in changes: self.logger.info("Showing hostkey") return HostkeyDialog("dialog.hostkey", "Host Key") elif "action.cpu_details" in changes: self.logger.info("Showing CPU details") return CPUFeaturesDialog("dialog.cpu_details", "CPU Details") elif "_save" in changes: self.widgets["dialog.hostkey"].close()
def quit(instance): def ui_quit(dialog, changes): instance.ui.quit() txt = "Are you sure you want to quit?" dialog = ui.ConfirmationDialog("dialog.exit", "Exit", txt, [ ui.Button("dialog.exit.yes", "Yes"), ui.CloseButton("dialog.exit.close", "No") ]) dialog.buttons[0].on_activate.clear() dialog.buttons[0].on_activate.connect(ui.CloseAction()) dialog.buttons[0].on_activate.connect(ui_quit) instance.show(dialog)
def quit(instance): def ui_quit(dialog, changes): utils.system.reboot() instance.ui.quit() txt = "Are you sure you want to quit? The system will be rebooted." dialog = ui.ConfirmationDialog("dialog.exit", "Exit", txt, [ ui.Button("dialog.exit.yes", "Reboot"), ui.CloseButton("dialog.exit.close", "Cancel") ]) dialog.buttons[0].on_activate.clear() dialog.buttons[0].on_activate.connect(ui.CloseAction()) dialog.buttons[0].on_activate.connect(ui_quit) instance.show(dialog)
def __drop_to_shell(self): def open_console(): utils.process.call("bash", shell=True) def return_ok(dialog, changes): with self.ui.suspended(): utils.console.reset() utils.console.writeln("Dropping to rescue shell...") open_console() try: txt = "Making changes in the rescue shell is unsupported. Do not " txt += "use this without guidance from support representatives" dialog = ui.ConfirmationDialog("dialog.shell", "Rescue Shell", txt) dialog.buttons[0].on_activate.clear() dialog.buttons[0].on_activate.connect(ui.CloseAction()) dialog.buttons[0].on_activate.connect(return_ok) self.show(dialog) except: # Error when the UI is not running open_console()
def on_merge(self, effective_changes): self.logger.info("Saving network stuff") changes = Changeset(self.pending_changes(False)) effective_model = Changeset(self.model()) effective_model.update(effective_changes) self.logger.debug("Changes: %s" % changes) self.logger.info("Effective changes %s" % effective_changes) self.logger.debug("Effective Model: %s" % effective_model) # This object will contain all transaction elements to be executed txs = utils.Transaction(_("Network Interface Configuration")) # Special case: A NIC was selected, display that dialog! if "nics" in changes and len(changes) == 1: iface = changes["nics"] self.logger.debug("Opening NIC Details dialog for '%s'" % iface) self._model_extra["dialog.nic.ifname"] = iface self._nic_dialog = NicDetailsDialog(self, iface) if network.NodeNetwork().is_configured(): txt = "Network Configuration detected an already configured " txt += "NIC. The configuration for that NIC is " txt += "going to be removed if changes are made. Proceed?" self._confirm_dialog = ui.ConfirmationDialog("dialog.confirm", "Confirm Network " "Settings", txt, ) return self._confirm_dialog else: return self._nic_dialog if "dialog.confirm.yes" in changes: self._confirm_dialog.close() return self._nic_dialog if "dialog.nic.close" in changes: self._nic_dialog.close() return if "button.toggle_bond" in changes: m_bond = defaults.NicBonding() mnet = defaults.Network() if m_bond.retrieve()["slaves"]: if mnet.retrieve()["iface"] == m_bond.retrieve()["name"]: # Remove network config if primary devce was this # bond mnet.configure_no_networking() m_bond.configure_no_bond() txs += m_bond.transaction() txs += mnet.transaction() else: self._bond_dialog = CreateBondDialog("dialog.bond") self.widgets.add(self._bond_dialog) return self._bond_dialog if "button.ping" in changes: self.logger.debug("Opening ping page") self.application.switch_to_plugin( ping.Plugin) return if "dialog.nic.identify" in changes: ifname = self._model_extra["dialog.nic.ifname"] nic = utils.network.NodeNetwork().build_nic_model(ifname) nic.identify() self.application.notice("Flashing lights of '%s'" % nic.ifname) return nameservers = [] dns_keys = ["dns[0]", "dns[1]"] if effective_changes.contains_any(dns_keys): nameservers += effective_model.values_for(dns_keys) if nameservers: self.logger.info("Setting new nameservers: %s" % nameservers) model = defaults.Nameservers() model.update(nameservers) txs += model.transaction() timeservers = [] ntp_keys = ["ntp[0]", "ntp[1]"] if effective_changes.contains_any(ntp_keys): timeservers += effective_model.values_for(ntp_keys) if timeservers: self.logger.info("Setting new timeservers: %s" % timeservers) model = defaults.Timeservers() model.update(timeservers) txs += model.transaction() hostname_keys = ["hostname"] if effective_changes.contains_any(hostname_keys): value = effective_model.values_for(hostname_keys) self.logger.info("Setting new hostname: %s" % value) model = defaults.Hostname() model.update(*value) txs += model.transaction() # For the NIC details dialog: if effective_changes.contains_any(self._nic_details_group): # If any networking related key was changed, reconfigure networking # Fetch the values for the nic keys, they are used as arguments args = effective_model.values_for(self._nic_details_group) txs += self._configure_nic(*args) if effective_changes.contains_any(self._bond_group): mb = defaults.NicBonding() mnet = defaults.Network() args = effective_model.values_for(["bond.name", "bond.slaves.selected", "bond.options"]) self.logger.debug("args: %s" % args) mb.update(*args) txs += mb.transaction() txs += mnet.transaction() self._bond_dialog.close() progress_dialog = ui.TransactionProgressDialog("dialog.txs", txs, self) progress_dialog.run() if "dialog.nic.save" in changes: # Close the remaing details dialog self._nic_dialog.close() # Behaves like a page reload return self.ui_content()
def show_dialog(self): def open_console(): if self.temp_cfg_file and os.path.isfile(self.temp_cfg_file): try: utils.process.call("reset; screen " + "ovirt-node-hosted-engine-setup" + " --config-append=%s" % self.temp_cfg_file, shell=True) self.__persist_configs() except: self.logger.exception("hosted-engine failed to deploy!", exc_info=True) else: self.logger.error("Cannot trigger ovirt-hosted-engine-setup" + " because the configuration file was not " + "generated, please check the location " + "referenced in /var/log/ovirt-node.log") self.application.show(self.ui_content()) def return_ok(dialog, changes): self.application.ui.close_dialog("Begin Hosted Engine Setup") with self.application.ui.suspended(): open_console() if self.application.current_plugin() is self: try: # if show_progressbar is not set, the download process has # never started (PXE) or it finished if self._show_progressbar: # Clear out the counters once we're done, and hide the # progress bar self.widgets["download.progress"].current(0) self.widgets["download.status"].text("") self._show_progressbar = False self._model["download.progress"] = 0 self._model["download.status"] = "" # if the temp config file is empty, we removed it in the model # because there was an exception, so don't do anything if self.temp_cfg_file and not os.path.isfile( self.temp_cfg_file): self.logger.debug("The temporary config file %s does not" "exist. Not running screen") return if self._install_ready: utils.console.writeln("Beginning Hosted Engine Setup ...") txt = "Setup will be ran with screen enabled that can be " txt += "reconnected in the event of a timeout or " txt += "connection failure.\n" txt += "\nIt can be reconnected by running 'screen -d -r'" dialog = ui.ConfirmationDialog("dialog.shell", "Begin Hosted Engine Setup", txt ) dialog.buttons[0].on_activate.clear() dialog.buttons[0].on_activate.connect(ui.CloseAction()) dialog.buttons[0].on_activate.connect(return_ok) self.application.show(dialog) else: if self._model['display_message']: msg = self._model['display_message'] self._model['display_message'] = '' else: msg = "\n\nError Downloading ISO/OVA Image!" dialog = ui.InfoDialog("dialog.notice", "Hosted Engine Setup", msg) self.application.show(dialog) except: # Error when the UI is not running self.logger.info("Exception on TUI!", exc_info=True) open_console() self.application.show(self.ui_content())
def on_merge(self, effective_changes): def close_dialog(): if self._dialog: self._dialog.close() self._dialog = None self._install_ready = False self._invalid_download = False self.temp_cfg_file = False effective_changes = Changeset(effective_changes) changes = Changeset(self.pending_changes(False)) effective_model = Changeset(self.model()) effective_model.update(effective_changes) self.logger.debug("Changes: %s" % changes) self.logger.debug("Effective Model: %s" % effective_model) if "button.dialog" in effective_changes: self._dialog = DeployDialog("Deploy Hosted Engine", self) self.widgets.add(self._dialog) return self._dialog if "button.status" in effective_changes: try: contents = utils.process.check_output( ["hosted-engine", "--vm-status"], stderr=utils.process.STDOUT ) except utils.process.CalledProcessError: contents = "\nFailed to collect hosted engine vm status, " \ "check ovirt-ha-broker logs." self.application.show(self.ui_content()) return ui.TextViewDialog("output.dialog", "Hosted Engine VM " "Status", contents) if "button.maintenance" in effective_changes: self._dialog = MaintenanceDialog("Hosted Engine Maintenance", self) self.widgets.add(self._dialog) return self._dialog if "maintenance.confirm" in effective_changes: close_dialog() if "maintenance.level" in effective_changes: level = effective_changes["maintenance.level"] try: utils.process.check_call(["hosted-engine", "--set-maintenance", "--mode=%s" % level]) except: self.logger.exception("Couldn't set maintenance level " "to %s" % level, exc_info=True) return ui.InfoDialog("dialog.error", "An error occurred", "Couldn't set maintenance level to " "%s. Check the logs" % level) if "deploy.additional" in effective_changes: close_dialog() def run_additional(*args): with self.application.ui.suspended(): try: utils.process.call( "reset; screen hosted-engine --deploy", shell=True) sys.stdout.write("Press <Return> to return to the TUI") console.wait_for_keypress() self.__persist_configs() except: self.logger.exception("hosted-engine failed to " "deploy!", exc_info=True) txt = ("Please set a password on the RHEV-M page of a host " "which has previously deployed hosted engine before " "continuing. This is required to retrieve the setup " "answer file") dialog = ui.ConfirmationDialog("dialog.add", "Prepare remote host", txt) yes_btn, cncl_btn = dialog.buttons yes_btn.label("Proceed") yes_btn.on_activate.connect(run_additional) return dialog if effective_changes.contains_any(["deploy.confirm"]): close_dialog() def make_tempfile(): if not os.path.exists(config.HOSTED_ENGINE_SETUP_DIR): os.makedirs(config.HOSTED_ENGINE_SETUP_DIR) if not os.path.exists(config.HOSTED_ENGINE_TEMPDIR): os.makedirs(config.HOSTED_ENGINE_TEMPDIR) temp_fd, temp_cfg_file = tempfile.mkstemp() os.close(temp_fd) return temp_cfg_file imagepath = effective_model["hosted_engine.diskpath"] pxe = effective_model["hosted_engine.pxe"] localpath = None # FIXME: dynamically enable the fields so we can't get into # this kind of situation. Selection should be ui.Options, not # a checkbox and a blank entry field # # Check whether we have unclear conditions if not imagepath and not pxe: self._model['display_message'] = "\n\nYou must enter a URL" \ " or choose PXE to install the Engine VM" return self.show_dialog() elif imagepath and pxe: self._model['display_message'] = "\n\nPlease choose either " \ "PXE or an image to " \ "retrieve, not both" return self.show_dialog() self.temp_cfg_file = make_tempfile() engine_keys = ["hosted_engine.diskpath", "hosted_engine.pxe"] txs = utils.Transaction("Setting up hosted engine") # FIXME: The "None" is for force_enable # Why are we setting force_enable? It clutters the code. We should # move force enabling it to checking for --dry instead model = HostedEngine() args = tuple(effective_model.values_for(engine_keys)) + (None,) model.update(*args) if "file://" in imagepath: localpath = imagepath[7:] elif imagepath: localpath = os.path.join(config.HOSTED_ENGINE_SETUP_DIR, os.path.basename(imagepath)) # Check whether we have enough conditions to run it right now if pxe or os.path.exists(localpath): def console_wait(event): event.wait() self._install_ready = True self.show_dialog() txs += model.transaction(self.temp_cfg_file) progress_dialog = ui.TransactionProgressDialog("dialog.txs", txs, self) t = threading.Thread(target=console_wait, args=(progress_dialog.event,)) t.start() progress_dialog.run() # The application doesn't wait until the progressdialog is # done, and it ends up being called asynchronously. Calling # in a thread and waiting to set threading.Event # time.sleep(5) # Otherwise start an async download else: path_parsed = urlparse(imagepath) if not path_parsed.scheme: self._model['display_message'] = ("\nCouldn't parse " "URL. please check " "it manually.") elif path_parsed.scheme == 'http' or \ path_parsed.scheme == 'https': self._show_progressbar = True self.application.show(self.ui_content()) self._image_retrieve(imagepath, config.HOSTED_ENGINE_SETUP_DIR) return self.ui_content()