예제 #1
0
    def add_new_tab(self, session_name, show_close_btn=True):
        """
        Add a new tab in the tab widget
        :param session_name: name to be displayed
        :param show_close_btn: if true we add the close button
        :return:
        """
        new_tab = QSSHSessionWidget(self)
        uuid = new_tab.uuid
        self.tabs.addTab(new_tab, session_name)

        if show_close_btn:
            kill_btn = QPushButton()
            kill_btn.setIcon(self.style().standardIcon(
                QStyle.SP_DialogCloseButton))
            kill_btn.clicked.connect(lambda: self.on_close(uuid))
            kill_btn.setToolTip('Close session')
            self.tabs.tabBar().setTabButton(self.tabs.count() - 1,
                                            QTabBar.RightSide, kill_btn)
        else:
            kill_btn = QPushButton()
            ico = QIcon()
            ico.addFile(resource_path('gui/icons/plus.png'))
            kill_btn.setIcon(ico)
            kill_btn.clicked.connect(self.on_new)
            kill_btn.setToolTip('New session')
            self.tabs.tabBar().setTabButton(self.tabs.count() - 1,
                                            QTabBar.RightSide, kill_btn)

        new_tab.logged_in.connect(self.on_login)
        new_tab.sessions_changed.connect(self.on_sessions_changed)
        logger.debug("Added new tab " + str(uuid))
예제 #2
0
    def kill_display(self):
        """
        Kill the display running on the server
        :return:
        """
        current_status = self.status

        if self.status is Status.FINISHED:
            self.terminate.emit(self.display_id)
            return

        try:
            logger.debug("Killing remote display " + str(self.display_name))
            self.status = Status.KILLING
            self.update_gui()

            self.kill_thread = KillThread(self.parent, self.session, self,
                                          current_status)
            self.kill_thread.finished.connect(self.on_killed)
            self.kill_thread.start()
        except:
            logger.error("Failed to start kill remote display thread " +
                         str(self.display_name))
            self.status = current_status
            self.update_gui()
예제 #3
0
    def __init__(self):
        super().__init__()

        pack_info = rcm_utils.pack_info()

        title = "Remote Connection Manager - CINECA - v" + pack_info.rcmVersion
        self.setWindowTitle(title)

        width = 1000
        height = 370

        screen_width = QDesktopWidget().width()
        screen_height = QDesktopWidget().height()

        self.setGeometry((screen_width / 2) - (width / 2),
                         (screen_height / 2) - (height / 2), width, height)

        self.setMinimumHeight(height)
        self.setMinimumWidth(width)

        self.build_menu()

        self.main_widget = MainWidget(self)
        self.setCentralWidget(self.main_widget)

        self.thread_pool = QThreadPool()

        logger.info("Welcome to RCM!")
        logger.debug("Multithreading with maximum %d threads" %
                     self.thread_pool.maxThreadCount())
예제 #4
0
    def update_gui(self):
        """
        Update the status of the job running on the server in the gui
        and set the buttons enabled True/False accordingly
        :return:
        """
        logger.debug("Updating display widget with status " + str(self.status))

        if self.status is Status.NOTDEFINED:
            self.connect_btn.setEnabled(False)
            self.share_btn.setEnabled(False)
            self.kill_btn.setEnabled(True)
            self.time.setText('Not defined')
            self.resources_label.setText('Not defined')

        if self.status is Status.PENDING:
            self.connect_btn.setEnabled(False)
            self.share_btn.setEnabled(False)
            self.kill_btn.setEnabled(True)
            self.time.setText('Not defined')
            self.resources_label.setText('Not defined')

        if self.status is Status.RUNNING:
            self.connect_btn.setEnabled(True)
            self.share_btn.setEnabled(True)
            self.kill_btn.setEnabled(True)
            if self.session:
                timeleft = str(self.session.hash['timeleft'])
                self.time.setText(timeleft)

                try:
                    strp_time = datetime.strptime(timeleft, "%H:%M:%S")
                    self.timeleft = timedelta(hours=strp_time.hour,
                                              minutes=strp_time.minute,
                                              seconds=strp_time.second)
                except:
                    self.timeleft = None
                self.resources_label.setText(str(self.session.hash['node']))
            else:
                self.time.setText('Not defined')
                self.resources_label.setText('Not defined')

        if self.status is Status.KILLING:
            self.connect_btn.setEnabled(False)
            self.share_btn.setEnabled(False)
            self.kill_btn.setEnabled(False)

        if self.status is Status.FINISHED:
            self.connect_btn.setEnabled(False)
            self.share_btn.setEnabled(False)
            self.kill_btn.setEnabled(True)

        self.status_label.setText(str(self.status))
        self.status_label.update()
예제 #5
0
    def reload(self):
        logger.debug("Reloading...")

        # Show the reload widget
        self.containerLoginWidget.hide()
        self.containerSessionWidget.hide()
        self.containerWaitingWidget.hide()
        self.containerReloadWidget.show()

        self.reload_thread = ReloadThread(self)
        self.reload_thread.finished.connect(self.on_reloaded)
        self.reload_thread.start()
예제 #6
0
    def remove_display(self, id):
        """
        Remove the display widget from the tab
        :param id: display id name
        :return:
        """
        # first we hide the display
        logger.debug("Hiding display " + str(id))
        self.displays[id].hide()

        # then we remove it from the layout and from the dictionary
        self.rows_ver_layout.removeWidget(self.displays[id])
        self.displays[id].setParent(None)
        del self.displays[id]

        logger.info("Removed display " + str(id))
    def on_reloaded(self):
        if self.display_sessions:
            # kill not existing sessions
            for display_id in list(self.displays.keys()):
                missing = True
                for session in self.display_sessions.get_sessions():
                    if str(display_id) == str(session.hash['session name']):
                        missing = False
                        break
                if missing:
                    self.remove_display(display_id)

            # update or create from scratch new sessions
            for session in self.display_sessions.get_sessions():
                display_id = str(session.hash['session name'])
                display_state = str(session.hash['state'])
                display_node = str(session.hash['node'])
                display_name = display_id.split('-')[0]
                display_timeleft = str(session.hash['timeleft'])

                if display_id in self.displays.keys():
                    logger.debug("Display " + display_id + " already exists")
                    self.displays[display_id].session = session
                    if self.displays[display_id].status != Status(
                            display_state):
                        self.displays[display_id].status = Status(
                            display_state)
                        self.displays[display_id].update_gui()
                else:
                    display_widget = QDisplaySessionWidget(
                        parent=self,
                        display_id=display_id,
                        display_name=display_name,
                        session=session,
                        status=Status(display_state),
                        resources=display_node,
                        timeleft=display_timeleft)
                    self.rows_ver_layout.addWidget(display_widget)
                    self.displays[display_id] = display_widget
                    logger.debug("Created display " + display_id)

        # Show the reload widget
        self.containerLoginWidget.hide()
        self.containerSessionWidget.show()
        self.containerWaitingWidget.hide()
        self.containerReloadWidget.hide()
예제 #8
0
파일: worker.py 프로젝트: hpcit/RCM
    def run(self):
        try:
            logger.debug("Worker for display " + str(self.display_id) +
                         " started")
            self.signals.status.emit(Status.PENDING)

            display_session = self.remote_connection_manager.newconn(
                queue=self.session_queue,
                geometry=self.display_size,
                sessionname=self.display_id,
                vnc_id=self.session_vnc)

            self.signals.status.emit(Status.RUNNING)

            self.display_widget.session = display_session
            self.remote_connection_manager.vncsession(
                display_session,
                gui_cmd=self.display_widget.enable_connect_button)

            logger.debug("Worker for display " + str(self.display_id) +
                         " finished")
        except Exception as e:
            logger.error(e)
예제 #9
0
    def run(self):
        try:
            logger.debug("Worker for display " + str(self.display_id) +
                         " started")
            self.signals.status.emit(Status.PENDING)

            api_version = self.remote_connection_manager.api_version()

            if api_version >= "1.0.0":
                display_session = self.remote_connection_manager.new(
                    queue="dummy_queue",
                    geometry="dummy_display_size",
                    sessionname=self.display_id,
                    vnc_id="dummy_vnc",
                    choices=self.display_dlg.choices)
            else:
                display_session = self.remote_connection_manager.new(
                    queue=self.display_dlg.session_queue,
                    geometry=self.display_dlg.display_size,
                    sessionname=self.display_id,
                    vnc_id=self.display_dlg.session_vnc,
                    choices=None)

            self.signals.status.emit(Status.RUNNING)

            self.display_widget.session = display_session
            self.remote_connection_manager.submit(
                display_session,
                gui_cmd=self.display_widget.enable_connect_button)

            logger.debug("Worker for display " + str(self.display_id) +
                         " finished")
        except Exception as e:
            self.signals.status.emit(Status.FINISHED)
            logger.error("Exception: " + str(e) + " - " +
                         str(traceback.format_exc()))
예제 #10
0
    def share_display(self):
        try:
            logger.info("Sharing display " + str(self.display_name))

            filename_suggested = self.session.hash['session name'].replace(
                ' ', '_') + '.vnc'
            options = QFileDialog.Options()
            options |= QFileDialog.DontUseNativeDialog
            filename, _ = QFileDialog.getSaveFileName(
                self,
                "Share display " + str(self.display_name),
                filename_suggested,
                " Vnc Files (*.vnc);;All Files (*)",
                options=options)

            if filename:
                with open(filename, 'w') as out_file:
                    out_file.write("[Connection]\n")
                    if self.session.hash['tunnel'] == 'y':
                        # rcm_tunnel is a key word to know that I need to tunnel across that node
                        out_file.write("rcm_tunnel={0}\n".format(
                            self.session.hash['nodelogin']))
                        out_file.write("host={0}\n".format(
                            self.session.hash['node']))
                    else:
                        out_file.write("host={0}\n".format(
                            self.session.hash['nodelogin']))
                    try:
                        port = int(self.session.hash['port'])
                    except Exception as e:
                        logger.debug(
                            str(e) + " - " + str(traceback.format_exc()))
                        port = 5900 + int(self.session.hash['display'])
                    out_file.write("port={0}\n".format(port))
                    out_file.write("password={0}\n".format(
                        self.session.hash['vncpassword']))
        except Exception as e:
            logger.debug(str(e) + " - " + str(traceback.format_exc()))
            logger.debug(str(self.session.hash))
            logger.error("Failed to share display " + str(self.display_name))
예제 #11
0
 def kill_reload_thread(self):
     if self.reload_thread:
         if not self.reload_thread.isFinished():
             logger.debug("killing reload thread")
             self.reload_thread.terminate()
예제 #12
0
 def kill_login_thread(self):
     if self.login_thread:
         if not self.login_thread.isFinished():
             logger.debug("killing login thread")
             self.login_thread.terminate()
예제 #13
0
    def update_executable(self):
        # update the executable only if we are running in a bundle
        if not pyinstaller_utils.is_bundled():
            return

        logger.info("Checking if a new client version is available...")
        current_exe_checksum = rcm_utils.compute_checksum(sys.executable)
        logger.debug("Current client checksum: " + str(current_exe_checksum))

        last_exe_checksum = self.platform_config.get_version()[0]
        last_exe_url = self.platform_config.get_version()[1]
        logger.debug("New client checksum: " + str(last_exe_checksum))

        if current_exe_checksum != last_exe_checksum:
            question_title = "Release download"
            question_text = "A new version of the \"Remote Connection Manager\" is available at: " \
                            + last_exe_url + ". " \
                            "It is highly recommended to install the new version to keep working properly. " \
                            "Do you want to install it now?"

            buttonReply = QMessageBox.question(
                self, question_title, question_text,
                QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
            if buttonReply == QMessageBox.No:
                return

            logger.info('Downloading the new client version...')
            exe_dir = os.path.dirname(sys.executable)
            tmp_dir = tempfile.gettempdir()
            last_exe_path = os.path.join(tmp_dir,
                                         os.path.basename(sys.executable))
            rcm_utils.download_file(last_exe_url, last_exe_path)
            downloaded_exe_checksum = rcm_utils.compute_checksum(last_exe_path)
            time.sleep(5)

            if downloaded_exe_checksum != last_exe_checksum:
                logger.warning('Downloaded file checksum mismatched. '
                               'Expected: ' + str(last_exe_path) +
                               '. Found: ' + str(downloaded_exe_checksum) +
                               '. Update stopped.')
                os.remove(last_exe_path)
            else:
                if sys.platform == 'win32':
                    batch_filename = os.path.join(tmp_dir, "RCM_update.bat")
                    with open(batch_filename, 'w') as batch_file:
                        batch_file.write("rem start update bat" + "\n")
                        batch_file.write("cd /D " + exe_dir + "\n")
                        batch_file.write("copy mybatch.bat mybatch.txt\n")
                        batch_file.write('ping -n 3 localhost >nul 2>&1' +
                                         "\n")
                        batch_file.write("del mybatch.txt\n")
                        batch_file.write("ren " +
                                         os.path.basename(sys.executable) +
                                         " _" +
                                         os.path.basename(sys.executable) +
                                         "\n")
                        batch_file.write("copy " + last_exe_path + "\n")
                        batch_file.write("del " + " _" +
                                         os.path.basename(sys.executable) +
                                         "\n")
                        batch_file.write("del " + last_exe_path + "\n")
                        batch_file.write("start " +
                                         os.path.basename(sys.executable) +
                                         "\n")
                        batch_file.write("del " + batch_filename + "\n")
                        batch_file.write("exit\n")

                    logger.info(
                        "The application will be closed and the new one will start in a while."
                    )
                    os.startfile(batch_filename)
                else:
                    batch_filename = os.path.join(tmp_dir, "RCM_update.sh")
                    with open(batch_filename, 'w') as batch_file:
                        batch_file.write("#!/bin/bash\n")
                        batch_file.write("#start update bat" + "\n")
                        batch_file.write("cd " + exe_dir + "\n")
                        batch_file.write("sleep 3 \n")
                        batch_file.write("rm " +
                                         os.path.basename(sys.executable) +
                                         "\n")
                        batch_file.write("cp " + last_exe_path + " .\n")
                        batch_file.write("chmod a+x " +
                                         os.path.basename(sys.executable) +
                                         "\n")
                        batch_file.write("sleep 2 \n")
                        batch_file.write("./" +
                                         os.path.basename(sys.executable) +
                                         "\n")

                    logger.info(
                        "The application will be closed and the new one will start in a while!"
                    )
                    subprocess.Popen(["sh", batch_filename])
        else:
            logger.info('The client is up-to-date')
예제 #14
0
 def kill_all_threads(self):
     if self.kill_thread:
         if not self.kill_thread.isFinished():
             logger.debug("killing kill display thread")
             self.kill_thread.terminate()