]>
Commit | Line | Data |
---|---|---|
3efd9988 FG |
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 | |
b32b8144 | 8 | from ceph_volume.util import system |
3efd9988 FG |
9 | |
10 | logger = logging.getLogger(__name__) | |
b32b8144 | 11 | mlogger = terminal.MultiLogger(__name__) |
3efd9988 FG |
12 | |
13 | ||
14 | def 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 | ||
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 | @decorators.needs_root | |
50 | def zap(self, args): | |
51 | device = args.device | |
52 | lv = api.get_lv_from_argument(device) | |
53 | if lv: | |
54 | # we are zapping a logical volume | |
55 | path = lv.lv_path | |
56 | else: | |
57 | # we are zapping a partition | |
58 | #TODO: ensure device is a partition | |
59 | path = device | |
60 | ||
b32b8144 FG |
61 | mlogger.info("Zapping: %s", path) |
62 | ||
63 | # check if there was a pv created with the | |
64 | # name of device | |
65 | pv = api.get_pv(pv_name=device) | |
66 | if pv: | |
67 | vg_name = pv.vg_name | |
68 | lv = api.get_lv(vg_name=vg_name) | |
69 | ||
70 | if lv: | |
71 | osd_path = "/var/lib/ceph/osd/{}-{}".format(lv.tags['ceph.cluster_name'], lv.tags['ceph.osd_id']) | |
72 | if system.path_is_mounted(osd_path): | |
73 | mlogger.info("Unmounting %s", osd_path) | |
74 | system.unmount(osd_path) | |
75 | ||
76 | if args.destroy and pv: | |
77 | logger.info("Found a physical volume created from %s, will destroy all it's vgs and lvs", device) | |
78 | vg_name = pv.vg_name | |
79 | mlogger.info("Destroying volume group %s because --destroy was given", vg_name) | |
80 | api.remove_vg(vg_name) | |
81 | mlogger.info("Destroying physical volume %s because --destroy was given", device) | |
82 | api.remove_pv(device) | |
83 | elif args.destroy and not pv: | |
84 | mlogger.info("Skipping --destroy because no associated physical volumes are found for %s", device) | |
3efd9988 FG |
85 | |
86 | wipefs(path) | |
87 | zap_data(path) | |
88 | ||
b32b8144 | 89 | if lv and not pv: |
3efd9988 FG |
90 | # remove all lvm metadata |
91 | lv.clear_tags() | |
92 | ||
93 | terminal.success("Zapping successful for: %s" % path) | |
94 | ||
95 | def main(self): | |
96 | sub_command_help = dedent(""" | |
b32b8144 FG |
97 | Zaps the given logical volume, raw device or partition for reuse by ceph-volume. |
98 | If given a path to a logical volume it must be in the format of vg/lv. Any | |
99 | filesystems present on the given device, vg/lv, or partition will be removed and | |
100 | all data will be purged. | |
101 | ||
102 | If the logical volume, raw device or partition is being used for any ceph related | |
103 | mount points they will be unmounted. | |
3efd9988 FG |
104 | |
105 | However, the lv or partition will be kept intact. | |
106 | ||
107 | Example calls for supported scenarios: | |
108 | ||
109 | Zapping a logical volume: | |
110 | ||
111 | ceph-volume lvm zap {vg name/lv name} | |
112 | ||
113 | Zapping a partition: | |
114 | ||
115 | ceph-volume lvm zap /dev/sdc1 | |
116 | ||
b32b8144 FG |
117 | If the --destroy flag is given and you are zapping a raw device or partition |
118 | then all vgs and lvs that exist on that raw device or partition will be destroyed. | |
119 | ||
120 | This is especially useful if a raw device or partition was used by ceph-volume lvm create | |
121 | or ceph-volume lvm prepare commands previously and now you want to reuse that device. | |
122 | ||
123 | For example: | |
124 | ||
125 | ceph-volume lvm zap /dev/sda --destroy | |
126 | ||
127 | If the --destroy flag is given and you are zapping an lv then the lv is still | |
128 | kept intact for reuse. | |
129 | ||
3efd9988 FG |
130 | """) |
131 | parser = argparse.ArgumentParser( | |
132 | prog='ceph-volume lvm zap', | |
133 | formatter_class=argparse.RawDescriptionHelpFormatter, | |
134 | description=sub_command_help, | |
135 | ) | |
136 | ||
137 | parser.add_argument( | |
138 | 'device', | |
139 | metavar='DEVICE', | |
140 | nargs='?', | |
b32b8144 FG |
141 | help='Path to an lv (as vg/lv), partition (as /dev/sda1) or device (as /dev/sda)' |
142 | ) | |
143 | parser.add_argument( | |
144 | '--destroy', | |
145 | action='store_true', | |
146 | default=False, | |
147 | help='Destroy all volume groups and logical volumes if you are zapping a raw device or partition', | |
3efd9988 FG |
148 | ) |
149 | if len(self.argv) == 0: | |
150 | print(sub_command_help) | |
151 | return | |
152 | args = parser.parse_args(self.argv) | |
153 | self.zap(args) |