mirror of
https://github.com/GNS3/gns3-gui.git
synced 2026-05-17 00:46:01 +03:00
189 lines
7.0 KiB
Python
189 lines
7.0 KiB
Python
#!/usr/bin/env python
|
|
#
|
|
# Copyright (C) 2015 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 <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
from .vm_wizard import VMWizard
|
|
from gns3.qt import QtWidgets
|
|
from gns3.controller import Controller
|
|
|
|
|
|
class VMWithImagesWizard(VMWizard):
|
|
"""
|
|
Base class for VM wizard with image management (Qemu, IOU...)
|
|
|
|
:param devices: List of existing device for this type
|
|
:param parent: parent widget
|
|
"""
|
|
|
|
def __init__(self, devices, parent):
|
|
# The list of images combo box (Qemu support multiple images)
|
|
self._images_combo_boxes = set()
|
|
|
|
# The list of radio button for existing image or new images
|
|
self._radio_existing_images_buttons = set()
|
|
|
|
super().__init__(devices, parent)
|
|
|
|
def refreshImageStepsButtons(self):
|
|
"""
|
|
When changing the server type (remote or local)
|
|
Refresh all the image selectors
|
|
"""
|
|
for radio_button in self._radio_existing_images_buttons:
|
|
radio_button.setChecked(radio_button.isChecked())
|
|
|
|
def _vmToggledSlot(self, checked):
|
|
super()._vmToggledSlot(checked)
|
|
if checked:
|
|
self.refreshImageStepsButtons()
|
|
|
|
def _remoteServerToggledSlot(self, checked):
|
|
super()._remoteServerToggledSlot(checked)
|
|
if checked:
|
|
self.refreshImageStepsButtons()
|
|
|
|
def _localToggledSlot(self, checked):
|
|
super()._localToggledSlot(checked)
|
|
if checked:
|
|
self.refreshImageStepsButtons()
|
|
|
|
def addImageSelector(self, radio_button, combo_box, line_edit, browser, image_selector, create_button=None, create_image_wizard=None, image_suffix=""):
|
|
"""
|
|
Add a remote image selector
|
|
|
|
:param radio_button: Radio button which toggle display of the listbox
|
|
:param combo_box: The image choice combo box
|
|
:param line_edit: The edit for the image
|
|
:param browser: file upload browser button
|
|
:param image_selector: function which display an image selector and return path
|
|
:param create_button: Image create button None if you don't need one
|
|
:param create_image_wizard: Wizard Class for creating a new image
|
|
"""
|
|
|
|
combo_box.currentIndexChanged.connect(lambda index: self._imageListIndexChangedSlot(index, combo_box, line_edit))
|
|
self._images_combo_boxes.add(combo_box)
|
|
|
|
browser.clicked.connect(lambda: self._imageBrowserSlot(line_edit, image_selector))
|
|
|
|
if create_button:
|
|
assert create_image_wizard is not None
|
|
create_button.clicked.connect(lambda: self._imageCreateSlot(line_edit, create_image_wizard, image_suffix))
|
|
|
|
self._existingImageToggledSlot(True, combo_box, line_edit, browser, create_button)
|
|
radio_button.toggled.connect(lambda checked: self._existingImageToggledSlot(checked, combo_box, line_edit, browser, create_button))
|
|
self._radio_existing_images_buttons.add(radio_button)
|
|
|
|
def _imageCreateSlot(self, line_edit, create_image_wizard, image_suffix):
|
|
create_dialog = create_image_wizard(self, self.getSettings()["compute_id"], self.uiNameLineEdit.text() + image_suffix)
|
|
if QtWidgets.QDialog.DialogCode.Accepted == create_dialog.exec():
|
|
line_edit.setText(create_dialog.uiLocationLineEdit.text())
|
|
|
|
def _imageBrowserSlot(self, line_edit, image_selector):
|
|
"""
|
|
Slot to open a file browser and select an image.
|
|
"""
|
|
|
|
path = image_selector(self, self._compute_id)
|
|
if not path:
|
|
return
|
|
line_edit.clear()
|
|
line_edit.setText(path)
|
|
|
|
def _imageListIndexChangedSlot(self, index, combo_box, line_edit):
|
|
"""
|
|
User select a different image in the combo box
|
|
"""
|
|
item = combo_box.itemData(index)
|
|
if item and item["path"]:
|
|
line_edit.setText(item["path"])
|
|
else:
|
|
line_edit.setText("")
|
|
|
|
def _existingImageToggledSlot(self, checked, combo_box, line_edit, browser, create_button):
|
|
"""
|
|
User select the option of using an existing image
|
|
"""
|
|
|
|
if create_button:
|
|
create_button.hide()
|
|
|
|
if checked:
|
|
combo_box.show()
|
|
browser.hide()
|
|
line_edit.hide()
|
|
if combo_box.count() > 0:
|
|
line_edit.setText(combo_box.itemData(combo_box.currentIndex())["path"])
|
|
else:
|
|
combo_box.hide()
|
|
line_edit.setText("")
|
|
line_edit.show()
|
|
browser.show()
|
|
if create_button:
|
|
create_button.show()
|
|
|
|
def loadImagesList(self, endpoint):
|
|
"""
|
|
Fill the list box with available Images"
|
|
|
|
:param endpoint: server endpoint with the list of Images
|
|
"""
|
|
|
|
Controller.instance().getCompute(endpoint, self._compute_id, self._getImagesFromServerCallback)
|
|
|
|
def _getImagesFromServerCallback(self, result, error=False, **kwargs):
|
|
"""
|
|
Callback for loadImagesList.
|
|
|
|
:param result: server response
|
|
:param error: indicates an error (boolean)
|
|
"""
|
|
|
|
if error:
|
|
QtWidgets.QMessageBox.critical(self, "Images", "Error while getting the VMs: {}".format(result["message"]))
|
|
return
|
|
|
|
# Wizard is closed
|
|
if self.currentPage() is None:
|
|
return
|
|
|
|
if len(result) == 0:
|
|
for radio_button in self._radio_existing_images_buttons:
|
|
if radio_button.isChecked() and self._widgetOnCurrentPage(radio_button):
|
|
for button in radio_button.parent().findChildren(QtWidgets.QRadioButton):
|
|
if button != radio_button:
|
|
button.setChecked(True)
|
|
button.hide()
|
|
else:
|
|
for radio_button in self._radio_existing_images_buttons:
|
|
if self._widgetOnCurrentPage(radio_button):
|
|
for button in radio_button.parent().findChildren(QtWidgets.QRadioButton):
|
|
if button == radio_button:
|
|
button.setChecked(True)
|
|
button.show()
|
|
|
|
for combo_box in self._images_combo_boxes:
|
|
if self._widgetOnCurrentPage(combo_box):
|
|
combo_box.clear()
|
|
for vm in result:
|
|
combo_box.addItem(vm["path"], vm)
|
|
|
|
def _widgetOnCurrentPage(self, widget):
|
|
"""
|
|
:returns Boolean True if widget is current active Wizard page
|
|
"""
|
|
return self.currentPage().findChild(widget.__class__, widget.objectName()) is not None
|