]> git.proxmox.com Git - ceph.git/blame - ceph/src/ceph-volume/ceph_volume/devices/lvm/zap.py
update sources to 12.2.10
[ceph.git] / ceph / src / ceph-volume / ceph_volume / devices / lvm / zap.py
CommitLineData
3efd9988
FG
1import argparse
2import logging
3
4from textwrap import dedent
5
6from ceph_volume import decorators, terminal, process
7from ceph_volume.api import lvm as api
3a9019d9 8from ceph_volume.util import system, encryption, disk
3efd9988
FG
9
10logger = logging.getLogger(__name__)
b32b8144 11mlogger = terminal.MultiLogger(__name__)
3efd9988
FG
12
13
14def wipefs(path):
15 """
16 Removes the filesystem from an lv or partition.
17 """
18 process.run([
3efd9988
FG
19 'wipefs',
20 '--all',
21 path
22 ])
23
24
25def zap_data(path):
26 """
27 Clears all data from the given path. Path should be
28 an absolute path to an lv or partition.
29
30 10M of data is written to the path to make sure that
31 there is no trace left of any previous Filesystem.
32 """
33 process.run([
34 'dd',
35 'if=/dev/zero',
36 'of={path}'.format(path=path),
37 'bs=1M',
38 'count=10',
39 ])
40
41
42class Zap(object):
43
44 help = 'Removes all data and filesystems from a logical volume or partition.'
45
46 def __init__(self, argv):
47 self.argv = argv
48
1adf2230
AA
49 def unmount_lv(self, lv):
50 if lv.tags.get('ceph.cluster_name') and lv.tags.get('ceph.osd_id'):
51 lv_path = "/var/lib/ceph/osd/{}-{}".format(lv.tags['ceph.cluster_name'], lv.tags['ceph.osd_id'])
3a9019d9 52 else:
1adf2230
AA
53 lv_path = lv.lv_path
54 dmcrypt_uuid = lv.lv_uuid
55 dmcrypt = lv.encrypted
56 if system.path_is_mounted(lv_path):
57 mlogger.info("Unmounting %s", lv_path)
58 system.unmount(lv_path)
3a9019d9 59 if dmcrypt and dmcrypt_uuid:
1adf2230 60 self.dmcrypt_close(dmcrypt_uuid)
3efd9988 61
1adf2230
AA
62 @decorators.needs_root
63 def zap(self, args):
64 for device in args.devices:
65 if disk.is_mapper_device(device):
66 terminal.error("Refusing to zap the mapper device: {}".format(device))
67 raise SystemExit(1)
68 lv = api.get_lv_from_argument(device)
69 if lv:
70 # we are zapping a logical volume
71 path = lv.lv_path
72 self.unmount_lv(lv)
73 else:
74 # we are zapping a partition
75 #TODO: ensure device is a partition
76 path = device
77 # check to if it is encrypted to close
78 partuuid = disk.get_partuuid(device)
79 if encryption.status("/dev/mapper/{}".format(partuuid)):
80 dmcrypt_uuid = partuuid
81 self.dmcrypt_close(dmcrypt_uuid)
82
83 mlogger.info("Zapping: %s", path)
84
85 # check if there was a pv created with the
86 # name of device
87 pvs = api.PVolumes()
88 pvs.filter(pv_name=device)
89 vgs = set([pv.vg_name for pv in pvs])
90 for pv in pvs:
91 vg_name = pv.vg_name
92 lv = None
93 if pv.lv_uuid:
94 lv = api.get_lv(vg_name=vg_name, lv_uuid=pv.lv_uuid)
95
96 if lv:
97 self.unmount_lv(lv)
98
99 if args.destroy:
100 for vg_name in vgs:
101 mlogger.info("Destroying volume group %s because --destroy was given", vg_name)
102 api.remove_vg(vg_name)
91327a77
AA
103 if not lv:
104 mlogger.info("Destroying physical volume %s because --destroy was given", device)
105 api.remove_pv(device)
1adf2230
AA
106
107 wipefs(path)
108 zap_data(path)
109
110 if lv and not pvs:
91327a77
AA
111 if args.destroy:
112 lvs = api.Volumes()
113 lvs.filter(vg_name=lv.vg_name)
114 if len(lvs) <= 1:
115 mlogger.info('Only 1 LV left in VG, will proceed to destroy volume group %s', lv.vg_name)
116 api.remove_vg(lv.vg_name)
117 else:
118 mlogger.info('More than 1 LV left in VG, will proceed to destroy LV only')
119 mlogger.info('Removing LV because --destroy was given: %s', lv)
120 api.remove_lv(lv)
121 else:
122 # just remove all lvm metadata, leaving the LV around
123 lv.clear_tags()
1adf2230
AA
124
125 terminal.success("Zapping successful for: %s" % ", ".join(args.devices))
126
127 def dmcrypt_close(self, dmcrypt_uuid):
128 dmcrypt_path = "/dev/mapper/{}".format(dmcrypt_uuid)
129 mlogger.info("Closing encrypted path %s", dmcrypt_path)
130 encryption.dmcrypt_close(dmcrypt_path)
3efd9988
FG
131
132 def main(self):
133 sub_command_help = dedent("""
1adf2230 134 Zaps the given logical volume(s), raw device(s) or partition(s) for reuse by ceph-volume.
b32b8144
FG
135 If given a path to a logical volume it must be in the format of vg/lv. Any
136 filesystems present on the given device, vg/lv, or partition will be removed and
137 all data will be purged.
138
139 If the logical volume, raw device or partition is being used for any ceph related
140 mount points they will be unmounted.
3efd9988
FG
141
142 However, the lv or partition will be kept intact.
143
144 Example calls for supported scenarios:
145
146 Zapping a logical volume:
147
148 ceph-volume lvm zap {vg name/lv name}
149
150 Zapping a partition:
151
152 ceph-volume lvm zap /dev/sdc1
153
1adf2230
AA
154 Zapping many raw devices:
155
156 ceph-volume lvm zap /dev/sda /dev/sdb /db/sdc
157
b32b8144
FG
158 If the --destroy flag is given and you are zapping a raw device or partition
159 then all vgs and lvs that exist on that raw device or partition will be destroyed.
160
161 This is especially useful if a raw device or partition was used by ceph-volume lvm create
162 or ceph-volume lvm prepare commands previously and now you want to reuse that device.
163
164 For example:
165
166 ceph-volume lvm zap /dev/sda --destroy
167
168 If the --destroy flag is given and you are zapping an lv then the lv is still
169 kept intact for reuse.
170
3efd9988
FG
171 """)
172 parser = argparse.ArgumentParser(
173 prog='ceph-volume lvm zap',
174 formatter_class=argparse.RawDescriptionHelpFormatter,
175 description=sub_command_help,
176 )
177
178 parser.add_argument(
1adf2230
AA
179 'devices',
180 metavar='DEVICES',
181 nargs='*',
182 default=[],
183 help='Path to one or many lv (as vg/lv), partition (as /dev/sda1) or device (as /dev/sda)'
b32b8144
FG
184 )
185 parser.add_argument(
186 '--destroy',
187 action='store_true',
188 default=False,
189 help='Destroy all volume groups and logical volumes if you are zapping a raw device or partition',
3efd9988
FG
190 )
191 if len(self.argv) == 0:
192 print(sub_command_help)
193 return
194 args = parser.parse_args(self.argv)
195 self.zap(args)