@@ -124,17 +124,46 @@ impl VolumeGroup {
124
124
. into_iter ( )
125
125
// todo: not needed as we did the select?
126
126
. filter ( |vg| vg. matches ( opts) )
127
- . collect :: < Vec < _ > > ( ) ;
127
+ . fold ( Vec :: < VolumeGroup > :: new ( ) , |mut acc, vg| {
128
+ match acc. iter_mut ( ) . find ( |e_vg| e_vg. name == vg. name ) {
129
+ None => acc. push ( vg) ,
130
+ Some ( e_vg) => {
131
+ e_vg. disks . extend ( vg. disks ) ;
132
+ }
133
+ }
134
+ acc
135
+ } ) ;
128
136
129
137
Ok ( vgs)
130
138
}
131
139
132
140
/// Import a volume group with the name provided or create one with the name
133
141
/// and disks provided currently only import is supported.
134
- pub ( crate ) async fn import_or_create (
135
- args : PoolArgs ,
136
- ) -> Result < VolumeGroup , Error > {
137
- let vg = Self :: import_inner ( args) . await ?;
142
+ pub ( crate ) async fn create ( args : PoolArgs ) -> Result < VolumeGroup , Error > {
143
+ let vg =
144
+ match VolumeGroup :: lookup ( CmnQueryArgs :: any ( ) . named ( & args. name ) )
145
+ . await
146
+ {
147
+ Ok ( _) => Self :: import_inner ( args) . await ,
148
+ Err ( Error :: NotFound {
149
+ ..
150
+ } ) => {
151
+ LvmCmd :: pv_create ( ) . args ( & args. disks ) . run ( ) . await ?;
152
+
153
+ LvmCmd :: vg_create ( )
154
+ . arg ( & args. name )
155
+ . tag ( Property :: Lvm )
156
+ . args ( args. disks )
157
+ . run ( )
158
+ . await ?;
159
+ let lookup = CmnQueryArgs :: ours ( )
160
+ . named ( & args. name )
161
+ . uuid_opt ( & args. uuid ) ;
162
+ VolumeGroup :: lookup ( lookup) . await
163
+ }
164
+ Err ( error) => Err ( error) ,
165
+ } ?;
166
+
138
167
info ! ( "The lvm vg pool '{}' has been created" , vg. name( ) ) ;
139
168
Ok ( vg)
140
169
}
@@ -149,6 +178,14 @@ impl VolumeGroup {
149
178
. with_vg ( CmnQueryArgs :: ours ( ) . uuid ( self . uuid ( ) ) . named ( self . name ( ) ) ) ;
150
179
LogicalVolume :: list ( & query) . await
151
180
}
181
+ async fn list_foreign_lvs ( & self ) -> Result < Vec < LogicalVolume > , Error > {
182
+ let query = super :: QueryArgs :: new ( )
183
+ . with_lv ( CmnQueryArgs :: any ( ) )
184
+ . with_vg ( CmnQueryArgs :: any ( ) . uuid ( self . uuid ( ) ) . named ( self . name ( ) ) ) ;
185
+ LogicalVolume :: list ( & query)
186
+ . await
187
+ . map ( |lvs| lvs. into_iter ( ) . filter ( |lv| !lv. ours ( ) ) . collect ( ) )
188
+ }
152
189
153
190
/// Import a volume group by its name, match the disks on the volume group
154
191
/// and if true add our tag to the volume group to make it available
@@ -191,22 +228,33 @@ impl VolumeGroup {
191
228
}
192
229
193
230
/// Delete the volume group.
194
- /// > Note: Currently the vg is only exported.
195
- /// todo: currently only exporting the VG.
231
+ /// > Note: The Vg is first exported and then destroyed.
196
232
pub ( crate ) async fn destroy ( mut self ) -> Result < ( ) , Error > {
197
- // As currently only import of volume group is supported
198
- // exporting the volume group on destroy.
199
- let name = self . name ( ) . to_string ( ) ;
200
233
self . export ( ) . await ?;
201
- info ! ( "LVM pool '{name}' has been destroyed successfully" ) ;
234
+
235
+ let foreign_lvs = self . list_foreign_lvs ( ) . await ?;
236
+ let name = self . name ( ) . to_string ( ) ;
237
+
238
+ if foreign_lvs. is_empty ( ) {
239
+ LvmCmd :: vg_remove ( )
240
+ . arg ( format ! ( "--select=vg_name={name}" ) )
241
+ . arg ( "-y" )
242
+ . run ( )
243
+ . await ?;
244
+
245
+ LvmCmd :: pv_remove ( ) . args ( & self . disks ) . run ( ) . await ?;
246
+
247
+ info ! ( "LVM pool '{}' has been destroyed successfully" , self . name( ) ) ;
248
+ } else {
249
+ warn ! ( "LVM pool '{}' is not destroyed as it contains foreign lvs: {foreign_lvs:?}" , self . name( ) ) ;
250
+ }
202
251
self . ptpl ( ) . destroy ( ) . ok ( ) ;
203
252
Ok ( ( ) )
204
253
}
205
254
206
255
/// Exports the volume group by unloading all logical volumes and finally
207
256
/// removing our tag from it
208
257
pub ( crate ) async fn export ( & mut self ) -> Result < ( ) , Error > {
209
- // todo: unload all logical volumes from this VG
210
258
let lvs = self . list_lvs ( ) . await ?;
211
259
for mut lv in lvs {
212
260
lv. export_bdev ( ) . await ?;
@@ -215,7 +263,21 @@ impl VolumeGroup {
215
263
LvmCmd :: vg_change ( self . name ( ) )
216
264
. untag ( Property :: Lvm )
217
265
. run ( )
218
- . await
266
+ . await ?;
267
+
268
+ info ! ( "LVM pool '{}' has been exported successfully" , self . name) ;
269
+ Ok ( ( ) )
270
+ }
271
+
272
+ /// Export all VG instances.
273
+ pub ( crate ) async fn export_all ( ) {
274
+ let Ok ( pools) = VolumeGroup :: list ( & CmnQueryArgs :: ours ( ) ) . await else {
275
+ return ;
276
+ } ;
277
+
278
+ for mut pool in pools {
279
+ pool. export ( ) . await . ok ( ) ;
280
+ }
219
281
}
220
282
221
283
/// Create a logical volume in this volume group.
0 commit comments