forked from storaged-project/blivet-gui
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlist_partitions.py
312 lines (231 loc) · 11.6 KB
/
list_partitions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# -*- coding: utf-8 -*-
# list_partitions.py
# Load and display partitions for selected device
#
# Copyright (C) 2014 Red Hat, Inc.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions of
# the GNU General Public License v.2, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY expressed or implied, including the implied warranties 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. Any Red Hat trademarks that are incorporated in the
# source code or documentation are not subject to the GNU General Public
# License and may only be used or replicated with the express permission of
# Red Hat, Inc.
#
# Red Hat Author(s): Vojtech Trefny <[email protected]>
#
# ---------------------------------------------------------------------------- #
class ListPartitions(object):
""" List of childs of selected device
"""
def __init__(self, blivet_gui):
self.blivet_gui = blivet_gui
self.installer_mode = self.blivet_gui.installer_mode
self.partitions_list = self.blivet_gui.builder.get_object("liststore_logical")
self.partitions_view = self.blivet_gui.builder.get_object("treeview_logical")
self.partitions_view.connect("button-release-event", self.on_right_click_event)
self.select = self.partitions_view.get_selection()
self.select.connect("changed", self.on_partition_selection_changed)
self.selected_partition = None
def update_partitions_list(self, selected_device):
""" Update partition view with selected disc children (partitions)
:param selected_device: selected device from list (eg. disk or VG)
:type device_name: blivet.Device
"""
self.partitions_list.clear()
def _get_real_child(child):
""" When adding a child device, we actually might want to add one
of its children instead -- e.g. when adding a partition that
is a PV we want to add the VG ("group device") etc.
"""
if self._is_group_device(child):
return self.blivet_gui.client.remote_call("get_group_device", child)
elif child.format and child.format.type == "luks" and child.children:
return self.blivet_gui.client.remote_call("get_luks_device", child)
else:
return child
def _add_chilren(childs, parent_iter=None):
for child in childs:
if child.children:
child_iter = self._add_to_store(child, parent_iter)
_add_chilren(self.blivet_gui.client.remote_call("get_children", child), child_iter)
else:
new_child = _get_real_child(child)
self._add_to_store(new_child, parent_iter)
if selected_device.is_disk:
childs = self.blivet_gui.client.remote_call("get_disk_children", selected_device)
for child in childs.partitions:
child = _get_real_child(child)
child_iter = self._add_to_store(child)
if hasattr(child, "is_extended") and child.is_extended:
for logical in childs.logicals:
logical = _get_real_child(logical)
self._add_to_store(logical, child_iter)
# lvmvg always has some children, at least a free space
elif selected_device.type == "lvmvg":
childs = self.blivet_gui.client.remote_call("get_children", selected_device)
_add_chilren(childs, None)
# for btrfs volumes and mdarrays its necessary to add the device itself to the view
# because these devices don't need to have children (only btrfs volume or only mdarray
# is a valid, usable device)
elif selected_device.type == "btrfs volume" or (selected_device.type == "mdarray" and not selected_device.children):
parent_iter = self._add_to_store(selected_device)
childs = self.blivet_gui.client.remote_call("get_children", selected_device)
_add_chilren(childs, parent_iter)
else:
childs = self.blivet_gui.client.remote_call("get_children", selected_device)
_add_chilren(childs, None)
# select first line in partitions view
self.select.select_path("0")
# expand all expanders
self.partitions_view.expand_all()
def _is_group_device(self, blivet_device):
# btrfs volume on raw disk
if blivet_device.type in ("btrfs volume", "lvmvg"):
return True
if blivet_device.format and blivet_device.format.type in ("lvmpv", "btrfs", "mdmember"):
return (len(blivet_device.children) > 0)
# encrypted group device
if blivet_device.format and blivet_device.format.type == "luks" and blivet_device.children:
luks_device = self.blivet_gui.client.remote_call("get_luks_device", blivet_device)
if luks_device.format and luks_device.format.type in ("lvmpv", "btrfs", "mdmember"):
return (len(luks_device.children) > 0)
return False
def _add_to_store(self, device, parent_iter=None):
""" Add new device to partitions list
:param device: device to add
:type device: blivet.device.Device
:param parent_iter: parent iter for this device
:type parent_iter: Gtk.TreeIter or None
"""
devtype = "lvm" if device.type == "lvmvg" else "raid" if device.type == "mdarray" else device.type
name = device.name if len(device.name) < 18 else device.name[:15] + "..." # FIXME
fmt = device.format.type if device.format else None
if self.installer_mode:
mnt = device.format.mountpoint if (device.format and device.format.mountable) else None
else:
mnt = device.format.system_mountpoint if (device.format and device.format.mountable) else None
device_iter = self.partitions_list.append(parent_iter, [device, name, devtype, fmt, str(device.size), mnt])
return device_iter
def _allow_delete_device(self, device):
if device.protected:
return False
if device.type in ("free space",) or not device.isleaf:
return False
else:
if not device.format.type:
return True
elif device.format.type == "swap":
return not device.format.status
else:
if not device.format.mountable:
return True
else:
return not device.format.status
def _allow_resize_device(self, device):
if device.protected or device.children:
return False
if device.type not in ("partition", "lvmlv", "luks/dm-crypt"):
return False
return device.resizable and device.format.resizable \
and (device.max_size > device.size or device.min_size < device.size)
def _allow_format_device(self, device):
if device.protected or device.children:
return False
if device.type not in ("partition", "lvmlv", "luks/dm-crypt", "mdarray"):
return False
if device.type == "partition" and device.is_extended:
return False
if device.format.type in ("mdmember", "btrfs"):
return False
return not device.format.status
def _allow_set_mountpoint(self, device):
if not self.blivet_gui.installer_mode:
return False
if device.type in ("lvmthinsnapshot", "lvmsnapshot") and not device.exists:
return False
return device.format.mountable
def _allow_set_partition_table(self, device):
# there is no special "device" representing disks in the UI
# so we are "editting" a free space
if device.type != "free space":
return False
# empty disk without disklabel
if device.is_uninitialized_disk:
return True
# empty disk with disklabel
if device.is_empty_disk and device.disk.format.type == "disklabel":
return True
return False
def _allow_add_device(self, device):
if device.protected:
return False
if device.type in ("free space", "btrfs volume", "lvmthinpool"):
return True
# empty lvmpv
if device.format and device.format.type == "lvmpv":
return not device.children
# snapshot of thin lv -- only if exists
if device.type == "lvmthinlv":
return device.exists
# snapshot of lvmlv -- only if there is free space in the vg and if exists
if device.type == "lvmlv":
return device.vg.free_space >= device.vg.pe_size and device.exists
def activate_action_buttons(self, selected_device):
""" Activate buttons in toolbar based on selected device
:param selected_device: Selected partition
:type selected_device: Gtk.TreeModelRow
"""
device = selected_device[0]
self.blivet_gui.deactivate_all_actions()
if device.type not in ("free space", "raw format"):
self.blivet_gui.activate_device_actions(["info"])
if self._allow_delete_device(device):
self.blivet_gui.activate_device_actions(["delete"])
if self._allow_resize_device(device):
self.blivet_gui.activate_device_actions(["resize"])
if self._allow_format_device(device):
self.blivet_gui.activate_device_actions(["format"])
if self._allow_add_device(device):
self.blivet_gui.activate_device_actions(["add"])
if self._allow_set_mountpoint(device):
self.blivet_gui.activate_device_actions(["mountpoint"])
if self._allow_set_partition_table(device):
self.blivet_gui.activate_device_actions(["partitiontable"])
if device.type == "lvmvg":
self.blivet_gui.activate_device_actions(["parents"])
if device.format:
if device.format.type == "luks" and not device.format.status and device.format.exists:
self.blivet_gui.activate_device_actions(["decrypt"])
elif device.format.mountable and device.format.system_mountpoint:
self.blivet_gui.activate_device_actions(["unmount"])
def select_device(self, device):
""" Select device from list """
def _search(model, path, treeiter, device):
if model[treeiter][0] == device:
self.select.select_path(path)
self.partitions_list.foreach(_search, device)
def on_partition_selection_changed(self, selection):
""" On selected partition action
"""
model, treeiter = selection.get_selected()
if treeiter:
self.blivet_gui.deactivate_all_actions()
self.activate_action_buttons(model[treeiter])
self.selected_partition = model[treeiter]
self.blivet_gui.logical_view.select_rectanlge(device=self.selected_partition[0])
else:
self.blivet_gui.deactivate_all_actions()
def on_right_click_event(self, treeview, event):
""" Right click event on partition treeview
"""
if event.button == 3:
selection = treeview.get_selection()
if selection:
self.blivet_gui.popup_menu.menu.popup_at_pointer(None)