@@ -40,7 +40,7 @@ let check_sm_feature_error (op:API.vdi_operations) sm_features sr =
4040 | `generate_config -> Some Vdi_generate_config
4141 | `clone -> Some Vdi_clone
4242 | `mirror -> Some Vdi_mirror
43- | `enable_cbt | `disable_cbt -> Some Vdi_configure_cbt
43+ | `enable_cbt | `disable_cbt | `data_destroy -> Some Vdi_configure_cbt
4444 | `set_on_boot -> Some Vdi_reset_on_boot
4545 ) in
4646 match required_sm_feature with
@@ -157,76 +157,88 @@ let check_operation_error ~__context ?(sr_records=[]) ?(pbd_records=[]) ?(vbd_re
157157 else if my_has_current_operation_vbd_records <> []
158158 then Some (Api_errors. other_operation_in_progress, [ " VDI" ; _ref ])
159159 else
160+
160161 let sm_features = Xapi_sr_operations. features_of_sr_internal ~__context ~_type:sr_type in
161162 let sm_feature_error = check_sm_feature_error op sm_features sr in
162163 if sm_feature_error <> None
163164 then sm_feature_error
165+
164166 else
165167 let allowed_for_cbt_metadata_vdi = match op with
166168 | `clone | `copy | `disable_cbt | `enable_cbt | `mirror | `resize | `resize_online | `snapshot | `set_on_boot -> false
167- | `blocked | `destroy | `force_unlock | `forget | `generate_config | `update -> true in
169+ | `blocked | `data_destroy | `destroy | `force_unlock | `forget | `generate_config | `update -> true in
168170 if not allowed_for_cbt_metadata_vdi && record.Db_actions. vDI_type = `cbt_metadata
169171 then Some (Api_errors. vdi_incompatible_type, [ _ref; Record_util. vdi_type_to_string `cbt_metadata ])
170172 else
171173 let allowed_when_cbt_enabled = match op with
172174 | `mirror | `set_on_boot -> false
173- | `blocked | `clone | `copy | `destroy | `disable_cbt | `enable_cbt | `force_unlock | `forget | `generate_config | `resize | `resize_online | `snapshot | `update -> true in
175+ | `blocked | `clone | `copy | `data_destroy | ` destroy | `disable_cbt | `enable_cbt | `force_unlock | `forget | `generate_config | `resize | `resize_online | `snapshot | `update -> true in
174176 if not allowed_when_cbt_enabled && record.Db_actions. vDI_cbt_enabled
175177 then Some (Api_errors. vdi_cbt_enabled, [_ref])
176- else (
177- match op with
178- | `forget ->
179- if ha_enabled && List. mem record.Db_actions. vDI_type [ `ha_statefile ; `redo_log ]
180- then Some (Api_errors. ha_is_enabled, [] )
181- else if List. mem record.Db_actions. vDI_type [ `rrd ]
182- then Some (Api_errors. vdi_has_rrds, [_ref])
183- else None
184- | `destroy ->
185- if sr_type = " udev"
186- then Some (Api_errors. vdi_is_a_physical_device, [_ref])
187- else
188- if is_tools_sr
189- then Some (Api_errors. sr_operation_not_supported, [Ref. string_of sr])
190- else if List. mem record.Db_actions. vDI_type [ `rrd ]
191- then Some (Api_errors. vdi_has_rrds, [_ref])
192- else
193- if ha_enabled && List. mem record.Db_actions. vDI_type [ `ha_statefile ; `redo_log ]
194- then Some (Api_errors. ha_is_enabled, [] )
195- else if List. mem record.Db_actions. vDI_type [`ha_statefile ; `metadata ] && Xapi_pool_helpers. ha_enable_in_progress ~__context
196- then Some (Api_errors. ha_enable_in_progress, [] )
197- else if List. mem record.Db_actions. vDI_type [`ha_statefile ; `metadata ] && Xapi_pool_helpers. ha_disable_in_progress ~__context
198- then Some (Api_errors. ha_disable_in_progress, [] )
199- else None
200- | `resize ->
201- if ha_enabled && List. mem record.Db_actions. vDI_type [ `ha_statefile ; `redo_log ]
202- then Some (Api_errors. ha_is_enabled, [] )
203- else None
204- | `resize_online ->
205- if ha_enabled && List. mem record.Db_actions. vDI_type [ `ha_statefile ; `redo_log ]
206- then Some (Api_errors. ha_is_enabled, [] )
207- else None
208- | `snapshot when record.Db_actions. vDI_sharable ->
209- Some (Api_errors. vdi_is_sharable, [ _ref ])
210- | `snapshot when reset_on_boot ->
211- Some (Api_errors. vdi_on_boot_mode_incompatible_with_operation, [] )
212- | `snapshot ->
213- if List. exists (fun (_ , op ) -> op = `copy ) current_ops
214- then Some (Api_errors. operation_not_allowed, [" Snapshot operation not allowed during copy." ])
215- else None
216- | `copy ->
217- if List. mem record.Db_actions. vDI_type [ `ha_statefile ; `redo_log ]
218- then Some (Api_errors. operation_not_allowed, [" VDI containing HA statefile or redo log cannot be copied (check the VDI's allowed operations)." ])
219- else None
220- | (`enable_cbt | `disable_cbt ) ->
221- if record.Db_actions. vDI_is_a_snapshot
222- then Some (Api_errors. operation_not_allowed, [" VDI is a snapshot: " ^ _ref])
223- else if not (List. mem record.Db_actions. vDI_type [ `user ; `system ])
224- then Some (Api_errors. vdi_incompatible_type, [ _ref; Record_util. vdi_type_to_string record.Db_actions. vDI_type ])
225- else if record.Db_actions. vDI_on_boot = `reset
226- then Some (Api_errors. vdi_on_boot_mode_incompatible_with_operation, [] )
227- else None
228- | `mirror | `clone | `generate_config | `force_unlock | `set_on_boot | `blocked | `update -> None
229- )
178+ else
179+
180+ let check_destroy () =
181+ if sr_type = " udev"
182+ then Some (Api_errors. vdi_is_a_physical_device, [_ref])
183+ else
184+ if is_tools_sr
185+ then Some (Api_errors. sr_operation_not_supported, [Ref. string_of sr])
186+ else if List. mem record.Db_actions. vDI_type [ `rrd ]
187+ then Some (Api_errors. vdi_has_rrds, [_ref])
188+ else
189+ if ha_enabled && List. mem record.Db_actions. vDI_type [ `ha_statefile ; `redo_log ]
190+ then Some (Api_errors. ha_is_enabled, [] )
191+ else if List. mem record.Db_actions. vDI_type [`ha_statefile ; `metadata ] && Xapi_pool_helpers. ha_enable_in_progress ~__context
192+ then Some (Api_errors. ha_enable_in_progress, [] )
193+ else if List. mem record.Db_actions. vDI_type [`ha_statefile ; `metadata ] && Xapi_pool_helpers. ha_disable_in_progress ~__context
194+ then Some (Api_errors. ha_disable_in_progress, [] )
195+ else None
196+ in
197+
198+ begin match op with
199+ | `forget ->
200+ if ha_enabled && List. mem record.Db_actions. vDI_type [ `ha_statefile ; `redo_log ]
201+ then Some (Api_errors. ha_is_enabled, [] )
202+ else if List. mem record.Db_actions. vDI_type [ `rrd ]
203+ then Some (Api_errors. vdi_has_rrds, [_ref])
204+ else None
205+ | `destroy -> check_destroy ()
206+ | `data_destroy ->
207+ if not record.Db_actions. vDI_is_a_snapshot
208+ then Some (Api_errors. operation_not_allowed, [" VDI is not a snapshot: " ^ _ref])
209+ else if not record.Db_actions. vDI_cbt_enabled
210+ then Some (Api_errors. vdi_no_cbt_metadata, [_ref])
211+ else check_destroy ()
212+ | `resize ->
213+ if ha_enabled && List. mem record.Db_actions. vDI_type [ `ha_statefile ; `redo_log ]
214+ then Some (Api_errors. ha_is_enabled, [] )
215+ else None
216+ | `resize_online ->
217+ if ha_enabled && List. mem record.Db_actions. vDI_type [ `ha_statefile ; `redo_log ]
218+ then Some (Api_errors. ha_is_enabled, [] )
219+ else None
220+ | `snapshot when record.Db_actions. vDI_sharable ->
221+ Some (Api_errors. vdi_is_sharable, [ _ref ])
222+ | `snapshot when reset_on_boot ->
223+ Some (Api_errors. vdi_on_boot_mode_incompatible_with_operation, [] )
224+ | `snapshot ->
225+ if List. exists (fun (_ , op ) -> op = `copy ) current_ops
226+ then Some (Api_errors. operation_not_allowed, [" Snapshot operation not allowed during copy." ])
227+ else None
228+ | `copy ->
229+ if List. mem record.Db_actions. vDI_type [ `ha_statefile ; `redo_log ]
230+ then Some (Api_errors. operation_not_allowed, [" VDI containing HA statefile or redo log cannot be copied (check the VDI's allowed operations)." ])
231+ else None
232+ | (`enable_cbt | `disable_cbt ) ->
233+ if record.Db_actions. vDI_is_a_snapshot
234+ then Some (Api_errors. operation_not_allowed, [" VDI is a snapshot: " ^ _ref])
235+ else if not (List. mem record.Db_actions. vDI_type [ `user ; `system ])
236+ then Some (Api_errors. vdi_incompatible_type, [ _ref; Record_util. vdi_type_to_string record.Db_actions. vDI_type ])
237+ else if record.Db_actions. vDI_on_boot = `reset
238+ then Some (Api_errors. vdi_on_boot_mode_incompatible_with_operation, [] )
239+ else None
240+ | `mirror | `clone | `generate_config | `force_unlock | `set_on_boot | `blocked | `update -> None
241+ end
230242
231243let assert_operation_valid ~__context ~self ~(op :API.vdi_operations ) =
232244 let pool = Helpers. get_pool ~__context in
@@ -520,9 +532,8 @@ let snapshot ~__context ~vdi ~driver_params =
520532 update_allowed_operations ~__context ~self: newvdi;
521533 newvdi
522534
523- let destroy ~__context ~self =
535+ let destroy_and_data_destroy_common ~__context ~self ~( operation :[`destroy | `data_destroy] ) =
524536 let sr = Db.VDI. get_SR ~__context ~self in
525- let location = Db.VDI. get_location ~__context ~self in
526537 Sm. assert_pbd_is_plugged ~__context ~sr ;
527538 Xapi_vdi_helpers. assert_managed ~__context ~vdi: self;
528539
@@ -532,18 +543,21 @@ let destroy ~__context ~self =
532543 let r = Db.VBD. get_record_internal ~__context ~self: vbd in
533544 r.Db_actions. vBD_currently_attached || r.Db_actions. vBD_reserved) vbds in
534545 if attached_vbds<> [] then
535- raise (Api_errors. Server_error (Api_errors. vdi_in_use, [(Ref. string_of self); " destroy" ]))
546+ let caller_name = match operation with `destroy -> " destroy" | `data_destroy -> " data_destroy" in
547+ raise (Api_errors. Server_error (Api_errors. vdi_in_use, [(Ref. string_of self); caller_name]))
536548 else
537549 begin
538550 let open Storage_access in
539551 let open Storage_interface in
540552 let task = Context. get_task_id __context in
553+ let location = Db.VDI. get_location ~__context ~self in
541554 let module C = Client (struct let rpc = rpc end ) in
555+ let call_f = match operation with `destroy -> C.VDI. destroy | `data_destroy -> C.VDI. data_destroy in
542556 transform_storage_exn
543557 (fun () ->
544- C.VDI. destroy ~dbg: (Ref. string_of task) ~sr: (Db.SR. get_uuid ~__context ~self: sr) ~vdi: location
558+ call_f ~dbg: (Ref. string_of task) ~sr: (Db.SR. get_uuid ~__context ~self: sr) ~vdi: location
545559 );
546- if Db. is_valid_ref __context self
560+ if operation = `destroy && Db. is_valid_ref __context self
547561 then Db.VDI. destroy ~__context ~self ;
548562
549563 (* destroy all the VBDs now rather than wait for the GC thread. This helps
@@ -558,6 +572,15 @@ let destroy ~__context ~self =
558572 |> List. iter (fun self -> Db.VM. set_suspend_VDI ~__context ~self ~value: Ref. null);
559573 end
560574
575+ let destroy = destroy_and_data_destroy_common ~operation: `destroy
576+
577+ let data_destroy ~__context ~self =
578+ if Db.VDI. get_type ~__context ~self <> `cbt_metadata then begin
579+ destroy_and_data_destroy_common ~__context ~self ~operation: `data_destroy ;
580+ Db.VDI. set_type ~__context ~self ~value: `cbt_metadata ;
581+ update_allowed_operations ~__context ~self
582+ end
583+
561584let resize_online ~__context ~vdi ~size =
562585 Sm. assert_pbd_is_plugged ~__context ~sr: (Db.VDI. get_SR ~__context ~self: vdi);
563586 Xapi_vdi_helpers. assert_managed ~__context ~vdi ;
0 commit comments