1 /*
2 * storage_conf.c: config handling for storage driver
3 *
4 * Copyright (C) 2006-2016 Red Hat, Inc.
5 * Copyright (C) 2006-2008 Daniel P. Berrange
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see
19 * <http://www.gnu.org/licenses/>.
20 */
21
22 #include <config.h>
23
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28
29 #include "virerror.h"
30 #include "datatypes.h"
31 #include "node_device_conf.h"
32 #include "storage_adapter_conf.h"
33 #include "storage_conf.h"
34 #include "storage_source_conf.h"
35
36 #include "virxml.h"
37 #include "viruuid.h"
38 #include "virbuffer.h"
39 #include "viralloc.h"
40 #include "virfile.h"
41 #include "virscsihost.h"
42 #include "virstring.h"
43 #include "virlog.h"
44 #include "virvhba.h"
45 #include "virutil.h"
46
47 #define VIR_FROM_THIS VIR_FROM_STORAGE
48
49 VIR_LOG_INIT("conf.storage_conf");
50
51 VIR_ENUM_IMPL(virStorageVol,
52 VIR_STORAGE_VOL_LAST,
53 "file", "block", "dir", "network",
54 "netdir", "ploop",
55 );
56
57 VIR_ENUM_IMPL(virStoragePool,
58 VIR_STORAGE_POOL_LAST,
59 "dir", "fs", "netfs",
60 "logical", "disk", "iscsi",
61 "iscsi-direct", "scsi", "mpath",
62 "rbd", "sheepdog", "gluster",
63 "zfs", "vstorage",
64 );
65
66 VIR_ENUM_IMPL(virStoragePoolFormatFileSystem,
67 VIR_STORAGE_POOL_FS_LAST,
68 "auto", "ext2", "ext3",
69 "ext4", "ufs", "iso9660", "udf",
70 "gfs", "gfs2", "vfat", "hfs+", "xfs", "ocfs2",
71 "vmfs",
72 );
73
74 VIR_ENUM_IMPL(virStoragePoolFormatFileSystemNet,
75 VIR_STORAGE_POOL_NETFS_LAST,
76 "auto", "nfs", "glusterfs", "cifs",
77 );
78
79 VIR_ENUM_IMPL(virStoragePoolFormatDisk,
80 VIR_STORAGE_POOL_DISK_LAST,
81 "unknown", "dos", "dvh", "gpt",
82 "mac", "bsd", "pc98", "sun", "lvm2",
83 );
84
85 VIR_ENUM_IMPL(virStoragePoolFormatLogical,
86 VIR_STORAGE_POOL_LOGICAL_LAST,
87 "unknown", "lvm2",
88 );
89
90
91 VIR_ENUM_IMPL(virStorageVolFormatDisk,
92 VIR_STORAGE_VOL_DISK_LAST,
93 "none", "linux", "fat16",
94 "fat32", "linux-swap",
95 "linux-lvm", "linux-raid",
96 "extended",
97 );
98
99 VIR_ENUM_IMPL(virStorageVolDefRefreshAllocation,
100 VIR_STORAGE_VOL_DEF_REFRESH_ALLOCATION_LAST,
101 "default", "capacity",
102 );
103
104 VIR_ENUM_IMPL(virStoragePartedFs,
105 VIR_STORAGE_PARTED_FS_TYPE_LAST,
106 "ext2", "ext2", "fat16",
107 "fat32", "linux-swap",
108 "ext2", "ext2",
109 "extended",
110 );
111
112 typedef const char *(*virStorageVolFormatToString)(int format);
113 typedef int (*virStorageVolFormatFromString)(const char *format);
114
115 typedef const char *(*virStoragePoolFormatToString)(int format);
116 typedef int (*virStoragePoolFormatFromString)(const char *format);
117
118 typedef struct _virStorageVolOptions virStorageVolOptions;
119 struct _virStorageVolOptions {
120 int defaultFormat;
121 int lastFormat;
122 virStorageVolFormatToString formatToString;
123 virStorageVolFormatFromString formatFromString;
124 };
125
126 /* Flags to indicate mandatory components in the pool source */
127 enum {
128 VIR_STORAGE_POOL_SOURCE_HOST = (1 << 0),
129 VIR_STORAGE_POOL_SOURCE_DEVICE = (1 << 1),
130 VIR_STORAGE_POOL_SOURCE_DIR = (1 << 2),
131 VIR_STORAGE_POOL_SOURCE_ADAPTER = (1 << 3),
132 VIR_STORAGE_POOL_SOURCE_NAME = (1 << 4),
133 VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN = (1 << 5),
134 VIR_STORAGE_POOL_SOURCE_NETWORK = (1 << 6),
135 };
136
137 typedef struct _virStoragePoolOptions virStoragePoolOptions;
138 struct _virStoragePoolOptions {
139 unsigned int flags;
140 int defaultFormat;
141 int lastFormat;
142
143 virXMLNamespace ns;
144
145 virStoragePoolFormatToString formatToString;
146 virStoragePoolFormatFromString formatFromString;
147 };
148
149 typedef struct _virStoragePoolTypeInfo virStoragePoolTypeInfo;
150 struct _virStoragePoolTypeInfo {
151 int poolType;
152 virStoragePoolOptions poolOptions;
153 virStorageVolOptions volOptions;
154 };
155
156
157 static int
virStorageVolumeFormatFromString(const char * format)158 virStorageVolumeFormatFromString(const char *format)
159 {
160 int ret = virStorageFileFormatTypeFromString(format);
161 if (ret == VIR_STORAGE_FILE_NONE)
162 return -1;
163 return ret;
164 }
165
166
167 static virStoragePoolTypeInfo poolTypeInfo[] = {
168 {.poolType = VIR_STORAGE_POOL_LOGICAL,
169 .poolOptions = {
170 .flags = (VIR_STORAGE_POOL_SOURCE_NAME |
171 VIR_STORAGE_POOL_SOURCE_DEVICE),
172 .defaultFormat = VIR_STORAGE_POOL_LOGICAL_LVM2,
173 .lastFormat = VIR_STORAGE_POOL_LOGICAL_LAST,
174 .formatFromString = virStoragePoolFormatLogicalTypeFromString,
175 .formatToString = virStoragePoolFormatLogicalTypeToString,
176 },
177 },
178 {.poolType = VIR_STORAGE_POOL_DIR,
179 .volOptions = {
180 .defaultFormat = VIR_STORAGE_FILE_RAW,
181 .lastFormat = VIR_STORAGE_FILE_LAST,
182 .formatFromString = virStorageVolumeFormatFromString,
183 .formatToString = virStorageFileFormatTypeToString,
184 },
185 },
186 {.poolType = VIR_STORAGE_POOL_FS,
187 .poolOptions = {
188 .flags = (VIR_STORAGE_POOL_SOURCE_DEVICE),
189 .defaultFormat = VIR_STORAGE_POOL_FS_AUTO,
190 .lastFormat = VIR_STORAGE_POOL_FS_LAST,
191 .formatFromString = virStoragePoolFormatFileSystemTypeFromString,
192 .formatToString = virStoragePoolFormatFileSystemTypeToString,
193 },
194 .volOptions = {
195 .defaultFormat = VIR_STORAGE_FILE_RAW,
196 .lastFormat = VIR_STORAGE_FILE_LAST,
197 .formatFromString = virStorageVolumeFormatFromString,
198 .formatToString = virStorageFileFormatTypeToString,
199 },
200 },
201 {.poolType = VIR_STORAGE_POOL_NETFS,
202 .poolOptions = {
203 .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
204 VIR_STORAGE_POOL_SOURCE_DIR),
205 .defaultFormat = VIR_STORAGE_POOL_NETFS_AUTO,
206 .lastFormat = VIR_STORAGE_POOL_NETFS_LAST,
207 .formatFromString = virStoragePoolFormatFileSystemNetTypeFromString,
208 .formatToString = virStoragePoolFormatFileSystemNetTypeToString,
209 },
210 .volOptions = {
211 .defaultFormat = VIR_STORAGE_FILE_RAW,
212 .lastFormat = VIR_STORAGE_FILE_LAST,
213 .formatFromString = virStorageVolumeFormatFromString,
214 .formatToString = virStorageFileFormatTypeToString,
215 },
216 },
217 {.poolType = VIR_STORAGE_POOL_ISCSI,
218 .poolOptions = {
219 .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
220 VIR_STORAGE_POOL_SOURCE_DEVICE |
221 VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN),
222 },
223 },
224 {.poolType = VIR_STORAGE_POOL_ISCSI_DIRECT,
225 .poolOptions = {
226 .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
227 VIR_STORAGE_POOL_SOURCE_DEVICE |
228 VIR_STORAGE_POOL_SOURCE_NETWORK |
229 VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN),
230 },
231 },
232 {.poolType = VIR_STORAGE_POOL_SCSI,
233 .poolOptions = {
234 .flags = (VIR_STORAGE_POOL_SOURCE_ADAPTER),
235 },
236 },
237 {.poolType = VIR_STORAGE_POOL_RBD,
238 .poolOptions = {
239 .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
240 VIR_STORAGE_POOL_SOURCE_NETWORK |
241 VIR_STORAGE_POOL_SOURCE_NAME),
242 },
243 .volOptions = {
244 .defaultFormat = VIR_STORAGE_FILE_RAW,
245 .formatFromString = virStorageVolumeFormatFromString,
246 .formatToString = virStorageFileFormatTypeToString,
247 }
248 },
249 {.poolType = VIR_STORAGE_POOL_SHEEPDOG,
250 .poolOptions = {
251 .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
252 VIR_STORAGE_POOL_SOURCE_NETWORK |
253 VIR_STORAGE_POOL_SOURCE_NAME),
254 },
255 },
256 {.poolType = VIR_STORAGE_POOL_GLUSTER,
257 .poolOptions = {
258 .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
259 VIR_STORAGE_POOL_SOURCE_NETWORK |
260 VIR_STORAGE_POOL_SOURCE_NAME |
261 VIR_STORAGE_POOL_SOURCE_DIR),
262 },
263 .volOptions = {
264 .defaultFormat = VIR_STORAGE_FILE_RAW,
265 .lastFormat = VIR_STORAGE_FILE_LAST,
266 .formatToString = virStorageFileFormatTypeToString,
267 .formatFromString = virStorageVolumeFormatFromString,
268 }
269 },
270 {.poolType = VIR_STORAGE_POOL_MPATH,
271 },
272 {.poolType = VIR_STORAGE_POOL_DISK,
273 .poolOptions = {
274 .flags = (VIR_STORAGE_POOL_SOURCE_DEVICE),
275 .defaultFormat = VIR_STORAGE_POOL_DISK_UNKNOWN,
276 .lastFormat = VIR_STORAGE_POOL_DISK_LAST,
277 .formatFromString = virStoragePoolFormatDiskTypeFromString,
278 .formatToString = virStoragePoolFormatDiskTypeToString,
279 },
280 .volOptions = {
281 .defaultFormat = VIR_STORAGE_VOL_DISK_NONE,
282 .lastFormat = VIR_STORAGE_VOL_DISK_LAST,
283 .formatFromString = virStorageVolFormatDiskTypeFromString,
284 .formatToString = virStorageVolFormatDiskTypeToString,
285 },
286 },
287 {.poolType = VIR_STORAGE_POOL_ZFS,
288 .poolOptions = {
289 .flags = (VIR_STORAGE_POOL_SOURCE_NAME |
290 VIR_STORAGE_POOL_SOURCE_DEVICE),
291 },
292 },
293 {.poolType = VIR_STORAGE_POOL_VSTORAGE,
294 .poolOptions = {
295 .flags = VIR_STORAGE_POOL_SOURCE_NAME,
296 },
297 .volOptions = {
298 .defaultFormat = VIR_STORAGE_FILE_RAW,
299 .lastFormat = VIR_STORAGE_FILE_LAST,
300 .formatFromString = virStorageVolumeFormatFromString,
301 .formatToString = virStorageFileFormatTypeToString,
302 },
303 },
304 };
305
306
307 static virStoragePoolTypeInfo *
virStoragePoolTypeInfoLookup(int type)308 virStoragePoolTypeInfoLookup(int type)
309 {
310 size_t i;
311 for (i = 0; i < G_N_ELEMENTS(poolTypeInfo); i++)
312 if (poolTypeInfo[i].poolType == type)
313 return &poolTypeInfo[i];
314
315 virReportError(VIR_ERR_INTERNAL_ERROR,
316 _("missing backend for pool type %d"), type);
317 return NULL;
318 }
319
320
321 static virStoragePoolOptions *
virStoragePoolOptionsForPoolType(int type)322 virStoragePoolOptionsForPoolType(int type)
323 {
324 virStoragePoolTypeInfo *backend = virStoragePoolTypeInfoLookup(type);
325 if (backend == NULL)
326 return NULL;
327 return &backend->poolOptions;
328 }
329
330
331 /* virStoragePoolOptionsPoolTypeSetXMLNamespace:
332 * @type: virStoragePoolType
333 * @ns: xmlopt namespace pointer
334 *
335 * Store the @ns in the pool options for the particular backend.
336 * This allows the parse/format code to then directly call the Namespace
337 * method space (parse, format, href, free) as needed during processing.
338 *
339 * Returns: 0 on success, -1 on failure.
340 */
341 int
virStoragePoolOptionsPoolTypeSetXMLNamespace(int type,virXMLNamespace * ns)342 virStoragePoolOptionsPoolTypeSetXMLNamespace(int type,
343 virXMLNamespace *ns)
344 {
345 virStoragePoolTypeInfo *backend = virStoragePoolTypeInfoLookup(type);
346
347 if (!backend)
348 return -1;
349
350 backend->poolOptions.ns = *ns;
351
352 return 0;
353 }
354
355
356 static virStorageVolOptions *
virStorageVolOptionsForPoolType(int type)357 virStorageVolOptionsForPoolType(int type)
358 {
359 virStoragePoolTypeInfo *backend = virStoragePoolTypeInfoLookup(type);
360 if (backend == NULL)
361 return NULL;
362 return &backend->volOptions;
363 }
364
365
366 int
virStoragePoolOptionsFormatPool(virBuffer * buf,int type)367 virStoragePoolOptionsFormatPool(virBuffer *buf,
368 int type)
369 {
370 virStoragePoolOptions *poolOptions;
371
372 if (!(poolOptions = virStoragePoolOptionsForPoolType(type)))
373 return -1;
374
375 if (!poolOptions->formatToString)
376 return 0;
377
378 virBufferAddLit(buf, "<poolOptions>\n");
379 virBufferAdjustIndent(buf, 2);
380
381 if (poolOptions->formatToString) {
382 size_t i;
383
384 virBufferAsprintf(buf, "<defaultFormat type='%s'/>\n",
385 (poolOptions->formatToString)(poolOptions->defaultFormat));
386
387 virBufferAddLit(buf, "<enum name='sourceFormatType'>\n");
388 virBufferAdjustIndent(buf, 2);
389
390 for (i = 0; i < poolOptions->lastFormat; i++)
391 virBufferAsprintf(buf, "<value>%s</value>\n",
392 (poolOptions->formatToString)(i));
393
394 virBufferAdjustIndent(buf, -2);
395 virBufferAddLit(buf, "</enum>\n");
396 }
397
398 virBufferAdjustIndent(buf, -2);
399 virBufferAddLit(buf, "</poolOptions>\n");
400 return 0;
401 }
402
403
404 int
virStoragePoolOptionsFormatVolume(virBuffer * buf,int type)405 virStoragePoolOptionsFormatVolume(virBuffer *buf,
406 int type)
407 {
408 size_t i;
409 virStorageVolOptions *volOptions;
410
411 if (!(volOptions = virStorageVolOptionsForPoolType(type)))
412 return -1;
413
414 if (!volOptions->formatToString)
415 return 0;
416
417 virBufferAddLit(buf, "<volOptions>\n");
418 virBufferAdjustIndent(buf, 2);
419
420 virBufferAsprintf(buf, "<defaultFormat type='%s'/>\n",
421 (volOptions->formatToString)(volOptions->defaultFormat));
422
423 virBufferAddLit(buf, "<enum name='targetFormatType'>\n");
424 virBufferAdjustIndent(buf, 2);
425
426 for (i = 0; i < volOptions->lastFormat; i++)
427 virBufferAsprintf(buf, "<value>%s</value>\n",
428 (volOptions->formatToString)(i));
429
430 virBufferAdjustIndent(buf, -2);
431 virBufferAddLit(buf, "</enum>\n");
432
433 virBufferAdjustIndent(buf, -2);
434 virBufferAddLit(buf, "</volOptions>\n");
435
436 return 0;
437 }
438
439
440 void
virStorageVolDefFree(virStorageVolDef * def)441 virStorageVolDefFree(virStorageVolDef *def)
442 {
443 size_t i;
444
445 if (!def)
446 return;
447
448 g_free(def->name);
449 g_free(def->key);
450
451 for (i = 0; i < def->source.nextent; i++)
452 g_free(def->source.extents[i].path);
453 g_free(def->source.extents);
454
455 virStorageSourceClear(&def->target);
456 g_free(def);
457 }
458
459
460 void
virStoragePoolSourceDeviceClear(virStoragePoolSourceDevice * dev)461 virStoragePoolSourceDeviceClear(virStoragePoolSourceDevice *dev)
462 {
463 VIR_FREE(dev->freeExtents);
464 VIR_FREE(dev->path);
465 }
466
467
468 void
virStoragePoolSourceClear(virStoragePoolSource * source)469 virStoragePoolSourceClear(virStoragePoolSource *source)
470 {
471 size_t i;
472
473 if (!source)
474 return;
475
476 for (i = 0; i < source->nhost; i++)
477 VIR_FREE(source->hosts[i].name);
478 VIR_FREE(source->hosts);
479
480 for (i = 0; i < source->ndevice; i++)
481 virStoragePoolSourceDeviceClear(&source->devices[i]);
482 VIR_FREE(source->devices);
483 VIR_FREE(source->dir);
484 VIR_FREE(source->name);
485 virStorageAdapterClear(&source->adapter);
486 virStorageSourceInitiatorClear(&source->initiator);
487 virStorageAuthDefFree(source->auth);
488 VIR_FREE(source->vendor);
489 VIR_FREE(source->product);
490 }
491
492
493 void
virStoragePoolSourceFree(virStoragePoolSource * source)494 virStoragePoolSourceFree(virStoragePoolSource *source)
495 {
496 virStoragePoolSourceClear(source);
497 g_free(source);
498 }
499
500
501 void
virStoragePoolDefFree(virStoragePoolDef * def)502 virStoragePoolDefFree(virStoragePoolDef *def)
503 {
504 if (!def)
505 return;
506
507 g_free(def->name);
508
509 virStoragePoolSourceClear(&def->source);
510
511 g_free(def->target.path);
512 g_free(def->target.perms.label);
513 g_free(def->refresh);
514 if (def->namespaceData && def->ns.free)
515 (def->ns.free)(def->namespaceData);
516 g_free(def);
517 }
518
519
520 static int
virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,virStoragePoolSource * source,int pool_type,xmlNodePtr node)521 virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,
522 virStoragePoolSource *source,
523 int pool_type,
524 xmlNodePtr node)
525 {
526 xmlNodePtr authnode;
527 xmlNodePtr adapternode;
528 int nsource;
529 size_t i;
530 virStoragePoolOptions *options;
531 int n;
532 g_autoptr(virStorageAuthDef) authdef = NULL;
533 g_autofree char *ver = NULL;
534 g_autofree xmlNodePtr *nodeset = NULL;
535 g_autofree char *sourcedir = NULL;
536 VIR_XPATH_NODE_AUTORESTORE(ctxt)
537
538 ctxt->node = node;
539
540 if ((options = virStoragePoolOptionsForPoolType(pool_type)) == NULL)
541 return -1;
542
543 source->name = virXPathString("string(./name)", ctxt);
544 if (pool_type == VIR_STORAGE_POOL_RBD && source->name == NULL) {
545 virReportError(VIR_ERR_XML_ERROR, "%s",
546 _("element 'name' is mandatory for RBD pool"));
547 return -1;
548 }
549
550 if (options->formatFromString) {
551 g_autofree char *format = NULL;
552
553 format = virXPathString("string(./format/@type)", ctxt);
554 if (format == NULL)
555 source->format = options->defaultFormat;
556 else
557 source->format = options->formatFromString(format);
558
559 if (source->format < 0) {
560 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
561 _("unknown pool format type %s"), format);
562 return -1;
563 }
564 }
565
566 if ((n = virXPathNodeSet("./host", ctxt, &nodeset)) < 0)
567 return -1;
568
569 if (n) {
570 source->hosts = g_new0(virStoragePoolSourceHost, n);
571 source->nhost = n;
572
573 for (i = 0; i < source->nhost; i++) {
574 source->hosts[i].name = virXMLPropString(nodeset[i], "name");
575 if (!source->hosts[i].name) {
576 virReportError(VIR_ERR_XML_ERROR, "%s",
577 _("missing storage pool host name"));
578 return -1;
579 }
580
581 if (virXMLPropInt(nodeset[i], "port", 10, VIR_XML_PROP_NONE,
582 &source->hosts[i].port, 0) < 0)
583 return -1;
584 }
585 }
586
587 VIR_FREE(nodeset);
588
589 virStorageSourceInitiatorParseXML(ctxt, &source->initiator);
590
591 nsource = virXPathNodeSet("./device", ctxt, &nodeset);
592 if (nsource < 0)
593 return -1;
594
595 for (i = 0; i < nsource; i++) {
596 virStoragePoolSourceDevice dev = { .path = NULL };
597 dev.path = virXMLPropString(nodeset[i], "path");
598
599 if (dev.path == NULL) {
600 virReportError(VIR_ERR_XML_ERROR, "%s",
601 _("missing storage pool source device path"));
602 return -1;
603 }
604
605 if (virXMLPropTristateBool(nodeset[i], "part_separator",
606 VIR_XML_PROP_NONE,
607 &dev.part_separator) < 0) {
608 virStoragePoolSourceDeviceClear(&dev);
609 return -1;
610 }
611
612 VIR_APPEND_ELEMENT(source->devices, source->ndevice, dev);
613 }
614
615 sourcedir = virXPathString("string(./dir/@path)", ctxt);
616 if (sourcedir)
617 source->dir = virFileSanitizePath(sourcedir);
618 /* In gluster, a missing dir defaults to "/" */
619 if (!source->dir && pool_type == VIR_STORAGE_POOL_GLUSTER)
620 source->dir = g_strdup("/");
621
622 if ((adapternode = virXPathNode("./adapter", ctxt))) {
623 if (virStorageAdapterParseXML(&source->adapter, adapternode, ctxt) < 0)
624 return -1;
625 }
626
627 if ((authnode = virXPathNode("./auth", ctxt))) {
628 if (!(authdef = virStorageAuthDefParse(authnode, ctxt)))
629 return -1;
630
631 if (authdef->authType == VIR_STORAGE_AUTH_TYPE_NONE) {
632 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
633 _("storage pool missing auth type"));
634 return -1;
635 }
636
637 source->auth = g_steal_pointer(&authdef);
638 }
639
640 /* Option protocol version string (NFSvN) */
641 if ((ver = virXPathString("string(./protocol/@ver)", ctxt))) {
642 if ((source->format != VIR_STORAGE_POOL_NETFS_NFS) &&
643 (source->format != VIR_STORAGE_POOL_NETFS_AUTO)) {
644 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
645 _("storage pool protocol ver unsupported for "
646 "pool type '%s'"),
647 virStoragePoolFormatFileSystemNetTypeToString(source->format));
648 return -1;
649 }
650 if (virStrToLong_uip(ver, NULL, 0, &source->protocolVer) < 0) {
651 virReportError(VIR_ERR_XML_ERROR,
652 _("storage pool protocol ver '%s' is malformed"),
653 ver);
654 return -1;
655 }
656 }
657
658 source->vendor = virXPathString("string(./vendor/@name)", ctxt);
659 source->product = virXPathString("string(./product/@name)", ctxt);
660
661 return 0;
662 }
663
664
665 virStoragePoolSource *
virStoragePoolDefParseSourceString(const char * srcSpec,int pool_type)666 virStoragePoolDefParseSourceString(const char *srcSpec,
667 int pool_type)
668 {
669 g_autoptr(xmlDoc) doc = NULL;
670 g_autoptr(xmlXPathContext) xpath_ctxt = NULL;
671 g_autoptr(virStoragePoolSource) def = NULL;
672
673 if (!(doc = virXMLParseStringCtxtRoot(srcSpec,
674 _("(storage_source_specification)"),
675 "source",
676 &xpath_ctxt)))
677 return NULL;
678
679 def = g_new0(virStoragePoolSource, 1);
680
681 if (virStoragePoolDefParseSource(xpath_ctxt, def, pool_type,
682 xpath_ctxt->node) < 0)
683 return NULL;
684
685 return g_steal_pointer(&def);
686 }
687
688
689 static int
virStorageDefParsePerms(xmlXPathContextPtr ctxt,virStoragePerms * perms,const char * permxpath)690 virStorageDefParsePerms(xmlXPathContextPtr ctxt,
691 virStoragePerms *perms,
692 const char *permxpath)
693 {
694 long long val;
695 VIR_XPATH_NODE_AUTORESTORE(ctxt)
696 xmlNodePtr node;
697 g_autofree char *mode = NULL;
698
699 node = virXPathNode(permxpath, ctxt);
700 if (node == NULL) {
701 /* Set default values if there is not <permissions> element */
702 perms->mode = (mode_t) -1;
703 perms->uid = (uid_t) -1;
704 perms->gid = (gid_t) -1;
705 perms->label = NULL;
706 return 0;
707 }
708
709 ctxt->node = node;
710
711 if ((mode = virXPathString("string(./mode)", ctxt))) {
712 int tmp;
713
714 if (virStrToLong_i(mode, NULL, 8, &tmp) < 0 || (tmp & ~0777)) {
715 virReportError(VIR_ERR_XML_ERROR, "%s",
716 _("malformed octal mode"));
717 return -1;
718 }
719 perms->mode = tmp;
720 } else {
721 perms->mode = (mode_t) -1;
722 }
723
724 if (virXPathNode("./owner", ctxt) == NULL) {
725 perms->uid = (uid_t) -1;
726 } else {
727 /* We previously could output -1, so continue to parse it */
728 if (virXPathLongLong("number(./owner)", ctxt, &val) < 0 ||
729 ((uid_t)val != val &&
730 val != -1)) {
731 virReportError(VIR_ERR_XML_ERROR, "%s",
732 _("malformed owner element"));
733 return -1;
734 }
735
736 perms->uid = val;
737 }
738
739 if (virXPathNode("./group", ctxt) == NULL) {
740 perms->gid = (gid_t) -1;
741 } else {
742 /* We previously could output -1, so continue to parse it */
743 if (virXPathLongLong("number(./group)", ctxt, &val) < 0 ||
744 ((gid_t) val != val &&
745 val != -1)) {
746 virReportError(VIR_ERR_XML_ERROR, "%s",
747 _("malformed group element"));
748 return -1;
749 }
750 perms->gid = val;
751 }
752
753 /* NB, we're ignoring missing labels here - they'll simply inherit */
754 perms->label = virXPathString("string(./label)", ctxt);
755 return 0;
756 }
757
758
759 static int
virStoragePoolDefRefreshParse(xmlXPathContextPtr ctxt,virStoragePoolDef * def)760 virStoragePoolDefRefreshParse(xmlXPathContextPtr ctxt,
761 virStoragePoolDef *def)
762 {
763 g_autofree virStoragePoolDefRefresh *refresh = NULL;
764 g_autofree char *allocation = NULL;
765 int tmp;
766
767 allocation = virXPathString("string(./refresh/volume/@allocation)", ctxt);
768
769 if (!allocation)
770 return 0;
771
772 if ((tmp = virStorageVolDefRefreshAllocationTypeFromString(allocation)) < 0) {
773 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
774 _("unknown storage pool volume refresh allocation type %s"),
775 allocation);
776 return -1;
777 }
778
779 refresh = g_new0(virStoragePoolDefRefresh, 1);
780
781 refresh->volume.allocation = tmp;
782 def->refresh = g_steal_pointer(&refresh);
783 return 0;
784 }
785
786
787 static void
virStoragePoolDefRefreshFormat(virBuffer * buf,virStoragePoolDefRefresh * refresh)788 virStoragePoolDefRefreshFormat(virBuffer *buf,
789 virStoragePoolDefRefresh *refresh)
790 {
791 if (!refresh)
792 return;
793
794 virBufferAddLit(buf, "<refresh>\n");
795 virBufferAdjustIndent(buf, 2);
796 virBufferAsprintf(buf, "<volume allocation='%s'/>\n",
797 virStorageVolDefRefreshAllocationTypeToString(refresh->volume.allocation));
798 virBufferAdjustIndent(buf, -2);
799 virBufferAddLit(buf, "</refresh>\n");
800 }
801
802
803 static int
virStoragePoolDefParseFeatures(virStoragePoolDef * def,xmlXPathContextPtr ctxt)804 virStoragePoolDefParseFeatures(virStoragePoolDef *def,
805 xmlXPathContextPtr ctxt)
806 {
807 g_autofree char *cow = virXPathString("string(./features/cow/@state)", ctxt);
808
809 if (cow) {
810 int val;
811 if (def->type != VIR_STORAGE_POOL_FS &&
812 def->type != VIR_STORAGE_POOL_DIR) {
813 virReportError(VIR_ERR_NO_SUPPORT, "%s",
814 _("cow feature may only be used for 'fs' and 'dir' pools"));
815 return -1;
816 }
817 if ((val = virTristateBoolTypeFromString(cow)) <= 0) {
818 virReportError(VIR_ERR_XML_ERROR,
819 _("invalid storage pool cow feature state '%s'"),
820 cow);
821 return -1;
822 }
823 def->features.cow = val;
824 }
825
826 return 0;
827 }
828
829
830 virStoragePoolDef *
virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)831 virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)
832 {
833 virStoragePoolOptions *options;
834 xmlNodePtr source_node;
835 g_autoptr(virStoragePoolDef) def = NULL;
836 virStoragePoolType type;
837 g_autofree char *uuid = NULL;
838 g_autofree char *target_path = NULL;
839
840 def = g_new0(virStoragePoolDef, 1);
841
842 if (virXMLPropEnum(ctxt->node, "type", virStoragePoolTypeFromString,
843 VIR_XML_PROP_REQUIRED, &type) < 0)
844 return NULL;
845
846 def->type = type;
847
848 if ((options = virStoragePoolOptionsForPoolType(def->type)) == NULL)
849 return NULL;
850
851 source_node = virXPathNode("./source", ctxt);
852 if (source_node) {
853 if (virStoragePoolDefParseSource(ctxt, &def->source, def->type,
854 source_node) < 0)
855 return NULL;
856 } else {
857 if (options->formatFromString)
858 def->source.format = options->defaultFormat;
859 }
860
861 def->name = virXPathString("string(./name)", ctxt);
862 if (def->name == NULL &&
863 options->flags & VIR_STORAGE_POOL_SOURCE_NAME)
864 def->name = g_strdup(def->source.name);
865
866 if (def->name == NULL) {
867 virReportError(VIR_ERR_XML_ERROR, "%s",
868 _("missing pool source name element"));
869 return NULL;
870 }
871
872 if (strchr(def->name, '/')) {
873 virReportError(VIR_ERR_XML_ERROR,
874 _("name %s cannot contain '/'"), def->name);
875 return NULL;
876 }
877
878 uuid = virXPathString("string(./uuid)", ctxt);
879 if (uuid == NULL) {
880 if (virUUIDGenerate(def->uuid) < 0) {
881 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
882 _("unable to generate uuid"));
883 return NULL;
884 }
885 } else {
886 if (virUUIDParse(uuid, def->uuid) < 0) {
887 virReportError(VIR_ERR_XML_ERROR, "%s",
888 _("malformed uuid element"));
889 return NULL;
890 }
891 }
892
893 if (virStoragePoolDefParseFeatures(def, ctxt) < 0)
894 return NULL;
895
896 if (options->flags & VIR_STORAGE_POOL_SOURCE_HOST) {
897 if (!def->source.nhost) {
898 virReportError(VIR_ERR_XML_ERROR, "%s",
899 _("missing storage pool source host name"));
900 return NULL;
901 }
902 }
903
904 if (options->flags & VIR_STORAGE_POOL_SOURCE_DIR) {
905 if (!def->source.dir) {
906 virReportError(VIR_ERR_XML_ERROR, "%s",
907 _("missing storage pool source path"));
908 return NULL;
909 }
910 }
911 if (options->flags & VIR_STORAGE_POOL_SOURCE_NAME) {
912 if (def->source.name == NULL) {
913 /* source name defaults to pool name */
914 def->source.name = g_strdup(def->name);
915 }
916 }
917
918 if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) &&
919 (virStorageAdapterValidate(&def->source.adapter)) < 0)
920 return NULL;
921
922 /* If DEVICE is the only source type, then its required */
923 if (options->flags == VIR_STORAGE_POOL_SOURCE_DEVICE) {
924 if (!def->source.ndevice) {
925 virReportError(VIR_ERR_XML_ERROR, "%s",
926 _("missing storage pool source device name"));
927 return NULL;
928 }
929 }
930
931 /* When we are working with a virtual disk we can skip the target
932 * path and permissions */
933 if (!(options->flags & VIR_STORAGE_POOL_SOURCE_NETWORK)) {
934 if (def->type == VIR_STORAGE_POOL_LOGICAL) {
935 target_path = g_strdup_printf("/dev/%s", def->source.name);
936 } else if (def->type == VIR_STORAGE_POOL_ZFS) {
937 target_path = g_strdup_printf("/dev/zvol/%s", def->source.name);
938 } else {
939 target_path = virXPathString("string(./target/path)", ctxt);
940 if (!target_path) {
941 virReportError(VIR_ERR_XML_ERROR, "%s",
942 _("missing storage pool target path"));
943 return NULL;
944 }
945 }
946 def->target.path = virFileSanitizePath(target_path);
947 if (!def->target.path)
948 return NULL;
949
950 if (virStorageDefParsePerms(ctxt, &def->target.perms,
951 "./target/permissions") < 0)
952 return NULL;
953 }
954
955 if (def->type == VIR_STORAGE_POOL_ISCSI_DIRECT &&
956 !def->source.initiator.iqn) {
957 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
958 _("missing initiator IQN"));
959 return NULL;
960 }
961
962 if (virStoragePoolDefRefreshParse(ctxt, def) < 0)
963 return NULL;
964
965 /* Make a copy of all the callback pointers here for easier use,
966 * especially during the virStoragePoolSourceClear method */
967 def->ns = options->ns;
968 if (def->ns.parse) {
969 if (virXMLNamespaceRegister(ctxt, &def->ns) < 0)
970 return NULL;
971 if ((def->ns.parse)(ctxt, &def->namespaceData) < 0)
972 return NULL;
973 }
974
975 return g_steal_pointer(&def);
976 }
977
978
979 virStoragePoolDef *
virStoragePoolDefParseNode(xmlDocPtr xml,xmlNodePtr root)980 virStoragePoolDefParseNode(xmlDocPtr xml,
981 xmlNodePtr root)
982 {
983 g_autoptr(xmlXPathContext) ctxt = NULL;
984
985 if (!virXMLNodeNameEqual(root, "pool")) {
986 virReportError(VIR_ERR_XML_ERROR,
987 _("unexpected root element <%s>, "
988 "expecting <pool>"),
989 root->name);
990 return NULL;
991 }
992
993 if (!(ctxt = virXMLXPathContextNew(xml)))
994 return NULL;
995
996 ctxt->node = root;
997 return virStoragePoolDefParseXML(ctxt);
998 }
999
1000
1001 static virStoragePoolDef *
virStoragePoolDefParse(const char * xmlStr,const char * filename,unsigned int flags)1002 virStoragePoolDefParse(const char *xmlStr,
1003 const char *filename,
1004 unsigned int flags)
1005 {
1006 virStoragePoolDef *ret = NULL;
1007 g_autoptr(xmlDoc) xml = NULL;
1008
1009 if ((xml = virXMLParse(filename, xmlStr, _("(storage_pool_definition)"),
1010 "storagepool.rng", flags & VIR_STORAGE_POOL_DEFINE_VALIDATE))) {
1011 ret = virStoragePoolDefParseNode(xml, xmlDocGetRootElement(xml));
1012 }
1013
1014 return ret;
1015 }
1016
1017
1018 virStoragePoolDef *
virStoragePoolDefParseString(const char * xmlStr,unsigned int flags)1019 virStoragePoolDefParseString(const char *xmlStr,
1020 unsigned int flags)
1021 {
1022 return virStoragePoolDefParse(xmlStr, NULL, flags);
1023 }
1024
1025
1026 virStoragePoolDef *
virStoragePoolDefParseFile(const char * filename)1027 virStoragePoolDefParseFile(const char *filename)
1028 {
1029 return virStoragePoolDefParse(NULL, filename, 0);
1030 }
1031
1032
1033 static int
virStoragePoolSourceFormat(virBuffer * buf,virStoragePoolOptions * options,virStoragePoolSource * src)1034 virStoragePoolSourceFormat(virBuffer *buf,
1035 virStoragePoolOptions *options,
1036 virStoragePoolSource *src)
1037 {
1038 size_t i, j;
1039
1040 virBufferAddLit(buf, "<source>\n");
1041 virBufferAdjustIndent(buf, 2);
1042
1043 if ((options->flags & VIR_STORAGE_POOL_SOURCE_HOST) && src->nhost) {
1044 for (i = 0; i < src->nhost; i++) {
1045 virBufferEscapeString(buf, "<host name='%s'",
1046 src->hosts[i].name);
1047 if (src->hosts[i].port)
1048 virBufferAsprintf(buf, " port='%d'", src->hosts[i].port);
1049 virBufferAddLit(buf, "/>\n");
1050 }
1051 }
1052
1053 if ((options->flags & VIR_STORAGE_POOL_SOURCE_DEVICE) &&
1054 src->ndevice) {
1055 for (i = 0; i < src->ndevice; i++) {
1056 virBufferEscapeString(buf, "<device path='%s'",
1057 src->devices[i].path);
1058 if (src->devices[i].part_separator !=
1059 VIR_TRISTATE_BOOL_ABSENT) {
1060 virBufferAsprintf(buf, " part_separator='%s'",
1061 virTristateBoolTypeToString(src->devices[i].part_separator));
1062 }
1063 if (src->devices[i].nfreeExtent) {
1064 virBufferAddLit(buf, ">\n");
1065 virBufferAdjustIndent(buf, 2);
1066 for (j = 0; j < src->devices[i].nfreeExtent; j++) {
1067 virBufferAsprintf(buf, "<freeExtent start='%llu' end='%llu'/>\n",
1068 src->devices[i].freeExtents[j].start,
1069 src->devices[i].freeExtents[j].end);
1070 }
1071 virBufferAdjustIndent(buf, -2);
1072 virBufferAddLit(buf, "</device>\n");
1073 } else {
1074 virBufferAddLit(buf, "/>\n");
1075 }
1076 }
1077 }
1078
1079 if (options->flags & VIR_STORAGE_POOL_SOURCE_DIR)
1080 virBufferEscapeString(buf, "<dir path='%s'/>\n", src->dir);
1081
1082 if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) &&
1083 (src->adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST ||
1084 src->adapter.type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST))
1085 virStorageAdapterFormat(buf, &src->adapter);
1086
1087 if (options->flags & VIR_STORAGE_POOL_SOURCE_NAME)
1088 virBufferEscapeString(buf, "<name>%s</name>\n", src->name);
1089
1090 if (options->flags & VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN)
1091 virStorageSourceInitiatorFormatXML(&src->initiator, buf);
1092
1093 if (options->formatToString) {
1094 const char *format = (options->formatToString)(src->format);
1095 if (!format) {
1096 virReportError(VIR_ERR_INTERNAL_ERROR,
1097 _("unknown pool format number %d"),
1098 src->format);
1099 return -1;
1100 }
1101 virBufferAsprintf(buf, "<format type='%s'/>\n", format);
1102 }
1103
1104 if (src->auth)
1105 virStorageAuthDefFormat(buf, src->auth);
1106
1107 if (src->protocolVer)
1108 virBufferAsprintf(buf, "<protocol ver='%u'/>\n", src->protocolVer);
1109
1110 virBufferEscapeString(buf, "<vendor name='%s'/>\n", src->vendor);
1111 virBufferEscapeString(buf, "<product name='%s'/>\n", src->product);
1112
1113 virBufferAdjustIndent(buf, -2);
1114 virBufferAddLit(buf, "</source>\n");
1115 return 0;
1116 }
1117
1118
1119 static void
virStoragePoolDefFormatFeatures(virBuffer * buf,virStoragePoolDef * def)1120 virStoragePoolDefFormatFeatures(virBuffer *buf,
1121 virStoragePoolDef *def)
1122 {
1123 if (def->features.cow == VIR_TRISTATE_BOOL_ABSENT)
1124 return;
1125
1126 virBufferAddLit(buf, "<features>\n");
1127 virBufferAdjustIndent(buf, 2);
1128 if (def->features.cow != VIR_TRISTATE_BOOL_ABSENT)
1129 virBufferAsprintf(buf, "<cow state='%s'/>\n",
1130 virTristateBoolTypeToString(def->features.cow));
1131 virBufferAdjustIndent(buf, -2);
1132 virBufferAddLit(buf, "</features>\n");
1133 }
1134
1135
1136 static int
virStoragePoolDefFormatBuf(virBuffer * buf,virStoragePoolDef * def)1137 virStoragePoolDefFormatBuf(virBuffer *buf,
1138 virStoragePoolDef *def)
1139 {
1140 virStoragePoolOptions *options;
1141 char uuid[VIR_UUID_STRING_BUFLEN];
1142 const char *type;
1143
1144 options = virStoragePoolOptionsForPoolType(def->type);
1145 if (options == NULL)
1146 return -1;
1147
1148 type = virStoragePoolTypeToString(def->type);
1149 if (!type) {
1150 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1151 _("unexpected pool type"));
1152 return -1;
1153 }
1154 virBufferAsprintf(buf, "<pool type='%s'", type);
1155 if (def->namespaceData && def->ns.format)
1156 virXMLNamespaceFormatNS(buf, &def->ns);
1157 virBufferAddLit(buf, ">\n");
1158 virBufferAdjustIndent(buf, 2);
1159 virBufferEscapeString(buf, "<name>%s</name>\n", def->name);
1160
1161 virUUIDFormat(def->uuid, uuid);
1162 virBufferAsprintf(buf, "<uuid>%s</uuid>\n", uuid);
1163
1164 virBufferAsprintf(buf, "<capacity unit='bytes'>%llu</capacity>\n",
1165 def->capacity);
1166 virBufferAsprintf(buf, "<allocation unit='bytes'>%llu</allocation>\n",
1167 def->allocation);
1168 virBufferAsprintf(buf, "<available unit='bytes'>%llu</available>\n",
1169 def->available);
1170
1171 virStoragePoolDefFormatFeatures(buf, def);
1172
1173 if (virStoragePoolSourceFormat(buf, options, &def->source) < 0)
1174 return -1;
1175
1176 /* RBD, Sheepdog, Gluster and Iscsi-direct devices are not local block devs nor
1177 * files, so they don't have a target */
1178 if (def->type != VIR_STORAGE_POOL_RBD &&
1179 def->type != VIR_STORAGE_POOL_SHEEPDOG &&
1180 def->type != VIR_STORAGE_POOL_GLUSTER &&
1181 def->type != VIR_STORAGE_POOL_ISCSI_DIRECT) {
1182 virBufferAddLit(buf, "<target>\n");
1183 virBufferAdjustIndent(buf, 2);
1184
1185 virBufferEscapeString(buf, "<path>%s</path>\n", def->target.path);
1186
1187 if (def->target.perms.mode != (mode_t) -1 ||
1188 def->target.perms.uid != (uid_t) -1 ||
1189 def->target.perms.gid != (gid_t) -1 ||
1190 def->target.perms.label) {
1191 virBufferAddLit(buf, "<permissions>\n");
1192 virBufferAdjustIndent(buf, 2);
1193 if (def->target.perms.mode != (mode_t) -1)
1194 virBufferAsprintf(buf, "<mode>0%o</mode>\n",
1195 def->target.perms.mode);
1196 if (def->target.perms.uid != (uid_t) -1)
1197 virBufferAsprintf(buf, "<owner>%d</owner>\n",
1198 (int) def->target.perms.uid);
1199 if (def->target.perms.gid != (gid_t) -1)
1200 virBufferAsprintf(buf, "<group>%d</group>\n",
1201 (int) def->target.perms.gid);
1202 virBufferEscapeString(buf, "<label>%s</label>\n",
1203 def->target.perms.label);
1204
1205 virBufferAdjustIndent(buf, -2);
1206 virBufferAddLit(buf, "</permissions>\n");
1207 }
1208
1209 virBufferAdjustIndent(buf, -2);
1210 virBufferAddLit(buf, "</target>\n");
1211 }
1212
1213 virStoragePoolDefRefreshFormat(buf, def->refresh);
1214
1215 if (def->namespaceData && def->ns.format) {
1216 if ((def->ns.format)(buf, def->namespaceData) < 0)
1217 return -1;
1218 }
1219
1220 virBufferAdjustIndent(buf, -2);
1221 virBufferAddLit(buf, "</pool>\n");
1222
1223 return 0;
1224 }
1225
1226
1227 char *
virStoragePoolDefFormat(virStoragePoolDef * def)1228 virStoragePoolDefFormat(virStoragePoolDef *def)
1229 {
1230 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
1231
1232 if (virStoragePoolDefFormatBuf(&buf, def) < 0)
1233 return NULL;
1234
1235 return virBufferContentAndReset(&buf);
1236 }
1237
1238
1239 static int
virStorageSize(const char * unit,const char * val,unsigned long long * ret)1240 virStorageSize(const char *unit,
1241 const char *val,
1242 unsigned long long *ret)
1243 {
1244 if (virStrToLong_ullp(val, NULL, 10, ret) < 0) {
1245 virReportError(VIR_ERR_XML_ERROR, "%s",
1246 _("malformed capacity element"));
1247 return -1;
1248 }
1249 /* off_t is signed, so you cannot create a file larger than 2**63
1250 * bytes in the first place. */
1251 if (virScaleInteger(ret, unit, 1, LLONG_MAX) < 0)
1252 return -1;
1253
1254 return 0;
1255 }
1256
1257
1258 static int
virStorageCheckCompat(const char * compat)1259 virStorageCheckCompat(const char *compat)
1260 {
1261 unsigned int result;
1262 g_auto(GStrv) version = NULL;
1263
1264 if (!compat)
1265 return 0;
1266
1267 version = g_strsplit(compat, ".", 2);
1268 if (!version || !version[1] ||
1269 virStrToLong_ui(version[0], NULL, 10, &result) < 0 ||
1270 virStrToLong_ui(version[1], NULL, 10, &result) < 0) {
1271 virReportError(VIR_ERR_XML_ERROR, "%s",
1272 _("forbidden characters in 'compat' attribute"));
1273 return -1;
1274 }
1275 return 0;
1276 }
1277
1278
1279 static virStorageVolDef *
virStorageVolDefParseXML(virStoragePoolDef * pool,xmlXPathContextPtr ctxt,unsigned int flags)1280 virStorageVolDefParseXML(virStoragePoolDef *pool,
1281 xmlXPathContextPtr ctxt,
1282 unsigned int flags)
1283 {
1284 virStorageVolOptions *options;
1285 xmlNodePtr node;
1286 size_t i;
1287 int n;
1288 g_autoptr(virStorageVolDef) def = NULL;
1289 g_autofree char *type = NULL;
1290 g_autofree char *allocation = NULL;
1291 g_autofree char *capacity = NULL;
1292 g_autofree char *unit = NULL;
1293 g_autofree char *backingStore = NULL;
1294 g_autofree xmlNodePtr *nodes = NULL;
1295
1296 virCheckFlags(VIR_VOL_XML_PARSE_NO_CAPACITY |
1297 VIR_VOL_XML_PARSE_OPT_CAPACITY, NULL);
1298
1299 options = virStorageVolOptionsForPoolType(pool->type);
1300 if (options == NULL)
1301 return NULL;
1302
1303 def = g_new0(virStorageVolDef, 1);
1304
1305 def->target.type = VIR_STORAGE_TYPE_FILE;
1306
1307 def->name = virXPathString("string(./name)", ctxt);
1308 if (def->name == NULL) {
1309 virReportError(VIR_ERR_XML_ERROR, "%s",
1310 _("missing volume name element"));
1311 return NULL;
1312 }
1313
1314 /* Normally generated by pool refresh, but useful for unit tests */
1315 def->key = virXPathString("string(./key)", ctxt);
1316
1317 /* Technically overridden by pool refresh, but useful for unit tests */
1318 type = virXPathString("string(./@type)", ctxt);
1319 if (type) {
1320 if ((def->type = virStorageVolTypeFromString(type)) < 0) {
1321 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1322 _("unknown volume type '%s'"), type);
1323 return NULL;
1324 }
1325 }
1326
1327 if ((backingStore = virXPathString("string(./backingStore/path)", ctxt))) {
1328 def->target.backingStore = virStorageSourceNew();
1329 def->target.backingStore->type = VIR_STORAGE_TYPE_FILE;
1330 def->target.backingStore->path = g_steal_pointer(&backingStore);
1331
1332 if (options->formatFromString) {
1333 g_autofree char *format = NULL;
1334
1335 format = virXPathString("string(./backingStore/format/@type)", ctxt);
1336 if (format == NULL)
1337 def->target.backingStore->format = options->defaultFormat;
1338 else
1339 def->target.backingStore->format = (options->formatFromString)(format);
1340
1341 if (def->target.backingStore->format < 0) {
1342 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1343 _("unknown volume format type %s"), format);
1344 return NULL;
1345 }
1346 }
1347
1348 def->target.backingStore->perms = g_new0(virStoragePerms, 1);
1349 if (virStorageDefParsePerms(ctxt, def->target.backingStore->perms,
1350 "./backingStore/permissions") < 0)
1351 return NULL;
1352 }
1353
1354 capacity = virXPathString("string(./capacity)", ctxt);
1355 unit = virXPathString("string(./capacity/@unit)", ctxt);
1356 if (capacity) {
1357 if (virStorageSize(unit, capacity, &def->target.capacity) < 0)
1358 return NULL;
1359 } else if (!(flags & VIR_VOL_XML_PARSE_NO_CAPACITY) &&
1360 !((flags & VIR_VOL_XML_PARSE_OPT_CAPACITY) &&
1361 virStorageSourceHasBacking(&def->target))) {
1362 virReportError(VIR_ERR_XML_ERROR, "%s", _("missing capacity element"));
1363 return NULL;
1364 }
1365 VIR_FREE(unit);
1366
1367 allocation = virXPathString("string(./allocation)", ctxt);
1368 if (allocation) {
1369 unit = virXPathString("string(./allocation/@unit)", ctxt);
1370 if (virStorageSize(unit, allocation, &def->target.allocation) < 0)
1371 return NULL;
1372 def->target.has_allocation = true;
1373 } else {
1374 def->target.allocation = def->target.capacity;
1375 }
1376
1377 def->target.path = virXPathString("string(./target/path)", ctxt);
1378 if (options->formatFromString) {
1379 g_autofree char *format = NULL;
1380
1381 format = virXPathString("string(./target/format/@type)", ctxt);
1382 if (format == NULL)
1383 def->target.format = options->defaultFormat;
1384 else
1385 def->target.format = (options->formatFromString)(format);
1386
1387 if (def->target.format < 0) {
1388 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1389 _("unknown volume format type %s"), format);
1390 return NULL;
1391 }
1392 }
1393
1394 def->target.perms = g_new0(virStoragePerms, 1);
1395 if (virStorageDefParsePerms(ctxt, def->target.perms,
1396 "./target/permissions") < 0)
1397 return NULL;
1398
1399 node = virXPathNode("./target/encryption", ctxt);
1400 if (node != NULL) {
1401 def->target.encryption = virStorageEncryptionParseNode(node, ctxt);
1402 if (def->target.encryption == NULL)
1403 return NULL;
1404 }
1405
1406 def->target.compat = virXPathString("string(./target/compat)", ctxt);
1407 if (virStorageCheckCompat(def->target.compat) < 0)
1408 return NULL;
1409
1410 if (virXPathNode("./target/nocow", ctxt))
1411 def->target.nocow = true;
1412
1413 if (virParseScaledValue("./target/clusterSize",
1414 "./target/clusterSize/@unit",
1415 ctxt, &def->target.clusterSize,
1416 1, ULLONG_MAX, false) < 0) {
1417 return NULL;
1418 }
1419
1420 if (virXPathNode("./target/features", ctxt)) {
1421 if ((n = virXPathNodeSet("./target/features/*", ctxt, &nodes)) < 0)
1422 return NULL;
1423
1424 if (!def->target.compat)
1425 def->target.compat = g_strdup("1.1");
1426
1427 def->target.features = virBitmapNew(VIR_STORAGE_FILE_FEATURE_LAST);
1428
1429 for (i = 0; i < n; i++) {
1430 int f = virStorageFileFeatureTypeFromString((const char*)nodes[i]->name);
1431
1432 if (f < 0) {
1433 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported feature %s"),
1434 (const char*)nodes[i]->name);
1435 return NULL;
1436 }
1437 ignore_value(virBitmapSetBit(def->target.features, f));
1438 }
1439 VIR_FREE(nodes);
1440 }
1441
1442 return g_steal_pointer(&def);
1443 }
1444
1445
1446 virStorageVolDef *
virStorageVolDefParseNode(virStoragePoolDef * pool,xmlDocPtr xml,xmlNodePtr root,unsigned int flags)1447 virStorageVolDefParseNode(virStoragePoolDef *pool,
1448 xmlDocPtr xml,
1449 xmlNodePtr root,
1450 unsigned int flags)
1451 {
1452 g_autoptr(xmlXPathContext) ctxt = NULL;
1453
1454 if (!virXMLNodeNameEqual(root, "volume")) {
1455 virReportError(VIR_ERR_XML_ERROR,
1456 _("unexpected root element <%s>, "
1457 "expecting <volume>"),
1458 root->name);
1459 return NULL;
1460 }
1461
1462 if (!(ctxt = virXMLXPathContextNew(xml)))
1463 return NULL;
1464
1465 ctxt->node = root;
1466 return virStorageVolDefParseXML(pool, ctxt, flags);
1467 }
1468
1469
1470 static virStorageVolDef *
virStorageVolDefParse(virStoragePoolDef * pool,const char * xmlStr,const char * filename,unsigned int flags)1471 virStorageVolDefParse(virStoragePoolDef *pool,
1472 const char *xmlStr,
1473 const char *filename,
1474 unsigned int flags)
1475 {
1476 virStorageVolDef *ret = NULL;
1477 g_autoptr(xmlDoc) xml = NULL;
1478
1479 if ((xml = virXMLParse(filename, xmlStr, _("(storage_volume_definition)"), NULL, false))) {
1480 ret = virStorageVolDefParseNode(pool, xml, xmlDocGetRootElement(xml), flags);
1481 }
1482
1483 return ret;
1484 }
1485
1486
1487 virStorageVolDef *
virStorageVolDefParseString(virStoragePoolDef * pool,const char * xmlStr,unsigned int flags)1488 virStorageVolDefParseString(virStoragePoolDef *pool,
1489 const char *xmlStr,
1490 unsigned int flags)
1491 {
1492 return virStorageVolDefParse(pool, xmlStr, NULL, flags);
1493 }
1494
1495
1496 virStorageVolDef *
virStorageVolDefParseFile(virStoragePoolDef * pool,const char * filename,unsigned int flags)1497 virStorageVolDefParseFile(virStoragePoolDef *pool,
1498 const char *filename,
1499 unsigned int flags)
1500 {
1501 return virStorageVolDefParse(pool, NULL, filename, flags);
1502 }
1503
1504
1505 static void
virStorageVolTimestampFormat(virBuffer * buf,const char * name,struct timespec * ts)1506 virStorageVolTimestampFormat(virBuffer *buf, const char *name,
1507 struct timespec *ts)
1508 {
1509 if (ts->tv_nsec < 0)
1510 return;
1511 virBufferAsprintf(buf, "<%s>%llu", name,
1512 (unsigned long long) ts->tv_sec);
1513 if (ts->tv_nsec)
1514 virBufferAsprintf(buf, ".%09ld", ts->tv_nsec);
1515 virBufferAsprintf(buf, "</%s>\n", name);
1516 }
1517
1518
1519 static int
virStorageVolTargetDefFormat(virStorageVolOptions * options,virBuffer * buf,virStorageSource * def,const char * type)1520 virStorageVolTargetDefFormat(virStorageVolOptions *options,
1521 virBuffer *buf,
1522 virStorageSource *def,
1523 const char *type)
1524 {
1525 virBufferAsprintf(buf, "<%s>\n", type);
1526 virBufferAdjustIndent(buf, 2);
1527
1528 virBufferEscapeString(buf, "<path>%s</path>\n", def->path);
1529
1530 if (options->formatToString) {
1531 const char *format = (options->formatToString)(def->format);
1532 if (!format) {
1533 virReportError(VIR_ERR_INTERNAL_ERROR,
1534 _("unknown volume format number %d"),
1535 def->format);
1536 return -1;
1537 }
1538 virBufferAsprintf(buf, "<format type='%s'/>\n", format);
1539 }
1540
1541 if (def->perms &&
1542 (def->perms->mode != (mode_t) -1 ||
1543 def->perms->uid != (uid_t) -1 ||
1544 def->perms->gid != (gid_t) -1 ||
1545 def->perms->label)) {
1546 virBufferAddLit(buf, "<permissions>\n");
1547 virBufferAdjustIndent(buf, 2);
1548
1549 if (def->perms->mode != (mode_t) -1)
1550 virBufferAsprintf(buf, "<mode>0%o</mode>\n",
1551 def->perms->mode);
1552 if (def->perms->uid != (uid_t) -1)
1553 virBufferAsprintf(buf, "<owner>%d</owner>\n",
1554 (int) def->perms->uid);
1555 if (def->perms->gid != (gid_t) -1)
1556 virBufferAsprintf(buf, "<group>%d</group>\n",
1557 (int) def->perms->gid);
1558
1559 virBufferEscapeString(buf, "<label>%s</label>\n",
1560 def->perms->label);
1561
1562 virBufferAdjustIndent(buf, -2);
1563 virBufferAddLit(buf, "</permissions>\n");
1564 }
1565
1566 if (def->timestamps) {
1567 virBufferAddLit(buf, "<timestamps>\n");
1568 virBufferAdjustIndent(buf, 2);
1569 virStorageVolTimestampFormat(buf, "atime", &def->timestamps->atime);
1570 virStorageVolTimestampFormat(buf, "mtime", &def->timestamps->mtime);
1571 virStorageVolTimestampFormat(buf, "ctime", &def->timestamps->ctime);
1572 virStorageVolTimestampFormat(buf, "btime", &def->timestamps->btime);
1573 virBufferAdjustIndent(buf, -2);
1574 virBufferAddLit(buf, "</timestamps>\n");
1575 }
1576
1577 if (def->encryption &&
1578 virStorageEncryptionFormat(buf, def->encryption) < 0)
1579 return -1;
1580
1581 virBufferEscapeString(buf, "<compat>%s</compat>\n", def->compat);
1582
1583 if (def->clusterSize > 0) {
1584 virBufferAsprintf(buf, "<clusterSize unit='B'>%llu</clusterSize>\n",
1585 def->clusterSize);
1586 }
1587
1588 if (def->features) {
1589 size_t i;
1590 bool empty = virBitmapIsAllClear(def->features);
1591
1592 if (empty) {
1593 virBufferAddLit(buf, "<features/>\n");
1594 } else {
1595 virBufferAddLit(buf, "<features>\n");
1596 virBufferAdjustIndent(buf, 2);
1597 }
1598
1599 for (i = 0; i < VIR_STORAGE_FILE_FEATURE_LAST; i++) {
1600 if (virBitmapIsBitSet(def->features, i))
1601 virBufferAsprintf(buf, "<%s/>\n",
1602 virStorageFileFeatureTypeToString(i));
1603 }
1604 if (!empty) {
1605 virBufferAdjustIndent(buf, -2);
1606 virBufferAddLit(buf, "</features>\n");
1607 }
1608 }
1609
1610 virBufferAdjustIndent(buf, -2);
1611 virBufferAsprintf(buf, "</%s>\n", type);
1612 return 0;
1613 }
1614
1615
1616 static void
virStorageVolDefFormatSourceExtents(virBuffer * buf,virStorageVolDef * def)1617 virStorageVolDefFormatSourceExtents(virBuffer *buf,
1618 virStorageVolDef *def)
1619 {
1620 size_t i;
1621 const char *thispath = NULL;
1622
1623 for (i = 0; i < def->source.nextent; i++) {
1624 if (thispath == NULL ||
1625 STRNEQ(thispath, def->source.extents[i].path)) {
1626 if (thispath != NULL)
1627 virBufferAddLit(buf, "</device>\n");
1628
1629 virBufferEscapeString(buf, "<device path='%s'>\n",
1630 def->source.extents[i].path);
1631 }
1632
1633 virBufferAdjustIndent(buf, 2);
1634 virBufferAsprintf(buf, "<extent start='%llu' end='%llu'/>\n",
1635 def->source.extents[i].start,
1636 def->source.extents[i].end);
1637 virBufferAdjustIndent(buf, -2);
1638 thispath = def->source.extents[i].path;
1639 }
1640 if (thispath != NULL)
1641 virBufferAddLit(buf, "</device>\n");
1642 }
1643
1644
1645 char *
virStorageVolDefFormat(virStoragePoolDef * pool,virStorageVolDef * def)1646 virStorageVolDefFormat(virStoragePoolDef *pool,
1647 virStorageVolDef *def)
1648 {
1649 virStorageVolOptions *options;
1650 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
1651 g_auto(virBuffer) sourceChildBuf = VIR_BUFFER_INITIALIZER;
1652
1653 options = virStorageVolOptionsForPoolType(pool->type);
1654 if (options == NULL)
1655 return NULL;
1656
1657 virBufferAsprintf(&buf, "<volume type='%s'>\n",
1658 virStorageVolTypeToString(def->type));
1659 virBufferAdjustIndent(&buf, 2);
1660
1661 virBufferEscapeString(&buf, "<name>%s</name>\n", def->name);
1662 virBufferEscapeString(&buf, "<key>%s</key>\n", def->key);
1663
1664 virBufferSetIndent(&sourceChildBuf, virBufferGetIndent(&buf) + 2);
1665
1666 if (def->source.nextent)
1667 virStorageVolDefFormatSourceExtents(&sourceChildBuf, def);
1668
1669 virXMLFormatElement(&buf, "source", NULL, &sourceChildBuf);
1670
1671 virBufferAsprintf(&buf, "<capacity unit='bytes'>%llu</capacity>\n",
1672 def->target.capacity);
1673 virBufferAsprintf(&buf, "<allocation unit='bytes'>%llu</allocation>\n",
1674 def->target.allocation);
1675 /* NB: Display only - since virStorageVolInfo is limited to just
1676 * 'capacity' and 'allocation' on output. Since we don't read this
1677 * in, be sure it was filled in before printing */
1678 if (def->target.physical)
1679 virBufferAsprintf(&buf, "<physical unit='bytes'>%llu</physical>\n",
1680 def->target.physical);
1681
1682 if (virStorageVolTargetDefFormat(options, &buf,
1683 &def->target, "target") < 0)
1684 return NULL;
1685
1686 if (virStorageSourceHasBacking(&def->target) &&
1687 virStorageVolTargetDefFormat(options, &buf,
1688 def->target.backingStore,
1689 "backingStore") < 0)
1690 return NULL;
1691
1692 virBufferAdjustIndent(&buf, -2);
1693 virBufferAddLit(&buf, "</volume>\n");
1694
1695 return virBufferContentAndReset(&buf);
1696 }
1697
1698
1699 static int
virStoragePoolSaveXML(const char * path,virStoragePoolDef * def,const char * xml)1700 virStoragePoolSaveXML(const char *path,
1701 virStoragePoolDef *def,
1702 const char *xml)
1703 {
1704 char uuidstr[VIR_UUID_STRING_BUFLEN];
1705
1706 virUUIDFormat(def->uuid, uuidstr);
1707 return virXMLSaveFile(path,
1708 virXMLPickShellSafeComment(def->name, uuidstr),
1709 "pool-edit", xml);
1710 }
1711
1712
1713 int
virStoragePoolSaveState(const char * stateFile,virStoragePoolDef * def)1714 virStoragePoolSaveState(const char *stateFile,
1715 virStoragePoolDef *def)
1716 {
1717 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
1718 g_autofree char *xml = NULL;
1719
1720 virBufferAddLit(&buf, "<poolstate>\n");
1721 virBufferAdjustIndent(&buf, 2);
1722
1723 if (virStoragePoolDefFormatBuf(&buf, def) < 0)
1724 return -1;
1725
1726 virBufferAdjustIndent(&buf, -2);
1727 virBufferAddLit(&buf, "</poolstate>\n");
1728
1729 if (!(xml = virBufferContentAndReset(&buf)))
1730 return -1;
1731
1732 if (virStoragePoolSaveXML(stateFile, def, xml))
1733 return -1;
1734
1735 return 0;
1736 }
1737
1738
1739 int
virStoragePoolSaveConfig(const char * configFile,virStoragePoolDef * def)1740 virStoragePoolSaveConfig(const char *configFile,
1741 virStoragePoolDef *def)
1742 {
1743 g_autofree char *xml = NULL;
1744
1745 if (!(xml = virStoragePoolDefFormat(def))) {
1746 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1747 _("failed to generate XML"));
1748 return -1;
1749 }
1750
1751 return virStoragePoolSaveXML(configFile, def, xml);
1752 }
1753
1754
1755 virStoragePoolSource *
virStoragePoolSourceListNewSource(virStoragePoolSourceList * list)1756 virStoragePoolSourceListNewSource(virStoragePoolSourceList *list)
1757 {
1758 virStoragePoolSource *source;
1759
1760 VIR_REALLOC_N(list->sources, list->nsources + 1);
1761
1762 source = &list->sources[list->nsources++];
1763 memset(source, 0, sizeof(*source));
1764
1765 return source;
1766 }
1767
1768
1769 char *
virStoragePoolSourceListFormat(virStoragePoolSourceList * def)1770 virStoragePoolSourceListFormat(virStoragePoolSourceList *def)
1771 {
1772 virStoragePoolOptions *options;
1773 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
1774 const char *type;
1775 size_t i;
1776
1777 options = virStoragePoolOptionsForPoolType(def->type);
1778 if (options == NULL)
1779 return NULL;
1780
1781 type = virStoragePoolTypeToString(def->type);
1782 if (!type) {
1783 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1784 _("unexpected pool type"));
1785 return NULL;
1786 }
1787
1788 virBufferAddLit(&buf, "<sources>\n");
1789 virBufferAdjustIndent(&buf, 2);
1790
1791 for (i = 0; i < def->nsources; i++)
1792 virStoragePoolSourceFormat(&buf, options, &def->sources[i]);
1793
1794 virBufferAdjustIndent(&buf, -2);
1795 virBufferAddLit(&buf, "</sources>\n");
1796
1797 return virBufferContentAndReset(&buf);
1798 }
1799
1800
1801 void
virStoragePoolSourceListFree(virStoragePoolSourceList * list)1802 virStoragePoolSourceListFree(virStoragePoolSourceList *list)
1803 {
1804 size_t i;
1805
1806 if (!list)
1807 return;
1808
1809 for (i = 0; i < list->nsources; i++)
1810 virStoragePoolSourceClear(&list->sources[i]);
1811
1812 g_free(list->sources);
1813 g_free(list);
1814 }
1815