#!/usr/bin/env python # # Copyright (C) 2016 GNS3 Technologies Inc. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import os import sys import copy import stat import shlex import socket import shutil import random import string import struct import psutil import signal import subprocess from gns3.qt import QtWidgets, QtCore, qslot from gns3.settings import LOCAL_SERVER_SETTINGS, DEFAULT_LOCAL_SERVER_HOST from gns3.local_config import LocalConfig from gns3.local_server_config import LocalServerConfig from gns3.utils.wait_for_connection_worker import WaitForConnectionWorker from gns3.utils.progress_dialog import ProgressDialog from gns3.utils.sudo import sudo from gns3.http_client import HTTPClient from gns3.controller import Controller import logging log = logging.getLogger(__name__) class StopLocalServerWorker(QtCore.QObject): """ Worker for displaying a progress dialog when closing the server """ # signals to update the progress dialog. error = QtCore.Signal(str, bool) finished = QtCore.Signal() updated = QtCore.Signal(int) def __init__(self, local_server_process): super().__init__() self._local_server_process = local_server_process self._precision = 100 # In MS self._remaining_trial = int(10 * (1000 / self._precision)) @qslot def _callbackSlot(self, *params): self._local_server_process.poll() if self._local_server_process.returncode is None and self._remaining_trial > 0: self._remaining_trial -= 1 QtCore.QTimer.singleShot(self._precision, self._callbackSlot) else: self.finished.emit() def run(self): QtCore.QTimer.singleShot(1000, self._callbackSlot) def cancel(self): return class LocalServer(QtCore.QObject): """ Manage the local server process """ def __init__(self, parent=None): # Remember if the server was started by us or not self._server_started_by_me = False self._local_server_path = "" self._local_server_process = None super().__init__() self._parent = parent self._config_directory = LocalConfig.instance().configDirectory() self._settings = {} self.localServerSettings() self._port = self._settings.get("port", 3080) if not self._settings.get("auto_start", True): if self._settings.get("host") is None: self._http_client = HTTPClient(self._settings) Controller.instance().setHttpClient(self._http_client) else: self._http_client = None self._stopping = False self._timer = QtCore.QTimer() self._timer.setInterval(5000) self._timer.timeout.connect(self._checkLocalServerRunningSlot) self._timer.start() def _pid_path(self): """ :returns: Path of the PID file """ return os.path.join(self._config_directory, "gns3_server.pid") def parent(self): """ Parent window """ if self._parent is None: from gns3.main_window import MainWindow return MainWindow.instance() return self._parent def _checkWindowsService(self, service_name): try: import pywintypes import win32service import win32serviceutil except ImportError as e: log.error("Could not check if the {} service is running: {}".format(service_name, e)) return try: if win32serviceutil.QueryServiceStatus(service_name, None)[1] != win32service.SERVICE_RUNNING: return False except pywintypes.error as e: if e.winerror == 1060: # service is not installed return False else: log.error("Could not check if the {} service is running: {}".format(service_name, e.strerror)) return True def _checkUbridgePermissions(self): """ Checks that uBridge can interact with network interfaces. """ path = os.path.abspath(self._settings["ubridge_path"]) if not path or len(path) == 0 or not os.path.exists(path) or not os.path.isfile(path): return False if sys.platform.startswith("win"): # do not check anything on Windows return True if os.geteuid() == 0: # we are root, so we should have privileged access. return True request_setuid = False if sys.platform.startswith("linux"): # test if the executable has the CAP_NET_RAW capability (Linux only) try: # test the 2nd byte and check if the 13th bit (CAP_NET_RAW) is set if "security.capability" not in os.listxattr(path) or not struct.unpack("