@@ -3,39 +3,33 @@ title = "XAPI's Storage Layers"
3
3
linkTitle = " Storage"
4
4
+++
5
5
6
+
6
7
{{% notice info %}}
7
8
The links in this page point to the source files of xapi
8
- [ v1.127.0] ( https://github.com/xapi-project/xen-api/tree/v1.127.0 ) , and xcp-idl
9
- [ v1.62.0] ( https://github.com/xapi-project/xcp-idl/tree/v1.62.0 ) , not to the
10
- latest source code.
11
-
12
- In the beginning of 2023, significant changes have been made in the layering.
13
- In particular, the wrapper code from ` storage_impl.ml ` has been pushed down the
14
- stack, below the mux, such that it only covers the SMAPIv1 backend and not
15
- SMAPIv3. Also, all of the code (from xcp-idl etc) is now present in this repo
16
- (xen-api).
9
+ [ v25.11.0] ( https://github.com/xapi-project/xen-api/tree/v25.11.0 ) .
17
10
{{% /notice %}}
18
11
12
+
19
13
Xapi directly communicates only with the SMAPIv2 layer. There are no
20
14
plugins directly implementing the SMAPIv2 interface, but the plugins in
21
15
other layers are accessed through it:
22
16
23
- {{< mermaid >}}
17
+ ``` mermaid
24
18
graph TD
25
19
A[xapi] --> B[SMAPIv2 interface]
26
- B --> C[ SMAPIv2 <-> SMAPIv1 translation: storage_access.ml]
20
+ B --> C[SMAPIv2 <-> SMAPIv1 state machine: storage_smapiv1_wrapper.ml]
21
+ C --> G[SMAPIv2 <-> SMAPIv1 translation: storage_smapiv1.ml]
27
22
B --> D[SMAPIv2 <-> SMAPIv3 translation: xapi-storage-script]
28
- C --> E[ SMAPIv1 plugins]
23
+ G --> E[SMAPIv1 plugins]
29
24
D --> F[SMAPIv3 plugins]
30
- {{< /mermaid >}}
25
+ ```
31
26
32
27
## SMAPIv1
33
28
34
29
These are the files related to SMAPIv1 in ` xen-api/ocaml/xapi/ ` :
35
30
36
- - [ sm.ml] ( https://github.com/xapi-project/xen-api/blob/v1.127.0/ocaml/xapi/sm.ml ) :
37
- OCaml "bindings" for the SMAPIv1 Python "drivers" (SM)
38
- - [ sm_exec.ml] ( https://github.com/xapi-project/xen-api/blob/v1.127.0/ocaml/xapi/sm_exec.ml ) :
31
+ - sm.ml: OCaml "bindings" for the SMAPIv1 Python "drivers" (SM)
32
+ - sm_exec.ml:
39
33
support for implementing the above "bindings". The
40
34
parameters are converted to XML-RPC, passed to the relevant python
41
35
script ("driver"), and then the standard output of the program is
@@ -46,37 +40,39 @@ These are the files related to SMAPIv1 in `xen-api/ocaml/xapi/`:
46
40
parameters in the args record.
47
41
- ` smint.ml ` : Contains types, exceptions, ... for the SMAPIv1 OCaml
48
42
interface
43
+ - ` storage_smapiv1_wrapper.ml ` : A state machine for SMAPIv1 operations. It computes
44
+ the required actions to reach the desired state from the current state.
45
+ - ` storage_smapiv1.ml ` : Contains the actual translation of SMAPIv2 calls to SMAPIv1
46
+ calls, by calling the bindings provided in sm.ml.
49
47
50
48
## SMAPIv2
51
49
52
50
These are the files related to SMAPIv2, which need to be modified to
53
51
implement new calls:
54
52
55
- - [ xcp-idl/storage/storage\_ interface.ml] ( https://github.com/xapi-project/xcp-idl /blob/v1.62.0 /storage/storage_interface.ml ) :
53
+ - [ xcp-idl/storage/storage\_ interface.ml] ( https://github.com/xapi-project/xen-api /blob/v25.11.0/ocaml/xapi-idl /storage/storage_interface.ml ) :
56
54
Contains the SMAPIv2 interface
57
- - [ xcp-idl/storage/storage\_ skeleton.ml] ( https://github.com/xapi-project/xcp-idl /blob/v1.62.0 /storage/storage_skeleton.ml ) :
55
+ - [ xcp-idl/storage/storage\_ skeleton.ml] ( https://github.com/xapi-project/xen-api /blob/v25.11.0/ocaml/xapi-idl /storage/storage_skeleton.ml ) :
58
56
A stub SMAPIv2 storage server implementation that matches the
59
57
SMAPIv2 storage server interface (this is verified by
60
- [ storage\_ skeleton\_ test.ml] ( https://github.com/xapi-project/xcp-idl /blob/v1.62.0 /storage/storage_skeleton_test.ml ) ),
58
+ [ storage\_ skeleton\_ test.ml] ( https://github.com/xapi-project/xen-api /blob/v25.11.0/ocaml/xapi-idl /storage/storage_skeleton_test.ml ) ),
61
59
each of its function just raise a ` Storage_interface.Unimplemented `
62
60
error. This skeleton is used to automatically fill the unimplemented
63
61
methods of the below storage servers to satisfy the interface.
64
- - [ xen-api/ocaml/xapi/storage\_ access.ml] ( https://github.com/xapi-project/xen-api/blob/v1.127.0/ocaml/xapi/storage_access.ml ) :
65
- [ module SMAPIv1] ( https://github.com/xapi-project/xen-api/blob/v1.127.0/ocaml/xapi/storage_access.ml#L104 ) :
66
- a SMAPIv2 server that does SMAPIv2 -> ; SMAPIv1 translation.
62
+ - [ xen-api/ocaml/xapi/storage\_ smapiv1.ml] ( https://github.com/xapi-project/xen-api/blob/v25.11.0/ocaml/xapi/storage_smapiv1.ml ) :
63
+ a SMAPIv2 server that does SMAPIv2 -> SMAPIv1 translation.
67
64
It passes the XML-RPC requests as the first command-line argument to the
68
65
corresponding Python script, which returns an XML-RPC response on standard
69
66
output.
70
- - [ xen-api/ocaml/xapi/storage\_ impl.ml] ( https://github.com/xapi-project/xen-api/blob/v1.127.0/ocaml/xapi/storage_impl.ml ) :
71
- The
72
- [ Wrapper] ( https://github.com/xapi-project/xen-api/blob/v1.127.0/ocaml/xapi/storage_impl.ml#L302 )
67
+ - [ xen-api/ocaml/xapi/storage_smapiv1_wrapper.ml] ( https://github.com/xapi-project/xen-api/blob/v25.11.0/ocaml/xapi/storage_smapiv1_wrapper.ml ) :
68
+ The [ Wrapper] ( https://github.com/xapi-project/xen-api/blob/v25.11.0/ocaml/xapi/storage_smapiv1_wrapper.ml#L360 )
73
69
module wraps a SMAPIv2 server (Server\_ impl) and takes care of
74
70
locking and datapaths (in case of multiple connections (=datapaths)
75
71
from VMs to the same VDI, it will use the superstate computed by the
76
- [ Vdi_automaton] ( https://github.com/xapi-project/xcp-idl /blob/v1.62.0 /storage/vdi_automaton.ml )
72
+ [ Vdi_automaton] ( https://github.com/xapi-project/xen-api /blob/v25.11.0/ocaml/xapi-idl /storage/vdi_automaton.ml )
77
73
in xcp-idl). It also implements some functionality, like the ` DP `
78
74
module, that is not implemented in lower layers.
79
- - [ xen-api/ocaml/xapi/storage\_ mux.ml] ( https://github.com/xapi-project/xen-api/blob/v1.127 .0/ocaml/xapi/storage_mux.ml ) :
75
+ - [ xen-api/ocaml/xapi/storage\_ mux.ml] ( https://github.com/xapi-project/xen-api/blob/v25.11 .0/ocaml/xapi/storage_mux.ml ) :
80
76
A SMAPIv2 server, which multiplexes between other servers. A
81
77
different SMAPIv2 server can be registered for each SR. Then it
82
78
forwards the calls for each SR to the "storage plugin" registered
@@ -85,30 +81,30 @@ implement new calls:
85
81
### How SMAPIv2 works:
86
82
87
83
We use [ message-switch] under the hood for RPC communication between
88
- [ xcp -idl] ( https://github.com/xapi-project/xcp -idl ) components. The
84
+ [ xapi -idl] ( https://github.com/xapi-project/xen-api/tree/v25.11.0/ocaml/xapi -idl ) components. The
89
85
main ` Storage_mux.Server ` (basically ` Storage_impl.Wrapper(Mux) ` ) is
90
86
[ registered to
91
- listen] ( https://github.com/xapi-project/xen-api/blob/v1.127 .0/ocaml/xapi/storage_access.ml#L1279 )
87
+ listen] ( https://github.com/xapi-project/xen-api/blob/v25.11 .0/ocaml/xapi/storage_access.ml#L500 )
92
88
on the "` org.xen.xapi.storage ` " queue [ during xapi's
93
- startup] ( https://github.com/xapi-project/xen-api/blob/v1.127 .0/ocaml/xapi/xapi.ml#L801 ) ,
89
+ startup] ( https://github.com/xapi-project/xen-api/blob/v25.11 .0/ocaml/xapi/xapi.ml#L1080 ) ,
94
90
and this is the main entry point for incoming SMAPIv2 function calls.
95
91
` Storage_mux ` does not really multiplex between different plugins right
96
92
now: [ earlier during xapi's
97
- startup] ( https://github.com/xapi-project/xen-api/blob/v1.127 .0/ocaml/xapi/xapi.ml#L799 ) ,
93
+ startup] ( https://github.com/xapi-project/xen-api/blob/v25.11 .0/ocaml/xapi/xapi.ml#L1076 ) ,
98
94
the same SMAPIv1 storage server module [ is
99
- registered] ( https://github.com/xapi-project/xen-api/blob/v1.127 .0/ocaml/xapi/storage_access.ml#L934 )
95
+ registered] ( https://github.com/xapi-project/xen-api/blob/v25.11 .0/ocaml/xapi/storage_access.ml#L934 )
100
96
on the various "` org.xen.xapi.storage.<sr type> ` " queues for each
101
97
supported SR type. (This will change with SMAPIv3, which is accessed via
102
98
a SMAPIv2 plugin outside of xapi that translates between SMAPIv2 and
103
99
SMAPIv3.) Then, in
104
- [ Storage\_ access.create\_ sr] ( https://github.com/xapi-project/xen-api/blob/v1.127 .0/ocaml/xapi/storage_access.ml#L1531 ) ,
100
+ [ Storage\_ access.create\_ sr] ( https://github.com/xapi-project/xen-api/blob/v25.11 .0/ocaml/xapi/storage_access.ml#L802 ) ,
105
101
which is called
106
- [ during SR.create] ( https://github.com/xapi-project/xen-api/blob/v1.127 .0/ocaml/xapi/xapi_sr.ml#L326 ) ,
102
+ [ during SR.create] ( https://github.com/xapi-project/xen-api/blob/v25.11 .0/ocaml/xapi/xapi_sr.ml#L391 ) ,
107
103
and also
108
- [ during PBD.plug] ( https://github.com/xapi-project/xen-api/blob/v1.127 .0/ocaml/xapi/xapi_pbd.ml#L121 ) ,
104
+ [ during PBD.plug] ( https://github.com/xapi-project/xen-api/blob/v25.11 .0/ocaml/xapi/xapi_pbd.ml#L175 ) ,
109
105
the relevant "` org.xen.xapi.storage.<sr type> ` " queue needed for that
110
106
PBD is [ registered with Storage_mux in
111
- Storage\_ access.bind] ( https://github.com/xapi-project/xen-api/blob/v1.127 .0/ocaml/xapi/storage_access.ml#L1107 )
107
+ Storage\_ access.bind] ( https://github.com/xapi-project/xen-api/blob/v25.11 .0/ocaml/xapi/storage_access.ml#L267 )
112
108
for the SR of that PBD.\
113
109
So basically what happens is that xapi registers itself as a SMAPIv2
114
110
server, and forwards incoming function calls to itself through
@@ -118,10 +114,10 @@ translation.
118
114
119
115
#### Registration of the various storage servers
120
116
121
- {{< mermaid >}}
117
+ ``` mermaid
122
118
sequenceDiagram
123
119
participant q as message-switch
124
- participant v1 as Storage_access .SMAPIv1
120
+ participant v1 as Storage_smapiv1 .SMAPIv1
125
121
participant svr as Storage_mux.Server
126
122
127
123
Note over q, svr: xapi startup, "Starting SMAPIv1 proxies"
@@ -134,11 +130,11 @@ q ->> svr:org.xen.xapi.storage
134
130
135
131
Note over q, svr: SR.create, PBD.plug
136
132
svr ->> q:org.xapi.storage.sr_type_2
137
- {{< /mermaid >}}
133
+ ```
138
134
139
135
#### What happens when a SMAPIv2 "function" is called
140
136
141
- {{< mermaid >}}
137
+ ``` mermaid
142
138
graph TD
143
139
144
140
call[SMAPIv2 call] --VDI.attach2--> org.xen.xapi.storage
@@ -148,24 +144,24 @@ org.xen.xapi.storage
148
144
org.xen.xapi.storage.SR_type_x
149
145
end
150
146
151
- org.xen.xapi.storage --VDI.attach2--> Storage_impl .Wrapper
147
+ org.xen.xapi.storage --VDI.attach2--> Storage_smapiv1_wrapper .Wrapper
152
148
153
149
subgraph xapi
154
150
subgraph Storage_mux.server
155
- Storage_impl .Wrapper --> Storage_mux.mux
151
+ Storage_smapiv1_wrapper .Wrapper --> Storage_mux.mux
156
152
end
157
- Storage_access .SMAPIv1
153
+ Storage_smapiv1 .SMAPIv1
158
154
end
159
155
160
156
Storage_mux.mux --VDI.attach2--> org.xen.xapi.storage.SR_type_x
161
- org.xen.xapi.storage.SR_type_x --VDI.attach2--> Storage_access .SMAPIv1
157
+ org.xen.xapi.storage.SR_type_x --VDI.attach2--> Storage_smapiv1 .SMAPIv1
162
158
163
159
subgraph SMAPIv1
164
160
driver_x[SMAPIv1 driver for SR_type_x]
165
161
end
166
162
167
- Storage_access .SMAPIv1 --vdi_attach--> driver_x
168
- {{< /mermaid >}}
163
+ Storage_smapiv1 .SMAPIv1 --vdi_attach--> driver_x
164
+ ```
169
165
170
166
### Interface Changes, Backward Compatibility, & SXM
171
167
@@ -182,47 +178,44 @@ translation. However, the former has large portions of code in its intermediate
182
178
layers, in addition to the basic SMAPIv2 <-> SMAPIv1 translation in
183
179
` storage_access.ml ` .
184
180
185
- These are the three files in xapi that implement the SMAPIv2 storage interface,
181
+ These are the two files in xapi that implement the SMAPIv2 storage interface,
186
182
from higher to lower level:
187
183
188
- - [ xen-api/ocaml/xapi/storage\_ impl.ml] ( https://github.com/xapi-project/xen-api/blob/v1.127.0/ocaml/xapi/storage_impl.ml ) :
189
- - [ xen-api/ocaml/xapi/storage\_ mux.ml] ( https://github.com/xapi-project/xen-api/blob/v1.127.0/ocaml/xapi/storage_mux.ml ) :
190
- - [ xen-api/ocaml/xapi/storage\_ access.ml] ( https://github.com/xapi-project/xen-api/blob/v1.127.0/ocaml/xapi/storage_access.ml ) :
184
+ - [ xen-api/ocaml/xapi/storage\_ mux.ml] ( https://github.com/xapi-project/xen-api/blob/v25.11.0/ocaml/xapi/storage_mux.ml ) :
185
+ - [ xen-api/ocaml/xapi/storage\_ access.ml] ( https://github.com/xapi-project/xen-api/blob/v25.11.0/ocaml/xapi/storage_access.ml ) :
191
186
192
187
Functionality implemented by higher layers is not implemented by the layers below it.
193
188
194
- #### Extra functionality in ` storage_impl.ml `
195
-
196
- In addition to its usual functions, ` Storage_impl.Wrapper ` also implements the
197
- ` UPDATES ` and ` TASK ` SMAPIv2 APIs, without calling the wrapped module.
189
+ #### Extra functionality in ` storage_task.ml `
198
190
199
- These are backed by the ` Updates ` , ` Task_server ` , and ` Scheduler ` modules from
191
+ ` storage_smapiv1_wrapper.ml ` also implements the ` UPDATES ` and ` TASK ` SMAPIv2 APIs. These are backed by the ` Updates ` , ` Task_server ` , and ` Scheduler ` modules from
200
192
xcp-idl, instantiated in xapi's ` Storage_task ` module. Migration code in
201
193
` Storage_mux ` will interact with these to update task progress. There is also
202
194
an event loop in xapi that keeps calling ` UPDATES.get ` to keep the tasks in
203
195
xapi's database in sync with the storage manager's tasks.
204
196
205
- ` Storage_impl.Wrapper ` also implements the legacy ` VDI.attach ` call by simply
197
+ ` Storage_smapiv1_wrapper.ml ` also implements the legacy ` VDI.attach ` call by simply
206
198
calling the newer ` VDI.attach2 ` call in the same module. In general, this is a
207
199
good place to implement a compatibility layer for deprecated functionality
208
200
removed from other layers, because this is the first module that intercepts a
209
201
SMAPIv2 call.
210
202
211
203
#### Extra functionality in ` storage_mux.ml `
212
204
213
- ` Storage_mux ` implements storage motion (SXM): it implements the ` DATA ` and
214
- ` DATA.MIRROR ` modules. Migration code will use the ` Storage_task ` module to run
215
- the operations and update the task's progress.
205
+ ` Storage_mux ` redirects all storage motion (SXM) code to ` storage_migrate.ml ` ,
206
+ and the multiplexed will be managed by ` storage_migrate.ml ` . The main implementation
207
+ resides in the ` DATA ` and ` DATA.MIRROR ` modules. Migration code will use
208
+ the ` Storage_task ` module to run the operations and update the task's progress.
216
209
217
210
It also implements the ` Policy ` module from the SMAPIv2 interface.
218
211
219
212
## SMAPIv3
220
213
221
214
[ SMAPIv3] ( https://xapi-project.github.io/xapi-storage/ ) has a slightly
222
215
different interface from SMAPIv2.The
223
- [ xapi-storage-script] ( https://github.com/xapi-project/xapi-storage-script )
216
+ [ xapi-storage-script] ( https://github.com/xapi-project/xen-api/tree/v25.11.0/ocaml/ xapi-storage-script )
224
217
daemon is a SMAPIv2 plugin separate from xapi that is doing the SMAPIv2
225
- ↔ SMAPIv3 translation. It keeps the plugins registered with xcp -idl
218
+ ↔ SMAPIv3 translation. It keeps the plugins registered with xapi -idl
226
219
(their message-switch queues) up to date as their files appear or
227
220
disappear from the relevant directory.
228
221
@@ -266,7 +259,7 @@ stored in subdirectories of the
266
259
` /usr/libexec/xapi-storage-script/datapath/ ` directories, respectively.
267
260
When it finds a new datapath plugin, it adds the plugin to a lookup table and
268
261
uses it the next time that datapath is required. When it finds a new volume
269
- plugin, it binds a new [ message-switch] queue named after the plugin's
262
+ plugin, it binds a new [ message-switch] ( https://github.com/xapi-project/xen-api/blob/v25.11.0/ocaml/xapi-storage-script/main.ml#L2023 ) queue named after the plugin's
270
263
subdirectory to a new server instance that uses these volume scripts.
271
264
272
265
To invoke a SMAPIv3 method, it executes a program named
@@ -278,11 +271,11 @@ are type-checked using the generated Python bindings, and so are the
278
271
outputs. The URIs of the SRs that xapi-storage-script knows about are
279
272
stored in the ` /var/run/nonpersistent/xapi-storage-script/state.db `
280
273
file, these URIs can be used on the command line when an sr argument is
281
- expected.` `
274
+ expected.
282
275
283
276
#### Registration of the various SMAPIv3 plugins
284
277
285
- {{< mermaid >}}
278
+ ``` mermaid
286
279
sequenceDiagram
287
280
participant q as message-switch
288
281
participant v1 as (Storage_access.SMAPIv1)
@@ -306,11 +299,11 @@ q ->> svr:org.xen.xapi.storage
306
299
307
300
Note over q, svr: SR.create, PBD.plug
308
301
svr ->> q:org.xapi.storage.sr_type_4
309
- {{< /mermaid >}}
302
+ ```
310
303
311
304
#### What happens when a SMAPIv3 "function" is called
312
305
313
- {{< mermaid >}}
306
+ ``` mermaid
314
307
graph TD
315
308
316
309
call[SMAPIv2 call] --VDI.attach2--> org.xen.xapi.storage
@@ -348,28 +341,28 @@ end
348
341
end
349
342
350
343
org.xen.xapi.storage.SR_type_x --VDI.attach2-->xapi-storage-script
351
- {{< /mermaid >}}
344
+ ```
352
345
353
346
## Error reporting
354
347
355
348
In our SMAPIv1 OCaml "bindings" in xapi
356
- ([ xen-api/ocaml/xapi/sm\_ exec.ml] ( https://github.com/xapi-project/xen-api/blob/v1.127 .0/ocaml/xapi/sm_exec.ml ) ),
349
+ ([ xen-api/ocaml/xapi/sm\_ exec.ml] ( https://github.com/xapi-project/xen-api/blob/v25.11 .0/ocaml/xapi/sm_exec.ml ) ),
357
350
[ when we inspect the error codes returned from a call to
358
- SM] ( https://github.com/xapi-project/xen-api/blob/v1.127 .0/ocaml/xapi/sm_exec.ml#L199 ) ,
351
+ SM] ( https://github.com/xapi-project/xen-api/blob/v25.11 .0/ocaml/xapi/sm_exec.ml#L421 ) ,
359
352
we translate some of the SMAPIv1/SM error codes to XenAPI errors, and
360
353
for others, we just [ construct an error
361
354
code] ( https://github.com/xapi-project/xen-api/blob/v1.127.0/ocaml/xapi/sm_exec.ml#L214 )
362
355
of the form ` SR_BACKEND_FAILURE_<SM error number> ` .
363
356
364
357
The file
365
- [ xcp-idl/storage/storage\_ interface.ml] ( https://github.com/xapi-project/xcp-idl /blob/v1.62 .0/storage/storage_interface.ml#L362 )
358
+ [ xcp-idl/storage/storage\_ interface.ml] ( https://github.com/xapi-project/xen-api /blob/v25.11 .0/ocaml/xapi-idl/ storage/storage_interface.ml#L343 )
366
359
defines a number of SMAPIv2 errors, ultimately all errors from the various
367
360
SMAPIv2 storage servers in xapi will be returned as one of these. Most of the
368
361
errors aren't converted into a specific exception in ` Storage_interface ` , but
369
362
are simply wrapped with ` Storage_interface.Backend_error ` .
370
363
371
364
The
372
- [ Storage\_ access .transform\_ storage\_ exn] ( https://github.com/xapi-project/xen-api/blob/v1.127 .0/ocaml/xapi/storage_access .ml#L29 )
365
+ [ Storage\_ utils .transform\_ storage\_ exn] ( https://github.com/xapi-project/xen-api/blob/v25.11 .0/ocaml/xapi/storage_utils .ml#L133 )
373
366
function is used by the client code in xapi to translate the SMAPIv2
374
367
errors into XenAPI errors again, this unwraps the errors wrapped with
375
368
` Storage_interface.Backend_error ` .
@@ -379,7 +372,7 @@ errors into XenAPI errors again, this unwraps the errors wrapped with
379
372
In the message forwarding layer, first we check the validity of VDI
380
373
operations using ` mark_vdi ` and ` mark_sr ` . These first check that the
381
374
operation is valid operations,
382
- using [ Xapi\_ vdi.check\_ operation\_ error] ( https://github.com/xapi-project/xen-api/blob/v1.127 .0/ocaml/xapi/xapi_vdi.ml#L57 ) ,
375
+ using [ Xapi\_ vdi.check\_ operation\_ error] ( https://github.com/xapi-project/xen-api/blob/v25.11 .0/ocaml/xapi/xapi_vdi.ml#L65 ) ,
383
376
for ` mark_vdi ` , which also inspects the current operations of the VDI,
384
377
and then, if the operation is valid, it is added to the VDI's current
385
378
operations, and update\_ allowed\_ operations is called. Then we forward
@@ -390,7 +383,7 @@ VDI's SR.
390
383
391
384
For the VDI operations, we check at two different places whether the SR
392
385
is attached: first, at the Xapi level, [ in
393
- Xapi\_ vdi.check\_ operation\_ error] ( https://github.com/xapi-project/xen-api/blob/v1.127 .0/ocaml/xapi/xapi_vdi.ml#L98 ) ,
386
+ Xapi\_ vdi.check\_ operation\_ error] ( https://github.com/xapi-project/xen-api/blob/v25.11 .0/ocaml/xapi/xapi_vdi.ml#L133 ) ,
394
387
for the resize operation, and then, at the SMAPIv1 level, in
395
388
` Sm.assert_pbd_is_plugged ` . ` Sm.assert_pbd_is_plugged ` performs the
396
389
same checks, plus it checks that the PBD is attached to the localhost,
0 commit comments