/[smeserver]/cdrom.image/sme9/updates/storage/deviceaction.py
ViewVC logotype

Annotation of /cdrom.image/sme9/updates/storage/deviceaction.py

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (hide annotations) (download) (as text)
Tue Jul 30 21:01:52 2013 UTC (10 years, 11 months ago) by charliebrady
Branch: MAIN
Content type: text/x-python
Add storage module from anaconda to updates directory, so that parts of it can be modified.

1 charliebrady 1.1 # deviceaction.py
2     # Device modification action classes for anaconda's storage configuration
3     # module.
4     #
5     # Copyright (C) 2009 Red Hat, Inc.
6     #
7     # This copyrighted material is made available to anyone wishing to use,
8     # modify, copy, or redistribute it subject to the terms and conditions of
9     # the GNU General Public License v.2, or (at your option) any later version.
10     # This program is distributed in the hope that it will be useful, but WITHOUT
11     # ANY WARRANTY expressed or implied, including the implied warranties of
12     # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13     # Public License for more details. You should have received a copy of the
14     # GNU General Public License along with this program; if not, write to the
15     # Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16     # 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
17     # source code or documentation are not subject to the GNU General Public
18     # License and may only be used or replicated with the express permission of
19     # Red Hat, Inc.
20     #
21     # Red Hat Author(s): Dave Lehman <dlehman@redhat.com>
22     #
23    
24     from udev import *
25     import math
26    
27     from devices import StorageDevice, PartitionDevice
28     from formats import getFormat
29     from errors import *
30     from parted import partitionFlag, PARTITION_LBA
31    
32     import gettext
33     _ = lambda x: gettext.ldgettext("anaconda", x)
34    
35     import logging
36     log = logging.getLogger("storage")
37    
38    
39     # The values are just hints as to the ordering.
40     # Eg: fsmod and devmod ordering depends on the mod (shrink -v- grow)
41     ACTION_TYPE_NONE = 0
42     ACTION_TYPE_DESTROY = 1000
43     ACTION_TYPE_RESIZE = 500
44     ACTION_TYPE_MIGRATE = 250
45     ACTION_TYPE_CREATE = 100
46    
47     action_strings = {ACTION_TYPE_NONE: "None",
48     ACTION_TYPE_DESTROY: "Destroy",
49     ACTION_TYPE_RESIZE: "Resize",
50     ACTION_TYPE_MIGRATE: "Migrate",
51     ACTION_TYPE_CREATE: "Create"}
52    
53     ACTION_OBJECT_NONE = 0
54     ACTION_OBJECT_FORMAT = 1
55     ACTION_OBJECT_DEVICE = 2
56    
57     object_strings = {ACTION_OBJECT_NONE: "None",
58     ACTION_OBJECT_FORMAT: "Format",
59     ACTION_OBJECT_DEVICE: "Device"}
60    
61     RESIZE_SHRINK = 88
62     RESIZE_GROW = 89
63    
64     resize_strings = {RESIZE_SHRINK: "Shrink",
65     RESIZE_GROW: "Grow"}
66    
67     def action_type_from_string(type_string):
68     if type_string is None:
69     return None
70    
71     for (k,v) in action_strings.items():
72     if v.lower() == type_string.lower():
73     return k
74    
75     return resize_type_from_string(type_string)
76    
77     def action_object_from_string(type_string):
78     if type_string is None:
79     return None
80    
81     for (k,v) in object_strings.items():
82     if v.lower() == type_string.lower():
83     return k
84    
85     def resize_type_from_string(type_string):
86     if type_string is None:
87     return None
88    
89     for (k,v) in resize_strings.items():
90     if v.lower() == type_string.lower():
91     return k
92    
93     class DeviceAction(object):
94     """ An action that will be carried out in the future on a Device.
95    
96     These classes represent actions to be performed on devices or
97     filesystems.
98    
99     The operand Device instance will be modified according to the
100     action, but no changes will be made to the underlying device or
101     filesystem until the DeviceAction instance's execute method is
102     called. The DeviceAction instance's cancel method should reverse
103     any modifications made to the Device instance's attributes.
104    
105     If the Device instance represents a pre-existing device, the
106     constructor should call any methods or set any attributes that the
107     action will eventually change. Device/DeviceFormat classes should verify
108     that the requested modifications are reasonable and raise an
109     exception if not.
110    
111     Only one action of any given type/object pair can exist for any
112     given device at any given time. This is enforced by the
113     DeviceTree.
114    
115     Basic usage:
116    
117     a = DeviceAction(dev)
118     a.execute()
119    
120     OR
121    
122     a = DeviceAction(dev)
123     a.cancel()
124    
125    
126     XXX should we back up the device with a deep copy for forcibly
127     cancelling actions?
128    
129     The downside is that we lose any checking or verification that
130     would get done when resetting the Device instance's attributes to
131     their original values.
132    
133     The upside is that we would be guaranteed to achieve a total
134     reversal. No chance of, eg: resizes ending up altering Device
135     size due to rounding or other miscalculation.
136     """
137     type = ACTION_TYPE_NONE
138     obj = ACTION_OBJECT_NONE
139    
140     def __init__(self, device):
141     if not isinstance(device, StorageDevice):
142     raise ValueError("arg 1 must be a StorageDevice instance")
143     self.device = device
144    
145    
146     def execute(self, intf=None):
147     """ perform the action """
148     pass
149    
150     def cancel(self):
151     """ cancel the action """
152     pass
153    
154     def isDestroy(self):
155     return self.type == ACTION_TYPE_DESTROY
156    
157     def isCreate(self):
158     return self.type == ACTION_TYPE_CREATE
159    
160     def isMigrate(self):
161     return self.type == ACTION_TYPE_MIGRATE
162    
163     def isResize(self):
164     return self.type == ACTION_TYPE_RESIZE
165    
166     def isShrink(self):
167     return (self.type == ACTION_TYPE_RESIZE and self.dir == RESIZE_SHRINK)
168    
169     def isGrow(self):
170     return (self.type == ACTION_TYPE_RESIZE and self.dir == RESIZE_GROW)
171    
172     def isDevice(self):
173     return self.obj == ACTION_OBJECT_DEVICE
174    
175     def isFormat(self):
176     return self.obj == ACTION_OBJECT_FORMAT
177    
178     @property
179     def format(self):
180     return self.device.format
181    
182     def __str__(self):
183     s = "%s %s" % (action_strings[self.type], object_strings[self.obj])
184     if self.isResize():
185     s += " (%s)" % resize_strings[self.dir]
186     if self.isFormat():
187     s += " %s on" % self.format.type
188     if self.isMigrate():
189     s += " to %s" % self.format.migrationTarget
190     s += " %s %s (id %d)" % (self.device.type, self.device.name,
191     self.device.id)
192     return s
193    
194     class ActionCreateDevice(DeviceAction):
195     """ Action representing the creation of a new device. """
196     type = ACTION_TYPE_CREATE
197     obj = ACTION_OBJECT_DEVICE
198    
199     def __init__(self, device):
200     # FIXME: assert device.fs is None
201     DeviceAction.__init__(self, device)
202    
203     def execute(self, intf=None):
204     self.device.create(intf=intf)
205    
206    
207     class ActionDestroyDevice(DeviceAction):
208     """ An action representing the deletion of an existing device. """
209     type = ACTION_TYPE_DESTROY
210     obj = ACTION_OBJECT_DEVICE
211    
212     def __init__(self, device):
213     # XXX should we insist that device.fs be None?
214     DeviceAction.__init__(self, device)
215     if device.exists:
216     device.teardown()
217    
218     def execute(self, intf=None):
219     self.device.destroy()
220    
221     # Make sure libparted does not keep cached info for this device
222     # and returns it when we create a new device with the same name
223     if self.device.partedDevice:
224     self.device.partedDevice.removeFromCache()
225    
226    
227     class ActionResizeDevice(DeviceAction):
228     """ An action representing the resizing of an existing device. """
229     type = ACTION_TYPE_RESIZE
230     obj = ACTION_OBJECT_DEVICE
231    
232     def __init__(self, device, newsize):
233     currentSize = long(math.floor(device.currentSize))
234     if currentSize == newsize:
235     raise ValueError("new size same as old size")
236    
237     if not device.resizable:
238     raise ValueError("device is not resizable")
239    
240     DeviceAction.__init__(self, device)
241     if newsize > currentSize:
242     self.dir = RESIZE_GROW
243     else:
244     self.dir = RESIZE_SHRINK
245     self.origsize = device.targetSize
246     self.device.targetSize = newsize
247    
248     def execute(self, intf=None):
249     self.device.resize(intf=intf)
250    
251     def cancel(self):
252     self.device.targetSize = self.origsize
253    
254    
255     class ActionCreateFormat(DeviceAction):
256     """ An action representing creation of a new filesystem. """
257     type = ACTION_TYPE_CREATE
258     obj = ACTION_OBJECT_FORMAT
259    
260     def __init__(self, device, format=None):
261     DeviceAction.__init__(self, device)
262     if format:
263     self.origFormat = device.format
264     if self.device.format.exists:
265     self.device.format.teardown()
266     self.device.format = format
267     else:
268     self.origFormat = getFormat(None)
269    
270     def execute(self, intf=None):
271     self.device.setup()
272    
273     if isinstance(self.device, PartitionDevice):
274     for flag in partitionFlag.keys():
275     # Keep the LBA flag on pre-existing partitions
276     if flag in [ PARTITION_LBA, self.format.partedFlag ]:
277     continue
278     self.device.unsetFlag(flag)
279    
280     if self.format.partedFlag is not None:
281     self.device.setFlag(self.format.partedFlag)
282    
283     if self.format.partedSystem is not None:
284     self.device.partedPartition.system = self.format.partedSystem
285    
286     self.device.disk.format.commitToDisk()
287    
288     self.device.format.create(intf=intf,
289     device=self.device.path,
290     options=self.device.formatArgs)
291     # Get the UUID now that the format is created
292     udev_settle()
293     self.device.updateSysfsPath()
294     info = udev_get_block_device(self.device.sysfsPath)
295     self.device.format.uuid = udev_device_get_uuid(info)
296    
297     def cancel(self):
298     self.device.format = self.origFormat
299    
300    
301     class ActionDestroyFormat(DeviceAction):
302     """ An action representing the removal of an existing filesystem.
303    
304     XXX this seems unnecessary
305     """
306     type = ACTION_TYPE_DESTROY
307     obj = ACTION_OBJECT_FORMAT
308    
309     def __init__(self, device):
310     DeviceAction.__init__(self, device)
311     self.origFormat = self.device.format
312     if device.format.exists:
313     device.format.teardown()
314     self.device.format = None
315    
316     def execute(self, intf=None):
317     """ wipe the filesystem signature from the device """
318     if self.origFormat:
319     self.device.setup(orig=True)
320     self.origFormat.destroy()
321     udev_settle()
322     self.device.teardown()
323    
324     def cancel(self):
325     self.device.format = self.origFormat
326    
327     @property
328     def format(self):
329     return self.origFormat
330    
331    
332     class ActionResizeFormat(DeviceAction):
333     """ An action representing the resizing of an existing filesystem.
334    
335     XXX Do we even want to support resizing of a filesystem without
336     also resizing the device it resides on?
337     """
338     type = ACTION_TYPE_RESIZE
339     obj = ACTION_OBJECT_FORMAT
340    
341     def __init__(self, device, newsize):
342     if long(math.floor(device.format.targetSize)) == newsize:
343     raise ValueError("new size same as old size")
344    
345     DeviceAction.__init__(self, device)
346     if newsize > long(math.floor(device.format.currentSize)):
347     self.dir = RESIZE_GROW
348     else:
349     self.dir = RESIZE_SHRINK
350     self.origSize = self.device.format.targetSize
351     self.device.format.targetSize = newsize
352    
353     def execute(self, intf=None):
354     self.device.setup(orig=True)
355     self.device.format.doResize(intf=intf)
356    
357     def cancel(self):
358     self.device.format.targetSize = self.origSize
359    
360     class ActionMigrateFormat(DeviceAction):
361     """ An action representing the migration of an existing filesystem. """
362     type = ACTION_TYPE_MIGRATE
363     obj = ACTION_OBJECT_FORMAT
364    
365     def __init__(self, device):
366     if not device.format.migratable or not device.format.exists:
367     raise ValueError("device format is not migratable")
368    
369     DeviceAction.__init__(self, device)
370     self.device.format.migrate = True
371    
372     def execute(self, intf=None):
373     self.device.setup(orig=True)
374     self.device.format.doMigrate(intf=intf)
375    
376     def cancel(self):
377     self.device.format.migrate = False
378    

admin@koozali.org
ViewVC Help
Powered by ViewVC 1.2.1 RSS 2.0 feed