Revision 99ca6b0b doc/design-shared-storage.rst
b/doc/design-shared-storage.rst | ||
---|---|---|
64 | 64 |
filesystems. |
65 | 65 |
- Introduction of shared block device disk template with device |
66 | 66 |
adoption. |
67 |
- Introduction of an External Storage Interface. |
|
67 | 68 |
|
68 | 69 |
Additionally, mid- to long-term goals include: |
69 | 70 |
|
70 | 71 |
- Support for external “storage pools”. |
71 |
- Introduction of an interface for communicating with external scripts, |
|
72 |
providing methods for the various stages of a block device's and |
|
73 |
instance's life-cycle. In order to provide storage provisioning |
|
74 |
capabilities for various SAN appliances, external helpers in the form |
|
75 |
of a “storage driver” will be possibly introduced as well. |
|
76 | 72 |
|
77 | 73 |
Refactoring of all code referring to constants.DTS_NET_MIRROR |
78 | 74 |
============================================================= |
... | ... | |
159 | 155 |
- The device will be available with the same path under all nodes in the |
160 | 156 |
node group. |
161 | 157 |
|
158 |
Introduction of an External Storage Interface |
|
159 |
============================================== |
|
160 |
Overview |
|
161 |
-------- |
|
162 |
|
|
163 |
To extend the shared block storage template and give Ganeti the ability |
|
164 |
to control and manipulate external storage (provisioning, removal, |
|
165 |
growing, etc.) we need a more generic approach. The generic method for |
|
166 |
supporting external shared storage in Ganeti will be to have an |
|
167 |
ExtStorage provider for each external shared storage hardware type. The |
|
168 |
ExtStorage provider will be a set of files (executable scripts and text |
|
169 |
files), contained inside a directory which will be named after the |
|
170 |
provider. This directory must be present across all nodes of a nodegroup |
|
171 |
(Ganeti doesn't replicate it), in order for the provider to be usable by |
|
172 |
Ganeti for this nodegroup (valid). The external shared storage hardware |
|
173 |
should also be accessible by all nodes of this nodegroup too. |
|
174 |
|
|
175 |
An “ExtStorage provider” will have to provide the following methods: |
|
176 |
|
|
177 |
- Create a disk |
|
178 |
- Remove a disk |
|
179 |
- Grow a disk |
|
180 |
- Attach a disk to a given node |
|
181 |
- Detach a disk from a given node |
|
182 |
- Verify its supported parameters |
|
183 |
|
|
184 |
The proposed ExtStorage interface borrows heavily from the OS |
|
185 |
interface and follows a one-script-per-function approach. An ExtStorage |
|
186 |
provider is expected to provide the following scripts: |
|
187 |
|
|
188 |
- `create` |
|
189 |
- `remove` |
|
190 |
- `grow` |
|
191 |
- `attach` |
|
192 |
- `detach` |
|
193 |
- `verify` |
|
194 |
|
|
195 |
All scripts will be called with no arguments and get their input via |
|
196 |
environment variables. A common set of variables will be exported for |
|
197 |
all commands, and some of them might have extra ones. |
|
198 |
|
|
199 |
- `VOL_NAME`: The name of the volume. This is unique for Ganeti and it |
|
200 |
uses it to refer to a specific volume inside the external storage. |
|
201 |
- `VOL_SIZE`: The volume's size in mebibytes. |
|
202 |
- `VOL_NEW_SIZE`: Available only to the `grow` script. It declares the |
|
203 |
new size of the volume after grow (in mebibytes). |
|
204 |
- `EXTP_name`: ExtStorage parameter, where `name` is the parameter in |
|
205 |
upper-case (same as OS interface's `OSP_*` parameters). |
|
206 |
|
|
207 |
All scripts except `attach` should return 0 on success and non-zero on |
|
208 |
error, accompanied by an appropriate error message on stderr. The |
|
209 |
`attach` script should return a string on stdout on success, which is |
|
210 |
the block device's full path, after it has been successfully attached to |
|
211 |
the host node. On error it should return non-zero. |
|
212 |
|
|
213 |
Implementation |
|
214 |
-------------- |
|
215 |
|
|
216 |
To support the ExtStorage interface, we will introduce a new disk |
|
217 |
template called `ext`. This template will implement the existing Ganeti |
|
218 |
disk interface in `lib/bdev.py` (create, remove, attach, assemble, |
|
219 |
shutdown, grow), and will simultaneously pass control to the external |
|
220 |
scripts to actually handle the above actions. The `ext` disk template |
|
221 |
will act as a translation layer between the current Ganeti disk |
|
222 |
interface and the ExtStorage providers. |
|
223 |
|
|
224 |
We will also introduce a new IDISK_PARAM called `IDISK_PROVIDER = |
|
225 |
provider`, which will be used at the command line to select the desired |
|
226 |
ExtStorage provider. This parameter will be valid only for template |
|
227 |
`ext` e.g.:: |
|
228 |
|
|
229 |
gnt-instance add -t ext --disk=0:size=2G,provider=sample_provider1 |
|
230 |
|
|
231 |
The Extstorage interface will support different disks to be created by |
|
232 |
different providers. e.g.:: |
|
233 |
|
|
234 |
gnt-instance add -t ext --disk=0:size=2G,provider=sample_provider1 |
|
235 |
--disk=1:size=1G,provider=sample_provider2 |
|
236 |
--disk=2:size=3G,provider=sample_provider1 |
|
237 |
|
|
238 |
Finally, the ExtStorage interface will support passing of parameters to |
|
239 |
the ExtStorage provider. This will also be done per disk, from the |
|
240 |
command line:: |
|
241 |
|
|
242 |
gnt-instance add -t ext --disk=0:size=1G,provider=sample_provider1, |
|
243 |
param1=value1,param2=value2 |
|
244 |
|
|
245 |
The above parameters will be exported to the ExtStorage provider's |
|
246 |
scripts as the enviromental variables: |
|
247 |
|
|
248 |
- `EXTP_PARAM1 = str(value1)` |
|
249 |
- `EXTP_PARAM2 = str(value2)` |
|
250 |
|
|
251 |
We will also introduce a new Ganeti client called `gnt-storage` which |
|
252 |
will be used to diagnose ExtStorage providers and show information about |
|
253 |
them, similarly to the way `gnt-os diagose` and `gnt-os info` handle OS |
|
254 |
definitions. |
|
255 |
|
|
162 | 256 |
Long-term shared storage goals |
163 | 257 |
============================== |
164 | 258 |
Storage pool handling |
... | ... | |
166 | 260 |
|
167 | 261 |
A new cluster configuration attribute will be introduced, named |
168 | 262 |
“storage_pools”, modeled as a dictionary mapping storage pools to |
169 |
external storage drivers (see below), e.g.::
|
|
263 |
external storage providers (see below), e.g.::
|
|
170 | 264 |
|
171 | 265 |
{ |
172 | 266 |
"nas1": "foostore", |
... | ... | |
188 | 282 |
of storage pools to different node groups, thus specifying the |
189 | 283 |
instances' “mobility domain”. |
190 | 284 |
|
191 |
New disk templates will also be necessary to facilitate the use of external |
|
192 |
storage. The proposed addition is a whole template namespace created by |
|
193 |
prefixing the pool names with a fixed string, e.g. “ext:”, forming names |
|
194 |
like “ext:nas1”, “ext:foo”. |
|
195 |
|
|
196 |
Interface to the external storage drivers |
|
197 |
----------------------------------------- |
|
198 |
|
|
199 |
In addition to external storage pools, a new interface will be |
|
200 |
introduced to allow external scripts to provision and manipulate shared |
|
201 |
storage. |
|
202 |
|
|
203 |
In order to provide storage provisioning and manipulation (e.g. growing, |
|
204 |
renaming) capabilities, each instance's disk template can possibly be |
|
205 |
associated with an external “storage driver” which, based on the |
|
206 |
instance's configuration and tags, will perform all supported storage |
|
207 |
operations using auxiliary means (e.g. XML-RPC, ssh, etc.). |
|
208 |
|
|
209 |
A “storage driver” will have to provide the following methods: |
|
210 |
|
|
211 |
- Create a disk |
|
212 |
- Remove a disk |
|
213 |
- Rename a disk |
|
214 |
- Resize a disk |
|
215 |
- Attach a disk to a given node |
|
216 |
- Detach a disk from a given node |
|
217 |
|
|
218 |
The proposed storage driver architecture borrows heavily from the OS |
|
219 |
interface and follows a one-script-per-function approach. A storage |
|
220 |
driver is expected to provide the following scripts: |
|
221 |
|
|
222 |
- `create` |
|
223 |
- `resize` |
|
224 |
- `rename` |
|
225 |
- `remove` |
|
226 |
- `attach` |
|
227 |
- `detach` |
|
228 |
|
|
229 |
These executables will be called once for each disk with no arguments |
|
230 |
and all required information will be passed through environment |
|
231 |
variables. The following environment variables will always be present on |
|
232 |
each invocation: |
|
233 |
|
|
234 |
- `INSTANCE_NAME`: The instance's name |
|
235 |
- `INSTANCE_UUID`: The instance's UUID |
|
236 |
- `INSTANCE_TAGS`: The instance's tags |
|
237 |
- `DISK_INDEX`: The current disk index. |
|
238 |
- `LOGICAL_ID`: The disk's logical id (if existing) |
|
239 |
- `POOL`: The storage pool the instance belongs to. |
|
240 |
|
|
241 |
Additional variables may be available in a per-script context (see |
|
242 |
below). |
|
243 |
|
|
244 |
Of particular importance is the disk's logical ID, which will act as |
|
245 |
glue between Ganeti and the external storage drivers; there are two |
|
246 |
possible ways of using a disk's logical ID in a storage driver: |
|
247 |
|
|
248 |
1. Simply use it as a unique identifier (e.g. UUID) and keep a separate, |
|
249 |
external database linking it to the actual storage. |
|
250 |
2. Encode all useful storage information in the logical ID and have the |
|
251 |
driver decode it at runtime. |
|
252 |
|
|
253 |
All scripts should return 0 on success and non-zero on error accompanied by |
|
254 |
an appropriate error message on stderr. Furthermore, the following |
|
255 |
special cases are defined: |
|
256 |
|
|
257 |
1. `create` In case of success, a string representing the disk's logical |
|
258 |
id must be returned on stdout, which will be saved in the instance's |
|
259 |
configuration and can be later used by the other scripts of the same |
|
260 |
storage driver. The logical id may be based on instance name, |
|
261 |
instance uuid and/or disk index. |
|
262 |
|
|
263 |
Additional environment variables present: |
|
264 |
- `DISK_SIZE`: The requested disk size in MiB |
|
265 |
|
|
266 |
2. `resize` In case of success, output the new disk size. |
|
267 |
|
|
268 |
Additional environment variables present: |
|
269 |
- `DISK_SIZE`: The requested disk size in MiB |
|
270 |
|
|
271 |
3. `rename` On success, a new logical id should be returned, which will |
|
272 |
replace the old one. This script is meant to rename the instance's |
|
273 |
backing store and update the disk's logical ID in case one of them is |
|
274 |
bound to the instance name. |
|
285 |
The pool, in which to put the new instance's disk, will be defined at |
|
286 |
the command line during `instance add`. This will become possible by |
|
287 |
replacing the IDISK_PROVIDER parameter with a new one, called `IDISK_POOL |
|
288 |
= pool`. The cmdlib logic will then look at the cluster-level mapping |
|
289 |
dictionary to determine the ExtStorage provider for the given pool. |
|
275 | 290 |
|
276 |
Additional environment variables present:
|
|
277 |
- `NEW_INSTANCE_NAME`: The instance's new name.
|
|
291 |
gnt-storage
|
|
292 |
-----------
|
|
278 | 293 |
|
294 |
The `gnt-storage` client can be extended to support pool management |
|
295 |
(creation/modification/deletion of pools, connection/disconnection of |
|
296 |
pools to nodegroups, etc.). It can also be extended to diagnose and |
|
297 |
provide information for internal disk templates too, such as lvm and |
|
298 |
drbd. |
|
279 | 299 |
|
280 | 300 |
.. vim: set textwidth=72 : |
Also available in: Unified diff