[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[PATCH 08/15] Add requires and obsoletes methods to DeviceAction classes.



These establish a mechanism for resolving dependencies between actions.
---
 pyanaconda/storage/deviceaction.py |  188 ++++++++++++++++++++++++++++++++++++
 1 files changed, 188 insertions(+), 0 deletions(-)

diff --git a/pyanaconda/storage/deviceaction.py b/pyanaconda/storage/deviceaction.py
index ca7b3bc..4396661 100644
--- a/pyanaconda/storage/deviceaction.py
+++ b/pyanaconda/storage/deviceaction.py
@@ -206,6 +206,22 @@ class DeviceAction(object):
                                  self.device.id)
         return s
 
+    def requires(self, action):
+        """ Return True if self requires action. """
+        return False
+
+    def obsoletes(self, action):
+        """ Return True is self obsoletes action.
+
+            DeviceAction instances obsolete other DeviceAction instances with
+            lower id and same device.
+        """
+        return (self.device.id == action.device.id and
+                self.type == action.type and
+                self.obj == action.obj and
+                self.id > action.id)
+
+
 class ActionCreateDevice(DeviceAction):
     """ Action representing the creation of a new device. """
     type = ACTION_TYPE_CREATE
@@ -218,6 +234,30 @@ class ActionCreateDevice(DeviceAction):
     def execute(self, intf=None):
         self.device.create(intf=intf)
 
+    def requires(self, action):
+        """ Return True if self requires action.
+
+            Device create actions require other actions when either of the
+            following is true:
+
+                - this action's device depends on the other action's device
+                - both actions are partition create actions on the same disk
+                  and this partition has a higher number
+        """
+        rc = False
+        if self.device.dependsOn(action.device):
+            rc = True
+        elif (action.isCreate and action.isDevice and
+              isinstance(self.device, PartitionDevice) and
+              isinstance(action.device, PartitionDevice) and
+              self.device.disk == action.device.disk):
+            # create partitions in ascending numerical order
+            selfNum = self.device.partedPartition.number
+            otherNum = action.device.partedPartition.number
+            if selfNum > otherNum:
+                rc = True
+        return rc
+
 
 class ActionDestroyDevice(DeviceAction):
     """ An action representing the deletion of an existing device. """
@@ -238,6 +278,54 @@ class ActionDestroyDevice(DeviceAction):
         if self.device.partedDevice:
             self.device.partedDevice.removeFromCache()
 
+    def requires(self, action):
+        """ Return True if self requires action.
+
+            Device destroy actions require other actions when either of the
+            following is true:
+
+                - the other action's device depends on this action's device
+                - both actions are partition create actions on the same disk
+                  and this partition has a lower number
+        """
+        rc = False
+        if action.device.dependsOn(self.device):
+            rc = True
+        elif (action.isDestroy and action.isDevice and
+              isinstance(self.device, PartitionDevice) and
+              isinstance(action.device, PartitionDevice) and
+              self.device.disk == action.device.disk):
+            # remove partitions in descending numerical order
+            selfNum = self.device.partedPartition.number
+            otherNum = action.device.partedPartition.number
+            if selfNum < otherNum:
+                rc = True
+        elif (action.isDestroy and action.isFormat and
+              action.device.id == self.device.id):
+            # device destruction comes after destruction of device's format
+            rc = True
+        return rc
+
+    def obsoletes(self, action):
+        """ Return True if self obsoletes action.
+
+            - obsoletes all actions w/ lower id that act on the same device,
+              including self, if device does not exist
+
+            - obsoletes all but ActionDestroyFormat actions w/ lower id on the
+              same device if device exists
+        """
+        rc = False
+        if action.device.id == self.device.id:
+            if self.id >= action.id and not self.device.exists:
+                rc = True
+            elif self.id > action.id and \
+                 self.device.exists and \
+                 not (action.isDestroy and action.isFormat):
+                rc = True
+
+        return rc
+
 
 class ActionResizeDevice(DeviceAction):
     """ An action representing the resizing of an existing device. """
@@ -266,6 +354,31 @@ class ActionResizeDevice(DeviceAction):
     def cancel(self):
         self.device.targetSize = self.origsize
 
+    def requires(self, action):
+        """ Return True if self requires action.
+
+            A device resize action requires another action if:
+
+                - the other action is a format resize on the same device and
+                  both are shrink operations
+                - the other action grows a device (or format it contains) that
+                  this action's device depends on
+                - the other action shrinks a device (or format it contains)
+                  that depends on this action's device
+        """
+        retval = False
+        if action.isResize:
+            if self.device.id == action.device.id and \
+               self.dir == action.dir and \
+               action.isFormat and self.isShrink:
+                retval = True
+            elif action.isGrow and self.device.dependsOn(action.device):
+                retval = True
+            elif action.isShrink and action.device.dependsOn(self.device):
+                retval = True
+
+        return retval
+
 
 class ActionCreateFormat(DeviceAction):
     """ An action representing creation of a new filesystem. """
@@ -312,6 +425,32 @@ class ActionCreateFormat(DeviceAction):
     def cancel(self):
         self.device.format = self.origFormat
 
+    def requires(self, action):
+        """ Return True if self requires action.
+
+            Format create action can require another action if:
+
+                - this action's device depends on the other action's device
+                  and the other action is not a device destroy action
+                - the other action is a create or resize of this action's
+                  device
+        """
+        return ((self.device.dependsOn(action.device) and
+                 not (action.isDestroy and action.isDevice)) or
+                (action.isDevice and (action.isCreate or action.isResize) and
+                 self.device.id == action.device.id))
+
+    def obsoletes(self, action):
+        """ Return True if this action obsoletes action.
+
+            Format create actions obsolete the following actions:
+
+                - format actions w/ lower id on this action's device
+        """
+        return (self.device.id == action.device.id and
+                self.obj == action.obj and
+                self.id > action.id)
+
 
 class ActionDestroyFormat(DeviceAction):
     """ An action representing the removal of an existing filesystem.
@@ -343,6 +482,29 @@ class ActionDestroyFormat(DeviceAction):
     def format(self):
         return self.origFormat
 
+    def requires(self, action):
+        """ Return True if self requires action.
+
+            Format destroy actions require other actions when:
+
+                - the other action's device depends on this action's device
+                  and the other action is a destroy action
+        """
+        return action.device.dependsOn(self.device) and action.isDestroy
+
+    def obsoletes(self, action):
+        """ Return True if this action obsoletes action.
+
+            Format destroy actions obsolete the following actions:
+
+            - format actions w/ lower id on same device, including self if
+              format does not exist
+        """
+        return (self.device.id == action.device.id and
+                self.obj == self.obj and
+                (self.id > action.id or
+                 self.id == action.id and not self.device.exists))
+
 
 class ActionResizeFormat(DeviceAction):
     """ An action representing the resizing of an existing filesystem.
@@ -372,6 +534,32 @@ class ActionResizeFormat(DeviceAction):
     def cancel(self):
         self.device.format.targetSize = self.origSize
 
+    def requires(self, action):
+        """ Return True if self requires action.
+
+            A format resize action requires another action if:
+
+                - the other action is a device resize on the same device and
+                  both are grow operations
+                - the other action shrinks a device (or format it contains)
+                  that depends on this action's device
+                - the other action grows a device (or format) that this
+                  action's device depends on
+        """
+        retval = False
+        if action.isResize:
+            if self.device.id == action.device.id and \
+               self.dir == action.dir and \
+               action.isDevice and self.isGrow:
+                retval = True
+            elif action.isShrink and action.device.dependsOn(self.device):
+                retval = True
+            elif action.isGrow and self.device.dependsOn(action.device):
+                retval = True
+
+        return retval
+
+
 class ActionMigrateFormat(DeviceAction):
     """ An action representing the migration of an existing filesystem. """
     type = ACTION_TYPE_MIGRATE
-- 
1.7.2.3


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]