123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- #!/usr/bin/python2
- #
- # The Qubes OS Project, http://www.qubes-os.org
- #
- # Copyright (C) 2012 Agnieszka Kostrzewa <agnieszka.kostrzewa@gmail.com>
- #
- # 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 2
- # 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, write to the Free Software
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- #
- #
- import sys
- import os
- from PyQt4.QtCore import *
- from PyQt4.QtGui import *
- from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent
- import subprocess
- import time
- from thread_monitor import *
- from datetime import datetime
- from string import replace
- mount_for_backup_path = '/usr/libexec/qubes-manager/mount_for_backup.sh'
- def check_if_mounted(dev_path):
- mounts_file = open("/proc/mounts")
- for m in list(mounts_file):
- if m.startswith(dev_path):
- return m.split(" ")[1]
- return None
- def mount_device(dev_path):
- try:
- mount_dir_name = "backup" + replace(str(datetime.now()),' ', '-').split(".")[0]
- pmount_cmd = [mount_for_backup_path, dev_path, mount_dir_name]
- res = subprocess.check_call(pmount_cmd)
- except Exception as ex:
- QMessageBox.warning (None, "Error mounting selected device!", "<b>Could not mount {0}.</b><br><br>ERROR: {1}".format(dev_path, ex))
- return None
- if res == 0:
- dev_mount_path = "/media/"+mount_dir_name
- return dev_mount_path
- return None
- def umount_device(dev_mount_path):
- while True:
- try:
- pumount_cmd = ["sudo", "pumount", "--luks-force", dev_mount_path]
- res = subprocess.check_call(pumount_cmd)
- if res == 0:
- dev_mount_path = None
- return dev_mount_path
- except Exception as ex:
- title = "Error unmounting backup device!"
- text = "<b>Could not unmount {0}.</b><br>\
- <b>Please retry or unmount it manually using</b><br> pumount {0}.<br><br>\
- ERROR: {1}".format(dev_mount_path, ex)
- button = QMessageBox.warning (None, title, text, QMessageBox.Ok | QMessageBox.Retry, QMessageBox.Retry)
- if button == QMessageBox.Ok:
- return dev_mount_path
- def fill_devs_list(dialog):
- dialog.dev_combobox.clear()
- dialog.dev_combobox.addItem("None")
-
- dialog.blk_manager.blk_lock.acquire()
- for a in dialog.blk_manager.attached_devs:
- if dialog.blk_manager.attached_devs[a]['attached_to']['vm'] == dialog.vm.name :
- att = a + " " + unicode(dialog.blk_manager.attached_devs[a]['size']) + " " + dialog.blk_manager.attached_devs[a]['desc']
- dialog.dev_combobox.addItem(att, QVariant(a))
- for a in dialog.blk_manager.free_devs:
- att = a + " " + unicode(dialog.blk_manager.free_devs[a]['size']) + " " + dialog.blk_manager.free_devs[a]['desc']
- dialog.dev_combobox.addItem(att, QVariant(a))
- dialog.blk_manager.blk_lock.release()
- dialog.dev_combobox.setCurrentIndex(0) #current selected is null ""
- dialog.prev_dev_idx = 0
- dialog.dir_line_edit.clear()
- enable_dir_line_edit(dialog, True)
- def enable_dir_line_edit(dialog, boolean):
- dialog.dir_line_edit.setEnabled(boolean)
- dialog.select_path_button.setEnabled(boolean)
- def dev_combobox_activated(dialog, idx):
- if idx == dialog.prev_dev_idx: #nothing has changed
- return
- #there was a change
- dialog.dir_line_edit.setText("")
- dialog.backup_dir = None
- if dialog.dev_mount_path != None:
- dialog.dev_mount_path = umount_device(dialog.dev_mount_path)
- if dialog.dev_mount_path != None:
- dialog.dev_combobox.setCurrentIndex(dialog.prev_dev_idx)
- return
- if dialog.dev_combobox.currentText() != "None": #An existing device chosen
- dev_name = str(dialog.dev_combobox.itemData(idx).toString())
- dialog.blk_manager.blk_lock.acquire()
- if dev_name in dialog.blk_manager.free_devs:
- if dev_name.startswith(dialog.vm.name): # originally attached to dom0
- dev_path = "/dev/"+dev_name.split(":")[1]
- else: # originally attached to another domain, eg. usbvm
- #attach it to dom0, then treat it as an attached device
- dialog.blk_manager.attach_device(dialog.vm, dev_name)
- dialog.blk_manager.update()
- if dev_name in dialog.blk_manager.attached_devs: #is attached to dom0
- assert dialog.blk_manager.attached_devs[dev_name]['attached_to']['vm'] == dialog.vm.name
- dev_path = "/dev/" + dialog.blk_manager.attached_devs[dev_name]['attached_to']['frontend']
- dialog.blk_manager.blk_lock.release()
- #check if device mounted
- dialog.dev_mount_path = check_if_mounted(dev_path)
- if dialog.dev_mount_path == None:
- dialog.dev_mount_path = mount_device(dev_path)
- if dialog.dev_mount_path == None:
- dialog.dev_combobox.setCurrentIndex(0) #if couldn't mount - set current device to "None"
- dialog.prev_dev_idx = 0
- return
-
- dialog.prev_dev_idx = idx
- if dialog.dev_mount_path != None:
- # Initialize path with root of mounted device
- dialog.dir_line_edit.setText(dialog.dev_mount_path)
- dialog.backup_dir = dialog.dev_mount_path
- dialog.select_dir_page.emit(SIGNAL("completeChanged()"))
-
- def select_path_button_clicked(dialog):
- dialog.backup_dir = dialog.dir_line_edit.text()
- file_dialog = QFileDialog()
- file_dialog.setReadOnly(True)
- if dialog.dev_mount_path != None:
- new_path = file_dialog.getExistingDirectory(dialog, "Select backup directory.", dialog.dev_mount_path)
- else:
- new_path = file_dialog.getExistingDirectory(dialog, "Select backup directory.", "~")
-
- if new_path:
- dialog.dir_line_edit.setText(new_path)
- dialog.backup_dir = new_path
- dialog.select_dir_page.emit(SIGNAL("completeChanged()"))
- def simulate_long_lasting_proces(period, progress_callback):
- for i in range(period):
- progress_callback((i*100)/period)
- time.sleep(1)
- progress_callback(100)
- return 0
|