]> git.proxmox.com Git - ceph.git/blob - ceph/src/ceph-volume/ceph_volume/devices/lvm/zap.py
update sources to 12.2.8
[ceph.git] / ceph / src / ceph-volume / ceph_volume / devices / lvm / zap.py
1 import argparse
2 import logging
3
4 from textwrap import dedent
5
6 from ceph_volume import decorators, terminal, process
7 from ceph_volume.api import lvm as api
8 from ceph_volume.util import system, encryption, disk
9
10 logger = logging.getLogger(__name__)
11 mlogger = terminal.MultiLogger(__name__)
12
13
14 def wipefs(path):
15 """
16 Removes the filesystem from an lv or partition.
17 """
18 process.run([
19 'wipefs',
20 '--all',
21 path
22 ])
23
24
25 def 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
42 class 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
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'])
52 else:
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)
59 if dmcrypt and dmcrypt_uuid:
60 self.dmcrypt_close(dmcrypt_uuid)
61
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)
103 mlogger.info("Destroying physical volume %s because --destroy was given", device)
104 api.remove_pv(device)
105
106 wipefs(path)
107 zap_data(path)
108
109 if lv and not pvs:
110 # remove all lvm metadata
111 lv.clear_tags()
112
113 terminal.success("Zapping successful for: %s" % ", ".join(args.devices))
114
115 def dmcrypt_close(self, dmcrypt_uuid):
116 dmcrypt_path = "/dev/mapper/{}".format(dmcrypt_uuid)
117 mlogger.info("Closing encrypted path %s", dmcrypt_path)
118 encryption.dmcrypt_close(dmcrypt_path)
119
120 def main(self):
121 sub_command_help = dedent("""
122 Zaps the given logical volume(s), raw device(s) or partition(s) for reuse by ceph-volume.
123 If given a path to a logical volume it must be in the format of vg/lv. Any
124 filesystems present on the given device, vg/lv, or partition will be removed and
125 all data will be purged.
126
127 If the logical volume, raw device or partition is being used for any ceph related
128 mount points they will be unmounted.
129
130 However, the lv or partition will be kept intact.
131
132 Example calls for supported scenarios:
133
134 Zapping a logical volume:
135
136 ceph-volume lvm zap {vg name/lv name}
137
138 Zapping a partition:
139
140 ceph-volume lvm zap /dev/sdc1
141
142 Zapping many raw devices:
143
144 ceph-volume lvm zap /dev/sda /dev/sdb /db/sdc
145
146 If the --destroy flag is given and you are zapping a raw device or partition
147 then all vgs and lvs that exist on that raw device or partition will be destroyed.
148
149 This is especially useful if a raw device or partition was used by ceph-volume lvm create
150 or ceph-volume lvm prepare commands previously and now you want to reuse that device.
151
152 For example:
153
154 ceph-volume lvm zap /dev/sda --destroy
155
156 If the --destroy flag is given and you are zapping an lv then the lv is still
157 kept intact for reuse.
158
159 """)
160 parser = argparse.ArgumentParser(
161 prog='ceph-volume lvm zap',
162 formatter_class=argparse.RawDescriptionHelpFormatter,
163 description=sub_command_help,
164 )
165
166 parser.add_argument(
167 'devices',
168 metavar='DEVICES',
169 nargs='*',
170 default=[],
171 help='Path to one or many lv (as vg/lv), partition (as /dev/sda1) or device (as /dev/sda)'
172 )
173 parser.add_argument(
174 '--destroy',
175 action='store_true',
176 default=False,
177 help='Destroy all volume groups and logical volumes if you are zapping a raw device or partition',
178 )
179 if len(self.argv) == 0:
180 print(sub_command_help)
181 return
182 args = parser.parse_args(self.argv)
183 self.zap(args)