Esempio n. 1
0
    def add_new_display(self):
        # cannot have more than 5 sessions
        if len(self.displays) >= 5:
            logger.warning("You have already 5 displays")
            return

        display_dlg = QDisplayDialog(list(self.displays.keys()),
                                     self.platform_config)
        display_dlg.setModal(True)

        if display_dlg.exec() != 1:
            return

        display_name = display_dlg.display_name
        display_id = '-'.join((display_name, str(uuid.uuid4())))
        display_widget = QDisplaySessionWidget(self,
                                               display_id=display_id,
                                               display_name=display_name)
        self.rows_ver_layout.addWidget(display_widget)
        self.displays[display_id] = display_widget

        # start the worker
        worker = Worker(display_widget, self.remote_connection_manager,
                        display_dlg.session_queue, display_dlg.session_vnc,
                        display_dlg.display_size)
        worker.signals.status.connect(display_widget.on_status_change)
        self.window().thread_pool.start(worker)

        logger.info("Added new display")
Esempio n. 2
0
    def on_logged(self):
        if self.is_logged:
            # Show the session widget
            self.containerLoginWidget.hide()
            self.containerWaitingWidget.hide()
            self.containerSessionWidget.show()

            logger.info("Logged in " + self.session_name)

            # update sessions list
            if self.session_name in list(self.sessions_list):
                self.sessions_list.remove(self.session_name)
            if self.session_name:
                self.sessions_list.appendleft(self.session_name)
                self.sessions_changed.emit(self.sessions_list)

            # update config file
            self.update_config_file(self.session_name)

            # check if a new version is available
            self.update_executable()

            # Emit the logged_in signal.
            self.logged_in.emit(self.session_name, self.uuid)

            # update the session list to be shown
            self.reload()
        else:
            # Show the login widget again
            self.containerLoginWidget.show()
            self.containerSessionWidget.hide()
            self.containerWaitingWidget.hide()
Esempio n. 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())
Esempio n. 4
0
    def login(self):
        self.user = str(self.user_line.text())
        self.host = str(self.host_line.text())
        password = str(self.pssw_line.text())

        if not self.host:
            logger.warning("Host field is empty")
            return

        if not self.user:
            logger.warning("User field is empty")
            return

        self.session_name = self.user + "@" + self.host
        logger.info("Logging into " + self.session_name)

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

        self.remote_connection_manager = manager.RemoteConnectionManager()
        self.remote_connection_manager.debug = False

        self.login_thread = LoginThread(self, self.host, self.user, password)
        self.login_thread.finished.connect(self.on_logged)
        self.login_thread.start()
Esempio n. 5
0
    def open_vnc_session(self):

        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        filename, _ = QFileDialog.getOpenFileName(
            self,
            "Open...",
            "",
            "VNC Files (*.vnc);;All Files (*)",
            options=options)

        current_session_widget = self.main_widget.tabs.currentWidget()

        if filename:
            # check if session needs tunneling
            file = open(filename, 'r')
            if 'rcm_tunnel' in file.read():
                file.seek(0)
                lines = file.readlines()
                for line in lines:
                    if 'rcm_tunnel' in line:
                        node = line.split('=')[1].rstrip()
                        if not current_session_widget.is_logged:
                            logger.error(
                                "You are not logged in the current session. Please log in."
                            )
                            return
                        if node == current_session_widget.host:
                            user = current_session_widget.user
                        else:
                            logger.error(
                                "The host of the current session (" +
                                current_session_widget.host +
                                ") is different from the host of the vnc file ("
                                + node + ")")
                            return
                    if 'host' in line:
                        hostname = line.split('=')[1].rstrip()
                    if 'port' in line:
                        port = line.split('=')[1].rstrip()
                        display = int(port) - 5900
                    if 'password' in line:
                        password = line.split('=')[1].rstrip()

                session = rcm.rcm_session(node=hostname,
                                          tunnel='y',
                                          display=display,
                                          nodelogin=node,
                                          username=user,
                                          vncpassword=password)
                current_session_widget.remote_connection_manager.vncsession(
                    session=session)
                logger.info("Connected to remote display " + str(display) +
                            " on " + node + " as " + str(user) +
                            " with tunnel")
            else:
                current_session_widget.remote_connection_manager.vncsession(
                    configFile=filename)
Esempio n. 6
0
 def connect_display(self):
     try:
         logger.info("Connecting to remote display " +
                     str(self.display_name))
         self.parent.remote_connection_manager.submit(
             self.session, gui_cmd=self.enable_connect_button)
     except:
         logger.error("Failed to connect to remote display " +
                      str(self.display_name))
Esempio n. 7
0
    def on_ok(self):
        """
        :return: Return accept signal if the display name is unique
        """

        session_line = self.findChild(QLineEdit, 'session_line')
        display_name = str(session_line.text())

        # if the display_name is empty, it is set to test
        # if it is not empty we validate it using a regex
        if not re.match(r'^[\w\_\s]{0,16}$', display_name):
            logger.error("Invalid display name: only alphanumeric "
                         "plus underscore plus space characters "
                         "are allowed for a maximum of 16 characters")
            return
        if display_name == "":
            self.display_name = "test"
        else:
            self.display_name = display_name

        # if the display name already exists, it returns
        if self.display_name in self.display_names:
            logger.error("session " + str(self.display_name) +
                         " already exists")
            return

        self.session_queue = str(self.session_queue_combo.currentText())
        self.session_vnc = str(self.session_vnc_combo.currentText())
        self.display_size = str(self.display_combo.currentText())

        # add a new display size if it's fine for us in the combobox for the next time
        if self.display_size not in list(self.display_size_list):
            if re.match(r'^\d{1,5}x\d{1,5}$', self.display_size):
                self.display_size_list.appendleft(self.display_size)
            else:
                logger.error("Invalid display size")
                return

        # convert full screen in the format width x height
        if self.display_size == "full_screen":
            screen_width = QDesktopWidget().width()
            screen_height = QDesktopWidget().height()
            self.display_size = str(screen_width) + "x" + str(screen_height)

        logger.info("session queue: " + self.session_queue + "; " +
                    "session vnc: " + self.session_vnc + "; " +
                    "display size: " + self.display_size + ";")

        self.update_config_file()
        self.accept()
    def login(self):
        if self.user != str(self.user_line.text()):
            self.user = str(self.user_line.text())
            self.session_name = ''
        if self.host != str(self.host_line.text()):
            self.host = str(self.host_line.text())
            self.session_name = ''
        if self.preload != str(self.preload_line.text()):
            self.preload = str(self.preload_line.text())
            self.session_name = ''
        password = str(self.pssw_line.text())

        if not self.host:
            logger.warning("Host field is empty")
            return

        if not self.user:
            logger.warning("User field is empty")
            return

        if not self.session_name:
            self.session_name = self.user + "@" + self.host
            if self.preload:
                # search this preload into existing sessions
                preload_name = ''
                for session_name, host, user, preload in self.sessions_list:
                    if preload == self.preload:
                        preload_name = ([''] + session_name.split('?')[1:])[-1]
                        break
                if not preload_name:
                    preload_name = hashlib.md5(
                        self.preload.encode()).hexdigest()[:4]
                self.session_name += "?" + preload_name
        logger.info("Logging...")

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

        self.remote_connection_manager = manager.RemoteConnectionManager()
        self.remote_connection_manager.debug = False

        self.login_thread = LoginThread(self,
                                        self.host,
                                        self.user,
                                        password,
                                        preload=self.preload)
        self.login_thread.finished.connect(self.on_logged)
        self.login_thread.start()
Esempio n. 9
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))
Esempio n. 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))
    def add_new_display(self):
        # cannot have more than 5 sessions
        if len(self.displays) >= 5:
            logger.warning("You have already 5 displays")
            return

        display_dialog_ui = None
        if self.platform_config:
            if 'jobscript_json_menu' in self.platform_config.config:
                display_dialog_ui = json.loads(
                    self.platform_config.config.get('jobscript_json_menu',
                                                    '{}'),
                    object_pairs_hook=collections.OrderedDict)
        if display_dialog_ui:
            display_dlg = QDynamicDisplayDialog(display_dialog_ui)
        else:
            display_dlg = QDisplayDialog(list(self.displays.keys()),
                                         self.platform_config)
        display_dlg.setModal(True)

        if display_dlg.exec() != 1:
            return

        display_name = display_dlg.display_name
        display_id = '-'.join((display_name, str(uuid.uuid4())))
        display_widget = QDisplaySessionWidget(self,
                                               display_id=display_id,
                                               display_name=display_name)
        self.rows_ver_layout.addWidget(display_widget)
        self.displays[display_id] = display_widget

        # start the worker
        worker = Worker(display_widget, self.remote_connection_manager,
                        display_dlg)
        worker.signals.status.connect(display_widget.on_status_change)
        self.window().thread_pool.start(worker)

        logger.info("Added new display")
    def on_logged(self):
        if self.is_logged:
            # Show the session widget
            self.containerLoginWidget.hide()
            self.containerWaitingWidget.hide()
            self.containerSessionWidget.show()

            logger.info("Logged as " + self.user + " to " + self.host)

            # update sessions list
            # warning, json load turns tuple into list
            # append new session only if content is different
            if self.session_name and list(
                    self.session_tuple())[1:] not in list(
                        self.sessions_list_content()):
                self.sessions_list.appendleft(self.session_tuple())
                #self.sessions_changed.emit(self.sessions_list)
                self.sessions_changed.emit(self.sessions_list_names(),
                                           self.sessions_list)

            # update config file
            self.update_config_file(self.session_name)

            # check if a new version is available
            self.update_executable()

            # Emit the logged_in signal.
            self.logged_in.emit(self.session_name, self.uuid)

            # update the session list to be shown
            self.reload()
        else:
            # Show the login widget again
            self.containerLoginWidget.show()
            self.containerSessionWidget.hide()
            self.containerWaitingWidget.hide()
Esempio n. 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')