Merge branch 'master' of git.qubes-os.org:/var/lib/qubes/git/marmarek/qubes-manager

This commit is contained in:
Joanna Rutkowska 2012-07-12 13:43:36 +02:00
commit 2bdfa028f4
2 changed files with 80 additions and 3 deletions

View File

@ -229,7 +229,7 @@
<x>0</x>
<y>0</y>
<width>769</width>
<height>25</height>
<height>22</height>
</rect>
</property>
<widget class="QMenu" name="menu_system">
@ -285,6 +285,7 @@
</widget>
<addaction name="action_createvm"/>
<addaction name="action_removevm"/>
<addaction name="action_clonevm"/>
<addaction name="separator"/>
<addaction name="action_resumevm"/>
<addaction name="action_pausevm"/>
@ -738,6 +739,18 @@
<string>Run command in the specified VM</string>
</property>
</action>
<action name="action_clonevm">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/templatevm.png</normaloff>:/templatevm.png</iconset>
</property>
<property name="text">
<string>Clone VM</string>
</property>
</action>
</widget>
<resources>
<include location="resources.qrc"/>

View File

@ -39,6 +39,7 @@ from qubes.qubes import dry_run
from qubes.qubes import qubes_guid_path
from qubes.qubes import QubesDaemonPidfile
from qubes.qubes import QubesHost
from qubes import qubes
from qubes import qubesutils
import qubesmanager.resources_rc
@ -647,8 +648,6 @@ class VmShutdownMonitor(QObject):
vm = self.vm
vm_start_time = vm.get_start_time()
if not vm.is_running() or (vm_start_time and vm_start_time >= datetime.utcnow() - timedelta(0,self.shutdown_time/1000)):
if vm.is_template():
trayIcon.showMessage ("You have just modified template '{0}'. You should now restart all the VMs based on it, so they could see the changes.".format(vm.name), msecs=8000)
return
reply = QMessageBox.question(None, "VM Shutdown",
@ -756,6 +755,7 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
self.context_menu = QMenu(self)
self.context_menu.addAction(self.action_removevm)
self.context_menu.addAction(self.action_resumevm)
self.context_menu.addAction(self.action_clonevm)
self.context_menu.addAction(self.action_pausevm)
self.context_menu.addAction(self.action_shutdownvm)
self.context_menu.addAction(self.action_killvm)
@ -1075,6 +1075,7 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
# Update available actions:
self.action_settings.setEnabled(vm.qid != 0)
self.action_removevm.setEnabled(not vm.installed_by_rpm and not (vm.last_running))
self.action_clonevm.setEnabled(not vm.installed_by_rpm and not (vm.last_running) and not vm.is_netvm())
self.action_resumevm.setEnabled(not vm.last_running)
self.action_pausevm.setEnabled(vm.last_running and vm.qid != 0)
self.action_shutdownvm.setEnabled(vm.last_running and vm.qid != 0)
@ -1087,6 +1088,7 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
else:
self.action_settings.setEnabled(False)
self.action_removevm.setEnabled(False)
self.action_clonevm.setEnabled(False)
self.action_resumevm.setEnabled(False)
self.action_pausevm.setEnabled(False)
self.action_shutdownvm.setEnabled(False)
@ -1215,6 +1217,68 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
thread_monitor.set_finished()
@pyqtSlot(name='on_action_clonevm_triggered')
def action_clonevm_triggered(self):
vm = self.get_selected_vm()
name_number = 1
name_format = vm.name + '-clone-%d'
while self.qvm_collection.get_vm_by_name(name_format % name_number):
name_number += 1
cmd = ['kdialog', '--title', 'Qubes clone VM', '--inputbox', 'Enter name for VM <b>'+vm.name+'</b> clone:', name_format % name_number]
kdialog = subprocess.Popen(cmd, stdout = subprocess.PIPE)
clone_name = kdialog.stdout.read().strip()
if clone_name == "":
return
thread_monitor = ThreadMonitor()
thread = threading.Thread (target=self.do_clone_vm, args=(vm, clone_name, thread_monitor))
thread.daemon = True
thread.start()
progress = QProgressDialog ("Cloning VM <b>{0}</b> to <b>{1}</b>...".format(vm.name, clone_name), "", 0, 0)
progress.setCancelButton(None)
progress.setModal(True)
progress.show()
while not thread_monitor.is_finished():
app.processEvents()
time.sleep (0.2)
progress.hide()
if not thread_monitor.success:
QMessageBox.warning (None, "Error while cloning VM", "Exception while cloning:<br>{0}".format(thread_monitor.error_msg))
def do_clone_vm(self, vm, dst_name, thread_monitor):
try:
self.qvm_collection.lock_db_for_writing()
self.qvm_collection.load()
src_vm = self.qvm_collection[vm.qid]
dst_vm = None
if isinstance(src_vm, qubes.QubesTemplateVm):
dst_vm = self.qvm_collection.add_new_templatevm(name=dst_name,
installed_by_rpm=False)
elif isinstance(src_vm, qubes.QubesAppVm):
dst_vm = self.qvm_collection.add_new_appvm(name=dst_name, template=src_vm.template,
label=src_vm.label)
elif hasattr(qubes, 'QubesHVm') and isinstance(src_vm, qubes.QubesHVm):
dst_vm = self.qvm_collection.add_new_hvm(name=dst_name, label=src_vm.label)
dst_vm.clone_attrs(src_vm)
dst_vm.clone_disk_files (src_vm=src_vm, verbose=False)
self.qvm_collection.save()
self.qvm_collection.unlock_db()
except Exception as ex:
if dst_vm:
self.qvm_collection.pop(dst_vm.qid)
self.qvm_collection.unlock_db()
thread_monitor.set_error_msg(str(ex))
thread_monitor.set_finished()
@pyqtSlot(name='on_action_resumevm_triggered')
def action_resumevm_triggered(self):
vm = self.get_selected_vm()