115
122
return bool(re.search("user:%s:..x" % username, out))
124
def _check_if_pool_source(conn, path):
126
If passed path is a host disk device like /dev/sda, want to let the user
129
if not _util.is_storage_capable(conn):
132
def check_pool(poolname, path):
133
pool = conn.storagePoolLookupByName(poolname)
134
xml = pool.XMLDesc(0)
136
for element in ["dir", "device", "adapter"]:
137
xml_path = _util.get_xml_path(xml,
138
"/pool/source/%s/@path" % element)
142
running_list = conn.listStoragePools()
143
inactive_list = conn.listDefinedStoragePools()
144
for plist in [running_list, inactive_list]:
146
p = check_pool(name, path)
151
def _check_if_path_managed(conn, path):
153
Determine if we can use libvirt storage APIs to create or lookup
154
the passed path. If we can't, throw an error
160
def lookup_vol_by_path():
162
vol = conn.storageVolLookupByPath(path)
168
pool = _util.lookup_pool_by_path(conn,
169
os.path.dirname(path))
170
vol = lookup_vol_by_path()[0]
173
if pool and pool.info()[0] != libvirt.VIR_STORAGE_POOL_RUNNING:
176
# Attempt to lookup path as a storage volume
179
# Pool may need to be refreshed, but if it errors,
184
vol, verr = lookup_vol_by_path()
190
if not (vol or pool):
191
# See if path is a pool source, and allow it through
192
pool = _check_if_pool_source(conn, path)
193
path_is_pool = bool(pool)
195
if not vol and not pool:
196
if not _util.is_uri_remote(conn.getURI()):
197
# Building local disk
198
return None, None, False
201
# Since there is no error, no pool was ever found
202
err = (_("Cannot use storage '%(path)s': '%(rootdir)s' is "
203
"not managed on the remote host.") %
205
'rootdir' : os.path.dirname(path)})
207
err = (_("Cannot use storage %(path)s: %(err)s") %
208
{ 'path' : path, 'err' : verr })
210
raise ValueError(err)
212
return vol, pool, path_is_pool
214
def _build_vol_install(path, pool, size, sparse):
215
# Path wasn't a volume. See if base of path is a managed
216
# pool, and if so, setup a StorageVolume object
218
raise ValueError(_("Size must be specified for non "
219
"existent volume path '%s'" % path))
221
logging.debug("Path '%s' is target for pool '%s'. "
222
"Creating volume '%s'." %
223
(os.path.dirname(path), pool.name(),
224
os.path.basename(path)))
226
volclass = Storage.StorageVolume.get_volume_for_pool(pool_object=pool)
227
cap = (size * 1024 * 1024 * 1024)
233
volinst = volclass(name=os.path.basename(path),
234
capacity=cap, allocation=alloc, pool=pool)
238
def _lookup_vol_name(conn, name_tuple):
240
lookup volume via tuple passed via __init__'s volName parameter
242
if type(name_tuple) is not tuple or len(name_tuple) != 2 \
243
or (type(name_tuple[0]) is not type(name_tuple[1]) is not str):
244
raise ValueError(_("volName must be a tuple of the form "
245
"('poolname', 'volname')"))
248
raise ValueError(_("'volName' requires a passed connection."))
249
if not _util.is_storage_capable(conn):
250
raise ValueError(_("Connection does not support storage lookup."))
253
pool = conn.storagePoolLookupByName(name_tuple[0])
254
return pool.storageVolLookupByName(name_tuple[1])
256
raise ValueError(_("Couldn't lookup volume object: %s" % str(e)))
118
258
class VirtualDisk(VirtualDevice):
431
610
self._set_selinux_label(selinuxLabel, validate=False)
432
611
self._set_format(format, validate=False)
435
self.__lookup_vol_name(volName)
613
self.__change_storage(self.path,
437
616
self.__validate_params()
442
prints a simple string representation for the disk instance
444
return "%s:%s" %(self.type, self.path)
620
# Parameters for specifying the backing storage
448
623
def _get_path(self):
626
retpath = self.vol_object.path()
627
elif self.vol_install:
628
retpath = (_util.get_xml_path(self.vol_install.pool.XMLDesc(0),
629
"/pool/target/path") + "/" +
630
self.vol_install.name)
450
633
def _set_path(self, val, validate=True):
451
634
if val is not None:
452
635
self._check_str(val, "path")
453
636
val = os.path.abspath(val)
456
self._vol_install = None
457
self._vol_object = None
460
self.__validate_wrapper("_path", val, validate)
461
path = property(_get_path, _set_path)
639
self.__change_storage(path=val)
640
self.__validate_wrapper("_path", val, validate, self.path)
641
def _xml_get_xpath(self):
643
for prop in self._target_props:
644
xpath = "./source/@" + prop
645
if self._xml_ctx.xpathEval(xpath):
647
return "./source/@file"
648
def _xml_set_xpath(self):
649
return "./source/@" + self.disk_type_to_target_prop(self.type)
650
path = _xml_property(_get_path, _set_path,
651
xml_get_xpath=_xml_get_xpath,
652
xml_set_xpath=_xml_set_xpath,)
655
def _get_vol_object(self):
656
return self._vol_object
657
def _set_vol_object(self, val, validate=True):
658
if val is not None and not isinstance(val, libvirt.virStorageVol):
659
raise ValueError(_("vol_object must be a virStorageVol instance"))
662
self.__change_storage(vol_object=val)
663
self.__validate_wrapper("_vol_object", val, validate, self.vol_object)
664
vol_object = property(_get_vol_object, _set_vol_object)
666
def _get_vol_install(self):
667
return self._vol_install
668
def _set_vol_install(self, val, validate=True):
669
if val is not None and not isinstance(val, Storage.StorageVolume):
670
raise ValueError(_("vol_install must be a StorageVolume "
674
self.__change_storage(vol_install=val)
675
self.__validate_wrapper("_vol_install", val, validate, self.vol_install)
676
vol_install = property(_get_vol_install, _set_vol_install)
463
681
def _get_clone_path(self):
464
682
return self._clone_path
465
683
def _set_clone_path(self, val, validate=True):
473
691
# If this disk isn't managed, don't pass 'conn' to this
474
692
# validation disk, to ensure we have permissions for manual
476
conn = self.__storage_specified() and self.conn or None
694
conn = self.__managed_storage() and self.conn or None
477
695
VirtualDisk(conn=conn, path=val)
478
696
except Exception, e:
479
697
raise ValueError(_("Error validating clone path: %s") % e)
480
self.__validate_wrapper("_clone_path", val, validate)
698
self.__validate_wrapper("_clone_path", val, validate, self.clone_path)
481
699
clone_path = property(_get_clone_path, _set_clone_path)
483
701
def _get_size(self):
702
retsize = self.__existing_storage_size()
705
retsize = self.vol_install.capacity / 1024.0 / 1024.0 / 1024.0
485
710
def _set_size(self, val, validate=True):
486
711
if val is not None:
487
712
if type(val) not in [int, float, long] or val < 0:
488
raise ValueError, _("'size' must be a number greater than 0.")
489
self.__validate_wrapper("_size", val, validate)
713
raise ValueError(_("'size' must be a number greater than 0."))
715
self.__validate_wrapper("_size", val, validate, self.size)
490
716
size = property(_get_size, _set_size)
492
718
def get_type(self):
721
return self.__existing_storage_dev_type()
494
722
def set_type(self, val, validate=True):
495
723
if val is not None:
496
724
self._check_str(val, "type")
497
725
if val not in self.types:
498
raise ValueError, _("Unknown storage type '%s'" % val)
499
self.__validate_wrapper("_type", val, validate)
500
type = property(get_type, set_type)
726
raise ValueError(_("Unknown storage type '%s'" % val))
727
self.__validate_wrapper("_type", val, validate, self.type)
728
type = _xml_property(get_type, set_type,
502
731
def get_device(self):
503
732
return self._device
504
733
def set_device(self, val, validate=True):
505
734
self._check_str(val, "device")
506
735
if val not in self.devices:
507
raise ValueError, _("Unknown device type '%s'" % val)
508
self.__validate_wrapper("_device", val, validate)
509
device = property(get_device, set_device)
736
raise ValueError(_("Unknown device type '%s'" % val))
738
if val == self._device:
744
self.__validate_wrapper("_device", val, validate, self.device)
745
device = _xml_property(get_device, set_device,
511
748
def get_driver_name(self):
512
return self._driverName
513
def set_driver_name(self, val):
749
retname = self._driverName
751
retname, ignore = self.__get_default_driver()
753
def set_driver_name(self, val, validate=True):
514
755
self._driverName = val
515
driver_name = property(get_driver_name, set_driver_name)
756
driver_name = _xml_property(get_driver_name, set_driver_name,
757
xpath="./driver/@name")
517
759
def get_driver_type(self):
518
return self._driverType
519
def set_driver_type(self, val):
760
rettype = self._driverType
762
ignore, rettype = self.__get_default_driver()
764
def set_driver_type(self, val, validate=True):
520
766
self._driverType = val
521
driver_type = property(get_driver_type, set_driver_type)
767
driver_type = _xml_property(get_driver_type, set_driver_type,
768
xpath="./driver/@type")
523
770
def get_sparse(self):
524
771
return self._sparse
525
772
def set_sparse(self, val, validate=True):
526
773
self._check_bool(val, "sparse")
527
self.__validate_wrapper("_sparse", val, validate)
774
self.__validate_wrapper("_sparse", val, validate, self.sparse)
528
775
sparse = property(get_sparse, set_sparse)
530
777
def get_read_only(self):
531
778
return self._readOnly
532
779
def set_read_only(self, val, validate=True):
533
780
self._check_bool(val, "read_only")
534
self.__validate_wrapper("_readOnly", val, validate)
535
read_only = property(get_read_only, set_read_only)
537
def _get_vol_object(self):
538
return self._vol_object
539
def _set_vol_object(self, val, validate=True):
540
if val is not None and not isinstance(val, libvirt.virStorageVol):
541
raise ValueError, _("vol_object must be a virStorageVol instance")
542
self.__validate_wrapper("_vol_object", val, validate)
543
vol_object = property(_get_vol_object, _set_vol_object)
545
def _get_vol_install(self):
546
return self._vol_install
547
def _set_vol_install(self, val, validate=True):
548
if val is not None and not isinstance(val, Storage.StorageVolume):
549
raise ValueError, _("vol_install must be a StorageVolume "
551
self.__validate_wrapper("_vol_install", val, validate)
552
vol_install = property(_get_vol_install, _set_vol_install)
781
self.__validate_wrapper("_readOnly", val, validate, self.read_only)
782
read_only = _xml_property(get_read_only, set_read_only,
783
xpath="./readonly", is_bool=True)
554
785
def _get_bus(self):
556
787
def _set_bus(self, val, validate=True):
557
788
if val is not None:
558
789
self._check_str(val, "bus")
559
self.__validate_wrapper("_bus", val, validate)
560
bus = property(_get_bus, _set_bus)
790
self.__validate_wrapper("_bus", val, validate, self.bus)
791
bus = _xml_property(_get_bus, _set_bus,
792
xpath="./target/@bus")
793
def _get_target(self):
795
def _set_target(self, val, validate=True):
798
self._check_str(val, "target")
800
target = _xml_property(_get_target, _set_target,
801
xpath="./target/@dev")
562
803
def _get_shareable(self):
563
804
return self._shareable
564
805
def _set_shareable(self, val, validate=True):
565
806
self._check_bool(val, "shareable")
566
self.__validate_wrapper("_shareable", val, validate)
567
shareable = property(_get_shareable, _set_shareable)
807
self.__validate_wrapper("_shareable", val, validate, self.shareable)
808
shareable = _xml_property(_get_shareable, _set_shareable,
809
xpath="./shareable", is_bool=True)
569
811
def _get_driver_cache(self):
570
812
return self._driver_cache
572
814
if val is not None:
573
815
self._check_str(val, "cache")
574
816
if val not in self.cache_types:
575
raise ValueError, _("Unknown cache mode '%s'" % val)
576
self.__validate_wrapper("_driver_cache", val, validate)
577
driver_cache = property(_get_driver_cache, _set_driver_cache)
817
raise ValueError(_("Unknown cache mode '%s'" % val))
818
self.__validate_wrapper("_driver_cache", val, validate,
820
driver_cache = _xml_property(_get_driver_cache, _set_driver_cache,
821
xpath="./driver/@cache")
579
823
# If there is no selinux support on the libvirt connection or the
580
824
# system, we won't throw errors if this is set, just silently ignore.
581
825
def _get_selinux_label(self):
582
return self._selinux_label
826
# If selinux_label manually specified, return it
827
# If we are using existing storage, pull the label from it
828
# If we are installing via vol_install, pull from the parent pool
829
# If we are creating local storage, use the expected label
830
retlabel = self._selinux_label
833
if self.__creating_storage() and not self.__managed_storage():
834
retlabel = self._expected_security_label()
836
retlabel = self._storage_security_label()
583
839
def _set_selinux_label(self, val, validate=True):
584
840
if val is not None:
585
841
self._check_str(val, "selinux_label")
738
1045
drvname = self.DRIVER_TAP
739
1046
drvtype = self.DRIVER_TAP_VDISK
741
# User already set driverName to a different value, respect that
742
if self._driverName and self._driverName != drvname:
744
self._driverName = drvname or None
746
if self._driverType and self._driverType != drvtype:
748
self._driverType = drvtype or None
750
def __lookup_vol_name(self, name_tuple):
752
lookup volume via tuple passed via __init__'s volName parameter
754
if type(name_tuple) is not tuple or len(name_tuple) != 2 \
755
or (type(name_tuple[0]) is not type(name_tuple[1]) is not str):
756
raise ValueError(_("volName must be a tuple of the form "
757
"('poolname', 'volname')"))
759
raise ValueError(_("'volName' requires a passed connection."))
760
if not _util.is_storage_capable(self.conn):
761
raise ValueError(_("Connection does not support storage lookup."))
763
pool = self.conn.storagePoolLookupByName(name_tuple[0])
764
self._set_vol_object(pool.storageVolLookupByName(name_tuple[1]),
767
raise ValueError(_("Couldn't lookup volume object: %s" % str(e)))
769
def __storage_specified(self):
1048
return drvname or None, drvtype or None
1050
def __managed_storage(self):
771
1052
Return bool representing if managed storage parameters have
772
1053
been explicitly specified or filled in
774
return (self.vol_object != None or self.vol_install != None)
1055
return (self.vol_object != None or self.vol_install != None or
1056
self._pool_object != None)
776
1058
def __creating_storage(self):
778
1060
Return True if the user requested us to create a device
780
1062
return not (self.__no_storage() or
781
(self.__storage_specified() and self.vol_object) or
1063
(self.__managed_storage() and
1064
self.vol_object or self._pool_object) or
782
1065
(self.path and os.path.exists(self.path)))
784
1067
def __no_storage(self):
786
1069
Return True if no path or storage was specified
788
no_storage = (not self.__storage_specified() and not self.path)
790
if (self.device != self.DEVICE_FLOPPY and
791
self.device != self.DEVICE_CDROM):
792
raise ValueError(_("Device type '%s' requires a path") %
796
def __check_if_path_managed(self):
798
Determine if we can use libvirt storage apis to create or lookup
804
def lookup_vol_by_path():
806
vol = self.conn.storageVolLookupByPath(self.path)
812
pool = _util.lookup_pool_by_path(self.conn,
813
os.path.dirname(self.path))
814
vol = lookup_vol_by_path()[0]
818
if pool and pool.info()[0] != libvirt.VIR_STORAGE_POOL_RUNNING:
821
# Attempt to lookup path as a storage volume
824
# Pool may need to be refreshed, but if it errors,
829
vol, verr = lookup_vol_by_path()
836
self._set_vol_object(vol, validate=False)
840
if not self._is_remote():
841
# Building local disk
845
# Since there is no error, no pool was ever found
846
err = (_("Cannot use storage '%(path)s': '%(rootdir)s' is "
847
"not managed on the remote host.") %
848
{ 'path' : self.path,
849
'rootdir' : os.path.dirname(self.path)})
851
err = (_("Cannot use storage %(path)s: %(err)s") %
852
{ 'path' : self.path, 'err' : verr })
854
raise ValueError(err)
856
# Path wasn't a volume. See if base of path is a managed
857
# pool, and if so, setup a StorageVolume object
858
if self.size == None:
859
raise ValueError(_("Size must be specified for non "
860
"existent volume path '%s'" % self.path))
862
logging.debug("Path '%s' is target for pool '%s'. "
863
"Creating volume '%s'." %
864
(os.path.dirname(self.path), pool.name(),
865
os.path.basename(self.path)))
867
volclass = Storage.StorageVolume.get_volume_for_pool(pool_object=pool)
868
cap = (self.size * 1024 * 1024 * 1024)
874
vol = volclass(name=os.path.basename(self.path),
875
capacity=cap, allocation=alloc, pool=pool)
876
self._set_vol_install(vol, validate=False)
879
def __sync_params(self):
881
Sync some parameters between storage objects and the older
887
newpath = self.vol_object.path()
888
elif self.vol_install:
889
newpath = (_util.get_xml_path(self.vol_install.pool.XMLDesc(0),
890
"/pool/target/path") + "/" +
891
self.vol_install.name)
893
if newpath and newpath != self.path:
894
logging.debug("Overwriting 'path' with value from StorageVolume"
896
self._set_path(newpath, validate=False)
899
newsize = self.vol_install.capacity/1024.0/1024.0/1024.0
900
if self.size != newsize:
901
logging.debug("Overwriting 'size' with value from "
902
"StorageVolume object")
903
self._set_size(newsize, validate=False)
1071
return (not self.__managed_storage() and not self.path)
905
1074
def _storage_security_label(self):
934
1106
if not self._validate:
1109
# No storage specified for a removable device type (CDROM, floppy)
937
1110
if self.__no_storage():
938
# No storage specified for a removable device type (CDROM, floppy)
939
self._type = self.TYPE_BLOCK
1111
if (self.device != self.DEVICE_FLOPPY and
1112
self.device != self.DEVICE_CDROM):
1113
raise ValueError(_("Device type '%s' requires a path") %
942
1118
storage_capable = bool(self.conn and
943
1119
_util.is_storage_capable(self.conn))
945
if storage_capable and not self.__storage_specified():
946
# Try to lookup self.path storage objects
947
self.__check_if_path_managed()
949
1121
if self._is_remote():
950
1122
if not storage_capable:
951
raise ValueError, _("Connection doesn't support remote "
953
if not self.__storage_specified():
954
raise ValueError, _("Must specify libvirt managed storage "
955
"if on a remote connection")
957
# Sync parameters between VirtualDisk and storage objects.
1123
raise ValueError(_("Connection doesn't support remote "
1125
if not self.__managed_storage():
1126
raise ValueError(_("Must specify libvirt managed storage "
1127
"if on a remote connection"))
960
1129
# The main distinctions from this point forward:
961
1130
# - Are we doing storage API operations or local media checks?
962
1131
# - Do we need to create the storage?
964
managed_storage = self.__storage_specified()
1133
managed_storage = self.__managed_storage()
965
1134
create_media = self.__creating_storage()
967
self.__set_dev_type()
969
1136
self.__set_format()
972
if not self.selinux_label:
973
# If we are using existing storage, pull the label from it
974
# If we are installing via vol_install, pull from the parent pool
975
# If we are creating local storage, use the expected label
978
if create_media and not managed_storage:
979
context = self._expected_security_label()
981
context = self._storage_security_label()
983
self._selinux_label = context or ""
985
1138
# If not creating the storage, our job is easy
986
1139
if not create_media: