Forráskód Böngészése

Used Watch API for block devices

Agnieszka Kostrzewa 12 éve
szülő
commit
9470f69be8
2 módosított fájl, 67 hozzáadás és 19 törlés
  1. 6 0
      qubesmanager/backup_utils.py
  2. 61 19
      qubesmanager/main.py

+ 6 - 0
qubesmanager/backup_utils.py

@@ -72,6 +72,8 @@ def umount_device(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']
@@ -79,6 +81,8 @@ def fill_devs_list(dialog):
     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()
@@ -107,6 +111,7 @@ def dev_combobox_activated(dialog, idx):
     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]
@@ -118,6 +123,7 @@ def dev_combobox_activated(dialog, idx):
         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)

+ 61 - 19
qubesmanager/main.py

@@ -557,9 +557,14 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
         self.setupUi(self)
         self.toolbar = self.toolBar
         
+        self.qubes_watch = qubesutils.QubesWatch()
         self.qvm_collection = QubesVmCollection()
         self.blk_manager = QubesBlockDevicesManager(self.qvm_collection)
-        
+        self.qubes_watch.setup_block_watch(self.blk_manager.block_devs_event)
+        self.blk_watch_thread = threading.Thread(target=self.qubes_watch.watch_loop)
+        self.blk_watch_thread.daemon = True
+        self.blk_watch_thread.start()
+
         self.connect(self.table, SIGNAL("itemSelectionChanged()"), self.table_selection_changed)
         
         self.table.setColumnWidth(0, self.column_width)
@@ -794,8 +799,10 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
             rows_with_blk = None
             if update_devs == True:
                 rows_with_blk = []
+                self.blk_manager.blk_lock.acquire()
                 for d in self.blk_manager.attached_devs:
                     rows_with_blk.append( self.blk_manager.attached_devs[d]['attached_to']['vm'])
+                self.blk_manager.blk_lock.release()
 
             if self.counter % 3 == 0 or out_of_schedule:
                 (self.last_measure_time, self.last_measure_results) = \
@@ -843,7 +850,7 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
 
  
     def update_block_devices(self):
-        res, msg = self.blk_manager.update()
+        res, msg = self.blk_manager.check_for_updates()
         if msg != None and len(msg) > 0:
             str = "\n".join(msg)
             trayIcon.showMessage ("Qubes Manager", str, msecs=5000)
@@ -1304,6 +1311,8 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
         else:
             self.blk_menu.clear()
             self.blk_menu.setEnabled(True)
+
+            self.blk_manager.blk_lock.acquire()
             if len(self.blk_manager.attached_devs) > 0 :
                 for d in self.blk_manager.attached_devs:
                     if self.blk_manager.attached_devs[d]['attached_to']['vm'] == vm.name:
@@ -1319,6 +1328,8 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
                     action = self.blk_menu.addAction(QIcon(":/add.png"), str)
                     action.setData(QVariant(d))
 
+            self.blk_manager.blk_lock.release()
+
             if self.blk_menu.isEmpty():
                 self.blk_menu.setEnabled(False)
  
@@ -1328,10 +1339,13 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
     def attach_dettach_device_triggered(self, action):
         dev = str(action.data().toString())
         vm = self.get_selected_vm()
+
+        self.blk_manager.blk_lock.acquire()
         if dev in self.blk_manager.attached_devs:
             self.blk_manager.detach_device(vm, dev)
         else:
             self.blk_manager.attach_device(vm, dev)
+        self.blk_manager.blk_lock.release()
 
 
 class QubesBlockDevicesManager():
@@ -1344,43 +1358,75 @@ class QubesBlockDevicesManager():
         self.current_attached = {}
         self.devs_changed = False
 
+        self.last_update_time = time.time()
+        self.blk_state_changed = True
+        self.msg = []
+        self.check_counter = 0
+        self.blk_lock = threading.Lock()
+
+        self.update()
+
+    def block_devs_event(self, xid):
+        now = time.time()
+        #don't update more often than 1/10 s
+        if now - self.last_update_time >= 0.1:
+            self.last_update_time = now
+
+            self.blk_lock.acquire()
+
+            self.blk_state_changed = True
+
+            self.blk_lock.release()
+
+    def check_for_updates(self):
+        self.blk_lock.acquire()
+
+        ret = (self.blk_state_changed, self.msg)
+        
+        if self.blk_state_changed == True:
+            self.check_counter += 1
+            
+            self.update()
+            ret = (self.blk_state_changed, self.msg)
+            
+            #let the update last for 3 manager-update cycles
+            if self.check_counter == 3:
+                self.check_counter = 0
+                self.blk_state_changed = False
+        self.msg = []            
+
+        self.blk_lock.release()
+
+        return ret
+            
+            
     def update(self):
         blk = qubesutils.block_list()
-        msg = []
         for b in blk:
             att = qubesutils.block_check_attached(None, blk[b]['device'], backend_xid = blk[b]['xid'])
             if b in self.current_blk:
                 if blk[b] == self.current_blk[b]:
                     if self.current_attached[b] != att: #devices the same, sth with attaching changed
                         self.current_attached[b] = att
-                        self.devs_changed = True
                 else:   #device changed ?!
                     self.current_blk[b] = blk[b]
                     self.current_attached[b] = att
-                    self.devs_changed = True
             else: #new device
                 self.current_blk[b] = blk[b]
                 self.current_attached[b] = att
-                self.devs_changed = True
-                msg.append("Attached new device: {0}".format(blk[b]['device']))
+                self.msg.append("Attached new device: {0}".format(blk[b]['device']))
 
         to_delete = []
         for b in self.current_blk: #remove devices that are not there anymore
             if b not in blk:
                 to_delete.append(b)
-                self.devs_changed = True
-                msg.append("Detached device: {0}".format(self.current_blk[b]['device']))
+                self.msg.append("Detached device: {0}".format(self.current_blk[b]['device']))
 
         for d in to_delete:
             del self.current_blk[d]
             del self.current_attached[d]
 
-        if self.devs_changed == True:
-            self.devs_changed = False
-            self.__update_blk_entries__()
-            return True, msg
-        else:
-            return False, None
+        self.__update_blk_entries__()
 
 
     def __update_blk_entries__(self):
@@ -1408,16 +1454,12 @@ class QubesBlockDevicesManager():
         backend_vm = self.qvm_collection.get_vm_by_name(backend_vm_name)
         trayIcon.showMessage ("Qubes Manager", "{0} - attaching {1}".format(vm.name, dev), msecs=3000)
         qubesutils.block_attach(vm, backend_vm, dev_id)
-        self.devs_changed = True
       
     def detach_device(self, vm, dev_name):
         dev_id = self.attached_devs[dev_name]['attached_to']['devid']
         vm_xid = self.attached_devs[dev_name]['attached_to']['xid']
         trayIcon.showMessage ("Qubes Manager", "{0} - detaching {1}".format(vm.name, dev_name), msecs=3000)
         qubesutils.block_detach(None, dev_id, vm_xid)
-        self.devs_changed = True
-
-
 
 
 class QubesTrayIcon(QSystemTrayIcon):