@@ -3,39 +3,33 @@ title = "XAPI's Storage Layers"
33linkTitle = " Storage"
44+++
55
6+
67{{% notice info %}}
78The 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 ) .
1710{{% /notice %}}
1811
12+
1913Xapi directly communicates only with the SMAPIv2 layer. There are no
2014plugins directly implementing the SMAPIv2 interface, but the plugins in
2115other layers are accessed through it:
2216
23- {{< mermaid >}}
17+ ``` mermaid
2418graph TD
2519A[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]
2722B --> D[SMAPIv2 <-> SMAPIv3 translation: xapi-storage-script]
28- C --> E[ SMAPIv1 plugins]
23+ G --> E[SMAPIv1 plugins]
2924D --> F[SMAPIv3 plugins]
30- {{< /mermaid >}}
25+ ```
3126
3227## SMAPIv1
3328
3429These are the files related to SMAPIv1 in ` xen-api/ocaml/xapi/ ` :
3530
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:
3933 support for implementing the above "bindings". The
4034 parameters are converted to XML-RPC, passed to the relevant python
4135 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/`:
4640 parameters in the args record.
4741- ` smint.ml ` : Contains types, exceptions, ... for the SMAPIv1 OCaml
4842 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.
4947
5048## SMAPIv2
5149
5250These are the files related to SMAPIv2, which need to be modified to
5351implement new calls:
5452
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 ) :
5654 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 ) :
5856 A stub SMAPIv2 storage server implementation that matches the
5957 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 ) ),
6159 each of its function just raise a ` Storage_interface.Unimplemented `
6260 error. This skeleton is used to automatically fill the unimplemented
6361 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.
6764 It passes the XML-RPC requests as the first command-line argument to the
6865 corresponding Python script, which returns an XML-RPC response on standard
6966 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 )
7369 module wraps a SMAPIv2 server (Server\_ impl) and takes care of
7470 locking and datapaths (in case of multiple connections (=datapaths)
7571 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 )
7773 in xcp-idl). It also implements some functionality, like the ` DP `
7874 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 ) :
8076 A SMAPIv2 server, which multiplexes between other servers. A
8177 different SMAPIv2 server can be registered for each SR. Then it
8278 forwards the calls for each SR to the "storage plugin" registered
@@ -85,30 +81,30 @@ implement new calls:
8581### How SMAPIv2 works:
8682
8783We 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
8985main ` Storage_mux.Server ` (basically ` Storage_impl.Wrapper(Mux) ` ) is
9086[ 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 )
9288on 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 ) ,
9490and this is the main entry point for incoming SMAPIv2 function calls.
9591` Storage_mux ` does not really multiplex between different plugins right
9692now: [ 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 ) ,
9894the 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 )
10096on the various "` org.xen.xapi.storage.<sr type> ` " queues for each
10197supported SR type. (This will change with SMAPIv3, which is accessed via
10298a SMAPIv2 plugin outside of xapi that translates between SMAPIv2 and
10399SMAPIv3.) 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 ) ,
105101which 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 ) ,
107103and 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 ) ,
109105the relevant "` org.xen.xapi.storage.<sr type> ` " queue needed for that
110106PBD 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 )
112108for the SR of that PBD.\
113109So basically what happens is that xapi registers itself as a SMAPIv2
114110server, and forwards incoming function calls to itself through
@@ -118,10 +114,10 @@ translation.
118114
119115#### Registration of the various storage servers
120116
121- {{< mermaid >}}
117+ ``` mermaid
122118sequenceDiagram
123119participant q as message-switch
124- participant v1 as Storage_access .SMAPIv1
120+ participant v1 as Storage_smapiv1 .SMAPIv1
125121participant svr as Storage_mux.Server
126122
127123Note over q, svr: xapi startup, "Starting SMAPIv1 proxies"
@@ -134,11 +130,11 @@ q ->> svr:org.xen.xapi.storage
134130
135131Note over q, svr: SR.create, PBD.plug
136132svr ->> q:org.xapi.storage.sr_type_2
137- {{< /mermaid >}}
133+ ```
138134
139135#### What happens when a SMAPIv2 "function" is called
140136
141- {{< mermaid >}}
137+ ``` mermaid
142138graph TD
143139
144140call[SMAPIv2 call] --VDI.attach2--> org.xen.xapi.storage
@@ -148,24 +144,24 @@ org.xen.xapi.storage
148144org.xen.xapi.storage.SR_type_x
149145end
150146
151- org.xen.xapi.storage --VDI.attach2--> Storage_impl .Wrapper
147+ org.xen.xapi.storage --VDI.attach2--> Storage_smapiv1_wrapper .Wrapper
152148
153149subgraph xapi
154150subgraph Storage_mux.server
155- Storage_impl .Wrapper --> Storage_mux.mux
151+ Storage_smapiv1_wrapper .Wrapper --> Storage_mux.mux
156152end
157- Storage_access .SMAPIv1
153+ Storage_smapiv1 .SMAPIv1
158154end
159155
160156Storage_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
162158
163159subgraph SMAPIv1
164160driver_x[SMAPIv1 driver for SR_type_x]
165161end
166162
167- Storage_access .SMAPIv1 --vdi_attach--> driver_x
168- {{< /mermaid >}}
163+ Storage_smapiv1 .SMAPIv1 --vdi_attach--> driver_x
164+ ```
169165
170166### Interface Changes, Backward Compatibility, & SXM
171167
@@ -182,47 +178,44 @@ translation. However, the former has large portions of code in its intermediate
182178layers, in addition to the basic SMAPIv2 <-> SMAPIv1 translation in
183179` storage_access.ml ` .
184180
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,
186182from higher to lower level:
187183
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 ) :
191186
192187Functionality implemented by higher layers is not implemented by the layers below it.
193188
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 `
198190
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
200192xcp-idl, instantiated in xapi's ` Storage_task ` module. Migration code in
201193` Storage_mux ` will interact with these to update task progress. There is also
202194an event loop in xapi that keeps calling ` UPDATES.get ` to keep the tasks in
203195xapi's database in sync with the storage manager's tasks.
204196
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
206198calling the newer ` VDI.attach2 ` call in the same module. In general, this is a
207199good place to implement a compatibility layer for deprecated functionality
208200removed from other layers, because this is the first module that intercepts a
209201SMAPIv2 call.
210202
211203#### Extra functionality in ` storage_mux.ml `
212204
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.
216209
217210It also implements the ` Policy ` module from the SMAPIv2 interface.
218211
219212## SMAPIv3
220213
221214[ SMAPIv3] ( https://xapi-project.github.io/xapi-storage/ ) has a slightly
222215different 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 )
224217daemon 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
226219(their message-switch queues) up to date as their files appear or
227220disappear from the relevant directory.
228221
@@ -266,7 +259,7 @@ stored in subdirectories of the
266259` /usr/libexec/xapi-storage-script/datapath/ ` directories, respectively.
267260When it finds a new datapath plugin, it adds the plugin to a lookup table and
268261uses 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
270263subdirectory to a new server instance that uses these volume scripts.
271264
272265To 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
278271outputs. The URIs of the SRs that xapi-storage-script knows about are
279272stored in the ` /var/run/nonpersistent/xapi-storage-script/state.db `
280273file, these URIs can be used on the command line when an sr argument is
281- expected.` `
274+ expected.
282275
283276#### Registration of the various SMAPIv3 plugins
284277
285- {{< mermaid >}}
278+ ``` mermaid
286279sequenceDiagram
287280participant q as message-switch
288281participant v1 as (Storage_access.SMAPIv1)
@@ -306,11 +299,11 @@ q ->> svr:org.xen.xapi.storage
306299
307300Note over q, svr: SR.create, PBD.plug
308301svr ->> q:org.xapi.storage.sr_type_4
309- {{< /mermaid >}}
302+ ```
310303
311304#### What happens when a SMAPIv3 "function" is called
312305
313- {{< mermaid >}}
306+ ``` mermaid
314307graph TD
315308
316309call[SMAPIv2 call] --VDI.attach2--> org.xen.xapi.storage
@@ -348,28 +341,28 @@ end
348341end
349342
350343org.xen.xapi.storage.SR_type_x --VDI.attach2-->xapi-storage-script
351- {{< /mermaid >}}
344+ ```
352345
353346## Error reporting
354347
355348In 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 ) ),
357350[ 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 ) ,
359352we translate some of the SMAPIv1/SM error codes to XenAPI errors, and
360353for others, we just [ construct an error
361354code] ( https://github.com/xapi-project/xen-api/blob/v1.127.0/ocaml/xapi/sm_exec.ml#L214 )
362355of the form ` SR_BACKEND_FAILURE_<SM error number> ` .
363356
364357The 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 )
366359defines a number of SMAPIv2 errors, ultimately all errors from the various
367360SMAPIv2 storage servers in xapi will be returned as one of these. Most of the
368361errors aren't converted into a specific exception in ` Storage_interface ` , but
369362are simply wrapped with ` Storage_interface.Backend_error ` .
370363
371364The
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 )
373366function is used by the client code in xapi to translate the SMAPIv2
374367errors into XenAPI errors again, this unwraps the errors wrapped with
375368` Storage_interface.Backend_error ` .
@@ -379,7 +372,7 @@ errors into XenAPI errors again, this unwraps the errors wrapped with
379372In the message forwarding layer, first we check the validity of VDI
380373operations using ` mark_vdi ` and ` mark_sr ` . These first check that the
381374operation 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 ) ,
383376for ` mark_vdi ` , which also inspects the current operations of the VDI,
384377and then, if the operation is valid, it is added to the VDI's current
385378operations, and update\_ allowed\_ operations is called. Then we forward
@@ -390,7 +383,7 @@ VDI's SR.
390383
391384For the VDI operations, we check at two different places whether the SR
392385is 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 ) ,
394387for the resize operation, and then, at the SMAPIv1 level, in
395388` Sm.assert_pbd_is_plugged ` . ` Sm.assert_pbd_is_plugged ` performs the
396389same checks, plus it checks that the PBD is attached to the localhost,
0 commit comments