Esempio n. 1
0
    def _exportConfigToDirectoryCallback(self, result, error=False, context={}, **kwargs):
        """
        Callback for exportConfigToDirectory.

        :param result: server response
        :param error: indicates an error (boolean)
        """

        if error:
            log.error("error while exporting {} configs: {}".format(self.name(), result["message"]))
            self.server_error_signal.emit(self.id(), result["message"])
        else:
            directory = context["directory"]
            if "startup_config_content" in result:
                config_path = os.path.join(directory, normalize_filename(self.name())) + "_startup-config.cfg"
                try:
                    with open(config_path, "wb") as f:
                        log.info("saving {} startup-config to {}".format(self.name(), config_path))
                        if result["startup_config_content"]:
                            f.write(result["startup_config_content"].encode("utf-8"))
                except OSError as e:
                    self.error_signal.emit(self.id(), "Could not export startup-config to {}: {}".format(config_path, e))
            if "private_config_content" in result:
                config_path = os.path.join(directory, normalize_filename(self.name())) + "_private-config.cfg"
                try:
                    with open(config_path, "wb") as f:
                        log.info("saving {} private-config to {}".format(self.name(), config_path))
                        if result["private_config_content"]:
                            f.write(result["private_config_content"].encode("utf-8"))
                except OSError as e:
                    self.error_signal.emit(self.id(), "Could not export private-config to {}: {}".format(config_path, e))
Esempio n. 2
0
    def importConfigFromDirectory(self, directory):
        """
        Imports a startup-config and a private-config from a directory.

        :param directory: source directory path
        """

        try:
            contents = os.listdir(directory)
        except OSError as e:
            return
        startup_config = normalize_filename(self.name()) + "_startup-config.cfg"
        private_config = normalize_filename(self.name()) + "_private-config.cfg"
        new_settings = {}
        if startup_config in contents:
            new_settings["startup_config"] = os.path.join(directory, startup_config)

        if private_config in contents:
            new_settings["private_config"] = os.path.join(directory, private_config)
        else:
            # private-config is optional
            log.debug("{}: no private-config file could be found, expected file name: {}".format(self.name(), private_config))

        if new_settings:
            self.update(new_settings)
Esempio n. 3
0
    def importConfigFromDirectory(self, directory):
        """
        Imports a startup-config and a private-config from a directory.

        :param directory: source directory path
        """

        try:
            contents = os.listdir(directory)
        except OSError as e:
            self.warning_signal.emit(self.id(), "Configuration could not be loaded from directory {}: {}".format(directory, e))
            return
        startup_config = normalize_filename(self.name()) + "_startup-config.cfg"
        private_config = normalize_filename(self.name()) + "_private-config.cfg"
        new_settings = {}
        if startup_config in contents:
            new_settings["startup_config"] = os.path.join(directory, startup_config)
        else:
            self.warning_signal.emit(self.id(), "no startup-config file could be found, expected file name: {}".format(startup_config))
        if private_config in contents:
            new_settings["private_config"] = os.path.join(directory, private_config)
        else:
            self.warning_signal.emit(self.id(), "no private-config file could be found, expected file name: {}".format(private_config))
        if new_settings:
            self.update(new_settings)
Esempio n. 4
0
    def _exportConfigToDirectoryCallback(self, result, error=False, context={}, **kwargs):
        """
        Callback for exportConfigToDirectory.

        :param result: server response
        :param error: indicates an error (boolean)
        """

        if error:
            log.error("error while exporting {} configs: {}".format(self.name(), result["message"]))
            self.server_error_signal.emit(self.id(), result["message"])
        else:
            directory = context["directory"]
            if "startup_config_content" in result:
                config_path = os.path.join(directory, normalize_filename(self.name())) + "_startup-config.cfg"
                try:
                    with open(config_path, "wb") as f:
                        log.info("saving {} startup-config to {}".format(self.name(), config_path))
                        f.write(result["startup_config_content"].encode("utf-8"))
                except OSError as e:
                    self.error_signal.emit(self.id(), "Could not export startup-config to {}: {}".format(config_path, e))
            if "private_config_content" in result:
                config_path = os.path.join(directory, normalize_filename(self.name())) + "_private-config.cfg"
                try:
                    with open(config_path, "wb") as f:
                        log.info("saving {} private-config to {}".format(self.name(), config_path))
                        f.write(result["private_config_content"].encode("utf-8"))
                except OSError as e:
                    self.error_signal.emit(self.id(), "Could not export private-config to {}: {}".format(config_path, e))
    def _iosRouterDeleteSlot(self):
        """
        Deletes an IOS router.
        """

        item = self.uiIOSRoutersTreeWidget.currentItem()
        if item:
            key = item.data(0, QtCore.Qt.UserRole)
            ios_router = self._ios_routers[key]

            # delete the base startup_config
            default_startup_config_name = "{}_base_startup-config.txt".format(normalize_filename(ios_router["name"]))
            if os.path.isfile(ios_router["startup_config"]) and ios_router["startup_config"] != self._base_startup_config_template \
                    and os.path.basename(ios_router["startup_config"]) == default_startup_config_name:
                if ios_router["startup_config"] not in self._base_configs_to_delete:
                    self._base_configs_to_delete.append(ios_router["startup_config"])

            # delete the base private_config
            default_private_config_name = "{}_base_private-config.txt".format(normalize_filename(ios_router["name"]))
            if os.path.isfile(ios_router["private_config"]) and ios_router["private_config"] != self._base_private_config_template \
                    and os.path.basename(ios_router["private_config"]) == default_private_config_name:
                if ios_router["private_config"] not in self._base_configs_to_delete:
                    self._base_configs_to_delete.append(ios_router["private_config"])

            del self._ios_routers[key]
            self.uiIOSRoutersTreeWidget.takeTopLevelItem(self.uiIOSRoutersTreeWidget.indexOfTopLevelItem(item))
            if self._ios_routers == {}:
                self.uiEditIOSRouterPushButton.setEnabled(False)
                self.uiDeleteIOSRouterPushButton.setEnabled(False)
                self.uiDecompressIOSPushButton.setEnabled(False)
Esempio n. 6
0
    def importConfigFromDirectory(self, directory):
        """
        Imports a startup-config and a private-config from a directory.

        :param directory: source directory path
        """

        try:
            contents = os.listdir(directory)
        except OSError as e:
            return
        startup_config = normalize_filename(
            self.name()) + "_startup-config.cfg"
        private_config = normalize_filename(
            self.name()) + "_private-config.cfg"
        new_settings = {}
        if startup_config in contents:
            new_settings["startup_config"] = os.path.join(
                directory, startup_config)

        if private_config in contents:
            new_settings["private_config"] = os.path.join(
                directory, private_config)
        else:
            # private-config is optional
            log.debug(
                "{}: no private-config file could be found, expected file name: {}"
                .format(self.name(), private_config))

        if new_settings:
            self.update(new_settings)
Esempio n. 7
0
    def importConfigFromDirectory(self, directory):
        """
        Imports IOU configs from a directory.

        :param directory: source directory path
        """

        contents = os.listdir(directory)
        startup_config = normalize_filename(
            self.name()) + "_startup-config.cfg"
        private_config = normalize_filename(
            self.name()) + "_private-config.cfg"
        new_settings = {}
        if startup_config in contents:
            new_settings["startup_config"] = os.path.join(
                directory, startup_config)
        else:
            self.warning_signal.emit(
                self.id(),
                "no startup-config file could be found, expected file name: {}"
                .format(startup_config))

        if private_config in contents:
            new_settings["private_config"] = os.path.join(
                directory, private_config)
        else:
            self.warning_signal.emit(
                self.id(),
                "no private-config file could be found, expected file name: {}"
                .format(private_config))

        if new_settings:
            self.update(new_settings)
Esempio n. 8
0
    def _exportConfigsCallback(self, result, error=False):
        """
        Callback for exportConfigs.

        :param result: server response
        :param error: indicates an error (boolean)
        """

        if error:
            log.error("error while exporting {} configs: {}".format(self.name(), result["message"]))
            self.server_error_signal.emit(self.id(), result["code"], result["message"])
        else:

            if "startup_config_base64" in result:
                config_path = os.path.join(self._export_directory, normalize_filename(self.name())) + "_startup-config.cfg"
                config = base64.decodebytes(result["startup_config_base64"].encode("utf-8"))
                try:
                    with open(config_path, "wb") as f:
                        log.info("saving {} startup-config to {}".format(self.name(), config_path))
                        f.write(config)
                except OSError as e:
                    self.error_signal.emit(self.id(), "could not export startup-config to {}: {}".format(config_path, e))

            if "private_config_base64" in result:
                config_path = os.path.join(self._export_directory, normalize_filename(self.name())) + "_private-config.cfg"
                config = base64.decodebytes(result["private_config_base64"].encode("utf-8"))
                try:
                    with open(config_path, "wb") as f:
                        log.info("saving {} private-config to {}".format(self.name(), config_path))
                        f.write(config)
                except OSError as e:
                    self.error_signal.emit(self.id(), "could not export private-config to {}: {}".format(config_path, e))

            self._export_directory = None
Esempio n. 9
0
    def importConfigFromDirectory(self, directory):
        """
        Imports a startup-config and a private-config from a directory.

        :param directory: source directory path
        """

        try:
            contents = os.listdir(directory)
        except OSError as e:
            self.warning_signal.emit(self.id(), "Configuration could not be loaded from directory {}: {}".format(directory, e))
            return
        startup_config = normalize_filename(self.name()) + "_startup-config.cfg"
        private_config = normalize_filename(self.name()) + "_private-config.cfg"
        new_settings = {}
        if startup_config in contents:
            new_settings["startup_config"] = os.path.join(directory, startup_config)
        else:
            self.warning_signal.emit(self.id(), "no startup-config file could be found, expected file name: {}".format(startup_config))
        if private_config in contents:
            new_settings["private_config"] = os.path.join(directory, private_config)
        else:
            self.warning_signal.emit(self.id(), "no private-config file could be found, expected file name: {}".format(private_config))
        if new_settings:
            self.update(new_settings)
Esempio n. 10
0
    def _exportConfigToDirectoryCallback(self, result, error=False, **kwargs):
        """
        Callback for exportConfigToDirectory.

        :param result: server response
        :param error: indicates an error (boolean)
        """

        if error:
            log.error("error while exporting {} configs: {}".format(
                self.name(), result["message"]))
            self.server_error_signal.emit(self.id(), result["message"])
        else:

            if "startup_script" in result:
                config_path = os.path.join(self._export_directory,
                                           normalize_filename(
                                               self.name())) + "_startup.vpc"
                config = result["startup_script"].encode("utf-8")
                try:
                    with open(config_path, "wb") as f:
                        log.info("saving {} script file to {}".format(
                            self.name(), config_path))
                        f.write(config)
                except OSError as e:
                    self.error_signal.emit(
                        self.id(),
                        "could not export the script file to {}: {}".format(
                            config_path, e))

            self._export_directory = None
Esempio n. 11
0
    def importConfigFromDirectory(self, directory):
        """
        Imports an initial-config from a directory.

        :param directory: source directory path
        """

        try:
            contents = os.listdir(directory)
        except OSError as e:
            self.warning_signal.emit(
                self.id(),
                "Can't list file in {}: {}".format(directory, str(e)))
            return
        script_file = normalize_filename(self.name()) + "_startup.vpc"
        new_settings = {}
        if script_file in contents:
            new_settings["script_file"] = os.path.join(directory, script_file)
        else:
            self.warning_signal.emit(
                self.id(),
                "no script file could be found, expected file name: {}".format(
                    script_file))
            return
        self.update(new_settings)
Esempio n. 12
0
    def importConfigsFromDirectory(self, directory):
        """
        Imports configs from a directory.

        :param directory: source directory path
        """

        if not hasattr(self, "configFiles"):
            return

        try:
            contents = os.listdir(directory)
        except OSError as e:
            self.error_signal.emit(self.id(), "Cannot list file in {}: {}".format(directory, str(e)))
            return

        for file in self.configFiles():
            # we can have / in the case of Docker
            filename = normalize_filename(self.name()) + "_{}".format(file.replace("/", "_"))
            if filename in contents:
                self.post("/files/{file}".format(file=file),
                          self._importConfigsFromDirectoryCallback,
                          pathlib.Path(os.path.join(directory, filename)))
            else:
                log.warning("{}: config file '{}' not found".format(self.name(), filename))
Esempio n. 13
0
    def _exportConfigsToDirectoryCallback(self,
                                          result,
                                          error=False,
                                          raw_body=None,
                                          context={},
                                          **kwargs):
        """
        Callback for exportConfigsToDirectory.

        :param result: server response
        :param error: indicates an error (boolean)
        """

        if error:
            # The file could be missing if there is no private-config for example.
            return

        export_directory = context["directory"]
        # we can have / in the case of Docker
        filename = normalize_filename(self.name()) + "_{}".format(
            context["file"].replace("/", "_"))
        config_path = os.path.join(export_directory, filename)
        try:
            with open(config_path, "wb") as f:
                log.debug("saving {} config to {}".format(
                    self.name(), config_path))
                f.write(raw_body)
        except OSError as e:
            self.error_signal.emit(
                self.id(),
                "could not export config to {}: {}".format(config_path, e))
Esempio n. 14
0
    def importConfigsFromDirectory(self, directory):
        """
        Imports configs from a directory.

        :param directory: source directory path
        """

        if not hasattr(self, "configFiles"):
            return

        try:
            contents = os.listdir(directory)
        except OSError as e:
            self.error_signal.emit(
                self.id(),
                "Cannot list file in {}: {}".format(directory, str(e)))
            return

        for file in self.configFiles():
            # we can have / in the case of Docker
            filename = normalize_filename(self.name()) + "_{}".format(
                file.replace("/", "_"))
            if filename in contents:
                self.post("/files/{file}".format(file=file),
                          self._importConfigsFromDirectoryCallback,
                          pathlib.Path(os.path.join(directory, filename)))
            else:
                log.warning("{}: config file '{}' not found".format(
                    self.name(), filename))
Esempio n. 15
0
    def importConfigs(self, directory):
        """
        Imports a startup-config and a private-config from a directory.

        :param directory: source directory path
        """

        contents = os.listdir(directory)
        startup_config = normalize_filename(self.name()) + "_startup-config.cfg"
        private_config = normalize_filename(self.name()) + "_private-config.cfg"
        new_settings = {}
        if startup_config in contents:
            new_settings["startup_config"] = os.path.join(directory, startup_config)
        else:
            self.warning_signal.emit(self.id(), "no startup-config file could be found, expected file name: {}".format(startup_config))
        if private_config in contents:
            new_settings["private_config"] = os.path.join(directory, private_config)
        else:
            self.warning_signal.emit(self.id(), "no private-config file could be found, expected file name: {}".format(private_config))
        if new_settings:
            self.update(new_settings)
Esempio n. 16
0
    def captureFileName(self, source_node_name):
        """
        Returns a capture file name.

        :param source_node_name: source node name

        :return: capture file name
        """

        capture_file_name = "{}_{}_to_{}_{}".format(source_node_name,
                                                    self.name().replace('/', '-'),
                                                    self.destinationNode().name(),
                                                    self.destinationPort().name().replace('/', '-'))

        return normalize_filename(capture_file_name) + ".pcap"
Esempio n. 17
0
def test_exportConfigToDirectory(iou_device, tmpdir):

    path = str(tmpdir)

    with patch("gns3.node.Node.httpGet") as mock:
        iou_device.exportConfigToDirectory(path)
        assert mock.called
        args, kwargs = mock.call_args
        assert args[0] == "/iou/vms/{vm_id}/configs".format(vm_id=iou_device.vm_id())

        # Callback
        args[1]({"startup_config_content": "TEST"}, context=kwargs["context"])

        with open(os.path.join(path, normalize_filename(iou_device.name()) + "_startup-config.cfg")) as f:
            assert f.read() == "TEST"
Esempio n. 18
0
    def captureFileName(self, source_node_name):
        """
        Returns a capture file name.

        :param source_node_name: source node name

        :return: capture file name
        """

        capture_file_name = "{}_{}_to_{}_{}".format(source_node_name,
                                                    self.name().replace('/', '-'),
                                                    self.destinationNode().name(),
                                                    self.destinationPort().name().replace('/', '-'))

        return normalize_filename(capture_file_name) + ".pcap"
Esempio n. 19
0
    def importConfig(self, directory):
        """
        Imports an initial-config from a directory.

        :param directory: source directory path
        """

        contents = os.listdir(directory)
        script_file = normalize_filename(self.name()) + "_startup.vpc"
        new_settings = {}
        if script_file in contents:
            new_settings["script_file"] = os.path.join(directory, script_file)
        else:
            self.warning_signal.emit(self.id(), "no script file could be found, expected file name: {}".format(script_file))
        if new_settings:
            self.update(new_settings)
Esempio n. 20
0
def test_exportConfigToDirectory(iou_device, tmpdir):

    path = str(tmpdir)

    with patch("gns3.node.Node.httpGet") as mock:
        iou_device.exportConfigToDirectory(path)
        assert mock.called
        args, kwargs = mock.call_args
        assert args[0] == "/iou/vms/{vm_id}/initial_config".format(vm_id=iou_device.vm_id())

        # Callback
        args[1]({"content": "TEST"}, context=kwargs["context"])

        with open(os.path.join(path, normalize_filename(iou_device.name()) + "_initial-config.cfg"
                               )) as f:
            assert f.read() == "TEST"
Esempio n. 21
0
    def importConfig(self, directory):
        """
        Imports an initial-config from a directory.

        :param directory: source directory path
        """

        contents = os.listdir(directory)
        initial_config = normalize_filename(self.name()) + "_initial-config.cfg"
        new_settings = {}
        if initial_config in contents:
            new_settings["initial_config"] = os.path.join(directory, initial_config)
        else:
            self.warning_signal.emit(self.id(), "no initial-config file could be found, expected file name: {}".format(initial_config))
        if new_settings:
            self.update(new_settings)
Esempio n. 22
0
    def importConfigFromDirectory(self, directory):
        """
        Imports an initial-config from a directory.

        :param directory: source directory path
        """

        contents = os.listdir(directory)
        initial_config = normalize_filename(self.name()) + "_initial-config.cfg"
        new_settings = {}
        if initial_config in contents:
            new_settings["initial_config"] = os.path.join(directory, initial_config)
        else:
            self.warning_signal.emit(self.id(), "no initial-config file could be found, expected file name: {}".format(initial_config))
        if new_settings:
            self.update(new_settings)
Esempio n. 23
0
def test_exportConfigToDirectory(tmpdir, vpcs_device):

    path = tmpdir / normalize_filename(vpcs_device.name()) + '_startup.vpc'

    with patch('gns3.node.Node.httpGet') as mock:
        vpcs_device.exportConfigToDirectory(str(tmpdir))

        assert mock.called
        args, kwargs = mock.call_args
        assert args[0] == "/vpcs/vms/{vm_id}".format(vm_id=vpcs_device.vm_id())

        # Callback
        args[1]({"startup_script": "echo TEST"})

        assert path.exists()

        with open(str(path)) as f:
            assert f.read() == "echo TEST"
Esempio n. 24
0
def test_exportConfigToDirectory(tmpdir, vpcs_device):

    path = tmpdir / normalize_filename(vpcs_device.name()) + '_startup.vpc'

    with patch('gns3.base_node.BaseNode.httpGet') as mock:
        vpcs_device.exportConfigToDirectory(str(tmpdir))

        assert mock.called
        args, kwargs = mock.call_args
        assert args[0] == "/vpcs/nodes/{node_id}".format(node_id=vpcs_device.node_id())

        # Callback
        args[1]({"startup_script": "echo TEST"}, context={"directory": str(tmpdir)})

        assert path.exists()

        with open(str(path)) as f:
            assert f.read() == "echo TEST"
Esempio n. 25
0
    def importConfigFromDirectory(self, directory):
        """
        Imports an initial-config from a directory.

        :param directory: source directory path
        """

        try:
            contents = os.listdir(directory)
        except OSError as e:
            return
        script_file = normalize_filename(self.name()) + "_startup.vpc"
        new_settings = {}
        if script_file in contents:
            new_settings["script_file"] = os.path.join(directory, script_file)
        else:
            return
        self.update(new_settings)
Esempio n. 26
0
    def importConfigFromDirectory(self, directory):
        """
        Imports an initial-config from a directory.

        :param directory: source directory path
        """

        try:
            contents = os.listdir(directory)
        except OSError as e:
            return
        script_file = normalize_filename(self.name()) + "_startup.vpc"
        new_settings = {}
        if script_file in contents:
            new_settings["script_file"] = os.path.join(directory, script_file)
        else:
            return
        self.update(new_settings)
Esempio n. 27
0
def test_exportConfigToDirectory(iou_device, tmpdir):

    path = str(tmpdir)

    with patch("gns3.base_node.BaseNode.httpGet") as mock:
        iou_device.exportConfigToDirectory(path)
        assert mock.called
        args, kwargs = mock.call_args
        assert args[0] == "/iou/nodes/{node_id}/configs".format(
            node_id=iou_device.node_id())

        # Callback
        args[1]({"startup_config_content": "TEST"}, context=kwargs["context"])

        with open(
                os.path.join(
                    path,
                    normalize_filename(iou_device.name()) +
                    "_startup-config.cfg")) as f:
            assert f.read() == "TEST"
Esempio n. 28
0
    def importConfigFromDirectory(self, directory):
        """
        Imports an initial-config from a directory.

        :param directory: source directory path
        """

        try:
            contents = os.listdir(directory)
        except OSError as e:
            self.warning_signal.emit(self.id(), "Can't list file in {}: {}".format(directory, str(e)))
            return
        script_file = normalize_filename(self.name()) + "_startup.vpc"
        new_settings = {}
        if script_file in contents:
            new_settings["script_file"] = os.path.join(directory, script_file)
        else:
            self.warning_signal.emit(self.id(), "no script file could be found, expected file name: {}".format(script_file))
            return
        self.update(new_settings)
Esempio n. 29
0
    def _exportConfigToDirectoryCallback(self, result, error=False, context={}, **kwargs):
        """
        Callback for exportConfigToDirectory.

        :param result: server response
        :param error: indicates an error (boolean)
        """

        if error:
            log.error("error while exporting {} configs: {}".format(self.name(), result["message"]))
            self.server_error_signal.emit(self.id(), result["message"])
        elif "startup_script" in result["properties"]:
            export_directory = context["directory"]
            config_path = os.path.join(export_directory, normalize_filename(self.name())) + "_startup.vpc"
            try:
                with open(config_path, "wb") as f:
                    log.info("saving {} script file to {}".format(self.name(), config_path))
                    if result["properties"]["startup_script"]:
                        f.write(result["properties"]["startup_script"].encode("utf-8"))
            except OSError as e:
                self.error_signal.emit(self.id(), "could not export the script file to {}: {}".format(config_path, e))
Esempio n. 30
0
    def _exportConfigsToDirectoryCallback(self, result, error=False, raw_body=None, context={}, **kwargs):
        """
        Callback for exportConfigsToDirectory.

        :param result: server response
        :param error: indicates an error (boolean)
        """

        if error:
            # The file could be missing if there is no private-config for example.
            return

        export_directory = context["directory"]
        # we can have / in the case of Docker
        filename = normalize_filename(self.name()) + "_{}".format(context["file"].replace("/", "_"))
        config_path = os.path.join(export_directory, filename)
        try:
            with open(config_path, "wb") as f:
                log.debug("saving {} config to {}".format(self.name(), config_path))
                f.write(raw_body)
        except OSError as e:
            self.error_signal.emit(self.id(), "could not export config to {}: {}".format(config_path, e))
    def _iosRouterNewSlot(self):
        """
        Creates a new IOS router.
        """

        wizard = IOSRouterWizard(self._ios_routers, parent=self)
        wizard.show()
        if wizard.exec_():

            ios_settings = wizard.getSettings()
            key = "{server}:{name}".format(server=ios_settings["server"], name=ios_settings["name"])

            ios_settings["startup_config"] = self._getBaseConfig(self._base_startup_config_template, "{}_base_startup-config.txt".format(normalize_filename(ios_settings["name"])))
            ios_settings["private_config"] = self._getBaseConfig(self._base_private_config_template, "{}_base_private-config.txt".format(normalize_filename(ios_settings["name"])))

            self._ios_routers[key] = IOS_ROUTER_SETTINGS.copy()
            self._ios_routers[key].update(ios_settings)

            if ios_settings["server"] == 'cloud':
                import logging
                log = logging.getLogger(__name__)

                log.debug(ios_settings["image"])
                # Start uploading the image to cloud files

                self._upload_image_progress_dialog = QtGui.QProgressDialog("Uploading image file {}".format(ios_settings['image']), "Cancel", 0, 0, parent=self)
                self._upload_image_progress_dialog.setWindowModality(QtCore.Qt.WindowModal)
                self._upload_image_progress_dialog.setWindowTitle("IOS image upload")
                self._upload_image_progress_dialog.show()
                try:
                    upload_thread = UploadFilesThread(
                        self,
                        cloud_settings=MainWindow.instance().cloudSettings(),
                        files_to_upload=[(
                            self._ios_routers[key]["path"],
                            'images/' + os.path.relpath(self._ios_routers[key]["path"],
                                                        self._main_window.settings()["images_path"])
                        )]
                    )
                    upload_thread.completed.connect(self._imageUploadComplete)
                    upload_thread.start()
                except Exception as e:
                    self._upload_image_progress_dialog.reject()
                    log.error(e)
                    QtGui.QMessageBox.critical(self, "IOS image upload", "Error uploading IOS image: {}".format(e))

            if ios_settings["platform"] == "c7200":
                self._ios_routers[key]["midplane"] = "vxr"
                self._ios_routers[key]["npe"] = "npe-400"
            else:
                self._ios_routers[key]["iomem"] = 5

            for slot_id in range(0, 7):
                slot = "slot{}".format(slot_id)
                if slot in ios_settings:
                    self._ios_routers[key][slot] = ios_settings[slot]

            for wic_id in range(0, 3):
                wic = "wic{}".format(wic_id)
                if wic in ios_settings:
                    self._ios_routers[key][wic] = ios_settings[wic]

            self._ios_routers[key].update(ios_settings)
            item = QtGui.QTreeWidgetItem(self.uiIOSRoutersTreeWidget)
            item.setText(0, self._ios_routers[key]["name"])
            item.setIcon(0, QtGui.QIcon(self._ios_routers[key]["default_symbol"]))
            item.setData(0, QtCore.Qt.UserRole, key)
            self._items.append(item)
            self.uiIOSRoutersTreeWidget.setCurrentItem(item)
    def _iosRouterEditSlot(self):
        """
        Edits an IOS router.
        """

        item = self.uiIOSRoutersTreeWidget.currentItem()
        if item:
            key = item.data(0, QtCore.Qt.UserRole)
            ios_router = self._ios_routers[key]
            dialog = ConfigurationDialog(ios_router["name"], ios_router, IOSRouterConfigurationPage(), parent=self)
            dialog.show()
            if dialog.exec_():
                if ios_router["name"] != item.text(0):
                    # rename the IOS router
                    new_key = "{server}:{name}".format(server=ios_router["server"], name=ios_router["name"])
                    if new_key in self._ios_routers:
                        QtGui.QMessageBox.critical(self, "IOS router", "IOS router name {} already exists for server {}".format(ios_router["name"],
                                                                                                                                ios_router["server"]))
                        ios_router["name"] = item.text(0)
                        return
                    self._ios_routers[new_key] = self._ios_routers[key]
                    del self._ios_routers[key]

                    # rename the base startup-config file
                    default_startup_config_name = "{}_base_startup-config.txt".format(normalize_filename(item.text(0)))
                    if os.path.isfile(ios_router["startup_config"]) and ios_router["startup_config"] != self._base_startup_config_template \
                            and os.path.basename(ios_router["startup_config"]) == default_startup_config_name:
                        try:
                            new_base_config_name = "{}_base_startup-config.txt".format(normalize_filename(ios_router["name"]))
                            new_base_startup_config_path = os.path.join(os.path.dirname(ios_router["startup_config"]), new_base_config_name)
                            os.rename(ios_router["startup_config"], new_base_startup_config_path)
                            ios_router["startup_config"] = new_base_startup_config_path
                        except OSError as e:
                            QtGui.QMessageBox.critical(self, "IOS router", "Could not rename {} to {}: {}".format(ios_router["startup_config"], new_base_startup_config_path, e))

                    # rename the base private-config file
                    default_private_config_name = "{}_base_private-config.txt".format(normalize_filename(item.text(0)))
                    if os.path.isfile(ios_router["private_config"]) and ios_router["private_config"] != self._base_private_config_template \
                            and os.path.basename(ios_router["private_config"]) == default_private_config_name:
                        try:
                            new_base_private_config = os.path.join(os.path.dirname(ios_router["private_config"]), "{}_base_private-config.txt".format(normalize_filename(ios_router["name"])))
                            os.rename(ios_router["private_config"], new_base_private_config)
                            ios_router["private_config"] = new_base_private_config
                        except OSError as e:
                            QtGui.QMessageBox.critical(self, "IOS router", "Could not rename {} to {}: {}".format(ios_router["private_config"], new_base_private_config, e))

                    item.setText(0, ios_router["name"])
                    item.setData(0, QtCore.Qt.UserRole, new_key)

                self._refreshInfo(ios_router)