def __init__(self, name, search_name=None, search_type=None): super(TargetDiscovery, self).__init__(name) self.dry_run = False self.eng = InstallEngine.get_instance() self.doc = self.eng.data_object_cache # create a root node to insert all discovered objects into self.root = Target(Target.DISCOVERED) # user specified search criteria self.search_name = search_name self.search_type = search_type # list of discovered swap and dump zvols self.swap_list = list() self.dump_list = list() # eeprom diag mode and bootdisk value self.sparc_diag_mode = False self.bootdisk = None # kernel architecture self.arch = platform.processor()
class CreateSimpleDataObjectCache(): '''A class that creates a simple data object''' def __init__(self, test_target=None): '''Initialize the class Parameters: -test_target - this arg is supplies the test directory ''' self.test_target = test_target self.engine = get_new_engine_instance() self.doc = self.engine.data_object_cache # Create the doc for finding the BE. self.desired_root = Target(Target.DESIRED) self.doc.persistent.insert_children(self.desired_root) self.logical = Logical(DEFAULT_LOGICAL_NAME) self.desired_root.insert_children(self.logical) self.zpool = Zpool(DEFAULT_ZPOOL_NAME) self.zpool.is_root = "true" self.logical.insert_children(self.zpool) self.vdev = Vdev(DEFAULT_VDEV_NAME) self.vdev.redundancy = "none" self.zpool.insert_children(self.vdev) self.be_obj = BE() self.zpool.insert_children(self.be_obj) self.be_obj.mountpoint = self.test_target
def setUp(self): # instantiate the engine self.eng = engine_test_utils.get_new_engine_instance() self.doc = self.eng.data_object_cache # create a Target DataObjects for later insertion self.target = Target("target") self.logical = Logical("logical") self.target.insert_children(self.logical)
def setUp(self): self.engine = engine_test_utils.get_new_engine_instance() self.doc = self.engine.data_object_cache.volatile # create DOC objects self.target = Target(Target.DESIRED) self.doc.insert_children(self.target) self.logical = Logical("logical")
class TestBE(unittest.TestCase): def setUp(self): self.engine = engine_test_utils.get_new_engine_instance() self.doc = self.engine.data_object_cache.volatile # create DOC objects self.target = Target(Target.DESIRED) self.doc.insert_children(self.target) self.logical = Logical("logical") def tearDown(self): self.target.delete_children() self.target.delete() engine_test_utils.reset_engine() def test_one_be_create(self): zpool = Zpool("test_zpool") zpool.action = "preserve" be1 = BE("be1") zpool.insert_children(be1) self.logical.insert_children(zpool) self.target.insert_children(self.logical) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_two_be_create(self): zpool = Zpool("test_zpool") zpool.action = "preserve" be1 = BE("be1") be2 = BE("be2") zpool.insert_children([be1, be2]) self.logical.insert_children(zpool) self.target.insert_children(self.logical) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_default_be_create(self): zpool = Zpool("test_zpool") zpool.action = "preserve" be1 = BE() zpool.insert_children(be1) self.logical.insert_children(zpool) self.target.insert_children(self.logical) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err))
class TestBE(unittest.TestCase): def setUp(self): self.engine = engine_test_utils.get_new_engine_instance() self.doc = self.engine.data_object_cache.volatile # create DOC objects self.target = Target(Target.DESIRED) self.doc.insert_children(self.target) self.logical = Logical("logical") def tearDown(self): self.target.delete_children() self.target.delete() engine_test_utils.reset_engine() def test_one_be_create(self): zpool = Zpool("test_zpool") zpool.action = "preserve" be1 = BE("be1") zpool.insert_children(be1) self.logical.insert_children(zpool) self.target.insert_children(self.logical) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_two_be_create(self): zpool = Zpool("test_zpool") zpool.action = "preserve" be1 = BE("be1") be2 = BE("be2") zpool.insert_children([be1, be2]) self.logical.insert_children(zpool) self.target.insert_children(self.logical) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_default_be_create(self): zpool = Zpool("test_zpool") zpool.action = "preserve" be1 = BE() zpool.insert_children(be1) self.logical.insert_children(zpool) self.target.insert_children(self.logical) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err))
def setUp(self): self.engine = engine_test_utils.get_new_engine_instance() self.doc = self.engine.data_object_cache.volatile # list of created files for zpool vdev usage self.file_list = [] # list of created zpools self.zpool_list = [] # create the basic DOC structure self.target = Target(Target.DESIRED) self.logical = Logical("logical") self.target.insert_children(self.logical) self.doc.insert_children(self.target)
def setUp(self): self.engine = engine_test_utils.get_new_engine_instance() self.doc = self.engine.data_object_cache.volatile # create some DOC objects self.target = Target(Target.DESIRED) self.doc.insert_children(self.target) self.disk = Disk("disk") self.disk.ctd = "c8t1d0" self.disk.disk_prop = DiskProp() self.disk.disk_prop.dev_size = Size(str(200) + Size.gb_units) self.disk.disk_prop.blocksize = BLOCKSIZE self.disk.disk_prop.cylsize = CYLSIZE self.disk.disk_geometry = DiskGeometry() self.target.insert_children(self.disk)
def setUp(self): self.engine = engine_test_utils.get_new_engine_instance() self.doc = self.engine.data_object_cache.volatile # create DOC objects self.target = Target(Target.DESIRED) self.doc.insert_children(self.target) self.logical = Logical("logical")
def setUp(self): # instantiate the engine self.eng = engine_test_utils.get_new_engine_instance() self.doc = self.eng.data_object_cache # create a Target DataObjects for later insertion self.target = Target("target") self.logical = Logical("logical") self.target.insert_children(self.logical)
def setUp(self): self.engine = engine_test_utils.get_new_engine_instance() self.doc = self.engine.data_object_cache.volatile # create DOC objects self.target = Target(Target.DESIRED) self.doc.insert_children(self.target) self.logical = Logical("logical") self.disk1 = Disk("disk") self.disk1.ctd = "c8t1d0" self.disk1.disk_prop = DiskProp() self.disk1.disk_prop.blocksize = 512 self.disk2 = Disk("disk2") self.disk2.ctd = "c8t2d0" self.disk2.disk_prop = DiskProp() self.disk2.disk_prop.blocksize = 512
def __init__(self, methodName="runTest"): unittest.TestCase.__init__(self, methodName) # extract drive informtion to construct a bare-bones DOC object dmd = diskmgt.descriptor_from_key(ALIAS, MASTER_CTD) alias = diskmgt.DMAlias(dmd.value) drive = alias.drive dma = drive.media.attributes if dma.ncylinders is None: raise RuntimeError("Unable to process disk label. Please " + "place a VTOC label on the disk.") # get the maximum size of the disk fd = os.open("/dev/rdsk/" + MASTER_CTD + "s2", os.O_RDONLY | os.O_NDELAY) try: media_info = drive.DKMinfo() fcntl.ioctl(fd, diskmgt.DKIOCGMEDIAINFO, C.addressof(media_info)) except IOError as error: print 'ioctl failed: ', str(error) raise finally: os.close(fd) # set the basic geometry self.disk = Disk(MASTER_CTD) self.disk.ctd = MASTER_CTD self.disk.disk_prop = DiskProp() self.disk.disk_prop.dev_size = Size( str(media_info.dki_capacity) + Size.sector_units) self.disk_size = self.disk.disk_prop.dev_size.sectors self.disk.geometry = DiskGeometry(dma.blocksize, dma.nheads * dma.nsectors) self.disk.geometry.ncyl = dma.ncylinders self.disk.geometry.nhead = dma.nheads self.disk.geometry.nsectors = dma.nsectors self.target = Target(Target.DESIRED) self.target.insert_children(self.disk)
def setUp(self): self.engine = engine_test_utils.get_new_engine_instance() self.doc = self.engine.data_object_cache.volatile # create some DOC objects self.target = Target(Target.DESIRED) self.doc.insert_children(self.target) self.disk = Disk("disk") self.disk.ctd = "c8t1d0" self.disk.disk_prop = DiskProp() self.disk.disk_prop.dev_size = Size(str(200) + Size.gb_units) self.disk.disk_prop.blocksize = BLOCKSIZE self.disk.disk_prop.cylsize = CYLSIZE self.disk.disk_geometry = DiskGeometry() self.target.insert_children(self.disk)
def setUp(self): self.engine = engine_test_utils.get_new_engine_instance() self.doc = self.engine.data_object_cache.volatile # create DOC objects self.target = Target(Target.DESIRED) self.doc.insert_children(self.target) self.logical = Logical("logical") self.disk1 = Disk("disk") self.disk1.ctd = "c8t1d0" self.disk1.disk_prop = DiskProp() self.disk1.disk_prop.blocksize = 512 self.disk2 = Disk("disk2") self.disk2.ctd = "c8t2d0" self.disk2.disk_prop = DiskProp() self.disk2.disk_prop.blocksize = 512
def __init__(self, methodName="runTest"): unittest.TestCase.__init__(self, methodName) # extract drive informtion to construct a bare-bones DOC object dmd = diskmgt.descriptor_from_key(ALIAS, MASTER_CTD) alias = diskmgt.DMAlias(dmd.value) drive = alias.drive dma = drive.media.attributes if dma.ncylinders is None: raise RuntimeError("Unable to process disk label. Please " + "place a VTOC label on the disk.") # get the maximum size of the disk fd = os.open("/dev/rdsk/" + MASTER_CTD + "s2", os.O_RDONLY|os.O_NDELAY) try: media_info = drive.DKMinfo() fcntl.ioctl(fd, diskmgt.DKIOCGMEDIAINFO, C.addressof(media_info)) except IOError as error: print 'ioctl failed: ', str(error) raise finally: os.close(fd) # set the basic geometry self.disk = Disk(MASTER_CTD) self.disk.ctd = MASTER_CTD self.disk.disk_prop = DiskProp() self.disk.disk_prop.dev_size = Size(str(media_info.dki_capacity) + Size.sector_units) self.disk_size = self.disk.disk_prop.dev_size.sectors self.disk.geometry = DiskGeometry(dma.blocksize, dma.nheads * dma.nsectors) self.disk.geometry.ncyl = dma.ncylinders self.disk.geometry.nhead = dma.nheads self.disk.geometry.nsectors = dma.nsectors self.target = Target(Target.DESIRED) self.target.insert_children(self.disk)
class TestZpool(unittest.TestCase): def setUp(self): self.engine = engine_test_utils.get_new_engine_instance() self.doc = self.engine.data_object_cache.volatile # create DOC objects self.target = Target(Target.DESIRED) self.doc.insert_children(self.target) self.logical = Logical("logical") self.disk1 = Disk("disk") self.disk1.ctd = "c8t1d0" self.disk1.disk_prop = DiskProp() self.disk1.disk_prop.blocksize = 512 self.disk2 = Disk("disk2") self.disk2.ctd = "c8t2d0" self.disk2.disk_prop = DiskProp() self.disk2.disk_prop.blocksize = 512 def tearDown(self): self.target.delete_children() self.target.delete() engine_test_utils.reset_engine() def test_one_disk_zpool_create(self): self.disk1.in_zpool = "test_zpool" zpool = Zpool("test_zpool") zpool.action = "create" self.logical.insert_children(zpool) self.target.insert_children([self.disk1, self.logical]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_two_disk_zpool_create(self): self.disk1.in_zpool = "test_zpool" self.disk2.in_zpool = "test_zpool" zpool = Zpool("test_zpool") zpool.action = "create" self.logical.insert_children(zpool) self.target.insert_children([self.disk1, self.disk2, self.logical]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_whole_disk_zpool_create(self): self.disk1.in_zpool = "test_zpool" self.disk1.whole_disk = True self.disk2.in_zpool = "test_zpool" self.disk2.whole_disk = True zpool = Zpool("test_zpool") zpool.action = "create" self.logical.insert_children(zpool) self.target.insert_children([self.disk1, self.disk2, self.logical]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_empty_zpool_delete(self): zpool = Zpool("test_zpool") zpool.action = "delete" self.logical.insert_children(zpool) self.target.insert_children(self.logical) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_full_zpool_delete(self): zpool = Zpool("test_zpool") zpool.action = "delete" fs1 = Filesystem("test_zpool/fs1") fs2 = Filesystem("test_zpool/fs2") fs3 = Filesystem("test_zpool/fs3") zpool.insert_children([fs1, fs2, fs3]) self.logical.insert_children(zpool) self.target.insert_children(self.logical) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_empty_zpool_preserve(self): zpool = Zpool("test_zpool") zpool.action = "preserve" self.logical.insert_children(zpool) self.target.insert_children(self.logical) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_full_zpool_preserve(self): zpool = Zpool("test_zpool") zpool.action = "preserve" fs1 = Filesystem("test_zpool/fs1") fs2 = Filesystem("test_zpool/fs2") fs3 = Filesystem("test_zpool/fs3") zpool.insert_children([fs1, fs2, fs3]) self.logical.insert_children(zpool) self.target.insert_children(self.logical) self.doc.insert_children(self.target) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_filesystem_create(self): zpool = Zpool("test_zpool") zpool.action = "preserve" fs1 = Filesystem("test_zpool/fs1") fs1.action = "create" fs2 = Filesystem("test_zpool/fs2") fs2.action = "create" fs3 = Filesystem("test_zpool/fs3") fs3.action = "create" zpool.insert_children([fs1, fs2, fs3]) self.logical.insert_children(zpool) self.target.insert_children(self.logical) self.doc.insert_children(self.target) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_filesystem_create_and_delete(self): zpool = Zpool("test_zpool") zpool.action = "preserve" fs1 = Filesystem("test_zpool/fs1") fs1.action = "create" fs2 = Filesystem("test_zpool/fs2") fs2.action = "delete" fs3 = Filesystem("test_zpool/fs3") fs3.action = "create" zpool.insert_children([fs1, fs2, fs3]) self.logical.insert_children(zpool) self.target.insert_children(self.logical) self.doc.insert_children(self.target) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_zvol_create(self): zpool = Zpool("test_zpool") zpool.action = "preserve" fs1 = Filesystem("test_zpool/swap") fs1.action = "create" fs2 = Filesystem("test_zpool/dump") fs2.action = "create" zpool.insert_children([fs1, fs2]) self.logical.insert_children(zpool) self.target.insert_children(self.logical) self.doc.insert_children(self.target) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_zvol_create_and_delete(self): zpool = Zpool("test_zpool") zpool.action = "preserve" fs1 = Filesystem("test_zpool/swap") fs1.action = "delete" fs2 = Filesystem("test_zpool/dump") fs2.action = "create" zpool.insert_children([fs1, fs2]) self.logical.insert_children(zpool) self.target.insert_children(self.logical) self.doc.insert_children(self.target) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_full_zpool_create(self): zpool = Zpool("test_zpool") zpool.action = "create" fs1 = Filesystem("test_zpool/swap") fs1.action = "create" fs2 = Filesystem("test_zpool/dump") fs2.action = "create" zpool.insert_children([fs1, fs2]) self.logical.insert_children(zpool) self.target.insert_children(self.logical) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_pool_and_dataset_options(self): zpool = Zpool("test_zpool") zpool.action = "preserve" fs1 = Filesystem("test_zpool/fs1") fs1.action = "create" fs2 = Filesystem("test_zpool/fs2") fs2.action = "create" fs3 = Filesystem("test_zpool/fs3") fs3.action = "create" pool_options = PoolOptions("pool options", dict()) fs_options = DatasetOptions("fs options", dict()) pool_options.data_dict["autoexpand"] = "off" fs_options.data_dict["atime"] = "on" zpool.insert_children([fs1, fs2, fs3, pool_options, fs_options]) self.logical.insert_children(zpool) self.target.insert_children(self.logical) self.doc.insert_children(self.target) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_two_disk_vdev_create(self): self.disk1.in_zpool = "test_zpool" self.disk1.in_vdev = "test_mirror" self.disk2.in_zpool = "test_zpool" self.disk2.in_vdev = "test_mirror" zpool = Zpool("test_zpool") zpool.action = "create" vdev = Vdev("test_mirror") vdev.redundancy = "mirror" zpool.insert_children(vdev) self.logical.insert_children(zpool) self.target.insert_children([self.disk1, self.disk2, self.logical]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_multi_disk_multi_vdev_create(self): self.disk1.in_zpool = "test_zpool" self.disk1.in_vdev = "test_mirror" self.disk2.in_zpool = "test_zpool" self.disk2.in_vdev = "test_mirror" self.disk3 = Disk("disk3") self.disk3.ctd = "c8t3d0" self.disk3.in_zpool = "test_zpool" self.disk3.in_vdev = "test_raidz" self.disk4 = Disk("disk4") self.disk4.ctd = "c8t4d0" self.disk4.in_zpool = "test_zpool" self.disk4.in_vdev = "test_raidz" self.disk5 = Disk("disk5") self.disk5.ctd = "c8t5d0" self.disk5.in_zpool = "test_zpool" self.disk5.in_vdev = "test_raidz" self.disk6 = Disk("disk6") self.disk6.ctd = "c8t6d0" self.disk6.in_zpool = "test_zpool" self.disk6.in_vdev = "test_spare" self.disk7 = Disk("disk7") self.disk7.ctd = "c8t7d0" self.disk7.in_zpool = "test_zpool" self.disk7.in_vdev = "test_log" zpool1 = Zpool("test_zpool") zpool1.action = "create" vdev1 = Vdev("test_mirror") vdev1.redundancy = "mirror" vdev2 = Vdev("test_raidz") vdev2.redundancy = "raidz" vdev3 = Vdev("test_log") vdev3.redundancy = "log" vdev4 = Vdev("test_spare") vdev4.redundancy = "spare" zpool1.insert_children([vdev1, vdev2, vdev3, vdev4]) self.logical.insert_children(zpool1) self.target.insert_children([self.disk1, self.disk2, self.disk3, \ self.disk4, self.disk5, self.disk6, self.disk7, self.logical]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err))
class TestValidateTarget(unittest.TestCase): """ test case for testing the validate_target function """ def setUp(self): # instantiate the engine self.eng = engine_test_utils.get_new_engine_instance() self.doc = self.eng.data_object_cache # create a Target DataObjects for later insertion self.target = Target("target") self.logical = Logical("logical") self.target.insert_children(self.logical) def tearDown(self): engine_test_utils.reset_engine() def test_two_filesystems(self): """ test to make sure two Filesystem objects correctly errors """ # create a basic zpool object zpool = Zpool("rpool") zpool.action = "use_existing" # create two filesystem objects fs1 = Filesystem("rpool/test1") fs2 = Filesystem("rpool/test2") # create the DOC structure self.logical.insert_children(zpool) zpool.insert_children([fs1, fs2]) self.doc.volatile.insert_children(self.target) self.assertRaises(RuntimeError, dc.validate_target) def test_delete_filesystem(self): """ test to make sure the delete action correctly errors """ # create a basic zpool object zpool = Zpool("rpool") zpool.action = "use_existing" # create one filesystem object with an action of delete fs = Filesystem("rpool/test1") fs.action = "delete" # create the DOC structure self.logical.insert_children(zpool) zpool.insert_children(fs) self.doc.volatile.insert_children(self.target) self.assertRaises(RuntimeError, dc.validate_target) def test_two_zpools(self): """ test to make sure two Zpool objects correctly errors """ # create two zpool objects zpool1 = Zpool("rpool") zpool1.action = "use_existing" zpool2 = Zpool("rpool-two") zpool2.action = "use_existing" # create one filesystem object fs1 = Filesystem("rpool/test1") # create the DOC structure self.logical.insert_children([zpool1, zpool2]) zpool1.insert_children(fs1) self.doc.volatile.insert_children(self.target) self.assertRaises(RuntimeError, dc.validate_target) def test_delete_zpool(self): """ test to make sure the delete action for zpools correctly errors """ # create a basic zpool object with an action of delete zpool = Zpool("rpool") zpool.action = "delete" # create one filesystem object fs = Filesystem("rpool/test1") # create the DOC structure self.logical.insert_children(zpool) zpool.insert_children(fs) self.doc.volatile.insert_children(self.target) self.assertRaises(RuntimeError, dc.validate_target) def test_create_pool(self): """ test to make sure the create action on a zpool correctly errors """ # create a basic zpool object with an action of create zpool = Zpool("rpool") zpool.action = "create" # create one filesystem object fs = Filesystem("rpool/test1") # create the DOC structure self.logical.insert_children(zpool) zpool.insert_children(fs) self.doc.volatile.insert_children(self.target) self.assertRaises(RuntimeError, dc.validate_target) def test_no_pool(self): """ test to make sure validate target fails if no pool is specified """ self.doc.volatile.insert_children(self.target) self.assertRaises(RuntimeError, dc.validate_target) def test_no_filesystem(self): """ test to make sure validate target fails if no filesystem is specified. """ # create a basic zpool object zpool = Zpool("rpool") zpool.action = "use_existing" # create the DOC structure self.logical.insert_children(zpool) self.doc.volatile.insert_children(self.target) self.assertRaises(RuntimeError, dc.validate_target)
def select_zone_targets(self, from_manifest): '''Logic to select the targets for a zone. Given the alternate pool dataset, and the targets from the manifest, make the selections. If no suitable selection can be made, then the SelectionError exception will be raised. This should only be the cause if the selected alternate pool dataset does not exist. Returns a new set of Targets that can be insterted into the Data Object Cache for TargetInstantiationZone to use. ''' # The selected alternate pool dataset must be set if self.selected_dataset is None: raise SelectionError("No dataset selected as alternate pool " "dataset.") # Verify selected dataset exists fs = Filesystem(self.selected_dataset) if not fs.exists: raise SelectionError("Dataset (%s) does not exist." % \ self.selected_dataset) if from_manifest: self.logger.debug("from_manifest =\n%s\n" % \ (str(from_manifest[0]))) else: self.logger.debug("from_manifest is empty\n") # Instantiate desired target, logical, and zpool objects. target = Target(Target.DESIRED) logical = Logical(DEFAULT_LOGICAL_NAME) logical.noswap = True logical.nodump = True zpool = logical.add_zpool(self.selected_dataset, is_root=True) for manifest_target in from_manifest: # Copy filesystem children into desired zpool for fs in manifest_target.get_descendants(class_type=Filesystem): zpool.insert_children(copy.deepcopy(fs)) # Copy BE children into desired zpool for be in manifest_target.get_descendants(class_type=BE): zpool.insert_children(copy.deepcopy(be)) # Check if we have a BE object under zpool. # If not, create one. be_list = zpool.get_children(class_type=BE) if not be_list: # Instantiate new BE object and insert it into zpool. be = BE() zpool.insert_children(be) else: # Zpool will have only one BE object. be = be_list[0] # Set BE's mountpoint to the mountpoint we need # to mount it at to do the installation. be.mountpoint = self.be_mountpoint # Insert desired logical object into the desired target object. target.insert_children(logical) # Insert desired target object into the DOC. self.doc.persistent.insert_children(target)
class TargetDiscovery(Checkpoint): """ Discover all logical and physical devices on the system. """ def __init__(self, name, search_name=None, search_type=None): super(TargetDiscovery, self).__init__(name) self.dry_run = False self.eng = InstallEngine.get_instance() self.doc = self.eng.data_object_cache # create a root node to insert all discovered objects into self.root = Target(Target.DISCOVERED) # user specified search criteria self.search_name = search_name self.search_type = search_type # list of discovered swap and dump zvols self.swap_list = list() self.dump_list = list() # eeprom diag mode and bootdisk value self.sparc_diag_mode = False self.bootdisk = None # kernel architecture self.arch = platform.processor() # croinfo dictionary self.cro_dict = dict() def is_bootdisk(self, name): """ is_bootdisk() -- simple method to compare the name of the disk in question with what libdevinfo reports as the bootdisk name - ctd name of the disk to check """ # cache the answer so we don't do multiple lookups to libdevinfo if self.bootdisk is None: self.bootdisk = devinfo.get_curr_bootdisk() return self.bootdisk == name def get_progress_estimate(self): # XXX return 1 def discover_disk(self, drive): """ discover_disk - method to discover a physical disk's attributes, partitions and slices drive - which physical drive to parse """ # create a DOC object for this drive. Set validate_children to False # so the shadow code doesn't adjust the start sector or size for any # children discovered new_disk = Disk("disk", validate_children=False) # extract drive attributes and media information drive_attributes = drive.attributes drive_media = drive.media if drive_media is None: # since the drive has no media, we can't determine any attributes # about it (geometry, slices, partitions, etc.) so simply return # None self.logger.debug("disk '%s' has no media" % drive.name) return None # if a drive is offline or down return None if drive_attributes.status == "DOWN": self.logger.debug("disk '%s' is offline" % drive.name) return None # set the wwn string, including lun if available wwn = getattr(drive.aliases[0].attributes, "wwn", None) if wwn is not None: lun = getattr(drive.aliases[0].attributes, "lun", None) if lun is not None: new_disk.wwn = "%s,%d" % (wwn, lun) else: new_disk.wwn = wwn for alias in drive.aliases: if self.verify_disk_read(alias.name, drive_media.attributes.blocksize): new_disk.active_ctds.append(alias.name) else: new_disk.passive_ctds.append(alias.name) # if only passive_ctds are found, return None if new_disk.passive_ctds and not new_disk.active_ctds: self.logger.debug("disk '%s' only has passive aliases" % drive.name) return None # set the new_disk ctd string if new_disk.wwn is None: # use the only alias name new_disk.ctd = drive.aliases[0].name else: # use the first active ctd new_disk.ctd = new_disk.active_ctds[0] new_disk.devid = drive.name new_disk.iscdrom = drive.cdrom new_disk.opath = drive_attributes.opath # set the devpath if os.path.islink(drive_attributes.opath): link = os.readlink(drive_attributes.opath) # clean up the link to get rid of the leading '../../devices/' and # trailing minor name if link.startswith("../../devices") and ":" in link: link = link.partition("../../devices")[2].rpartition(":")[0] new_disk.devpath = link # check for SPARC eeprom settings which would interfere with finding # the boot disk if self.arch == "sparc": if not self.sparc_diag_mode: # check eeprom settings cmd = [EEPROM, "diag-switch?"] p = run(cmd) diag_switch_value = p.stdout.partition("=")[2] if diag_switch_value.strip().lower() == "true": # set a variable so we don't check every single disk and # log a message self.sparc_diag_mode = True self.logger.info("Unable to determine bootdisk with " + \ "diag-switch? eeprom setting set to " + \ "'true'. Please set diag-switch? " + \ "to false and reboot the system") # check for the bootdisk if not self.sparc_diag_mode: if self.is_bootdisk(new_disk.ctd): new_disk.disk_keyword = DiskKeyword() # set vendor information for the drive new_disk.disk_prop = DiskProp() if drive.controllers: new_disk.disk_prop.dev_type = drive.controllers[0].attributes.type # check for any Iscsi object in the DOC. If found, change the # dev_type from 'scsi' to 'iSCSI' to allow the installers finer # granularity when choosing these types of LUNs iscsi_check = self.doc.get_descendants(class_type=Iscsi) if iscsi_check: cmd = [ISCSIADM, "list", "target", "-S"] p = run(cmd) if new_disk.ctd in p.stdout: new_disk.disk_prop.dev_type = "iSCSI" new_disk.disk_prop.dev_vendor = drive_attributes.vendor_id # set the alias and receptacle for disks, if possible if not new_disk.iscdrom and new_disk.ctd in self.cro_dict: new_disk.disk_prop.dev_chassis = self.cro_dict[new_disk.ctd][1] new_disk.receptacle = self.cro_dict[new_disk.ctd][2] # store the media attributes locally so libdiskmgt doesn't have to keep # looking them up drive_media_attributes = drive_media.attributes # retrieve the drive's geometry new_disk = self.set_geometry(drive_media_attributes, new_disk) # keep a list of slices already visited so they're not discovered # again later visited_slices = [] # if this system is x86 and the drive reports *VTOC* slices but no # fdisk partitions, don't report any of the slices. This probably # means there is no label at all on the disk: # On x86 libdiskmgmt will report slices, but no partitions # when the disk has no partition table/label at all. if self.arch == "i386" \ and drive_media.slices \ and not drive_media.partitions \ and new_disk.label != "GPT": # Unset the erroneous disk label new_disk._label = None return new_disk if new_disk.label == "VTOC": for partition in drive_media.partitions: new_partition = self.discover_partition( partition, drive_media_attributes.blocksize) # add the partition to the disk object new_disk.insert_children(new_partition) # check for slices associated with this partition # if found, add them as children for slc in partition.media.slices: # discover the slice new_slice = self.discover_slice( slc, drive_media_attributes.blocksize) # constrain when a slice is added to the DOC. # We only want to add a slice when the partition id # is a Solaris partition (non EFI) if new_partition.is_solaris: new_partition.insert_children(new_slice) # keep a record this slice so it's not discovered again visited_slices.append(slc.name) for slc in drive_media.slices: # discover the slice if it's not already been found if slc.name not in visited_slices: new_slice = self.discover_slice( slc, drive_media_attributes.blocksize) new_disk.insert_children(new_slice) # If the disk has a GPT label then the protective MBR # reported by libdiskmgt should be ignored. The GPT partitions # are reported by libdiskmgt as "slices", similar to VTOC slices elif new_disk.label == "GPT": # EFI/GPT label on disc. Discover GPT partitions. # libdiskmgt's information about GPT partitions is incomplete # so use libefi to fill in what is missing. fh = os.open(new_disk.opath, os.O_RDONLY | os.O_NDELAY) try: gptp = efi_read(fh) try: for slc in drive_media.slices: efi_part = gptp.contents.efi_parts[ slc.attributes.index] new_gpart = self.discover_gptpartition( slc, drive_media_attributes.blocksize, efi_part) new_disk.insert_children(new_gpart) finally: efi_free(gptp) finally: os.close(fh) return new_disk def verify_disk_read(self, ctd, blocksize): """ verify_disk_read() - method to verify a low-level read from the raw ctd path. """ raw = "/dev/rdsk/%s" % ctd raw2 = raw + "s2" # Depending on the label used, we need to check both the raw device and # slice 2 to see if the disk can be read. for raw_disk in [raw, raw2]: fd = None try: try: fd = os.open(raw_disk, os.O_RDONLY | os.O_NDELAY) try: _none = os.read(fd, blocksize) except OSError: # the read() call failed continue else: return True except OSError: # the open() call failed continue finally: if fd is not None: os.close(fd) return False def set_geometry(self, dma, new_disk): """ set_geometry() - method to set the geometry of the Disk DOC object from the libdiskmgt drive object. dma - the drive's media attributes as returned by libdiskmgt new_disk - Disk DOC object """ new_geometry = None # If the disk has a GPT label (or no label), ncylinders will be # None if dma.ncylinders is None: # XXX - libdiskmgt calculation of DM_NACCESSIBLE for GPT disks # is broken, so we use DM_SIZE since we can access all blocks on # the disk anyway because we don't need to worry about VTOC # imposed cylinder alignment on disk size. # Bugster CR: 7099417 new_disk.disk_prop.dev_size = Size( str(dma.size) + Size.sector_units, dma.blocksize) # set only the blocksize (not the cylinder size) new_geometry = DiskGeometry(dma.blocksize, None) # set the label of the disk, if possible if dma.efi: new_disk.label = "GPT" new_geometry.efi = True else: new_disk.label = "VTOC" # set the disk's volid new_disk.volid = dma.label ncyl = dma.ncylinders nhead = dma.nheads nsect = dma.nsectors new_disk.disk_prop.dev_size = Size( str(dma.naccessible) + Size.sector_units, dma.blocksize) new_geometry = DiskGeometry(dma.blocksize, nhead * nsect) new_geometry.ncyl = ncyl new_geometry.nheads = nhead new_geometry.nsectors = nsect new_disk.geometry = new_geometry return new_disk def discover_pseudo(self, controller): """ discover_psuedo - method to discover pseudo controller information, usually zvol swap and dump """ for drive in controller.drives: for slc in drive.media.slices: stats = slc.use_stats if "used_by" in stats: if stats["used_name"][0] == "dump": if slc.name.startswith(ZVOL_PATH): # remove the /dev/zvol/dsk from the path self.dump_list.append(slc.name[14:]) if stats["used_name"][0] == "swap": if slc.name.startswith(ZVOL_PATH): # remove the /dev/zvol/dsk from the path self.swap_list.append(slc.name[14:]) def discover_partition(self, partition, blocksize): """ discover_partition - method to discover a physical disk's partition layout partition - partition object as discovered by ldm blocksize - blocksize of the disk """ # store the attributes locally so libdiskmgt doesn't have to keep # looking them up partition_attributes = partition.attributes # partition name is ctdp path. Split the string on "p" root_path, _none, index = partition.name.partition("p") # create a DOC object for this partition. Set validate_children to # False so the shadow code doesn't adjust the start sector or size for # any children discovered new_partition = Partition(index, validate_children=False) new_partition.action = "preserve" new_partition.part_type = partition_attributes.id # check the partition's ID to set the partition type correctly if partition_attributes.id == \ Partition.name_to_num("Solaris/Linux swap"): try: # try to call prtvtoc on slice 2. If it succeeds, this is a # solaris1 partition. slice2 = root_path + "s2" cmd = [PRTVTOC, slice2] run(cmd, stdout=Popen.DEVNULL) except CalledProcessError: # the call to prtvtoc failed which means this partition is # Linux swap. To be sure, prtvtoc failure might also mean an # unlabeled Solaris1 partition but we aren't going to worry # about that for now. Displaying an unlabeled (and therefore # unused) Solaris1 partition should not have any unforeseen # consequences in terms of data loss. new_partition.is_linux_swap = True new_partition.size = Size(str(partition_attributes.nsectors) + \ Size.sector_units, blocksize=blocksize) new_partition.start_sector = long(partition_attributes.relsect) new_partition.size_in_sectors = partition_attributes.nsectors # If the partition is an EFI system partition check to see if it # is PCFS formatted. We only do this on EFI system partitions to save # time since mounting can be slow. if new_partition.is_efi_system: ctdp = partition.name.rsplit('/', 1)[-1] new_partition._is_pcfs_formatted = self.is_pcfs_formatted(ctdp) return new_partition def discover_gptpartition(self, partition, blocksize, efipart): """ discover_gptpartition - method to discover a physical disk's GPT partition layout. # Note that libdiskmgmt terminology treats GPT partitions as slices # as does the Solaris cXtYdZsN notation # We shall refer to them as GPT partitions though, like the rest of # the world does. partition - object as discovered by ldm blocksize - blocksize of the disk efipart - DK_PART EFI cstruct """ # store the attributes locally so libdiskmgt doesn't have to keep # looking them up gpart_attributes = partition.attributes new_gpart = GPTPartition(str(gpart_attributes.index)) new_gpart.action = "preserve" new_gpart.size = Size(str(gpart_attributes.size) + Size.sector_units, blocksize=blocksize) new_gpart.start_sector = long(gpart_attributes.start) new_gpart.size_in_sectors = gpart_attributes.size stats = partition.use_stats if "used_by" in stats: new_gpart.in_use = stats # EFI partition type GUID and p_flag not provided by libdiskmgt. Fall # back on libefi provided DK_PART data. new_gpart.part_type = '{%s}' % str(efipart.p_guid) new_gpart.guid = copy.copy(efipart.p_guid) new_gpart.uguid = copy.copy(efipart.p_uguid) new_gpart.flag = efipart.p_flag # If the partition is an EFI system partition check to see if it # is PCFS formatted. We only do this on EFI system partition to save # time since mounting can be slow. if new_gpart.is_efi_system: ctds = partition.name.rsplit('/', 1)[-1] new_gpart._is_pcfs_formatted = self.is_pcfs_formatted(ctds) return new_gpart def discover_slice(self, slc, blocksize): """ discover_slices - method to discover a physical disk's slice layout. slc - slice object as discovered by ldm blocksize - blocksize of the disk """ # store the attributes locally so libdiskmgt doesn't have to keep # looking them up slc_attributes = slc.attributes new_slice = Slice(str(slc_attributes.index)) new_slice.action = "preserve" new_slice.tag = slc_attributes.tag new_slice.flag = slc_attributes.flag new_slice.size = Size(str(slc_attributes.size) + Size.sector_units, blocksize=blocksize) new_slice.start_sector = long(slc_attributes.start) new_slice.size_in_sectors = slc_attributes.size stats = slc.use_stats if "used_by" in stats: new_slice.in_use = stats return new_slice def discover_zpools(self, search_name=""): """ discover_zpools - method to walk zpool list output to create Zpool objects. Returns a logical DOC object with all zpools populated. """ # create a logical element logical = Logical("logical") # set noswap and nodump to True until a zvol is found otherwise logical.noswap = True logical.nodump = True # retreive the list of zpools cmd = [ZPOOL, "list", "-H", "-o", "name"] p = run(cmd) # Get the list of zpools zpool_list = p.stdout.splitlines() # walk the list and populate the DOC for zpool_name in zpool_list: # if the user has specified a specific search name, only run # discovery on that particular pool name if search_name and zpool_name != search_name: continue self.logger.debug("Populating DOC for zpool: %s", zpool_name) # create a new Zpool DOC object and insert it zpool = Zpool(zpool_name) zpool.action = "preserve" logical.insert_children(zpool) # check to see if the zpool is the boot pool cmd = [ZPOOL, "list", "-H", "-o", "bootfs", zpool_name] p = run(cmd) if p.stdout.rstrip() != "-": zpool.is_root = True # get the mountpoint of the zpool cmd = [ZFS, "get", "-H", "-o", "value", "mountpoint", zpool_name] p = run(cmd) zpool.mountpoint = p.stdout.strip() # set the vdev_mapping on each physical object in the DOC tree for # this zpool self.set_vdev_map(zpool) # for each zpool, get all of its datasets. Switch to the C locale # so we don't have issues with LC_NUMERIC settings cmd = [ ZFS, "list", "-r", "-H", "-o", "name,type,used,mountpoint", zpool_name ] p = run(cmd, env={"LC_ALL": "C"}) # walk each dataset and create the appropriate DOC objects for # each. Skip the first line of list output, as the top level # dataset (also the dataset with the same name as that of the # zpool) may have a different mountpoint than the zpool. for dataset in p.stdout.rstrip().split("\n")[1:]: try: name, ds_type, ds_size, mountpoint = dataset.split(None, 3) except ValueError as err: # trap on ValueError so any inconsistencies are captured self.logger.debug("Unable to process dataset: %r" % dataset) self.logger.debug(str(err)) continue # fix the name field to remove the name of the pool name = name.partition(zpool_name + "/")[2] if ds_type == "filesystem": obj = Filesystem(name) obj.mountpoint = mountpoint elif ds_type == "volume": obj = Zvol(name) obj.size = Size(ds_size) # check for swap/dump. If there's a match, set the zvol # 'use' attribute and the noswap/nodump attribute of # logical. The zpool name needs to be re-attached to the # zvol name to match what was already parsed if os.path.join(zpool_name, name) in self.swap_list: obj.use = "swap" logical.noswap = False if os.path.join(zpool_name, name) in self.dump_list: obj.use = "dump" logical.nodump = False obj.action = "preserve" zpool.insert_children(obj) return logical def set_vdev_map(self, zpool): """ set_vdev_map() - walk the vdev_map to set the zpool's vdev entries and update existing physical DOC entries with the proper in_zpool and in_vdev attributes. zpool - zpool DOC object """ # get the list of Disk DOC objects already inserted disklist = self.root.get_children(class_type=Disk) # get the vdev mappings for this pool vdev_map = vdevs._get_vdev_mapping(zpool.name) for vdev_type, vdev_entries in vdev_map.iteritems(): in_vdev_label = "%s-%s" % (zpool.name, vdev_type) if vdev_type != "none": redundancy = vdev_type.partition("-")[0] else: redundancy = vdev_type # create a Vdev DOC entry for the vdev_type zpool.add_vdev(in_vdev_label, redundancy) for full_entry in vdev_entries: # remove the device path from the entry entry = full_entry.rpartition("/dev/dsk/")[2] # try to partition the entry for GPT partitions and # VTOC slices. # Both are identified by the letter "s" preceding the index. (vdev_ctd, vdev_letter, vdev_index) = entry.rpartition("s") # if the entry is not a GPT partition or VTOC slice, # vdev_letter and index will be empty strings if not vdev_letter: # try to partition the entry for MBR partitions (vdev_ctd, vdev_letter, vdev_index) = \ entry.rpartition("p") # if the entry is also not a partition skip this entry if not vdev_letter: continue # walk the disk list looking for a matching ctd for disk in disklist: if hasattr(disk, "ctd"): if disk.ctd == vdev_ctd: # this disk is a match if vdev_letter == "s": if disk.label == "VTOC": child_list = disk.get_descendants( class_type=Slice) elif disk.label == "GPT": child_list = disk.get_descendants( class_type=GPTPartition) elif vdev_letter == "p": child_list = disk.get_descendants( class_type=Partition) # walk the child list and look for a matching name for child in child_list: if child.name == vdev_index: # set the in_zpool and in_vdev attributes child.in_zpool = zpool.name child.in_vdev = in_vdev_label # break out of the disklist walk break def discover_BEs(self, zpool_name="", name=None): """ discover_BEs - method to discover all Boot Environments (BEs) on the system. """ be_list = be.be_list(name) # walk each zpool already discovered and add BEs as necessary for zpool in self.root.get_descendants(class_type=Zpool): # check to see if we only want a subset of zpools. if zpool_name and zpool_name != zpool.name: continue for be_name, be_pool, root_ds, is_active in be_list: if be_pool == zpool.name: zpool.insert_children(BE(be_name)) def discover_entire_system(self, add_physical=True): """ discover_entire_system - populates the root node of the DOC tree with the entire physical layout of the system. add_physical - boolean value to signal if physical targets should be added to the DOC. """ # to find all the drives on the system, first start with the # controllers for controller in diskmgt.descriptors_by_type(const.CONTROLLER): # skip USB floppy controllers if controller.floppy_controller: continue # trap on the "/pseudo" controller (zvol swap and dump) if controller.name == "/pseudo" and add_physical: self.discover_pseudo(controller) else: # extract every drive on the given controller for drive in controller.drives: # query libdiskmgt for the drive's information new_disk = self.discover_disk(drive) # skip invalid drives and CDROM drives if new_disk is None or new_disk.iscdrom: continue if add_physical: self.root.insert_children(new_disk) # extract all of the devpaths from all of the drives already inserted devpath_list = [ disk.devpath for disk in self.root.get_descendants(class_type=Disk) ] # now walk all the drives in the system to make sure we pick up any # disks which have no controller (OVM Xen disks) self.logger.debug("Adding drives without controllers to the DOC") for drive in diskmgt.descriptors_by_type(const.DRIVE): # skip drives that have controllers. They would have already been # discovered above. if drive.controllers: continue # skip any drive whose opath starts with "/dev/zvol/rdsk" if drive.attributes.opath.startswith(ZVOL_RPATH): continue new_disk = self.discover_disk(drive) # skip invalid drives and CDROM drives if new_disk is None or new_disk.iscdrom or new_disk.ctd == "dump": continue # skip any disk we've already discovered if new_disk.devpath in devpath_list: continue if add_physical: self.root.insert_children(new_disk) def setup_iscsi(self): """ set up the iSCSI initiator appropriately (if specified) such that any physical/logical iSCSI devices can be discovered. """ # pull out all of the iscsi entries from the DOC iscsi_list = self.doc.get_descendants(class_type=Iscsi) # if there's nothing to do, simply return if not iscsi_list: return # check each entry in the iscsi_list. If any of them do not have a ctd # value already, set up the mapping to the LUN. for iscsi in iscsi_list: if not iscsi.ctd_list: # attempt to connect to the target try: iscsi.setup_iscsi() except (CalledProcessError, RuntimeError): # remove the iSCSI configuration since it's invalid iscsi.teardown() raise # map the iSCSI object back to its parent Disk object for AI. if isinstance(iscsi.parent, Disk): iscsi.parent.ctd = iscsi.ctd_list[0] def setup_croinfo(self): """ set up a DataObjectDict representing the output from /usr/sbin/croinfo """ cmd = [CROINFO, "-h", "-O", "cAR"] p = run(cmd) # for systems that do not support CRO, nothing will be returned in # stdout so simply return. if not p.stdout: return # keep a positional counter since we can't use OrderedDicts until 2.7 i = 1 for line in p.stdout.splitlines(): (ctd, alias, receptacle) = line.split(":") # skip any entries where the ctd is missing. if not ctd: continue self.cro_dict[ctd] = (i, alias or None, receptacle) i += 1 if self.cro_dict: # Only insert if there is something in it self.doc.persistent.insert_children( DataObjectDict(CRO_LABEL, self.cro_dict, generate_xml=True)) def execute(self, dry_run=False): """ primary execution checkpoint for Target Discovery """ self.dry_run = dry_run # look to see if the persistent tree already has a DISCOVERED Target # node. discovered = \ self.doc.persistent.get_descendants(name=Target.DISCOVERED) if discovered: # target discovery has already run once. Before continuing to run # it again, force libdiskmgt to rebuild its cache. self.logger.debug("Found existing Target.DISCOVERED object. " "Forcing libdiskmgt to refresh its cache.") diskmgt.cache_update() # setup croinfo mappings self.setup_croinfo() # setup iSCSI so that all iSCSI physical and logical devices can be # discovered self.setup_iscsi() # check to see if the user specified a search_type if self.search_type == DISK_SEARCH_NAME: if isinstance(self.search_name, list): for name in self.search_name: drive = retrieve_drive(name) new_disk = self.discover_disk(drive) if new_disk is not None: self.root.insert_children(new_disk) else: drive = retrieve_drive(self.search_name) new_disk = self.discover_disk(drive) if new_disk is not None: self.root.insert_children(new_disk) elif self.search_type == ZPOOL_SEARCH_NAME: self.discover_entire_system(add_physical=False) self.root.insert_children(self.discover_zpools(self.search_name)) # Add all Boot Environments that are contained in this zpool self.discover_BEs(self.search_name) else: self.discover_entire_system() # Add the discovered zpool objects self.root.insert_children(self.discover_zpools()) # Add all Boot Environments self.discover_BEs() # If this is the first run of discovery, simply insert the entire root if not discovered: self.doc.persistent.insert_children(self.root) else: # take the first (and only) entry in the list and add each new # child object to the existing discovered tree discovered = discovered[0] for child in self.root.children: discovered.insert_children(child) def is_pcfs_formatted(self, ctdn): """ is_pcfs_formatted() Return a Boolean value of True if the GPT partition guid is already formatted with a pcfs filesystem. This test is useful in conjuction with the is_efi_system property to determine if an existing EFI system partition can be reused to store the Solaris UEFI boot program. If False, a format using mkfs on the partition would be required. """ dev_dsk = "/dev/dsk/%s" % ctdn if os.path.exists(dev_dsk) is False: raise RuntimeError("No such block device exists: %s" % dev_dsk) # Check to see if it's mounted first. If it is we can look at the # fstype it is mounted with. mntmatch = None try: mnttab_open() mntmatch = getmntany(mnt_special=dev_dsk) finally: mnttab_close() # Mounted if mntmatch is not None: if mntmatch.get('mnt_fstype') == 'pcfs': return True else: return False # Not mounted else: # Try to mount with pcfs. This is a much more robust and reliable # check that the ESP is usable than simply checking with # fstyp(1M) mount_point = tempfile.mkdtemp(dir="/system/volatile", prefix="esp_%s_" % (ctdn)) try: mount_cmd = [PCFSMOUNT, dev_dsk, mount_point] run(mount_cmd) umount_cmd = [UMOUNT, dev_dsk] run(umount_cmd) return True except CalledProcessError: return False finally: os.rmdir(mount_point) return False
class TestTI(unittest.TestCase): # set the arch if platform.processor() == "i386": ARCH = "x86" else: ARCH = "sparc" def __init__(self, methodName="runTest"): unittest.TestCase.__init__(self, methodName) # extract drive informtion to construct a bare-bones DOC object dmd = diskmgt.descriptor_from_key(ALIAS, MASTER_CTD) alias = diskmgt.DMAlias(dmd.value) drive = alias.drive dma = drive.media.attributes if dma.ncylinders is None: raise RuntimeError("Unable to process disk label. Please " + "place a VTOC label on the disk.") # get the maximum size of the disk fd = os.open("/dev/rdsk/" + MASTER_CTD + "s2", os.O_RDONLY|os.O_NDELAY) try: media_info = drive.DKMinfo() fcntl.ioctl(fd, diskmgt.DKIOCGMEDIAINFO, C.addressof(media_info)) except IOError as error: print 'ioctl failed: ', str(error) raise finally: os.close(fd) # set the basic geometry self.disk = Disk(MASTER_CTD) self.disk.ctd = MASTER_CTD self.disk.disk_prop = DiskProp() self.disk.disk_prop.dev_size = Size(str(media_info.dki_capacity) + Size.sector_units) self.disk_size = self.disk.disk_prop.dev_size.sectors self.disk.geometry = DiskGeometry(dma.blocksize, dma.nheads * dma.nsectors) self.disk.geometry.ncyl = dma.ncylinders self.disk.geometry.nhead = dma.nheads self.disk.geometry.nsectors = dma.nsectors self.target = Target(Target.DESIRED) self.target.insert_children(self.disk) def setUp(self): self.engine = engine_test_utils.get_new_engine_instance() self.doc = self.engine.data_object_cache.volatile self.doc.insert_children(self.target) def tearDown(self): engine_test_utils.reset_engine() def get_fdisk(self): cmd = ["/usr/sbin/fdisk", "-W", "-", "/dev/rdsk/" + MASTER_CTD + "p0"] p = Popen.check_call(cmd, stdout=Popen.STORE, stderr=Popen.STORE) if p.returncode != 0: raise RuntimeError(" ".join(cmd) + " failed") return p.stdout, p.stderr def get_prtvtoc(self): cmd = ["/usr/sbin/prtvtoc", "/dev/rdsk/" + MASTER_CTD + "s0"] p = Popen.check_call(cmd, stdout=Popen.STORE, stderr=Popen.STORE) if p.returncode != 0: raise RuntimeError(" ".join(cmd) + " failed") return p.stdout, p.stderr def test_x86_single_partition(self): if self.ARCH != "x86": raise SkipTest("test not supported on sparc") # set the partition size to 50% of the disk size partition_size = int(float(self.disk_size) / 2.0) p = self.disk.add_partition(1, self.disk.geometry.cylsize, partition_size, Size.sector_units) # register a TI checkpoint and execute it self.engine.register_checkpoint("ti", "solaris_install/target/instantiation", "TargetInstantiation") status, failed_cp = self.engine.execute_checkpoints() if status != InstallEngine.EXEC_SUCCESS: err = errsvc.get_errors_by_mod_id(failed_cp[0])[0] self.fail(err.error_data[liberrsvc.ES_DATA_EXCEPTION]) # verify the data outs, errs = self.get_fdisk() lines = [line.strip().split() for line in outs.splitlines() \ if line and not line.startswith("*")] # by default, fdisk will show a minimum of 4 lines, 1 for each primary # partition. Since we're only testing line 1, ignore the rest self.assertEqual(lines[0][0], str(p.part_type)) self.assertEqual(lines[0][8], str(self.disk.geometry.cylsize)) self.assertEqual(lines[0][9], str(p.size.sectors)) def test_x86_five_partitions(self): if self.ARCH != "x86": raise SkipTest("test not supported on sparc") # set the partition size of each of the partitions to 10% of the disk p_size = int(float(self.disk_size) * 0.10) norm_size = p_size / self.disk.geometry.cylsize * \ self.disk.geometry.cylsize # add 5 partitions. Partition 1 will be the extended partition and # partition 5 will be the solaris2 partition self.disk.add_partition(1, self.disk.geometry.cylsize, p_size, Size.sector_units, 15) # linux native partition self.disk.add_partition(2, self.disk.geometry.cylsize + p_size + 1, p_size, Size.sector_units, 131) # linux native partition self.disk.add_partition(3, self.disk.geometry.cylsize + (2 * p_size) + 2, p_size, Size.sector_units, 131) # linux native partition self.disk.add_partition(4, self.disk.geometry.cylsize + (3 * p_size) + 3, p_size, Size.sector_units, 131) # logical partition inside partition 1 with a partition type of # solaris2. Allow for an offset on either side of 63 sectors self.disk.add_partition(5, self.disk.geometry.cylsize + 63, p_size - 63, Size.sector_units) # register a TI checkpoint and execute it self.engine.register_checkpoint("ti", "solaris_install/target/instantiation", "TargetInstantiation") status, failed_cp = self.engine.execute_checkpoints() if status != InstallEngine.EXEC_SUCCESS: err = errsvc.get_errors_by_mod_id(failed_cp[0])[0] self.fail(err.error_data[liberrsvc.ES_DATA_EXCEPTION]) # verify the data outs, errs = self.get_fdisk() lines = [line.strip().split() for line in outs.splitlines() \ if line and not line.startswith("*")] # verify the partition types (first column) self.assertEqual(lines[0][0], "15") self.assertEqual(lines[1][0], "131") self.assertEqual(lines[2][0], "131") self.assertEqual(lines[3][0], "131") self.assertEqual(lines[4][0], "191") # verify the size (10th column) self.assertEqual(lines[0][9], str(norm_size)) self.assertEqual(lines[1][9], str(norm_size)) self.assertEqual(lines[2][9], str(norm_size)) self.assertEqual(lines[3][9], str(norm_size)) self.assertEqual(lines[4][9], str(norm_size - 63)) def test_x86_single_slice(self): if self.ARCH != "x86": raise SkipTest("test not supported on sparc") # set the partition size to 50% of the disk size p_size = int(float(self.disk_size) / 2.0) # add a partition at start_sector CYLSIZE part = self.disk.add_partition(1, self.disk.geometry.cylsize, p_size, Size.sector_units) # add a 1 GB slice to the partition part.add_slice(0, self.disk.geometry.cylsize, 1, Size.gb_units) # register a TI checkpoint and execute it self.engine.register_checkpoint("ti", "solaris_install/target/instantiation", "TargetInstantiation") status, failed_cp = self.engine.execute_checkpoints() # verify the data outs, errs = self.get_prtvtoc() lines = [line.strip().split() for line in outs.splitlines() \ if line and not line.startswith("*")] self.assertEqual(lines[0][3], str(self.disk.geometry.cylsize)) self.assertEqual(lines[0][4], str(GBSECTOR))
class TestValidateTarget(unittest.TestCase): """ test case for testing the validate_target function """ def setUp(self): # instantiate the engine self.eng = engine_test_utils.get_new_engine_instance() self.doc = self.eng.data_object_cache # create a Target DataObjects for later insertion self.target = Target("target") self.logical = Logical("logical") self.target.insert_children(self.logical) def tearDown(self): engine_test_utils.reset_engine() def test_two_filesystems(self): """ test to make sure two Filesystem objects correctly errors """ # create a basic zpool object zpool = Zpool("rpool") zpool.action = "use_existing" # create two filesystem objects fs1 = Filesystem("rpool/test1") fs2 = Filesystem("rpool/test2") # create the DOC structure self.logical.insert_children(zpool) zpool.insert_children([fs1, fs2]) self.doc.volatile.insert_children(self.target) self.assertRaises(RuntimeError, dc.validate_target) def test_delete_filesystem(self): """ test to make sure the delete action correctly errors """ # create a basic zpool object zpool = Zpool("rpool") zpool.action = "use_existing" # create one filesystem object with an action of delete fs = Filesystem("rpool/test1") fs.action = "delete" # create the DOC structure self.logical.insert_children(zpool) zpool.insert_children(fs) self.doc.volatile.insert_children(self.target) self.assertRaises(RuntimeError, dc.validate_target) def test_two_zpools(self): """ test to make sure two Zpool objects correctly errors """ # create two zpool objects zpool1 = Zpool("rpool") zpool1.action = "use_existing" zpool2 = Zpool("rpool-two") zpool2.action = "use_existing" # create one filesystem object fs1 = Filesystem("rpool/test1") # create the DOC structure self.logical.insert_children([zpool1, zpool2]) zpool1.insert_children(fs1) self.doc.volatile.insert_children(self.target) self.assertRaises(RuntimeError, dc.validate_target) def test_delete_zpool(self): """ test to make sure the delete action for zpools correctly errors """ # create a basic zpool object with an action of delete zpool = Zpool("rpool") zpool.action = "delete" # create one filesystem object fs = Filesystem("rpool/test1") # create the DOC structure self.logical.insert_children(zpool) zpool.insert_children(fs) self.doc.volatile.insert_children(self.target) self.assertRaises(RuntimeError, dc.validate_target) def test_create_root_pool(self): """ test to make sure the create action on the bootfs correctly errors """ # create a basic zpool object with an action of create zpool = Zpool("rpool") zpool.action = "create" # create one filesystem object fs = Filesystem("rpool/test1") # create the DOC structure self.logical.insert_children(zpool) zpool.insert_children(fs) self.doc.volatile.insert_children(self.target) self.assertRaises(RuntimeError, dc.validate_target) def test_simple_target(self): """ test to make sure a simple target validates correctly. No actual ZFS code is executed here. """ # create a basic zpool object zpool = Zpool("rpool") zpool.action = "use_existing" # create one filesystem object fs = Filesystem("rpool/test1") fs.dataset_path = fs.name # create the DOC structure self.logical.insert_children(zpool) zpool.insert_children(fs) self.doc.volatile.insert_children(self.target) zpool_name, dataset, action, dataset_mp = dc.validate_target() self.assertTrue(zpool_name == zpool.name) self.assertTrue(dataset == "rpool/test1") self.assertTrue(action == "create") # the mountpoint will be None since the Filesystem.from_xml() method # is not called to determine the actual mountpoint self.assertFalse(dataset_mp)
class TestDiskSlice(unittest.TestCase): def setUp(self): self.engine = engine_test_utils.get_new_engine_instance() self.doc = self.engine.data_object_cache.volatile # create some DOC objects self.target = Target(Target.DESIRED) self.doc.insert_children(self.target) self.disk = Disk("disk") self.disk.ctd = "c8t1d0" self.disk.disk_prop = DiskProp() self.disk.disk_prop.dev_size = Size(str(200) + Size.gb_units) self.disk.disk_prop.blocksize = BLOCKSIZE self.disk.disk_prop.cylsize = CYLSIZE self.disk.disk_geometry = DiskGeometry() self.target.insert_children(self.disk) def tearDown(self): engine_test_utils.reset_engine() def test_update_vtoc(self): slice1 = Slice(1) slice1.action = "create" slice1.size = Size("4" + Size.sector_units) slice1.start_sector = 1 slice1.tag = const.V_BOOT slice1.flag = const.V_RONLY slice2 = Slice(2) slice2.action = "create" slice2.size = Size("8" + Size.sector_units) slice2.start_sector = 10 slice2.tag = const.V_BACKUP slice2.flag = const.V_RONLY slice3 = Slice(3) slice3.action = "preserve" slice3.size = Size("20" + Size.sector_units) slice3.start_sector = 20 slice3.tag = const.V_USR slice3.flag = const.V_UNMNT slices_list = [slice1, slice2, slice3] extvtocp = C.pointer(cstruct.extvtoc()) c = extvtocp.contents self.disk.geometry.ncly = 5 self.disk._update_vtoc_struct(extvtocp, slices_list, 10) self.failIf(\ c.v_part[int(slice1.name)].p_size != slice1.size.sectors or \ c.v_part[int(slice1.name)].p_start != slice1.start_sector or \ c.v_part[int(slice1.name)].p_tag != slice1.tag or \ c.v_part[int(slice1.name)].p_flag != slice1.flag) self.failIf(\ c.v_part[int(slice2.name)].p_size != slice2.size.sectors or \ c.v_part[int(slice2.name)].p_start != slice2.start_sector or \ c.v_part[int(slice2.name)].p_tag != slice2.tag or \ c.v_part[int(slice2.name)].p_flag != slice2.flag) self.failIf(\ c.v_part[int(slice3.name)].p_size != slice3.size.sectors or \ c.v_part[int(slice3.name)].p_start != slice3.start_sector or \ c.v_part[int(slice3.name)].p_tag != slice3.tag or \ c.v_part[int(slice3.name)].p_flag != slice3.flag) def test_slice_on_part(self): self.disk.geometry.nheads = 24 self.disk.geometry.nsectors = 848 self.disk.geometry.blocksize = 512 self.disk.geometry.ncyl = 14089 part = Partition(2) part.action = "create" part.start_sector = 0 part.size = Size("50" + Size.gb_units) part.part_type = "primary" part.bootid = Partition.ACTIVE self.disk.insert_children(part) slice1 = Slice(1) slice1.action = "create" slice1.size = Size(str(GBSECTOR) + Size.sector_units) slice1.start_sector = CYLSIZE slice1.tag = const.V_USR slice1.flag = 0 part.insert_children(slice1) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_swap_slices(self): self.disk.geometry.nheads = 24 self.disk.geometry.nsectors = 848 self.disk.geometry.blocksize = 512 self.disk.geometry.ncyl = 14089 part = Partition(2) part.action = "create" part.start_sector = 0 part.size = Size("50" + Size.gb_units) part.part_type = "primary" part.bootid = Partition.ACTIVE self.disk.insert_children(part) slice1 = Slice(1) slice1.action = "create" slice1.size = Size(str(GBSECTOR) + Size.sector_units) slice1.start_sector = CYLSIZE slice1.tag = const.V_SWAP slice1.is_swap = True slice2 = Slice(2) slice2.action = "create" slice2.size = Size(str(GBSECTOR) + Size.sector_units) slice2.start_sector = slice1.start_sector + slice1.size.sectors slice2.tag = const.V_SWAP slice2.is_swap = True part.insert_children([slice1, slice2]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err))
class TestZpoolVdevs(unittest.TestCase): """ Test case for exercising creation of Zpool objects and validating against real zpools """ def create_file(self, path, size="64m"): # look for the file first. if it exists, remove if if os.path.isfile(path): os.unlink(path) # create the file with mkfile cmd = [MKFILE, size, path] p = Popen.check_call(cmd, stdout=Popen.STORE, stderr=Popen.STORE) # add the file to the list to destroy later self.file_list.append(path) def setUp(self): self.engine = engine_test_utils.get_new_engine_instance() self.doc = self.engine.data_object_cache.volatile # list of created files for zpool vdev usage self.file_list = [] # list of created zpools self.zpool_list = [] # create the basic DOC structure self.target = Target(Target.DESIRED) self.logical = Logical("logical") self.target.insert_children(self.logical) self.doc.insert_children(self.target) def tearDown(self): engine_test_utils.reset_engine() # walk the zpool_list and call destroy for zpool in self.zpool_list: zpool.destroy(dry_run=False, force=True) # walk the file_list call unlink() on them for f in self.file_list: if os.path.isfile(f): os.unlink(f) def test_simple_vdev(self): """ 1 single vdev """ # create a single 64M file f1 = "/var/tmp/ti_file_1" self.create_file(f1) # create a new Disk object d = Disk("disk") d.ctd = f1 d.in_zpool = "ti_zpool_test" d.whole_disk = True self.target.insert_children(d) # create a new Zpool object zpool = self.logical.add_zpool("ti_zpool_test") # create the zpool and store it for later teardown try: t = instantiation.TargetInstantiation("test_ti") t.execute(dry_run=False) self.zpool_list.append(zpool) except Exception as err: import traceback print traceback.print_exc() self.fail(str(err)) # pull the vdevs and verify vdev_map = vdevs._get_vdev_mapping(zpool.name) # verify the map is correct self.assertTrue("none" in vdev_map) self.assertEquals(1, len(vdev_map["none"])) self.assertEquals([f1], vdev_map["none"]) def test_mirror_vdevs(self): """ 2 mirrored root disks """ # create two 64M files f1 = "/var/tmp/ti_file_1" self.create_file(f1) f2 = "/var/tmp/ti_file_2" self.create_file(f2) # create two disk objects d1 = Disk("disk1") d1.ctd = f1 d1.in_zpool = "ti_zpool_test" d1.in_vdev = "mirror-0" d1.whole_disk = True d2 = Disk("disk2") d2.ctd = f2 d2.in_zpool = "ti_zpool_test" d2.in_vdev = "mirror-0" d2.whole_disk = True self.target.insert_children([d1, d2]) # create a new Zpool object zpool = self.logical.add_zpool("ti_zpool_test") zpool.add_vdev("mirror-0", "mirror") # create the zpool and store it for later teardown try: t = instantiation.TargetInstantiation("test_ti") t.execute(dry_run=False) self.zpool_list.append(zpool) except Exception as err: import traceback print traceback.print_exc() self.fail(str(err)) # pull the vdevs and verify vdev_map = vdevs._get_vdev_mapping(zpool.name) # verify the map is correct self.assertTrue("mirror-0" in vdev_map) self.assertEquals(2, len(vdev_map["mirror-0"])) self.assertEquals([f1, f2], vdev_map["mirror-0"]) def test_complex_vdevs1(self): """ 10 disks: Mirrored root + raidz datapool with log and spare """ # create 10 files for i in range(1, 11): f = "/var/tmp/ti_file_%d" % i self.create_file(f) # create 10 disk objects for i in range(1, 11): d = Disk("disk%d" % i) d.ctd = self.file_list[i - 1] if i in [1, 2]: d.in_zpool = "ti_zpool_test_root" d.in_vdev = "root-mirror" elif i in [3, 4, 5, 6]: d.in_zpool = "ti_zpool_test_datapool" d.in_vdev = "datapool-raidz" elif i in [7, 8]: d.in_zpool = "ti_zpool_test_datapool" d.in_vdev = "datapool-log" elif i in [9, 10]: d.in_zpool = "ti_zpool_test_datapool" d.in_vdev = "datapool-spare" self.target.insert_children(d) # create two new zpool objects zpool1 = self.logical.add_zpool("ti_zpool_test_root") zpool1.add_vdev("root-mirror", "mirror") zpool2 = self.logical.add_zpool("ti_zpool_test_datapool") zpool2.add_vdev("datapool-raidz", "raidz") zpool2.add_vdev("datapool-log", "log") zpool2.add_vdev("datapool-spare", "spare") # create the zpools and store it for later teardown try: t = instantiation.TargetInstantiation("test_ti") t.execute(dry_run=False) self.zpool_list.append(zpool1) self.zpool_list.append(zpool2) except Exception as err: import traceback print traceback.print_exc() self.fail(str(err)) # pull the vdevs and verify vdev_map1 = vdevs._get_vdev_mapping(zpool1.name) # verify the map is correct self.assertTrue("mirror-0" in vdev_map1) self.assertTrue(len(vdev_map1["mirror-0"]) == 2) self.assertTrue(vdev_map1["mirror-0"] == self.file_list[:2]) vdev_map2 = vdevs._get_vdev_mapping(zpool2.name) self.assertTrue("spare" in vdev_map2) self.assertTrue("logs" in vdev_map2) self.assertTrue("raidz-0" in vdev_map2) self.assertTrue(2, len(vdev_map2["spare"])) self.assertTrue(2, len(vdev_map2["logs"])) self.assertTrue(4, len(vdev_map2["raidz-0"])) self.assertEquals(self.file_list[-2:], vdev_map2["spare"]) self.assertEquals(self.file_list[6:8], vdev_map2["logs"]) self.assertEquals(self.file_list[2:6], vdev_map2["raidz-0"]) def test_mirror_log(self): """ test the logmirror vdev label """ # create three 64M files f1 = "/var/tmp/ti_file_1" self.create_file(f1) f2 = "/var/tmp/ti_file_2" self.create_file(f2) f3 = "/var/tmp/ti_file_3" self.create_file(f3) # create two disk objects d1 = Disk("disk1") d1.ctd = f1 d1.in_zpool = "ti_zpool_test" d1.in_vdev = "none" d1.whole_disk = True d2 = Disk("disk2") d2.ctd = f2 d2.in_zpool = "ti_zpool_test" d2.in_vdev = "mirror-1" d2.whole_disk = True d3 = Disk("disk3") d3.ctd = f3 d3.in_zpool = "ti_zpool_test" d3.in_vdev = "mirror-1" d3.whole_disk = True self.target.insert_children([d1, d2, d3]) # create a new Zpool object zpool = self.logical.add_zpool("ti_zpool_test") zpool.add_vdev("none", "none") zpool.add_vdev("mirror-1", "logmirror") # create the zpool and store it for later teardown try: t = instantiation.TargetInstantiation("test_ti") t.execute(dry_run=False) self.zpool_list.append(zpool) except Exception as err: import traceback print traceback.print_exc() self.fail(str(err)) # pull the vdevs and verify vdev_map = vdevs._get_vdev_mapping(zpool.name) # verify the map is correct self.assertTrue("mirror-1" in vdev_map) self.assertEquals(2, len(vdev_map["mirror-1"])) self.assertEquals([f2, f3], vdev_map["mirror-1"]) def test_duplicate_in_vdev(self): # create four 64M files f1 = "/var/tmp/ti_file_1" self.create_file(f1) f2 = "/var/tmp/ti_file_2" self.create_file(f2) f3 = "/var/tmp/ti_file_3" self.create_file(f3) f4 = "/var/tmp/ti_file_4" self.create_file(f4) # create four disk objects d1 = Disk("disk1") d1.ctd = f1 d1.in_zpool = "ti_myroot" d1.in_vdev = "datavdev" d1.whole_disk = True # match the in_vdev for d2 and d3 with d1, but use a different pool and # a different redundancy d2 = Disk("disk2") d2.ctd = f2 d2.in_zpool = "ti_data" d2.in_vdev = "datavdev" d2.whole_disk = True d3 = Disk("disk3") d3.ctd = f3 d3.in_zpool = "ti_data" d3.in_vdev = "datavdev" d3.whole_disk = True d4 = Disk("disk4") d4.ctd = f4 d4.in_zpool = "ti_data" d4.in_vdev = "sparevdev" d4.whole_disk = True self.target.insert_children([d1, d2, d3, d4]) # create two new Zpool object zpool1 = self.logical.add_zpool("ti_myroot") zpool1.add_vdev("datavdev", redundancy="none") zpool2 = self.logical.add_zpool("ti_data") zpool2.add_vdev("datavdev", "mirror") zpool2.add_vdev("sparevdev", "spare") # create the zpools and store it for later teardown try: t = instantiation.TargetInstantiation("test_ti") t.execute(dry_run=False) self.zpool_list.append(zpool1) self.zpool_list.append(zpool2) except Exception as err: import traceback print traceback.print_exc() self.fail(str(err)) # pull the vdevs and verify zpool1_vdev_map = vdevs._get_vdev_mapping(zpool1.name) zpool2_vdev_map = vdevs._get_vdev_mapping(zpool2.name) # verify both maps are correct self.assertTrue("none" in zpool1_vdev_map) self.assertEquals([f1], zpool1_vdev_map["none"]) self.assertTrue("mirror-0" in zpool2_vdev_map) self.assertTrue("spare" in zpool2_vdev_map) self.assertEquals(2, len(zpool2_vdev_map["mirror-0"])) self.assertEquals([f2, f3], zpool2_vdev_map["mirror-0"]) self.assertEquals(1, len(zpool2_vdev_map["spare"])) self.assertEquals([f4], zpool2_vdev_map["spare"]) def test_invalid_vdev_labels(self): # create four 64M files f1 = "/var/tmp/ti_file_1" self.create_file(f1) f2 = "/var/tmp/ti_file_2" self.create_file(f2) f3 = "/var/tmp/ti_file_3" self.create_file(f3) f4 = "/var/tmp/ti_file_4" self.create_file(f4) # create four disk objects. D1 has no in_zpool set d1 = Disk("disk1") d1.ctd = f1 d1.in_vdev = "datavdev" d1.whole_disk = True # d2 and d3 have no in_vdev set d2 = Disk("disk2") d2.ctd = f2 d2.in_zpool = "ti_myroot" d2.whole_disk = True d3 = Disk("disk3") d3.ctd = f3 d3.in_zpool = "ti_data" d3.whole_disk = True # d4 has both set d4 = Disk("disk4") d4.ctd = f4 d4.in_zpool = "ti_data" d4.in_vdev = "datavdev" d4.whole_disk = True self.target.insert_children([d1, d2, d3, d4]) # create two new Zpool object zpool1 = self.logical.add_zpool("ti_myroot") zpool1.add_vdev("datavdev", redundancy="none") zpool2 = self.logical.add_zpool("ti_data") zpool2.add_vdev("datavdev", "mirror") self.zpool_list.append(zpool1) self.zpool_list.append(zpool2) t = instantiation.TargetInstantiation("test_ti") self.assertRaises(RuntimeError, t.execute)
class TestDiskLabeling(unittest.TestCase): def setUp(self): self.engine = engine_test_utils.get_new_engine_instance() self.doc = self.engine.data_object_cache.volatile # create some DOC objects self.target = Target(Target.DESIRED) self.doc.insert_children(self.target) self.disk = Disk("disk") self.disk.ctd = "c8t1d0" self.disk.disk_prop = DiskProp() self.disk.disk_prop.blocksize = BLOCKSIZE self.disk.disk_prop.cylsize = CYLSIZE self.disk.disk_geometry = DiskGeometry() self.disk.disk_prop.dev_size = Size("500gb") self.target.insert_children(self.disk) def tearDown(self): engine_test_utils.reset_engine() def test_part_preserve(self): part = Partition(1) part.action = "preserve" part.part_type = "primary" part.bootid = Partition.ACTIVE part.size = Size("0b") part.start_sector = 0 part2 = Partition(2) part2.action = "preserve" part2.part_type = "primary" part2.bootid = 0 part2.size = Size("0b") part2.start_sector = 0 self.disk.insert_children([part, part2]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_slice_on_part_preserve(self): part = Partition(1) part.action = "preserve" part.type = "primary" part.bootid = Partition.ACTIVE part.start_sector = 0 part.size = Size("50" + Size.gb_units) part2 = Partition(2) part2.action = "preserve" part2.type = "primary" part2.bootid = 0 part2.size = Size("50" + Size.gb_units) part2.start_sector = 50 * GBSECTOR + 50 self.disk.insert_children([part, part2]) slice1 = Slice(1) slice1.action = "preserve" slice1.size = Size(str(GBSECTOR) + Size.sector_units) slice1.start_sector = CYLSIZE slice2 = Slice(2) slice2.action = "preserve" slice2.size = Size(str(GBSECTOR) + Size.sector_units) slice2.start_sector = CYLSIZE + GBSECTOR + 1 slice3 = Slice(3) slice3.action = "preserve" slice3.size = Size(str(GBSECTOR) + Size.sector_units) slice3.start_sector = CYLSIZE + (2 * GBSECTOR + 2) part.insert_children([slice1, slice2, slice3]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_slice_preserve(self): slice1 = Slice(1) slice1.action = "preserve" slice1.size = Size(str(GBSECTOR) + Size.sector_units) slice1.start_sector = CYLSIZE slice2 = Slice(2) slice2.action = "preserve" slice2.size = Size(str(GBSECTOR) + Size.sector_units) slice2.start_sector = CYLSIZE + GBSECTOR + 1 slice3 = Slice(3) slice3.action = "preserve" slice3.size = Size(str(GBSECTOR) + Size.sector_units) slice3.start_sector = CYLSIZE + (2 * GBSECTOR + 2) self.disk.insert_children([slice1, slice2, slice3]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_part_not_preserve(self): part = Partition(1) part.action = "create" part.part_type = "primary" part.bootid = Partition.ACTIVE part.size = Size("2gb") part2 = Partition(2) part2.action = "destroy" part2.part_type = "primary" part2.bootid = 0 part2.size = Size("2gb") self.disk.insert_children([part, part2]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_slice_on_part_not_preserve(self): part = Partition(1) part.action = "preserve" part.part_type = "primary" part.bootid = Partition.ACTIVE part.size = Size("50" + Size.gb_units) part.start_sector = 0 part2 = Partition(2) part2.action = "preserve" part2.part_type = "primary" part2.bootid = 0 part2.size = Size("50" + Size.gb_units) part2.start_sector = 50 * GBSECTOR + 50 self.disk.insert_children([part, part2]) slice1 = Slice(1) slice1.action = "create" slice1.size = Size(str(GBSECTOR) + Size.sector_units) slice1.start_sector = CYLSIZE slice2 = Slice(2) slice2.action = "create" slice2.size = Size(str(GBSECTOR) + Size.sector_units) slice2.start_sector = CYLSIZE + GBSECTOR + 1 slice3 = Slice(3) slice3.action = "destroy" slice3.size = Size(str(GBSECTOR) + Size.sector_units) slice3.start_sector = CYLSIZE + (2 * GBSECTOR + 2) part.insert_children([slice1, slice2, slice3]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_slice_not_preserve(self): slice1 = Slice(1) slice1.action = "create" slice1.size = Size(str(GBSECTOR) + Size.sector_units) slice1.start_sector = CYLSIZE slice2 = Slice(2) slice2.action = "create" slice2.size = Size(str(GBSECTOR) + Size.sector_units) slice2.start_sector = CYLSIZE + GBSECTOR + 1 slice3 = Slice(3) slice3.action = "destroy" slice3.size = Size(str(GBSECTOR) + Size.sector_units) slice3.start_sector = CYLSIZE + (2 * GBSECTOR + 2) self.disk.insert_children([slice1, slice2, slice3]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err))
class TestValidateTarget(unittest.TestCase): """ test case for testing the validate_target function """ def setUp(self): # instantiate the engine self.eng = engine_test_utils.get_new_engine_instance() self.doc = self.eng.data_object_cache # create a Target DataObjects for later insertion self.target = Target("target") self.logical = Logical("logical") self.target.insert_children(self.logical) def tearDown(self): engine_test_utils.reset_engine() def test_two_filesystems(self): """ test to make sure two Filesystem objects correctly errors """ # create a basic zpool object zpool = Zpool("rpool") zpool.action = "use_existing" # create two filesystem objects fs1 = Filesystem("rpool/test1") fs2 = Filesystem("rpool/test2") # create the DOC structure self.logical.insert_children(zpool) zpool.insert_children([fs1, fs2]) self.doc.volatile.insert_children(self.target) self.assertRaises(RuntimeError, dc.validate_target) def test_delete_filesystem(self): """ test to make sure the delete action correctly errors """ # create a basic zpool object zpool = Zpool("rpool") zpool.action = "use_existing" # create one filesystem object with an action of delete fs = Filesystem("rpool/test1") fs.action = "delete" # create the DOC structure self.logical.insert_children(zpool) zpool.insert_children(fs) self.doc.volatile.insert_children(self.target) self.assertRaises(RuntimeError, dc.validate_target) def test_two_zpools(self): """ test to make sure two Zpool objects correctly errors """ # create two zpool objects zpool1 = Zpool("rpool") zpool1.action = "use_existing" zpool2 = Zpool("rpool-two") zpool2.action = "use_existing" # create one filesystem object fs1 = Filesystem("rpool/test1") # create the DOC structure self.logical.insert_children([zpool1, zpool2]) zpool1.insert_children(fs1) self.doc.volatile.insert_children(self.target) self.assertRaises(RuntimeError, dc.validate_target) def test_delete_zpool(self): """ test to make sure the delete action for zpools correctly errors """ # create a basic zpool object with an action of delete zpool = Zpool("rpool") zpool.action = "delete" # create one filesystem object fs = Filesystem("rpool/test1") # create the DOC structure self.logical.insert_children(zpool) zpool.insert_children(fs) self.doc.volatile.insert_children(self.target) self.assertRaises(RuntimeError, dc.validate_target) def test_create_root_pool(self): """ test to make sure the create action on the bootfs correctly errors """ # create a basic zpool object with an action of create zpool = Zpool("rpool") zpool.action = "create" # create one filesystem object fs = Filesystem("rpool/test1") # create the DOC structure self.logical.insert_children(zpool) zpool.insert_children(fs) self.doc.volatile.insert_children(self.target) self.assertRaises(RuntimeError, dc.validate_target) def test_simple_target(self): """ test to make sure a simple target validates correctly. No actual ZFS code is executed here. """ # create a basic zpool object zpool = Zpool("rpool") zpool.action = "use_existing" # create one filesystem object fs = Filesystem("rpool/test1") fs.dataset_path = fs.name # create the DOC structure self.logical.insert_children(zpool) zpool.insert_children(fs) self.doc.volatile.insert_children(self.target) zpool_name, dataset, action, dataset_mp = dc.validate_target() self.assertTrue(zpool_name == zpool.name) self.assertTrue(dataset == "rpool/test1") self.assertTrue(action == "create") # the mountpoint will be None since the Filesystem.from_xml() method # is not called to determine the actual mountpoint self.assertFalse(dataset_mp)
class TestDiskPartition(unittest.TestCase): def setUp(self): self.engine = engine_test_utils.get_new_engine_instance() self.doc = self.engine.data_object_cache.volatile # create some DOC objects self.target = Target(Target.DESIRED) self.doc.insert_children(self.target) self.disk = Disk("disk") self.disk.ctd = "c8t1d0" self.disk.disk_prop = DiskProp() self.disk.disk_prop.dev_size = Size(str(200) + Size.gb_units) self.disk.disk_prop.blocksize = BLOCKSIZE self.disk.disk_prop.cylsize = CYLSIZE self.disk.disk_geometry = DiskGeometry() self.target.insert_children(self.disk) def tearDown(self): engine_test_utils.reset_engine() def test_create_single_partition(self): part = Partition(2) part.action = "create" part.start_sector = 0 part.size = Size("50" + Size.gb_units) part.part_type = "primary" part.bootid = Partition.ACTIVE self.disk.insert_children(part) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_create_multiple_partitions(self): part = Partition(2) part.action = "create" part.start_sector = 0 part.size = Size("20" + Size.gb_units) part.part_type = "primary" part.bootid = Partition.ACTIVE part2 = Partition(4) part2.action = "create" part2.start_sector = 50 * GBSECTOR + 50 part2.size = Size("50" + Size.gb_units) part2.part_type = "extended" part2.bootid = 0 self.disk.insert_children([part, part2]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_create_destroy_multiple_partitions(self): part = Partition(1) part.action = "create" part.start_sector = 0 part.size = Size("50" + Size.gb_units) part.part_type = "primary" part.bootid = Partition.ACTIVE part2 = Partition(2) part2.action = "destroy" part2.start_sector = 50 * GBSECTOR + 51 part2.size = Size("50" + Size.gb_units) part2.part_type = "primary" part2.bootid = 0 self.disk.insert_children([part, part2]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err))
class TestDiskPartition(unittest.TestCase): def setUp(self): self.engine = engine_test_utils.get_new_engine_instance() self.doc = self.engine.data_object_cache.volatile # create some DOC objects self.target = Target(Target.DESIRED) self.doc.insert_children(self.target) self.disk = Disk("disk") self.disk.ctd = "c8t1d0" self.disk.disk_prop = DiskProp() self.disk.disk_prop.dev_size = Size(str(200) + Size.gb_units) self.disk.disk_prop.blocksize = BLOCKSIZE self.disk.disk_prop.cylsize = CYLSIZE self.disk.disk_geometry = DiskGeometry() self.target.insert_children(self.disk) def tearDown(self): engine_test_utils.reset_engine() def test_create_single_partition(self): part = Partition(2) part.action = "create" part.start_sector = 0 part.size = Size("50" + Size.gb_units) part.part_type = "primary" part.bootid = Partition.ACTIVE self.disk.insert_children(part) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_create_multiple_partitions(self): part = Partition(2) part.action = "create" part.start_sector = 0 part.size = Size("20" + Size.gb_units) part.part_type = "primary" part.bootid = Partition.ACTIVE part2 = Partition(4) part2.action = "create" part2.start_sector = 50 * GBSECTOR + 50 part2.size = Size("50" + Size.gb_units) part2.part_type = "extended" part2.bootid = 0 self.disk.insert_children([part, part2]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_create_destroy_multiple_partitions(self): part = Partition(1) part.action = "create" part.start_sector = 0 part.size = Size("50" + Size.gb_units) part.part_type = "primary" part.bootid = Partition.ACTIVE part2 = Partition(2) part2.action = "destroy" part2.start_sector = 50 * GBSECTOR + 51 part2.size = Size("50" + Size.gb_units) part2.part_type = "primary" part2.bootid = 0 self.disk.insert_children([part, part2]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err))
class TargetDiscovery(Checkpoint): """ Discover all logical and physical devices on the system. """ def __init__(self, name, search_name=None, search_type=None): super(TargetDiscovery, self).__init__(name) self.dry_run = False self.eng = InstallEngine.get_instance() self.doc = self.eng.data_object_cache # create a root node to insert all discovered objects into self.root = Target(Target.DISCOVERED) # user specified search criteria self.search_name = search_name self.search_type = search_type # list of discovered swap and dump zvols self.swap_list = list() self.dump_list = list() # eeprom diag mode and bootdisk value self.sparc_diag_mode = False self.bootdisk = None # kernel architecture self.arch = platform.processor() def is_bootdisk(self, name): """ is_bootdisk() -- simple method to compare the name of the disk in question with what libdevinfo reports as the bootdisk name - ctd name of the disk to check """ # cache the answer so we don't do multiple lookups to libdevinfo if self.bootdisk is None: self.bootdisk = devinfo.get_curr_bootdisk() return self.bootdisk == name def get_progress_estimate(self): # XXX return 1 def discover_disk(self, drive): """ discover_disk - method to discover a physical disk's attributes, partitions and slices drive - which physical drive to parse """ # create a DOC object for this drive. Set validate_children to False # so the shadow code doesn't adjust the start sector or size for any # children discovered new_disk = Disk("disk", validate_children=False) # extract drive attributes and media information drive_attributes = drive.attributes drive_media = drive.media # if a drive is offline or down return None if drive_attributes.status == "DOWN": self.logger.debug("disk '%s' is offline" % new_disk.name) return None # set attributes for the disk if type(drive.aliases) is list and len(drive.aliases) > 0: new_disk.wwn = getattr(drive.aliases[0].attributes, "wwn", None) existing_wwns = [d.wwn for d in \ self.root.get_descendants(class_type=Disk) \ if d.wwn is not None] if new_disk.wwn is not None and new_disk.wwn in existing_wwns: # this wwn has already been discovered, so skip further discovery return None for alias in drive.aliases: # check to see if the wwn changes between drive aliases if getattr(alias.attributes, "wwn", None) != new_disk.wwn: self.logger.warning("disk '%s' has different wwn for the " "aliases" % new_disk.ctd) return None if drive_media is not None: if self.verify_disk_read(alias.name, drive_media.attributes.blocksize): new_disk.active_ctds.append(alias.name) else: new_disk.passive_ctds.append(alias.name) # set the new_disk ctd string if new_disk.wwn is None: # use the only alias name new_disk.ctd = drive.aliases[0].name else: # use the first active ctd new_disk.ctd = new_disk.active_ctds[0] new_disk.devid = drive.name new_disk.iscdrom = drive.cdrom new_disk.opath = drive_attributes.opath # set the devpath if os.path.islink(drive_attributes.opath): link = os.readlink(drive_attributes.opath) # clean up the link to get rid of the leading '../../devices/' and # trailing minor name if link.startswith("../../devices") and ":" in link: link = link.partition("../../devices")[2].rpartition(":")[0] new_disk.devpath = link # check for SPARC eeprom settings which would interfere with finding # the boot disk if self.arch == "sparc": if not self.sparc_diag_mode: # check eeprom settings cmd = [EEPROM, "diag-switch?"] p = run(cmd) diag_switch_value = p.stdout.partition("=")[2] if diag_switch_value.strip().lower() == "true": # set a variable so we don't check every single disk and # log a message self.sparc_diag_mode = True self.logger.info("Unable to determine bootdisk with " + \ "diag-switch? eeprom setting set to " + \ "'true'. Please set diag-switch? " + \ "to false and reboot the system") # check for the bootdisk if not self.sparc_diag_mode: if self.is_bootdisk(new_disk.ctd): new_disk.disk_keyword = DiskKeyword() # set vendor information for the drive new_disk.disk_prop = DiskProp() if drive.controllers: new_disk.disk_prop.dev_type = drive.controllers[0].attributes.type new_disk.disk_prop.dev_vendor = drive_attributes.vendor_id # walk the media node to extract partitions and slices if drive_media is None: # since the drive has no media, we can't determine any attributes # about it (geometry, slices, partitions, etc.) so simply return # None return None else: # store the attributes locally so libdiskmgt doesn't have to keep # looking them up drive_media_attributes = drive_media.attributes # if a drive comes back without basic information, skip discovery # entirely if not DMMediaAttr.NACCESSIBLE in drive_media_attributes or \ not DMMediaAttr.BLOCKSIZE in drive_media_attributes: self.logger.debug("skipping discovery of %s" % new_disk.ctd) return None # retrieve the drive's geometry new_disk = self.set_geometry(drive_media_attributes, new_disk) # keep a list of slices already visited so they're not discovered # again later visited_slices = [] # if this system is x86 and the drive has slices but no fdisk # partitions, don't report any of the slices if self.arch == "i386" and drive_media.slices and not \ drive_media.partitions: return new_disk for partition in drive_media.partitions: new_partition = self.discover_partition( partition, drive_media_attributes.blocksize) # add the partition to the disk object new_disk.insert_children(new_partition) # check for slices associated with this partition. If found, # add them as children for slc in partition.media.slices: # discover the slice new_slice = self.discover_slice( slc, drive_media_attributes.blocksize) # constrain when a slice is added to the DOC. We only want # to add a slice when: # - the partition id is a Solaris partition (non EFI) # - the fstyp is 'zfs' (for EFI labeled disks) # - the fstyp is 'unknown_fstyp' AND it's slice 8 (for EFI # labeled disks) if new_partition.is_solaris: new_partition.insert_children(new_slice) elif new_partition.part_type == 238: # call fstyp to try to figure out the slice type cmd = [FSTYP, slc.name] p = run(cmd, check_result=Popen.ANY) if p.returncode == 0: if p.stdout.strip() == "zfs": # add the slice since it's used by zfs new_partition.insert_children(new_slice) else: if p.stderr.startswith("unknown_fstyp") and \ new_slice.name == "8": # add the slice since it's an EFI boot slice new_partition.insert_children(new_slice) # keep a record this slice so it's not discovered again visited_slices.append(slc.name) for slc in drive_media.slices: # discover the slice if it's not already been found if slc.name not in visited_slices: new_slice = self.discover_slice( slc, drive_media_attributes.blocksize) new_disk.insert_children(new_slice) return new_disk def verify_disk_read(self, ctd, blocksize): """ verify_disk_read() - method to verify a low-level read from the raw ctd path. """ raw = "/dev/rdsk/%s" % ctd raw2 = raw + "s2" # Depending on the label used, we need to check both the raw device and # slice 2 to see if the disk can be read. for raw_disk in [raw, raw2]: fd = None try: try: fd = os.open(raw_disk, os.O_RDONLY | os.O_NDELAY) try: _none = os.read(fd, blocksize) except OSError: # the read() call failed continue else: return True except OSError: # the open() call failed continue finally: if fd is not None: os.close(fd) return False def set_geometry(self, dma, new_disk): """ set_geometry() - method to set the geometry of the Disk DOC object from the libdiskmgt drive object. dma - the drive's media attributes as returned by libdiskmgt new_disk - Disk DOC object """ new_geometry = None # If the disk has a GPT label (or no label), ncylinders will be # None if dma.ncylinders is None: new_disk.disk_prop.dev_size = Size( str(dma.naccessible) + Size.sector_units, dma.blocksize) # set only the blocksize (not the cylinder size) new_geometry = DiskGeometry(dma.blocksize, None) # set the label of the disk, if possible if dma.efi: new_disk.label = "GPT" new_geometry.efi = True else: new_disk.label = "VTOC" # set the disk's volid new_disk.volid = dma.label ncyl = dma.ncylinders nhead = dma.nheads nsect = dma.nsectors new_disk.disk_prop.dev_size = Size( str(ncyl * nhead * nsect) + Size.sector_units, dma.blocksize) new_geometry = DiskGeometry(dma.blocksize, nhead * nsect) new_geometry.ncyl = ncyl new_geometry.nheads = nhead new_geometry.nsectors = nsect new_disk.geometry = new_geometry return new_disk def discover_pseudo(self, controller): """ discover_psuedo - method to discover pseudo controller information, usually zvol swap and dump """ for drive in controller.drives: for slc in drive.media.slices: stats = slc.use_stats if "used_by" in stats: if stats["used_name"][0] == "dump": if slc.name.startswith(ZVOL_PATH): # remove the /dev/zvol/dsk from the path self.dump_list.append(slc.name[14:]) if stats["used_name"][0] == "swap": if slc.name.startswith(ZVOL_PATH): # remove the /dev/zvol/dsk from the path self.swap_list.append(slc.name[14:]) def discover_partition(self, partition, blocksize): """ discover_partition - method to discover a physical disk's partition layout partition - partition object as discovered by ldm blocksize - blocksize of the disk """ # store the attributes locally so libdiskmgt doesn't have to keep # looking them up partition_attributes = partition.attributes # partition name is ctdp path. Split the string on "p" root_path, _none, index = partition.name.partition("p") # create a DOC object for this partition. Set validate_children to # False so the shadow code doesn't adjust the start sector or size for # any children discovered new_partition = Partition(index, validate_children=False) new_partition.action = "preserve" new_partition.part_type = partition_attributes.id # check the partition's ID to set the partition type correctly if partition_attributes.id == \ Partition.name_to_num("Solaris/Linux swap"): try: # try to call prtvtoc on slice 2. If it succeeds, this is a # solaris1 partition. slice2 = root_path + "s2" cmd = [PRTVTOC, slice2] run(cmd, stdout=Popen.DEVNULL) except CalledProcessError: # the call to prtvtoc failed which means this partition is # Linux swap. To be sure, prtvtoc failure might also mean an # unlabeled Solaris1 partition but we aren't going to worry # about that for now. Displaying an unlabeled (and therefore # unused) Solaris1 partition should not have any unforeseen # consequences in terms of data loss. new_partition.is_linux_swap = True new_partition.size = Size(str(partition_attributes.nsectors) + \ Size.sector_units, blocksize=blocksize) new_partition.start_sector = long(partition_attributes.relsect) new_partition.size_in_sectors = partition_attributes.nsectors return new_partition def discover_slice(self, slc, blocksize): """ discover_slices - method to discover a physical disk's slice layout. slc - slice object as discovered by ldm blocksize - blocksize of the disk """ # store the attributes locally so libdiskmgt doesn't have to keep # looking them up slc_attributes = slc.attributes new_slice = Slice(str(slc_attributes.index)) new_slice.action = "preserve" new_slice.tag = slc_attributes.tag new_slice.flag = slc_attributes.flag new_slice.size = Size(str(slc_attributes.size) + Size.sector_units, blocksize=blocksize) new_slice.start_sector = long(slc_attributes.start) new_slice.size_in_sectors = slc_attributes.size stats = slc.use_stats if "used_by" in stats: new_slice.in_use = stats return new_slice def discover_zpools(self, search_name=""): """ discover_zpools - method to walk zpool list output to create Zpool objects. Returns a logical DOC object with all zpools populated. """ # create a logical element logical = Logical("logical") # set noswap and nodump to True until a zvol is found otherwise logical.noswap = True logical.nodump = True # retreive the list of zpools cmd = [ZPOOL, "list", "-H", "-o", "name"] p = run(cmd) # Get the list of zpools zpool_list = p.stdout.splitlines() # walk the list and populate the DOC for zpool_name in zpool_list: # if the user has specified a specific search name, only run # discovery on that particular pool name if search_name and zpool_name != search_name: continue self.logger.debug("Populating DOC for zpool: %s", zpool_name) # create a new Zpool DOC object and insert it zpool = Zpool(zpool_name) zpool.action = "preserve" logical.insert_children(zpool) # check to see if the zpool is the boot pool cmd = [ZPOOL, "list", "-H", "-o", "bootfs", zpool_name] p = run(cmd) if p.stdout.rstrip() != "-": zpool.is_root = True # get the mountpoint of the zpool cmd = [ZFS, "get", "-H", "-o", "value", "mountpoint", zpool_name] p = run(cmd) zpool.mountpoint = p.stdout.strip() # set the vdev_mapping on each physical object in the DOC tree for # this zpool self.set_vdev_map(zpool) # for each zpool, get all of its datasets. Switch to the C locale # so we don't have issues with LC_NUMERIC settings cmd = [ ZFS, "list", "-r", "-H", "-o", "name,type,used,mountpoint", zpool_name ] p = run(cmd, env={"LC_ALL": "C"}) # walk each dataset and create the appropriate DOC objects for # each. Skip the first line of list output, as the top level # dataset (also the dataset with the same name as that of the # zpool) may have a different mountpoint than the zpool. for dataset in p.stdout.rstrip().split("\n")[1:]: try: name, ds_type, ds_size, mountpoint = dataset.split(None, 3) except ValueError as err: # trap on ValueError so any inconsistencies are captured self.logger.debug("Unable to process dataset: %r" % dataset) self.logger.debug(str(err)) continue # fix the name field to remove the name of the pool name = name.partition(zpool_name + "/")[2] if ds_type == "filesystem": obj = Filesystem(name) obj.mountpoint = mountpoint elif ds_type == "volume": obj = Zvol(name) obj.size = Size(ds_size) # check for swap/dump. If there's a match, set the zvol # 'use' attribute and the noswap/nodump attribute of # logical. The zpool name needs to be re-attached to the # zvol name to match what was already parsed if os.path.join(zpool_name, name) in self.swap_list: obj.use = "swap" logical.noswap = False if os.path.join(zpool_name, name) in self.dump_list: obj.use = "dump" logical.nodump = False obj.action = "preserve" zpool.insert_children(obj) return logical def set_vdev_map(self, zpool): """ set_vdev_map() - walk the vdev_map to set the zpool's vdev entries and update existing physical DOC entries with the proper in_zpool and in_vdev attributes. zpool - zpool DOC object """ # get the list of Disk DOC objects already inserted disklist = self.root.get_children(class_type=Disk) # get the vdev mappings for this pool vdev_map = vdevs._get_vdev_mapping(zpool.name) for vdev_type, vdev_entries in vdev_map.iteritems(): in_vdev_label = "%s-%s" % (zpool.name, vdev_type) if vdev_type != "none": redundancy = vdev_type.partition("-")[0] else: redundancy = vdev_type # create a Vdev DOC entry for the vdev_type zpool.add_vdev(in_vdev_label, redundancy) for full_entry in vdev_entries: # remove the device path from the entry entry = full_entry.rpartition("/dev/dsk/")[2] # try to partition the entry for slices (vdev_ctd, vdev_letter, vdev_index) = entry.rpartition("s") # if the entry is not a slice, vdev_letter and index will # be empty strings if not vdev_letter: # try to partition the entry for partitions (vdev_ctd, vdev_letter, vdev_index) = \ entry.rpartition("p") # if the entry is also not a partition skip this entry if not vdev_letter: continue # walk the disk list looking for a matching ctd for disk in disklist: if hasattr(disk, "ctd"): if disk.ctd == vdev_ctd: # this disk is a match if vdev_letter == "s": child_list = disk.get_descendants( class_type=Slice) elif vdev_letter == "p": child_list = disk.get_descendants( class_type=Partition) # walk the child list and look for a matching name for child in child_list: if child.name == vdev_index: # set the in_zpool and in_vdev attributes child.in_zpool = zpool.name child.in_vdev = in_vdev_label # break out of the disklist walk break def discover_BEs(self, zpool_name="", name=None): """ discover_BEs - method to discover all Boot Environments (BEs) on the system. """ be_list = be.be_list(name) # walk each zpool already discovered and add BEs as necessary for zpool in self.root.get_descendants(class_type=Zpool): # check to see if we only want a subset of zpools. if zpool_name and zpool_name != zpool.name: continue for be_name, be_pool, root_ds, is_active in be_list: if be_pool == zpool.name: zpool.insert_children(BE(be_name)) def discover_entire_system(self, add_physical=True): """ discover_entire_system - populates the root node of the DOC tree with the entire physical layout of the system. add_physical - boolean value to signal if physical targets should be added to the DOC. """ # to find all the drives on the system, first start with the # controllers for controller in diskmgt.descriptors_by_type(const.CONTROLLER): # trap on the "/pseudo" controller (zvol swap and dump) if controller.name == "/pseudo" and add_physical: self.discover_pseudo(controller) else: # extract every drive on the given controller for drive in controller.drives: # skip USB floppy drives if controller.attributes is not None and \ controller.attributes.type == const.CTYPE_USB: try: di_props = di_find_prop("compatible", controller.name) except Exception: di_props = list() if const.DI_FLOPPY in di_props: continue # query libdiskmgt for the drive's information new_disk = self.discover_disk(drive) # skip invalid drives and CDROM drives if new_disk is None or new_disk.iscdrom: continue if add_physical: self.root.insert_children(new_disk) # extract all of the devpaths from all of the drives already inserted devpath_list = [ disk.devpath for disk in self.root.get_descendants(class_type=Disk) ] # now walk all the drives in the system to make sure we pick up any # disks which have no controller (OVM Xen disks) for drive in diskmgt.descriptors_by_type(const.DRIVE): new_disk = self.discover_disk(drive) # skip invalid drives and CDROM drives if new_disk is None or new_disk.iscdrom or new_disk.ctd == "dump": continue # skip any disk we've already discovered if new_disk.devpath in devpath_list: continue if add_physical: self.root.insert_children(new_disk) def sparc_label_check(self): """ sparc_label_check - method to check for any unlabeled disks within the system. The AI manifest is checked to ensure discovery.py does not try to apply a VTOC label to a disk specified with slices marked with the 'preserve' action. """ # extract all of the disk objects from the AI manifest ai_disk_list = self.doc.volatile.get_descendants(class_type=Disk) # create a new list of disk CTD values where the user has specified a # 'preserve' action for a slice. preserve_disks = list() for ai_disk in ai_disk_list: slice_list = ai_disk.get_descendants(class_type=Slice) for slc in slice_list: if slc.action == "preserve": preserve_disks.append(ai_disk.ctd) # Since libdiskmgt has no mechanism to update it's internal view of the # disk layout once its scanned /dev, fork a process and allow # libdiskmgt to instantiate the drives first. Then in the context of # the main process, when libdiskmgt gathers drive information, the # drive list will be up to date. pid = os.fork() if pid == 0: for drive in diskmgt.descriptors_by_type(const.DRIVE): if drive.media is None: continue disk = Disk("disk") disk.ctd = drive.aliases[0].name # verify the drive can be read. If not, continue to the next # drive. if not self.verify_disk_read(disk.ctd, drive.media.attributes.blocksize): self.logger.debug("Skipping label check for %s" % disk.ctd) continue dma = drive.media.attributes # If a disk is missing some basic attributes then it most # likely has no disk label. Force a VTOC label onto the disk # so its geometry can be correctly determined. This should # only happen for unlabeled SPARC disks, so we're safe to apply # a VTOC label without fear of trashing fdisk partitions # containing other OSes. if (not DMMediaAttr.NACCESSIBLE in dma or \ not DMMediaAttr.BLOCKSIZE in dma) and \ not dma.removable: # only label the disk if it does not have any preserved # slices. if disk.ctd not in preserve_disks: if not self.dry_run: self.logger.info("%s is unlabeled. Forcing a " "VTOC label" % disk.ctd) try: disk.force_vtoc() except CalledProcessError as err: self.logger.info( "Warning: unable to label " "%s: %s\nThis warning can be ignored, " "unless the disk is your install volume." % (disk.ctd, err.popen.stderr)) else: self.logger.info("%s is unlabeled. Not forcing " "a VTOC label due to dry_run " "flag" % disk.ctd) else: self.logger.info( "%s is unlabeled but manifest " "specifies 'preserved' slices. Not forcing a " "VTOC label onto the disk." % disk.ctd) os._exit(0) else: _none, status = os.wait() if status != 0: raise RuntimeError("Unable to fork a process to reset drive " "geometry") def setup_iscsi(self): """ set up the iSCSI initiator appropriately (if specified) such that any physical/logical iSCSI devices can be discovered. """ SVC = "svc:/network/iscsi/initiator:default" # pull out all of the iscsi entries from the DOC iscsi_list = self.doc.get_descendants(class_type=Iscsi) # if there's nothing to do, simply return if not iscsi_list: return # verify iscsiadm is available if not os.path.exists(ISCSIADM): raise RuntimeError("iSCSI discovery enabled but %s does " \ "not exist" % ISCSIADM) # ensure the iscsi/initiator service is online state_cmd = [SVCS, "-H", "-o", "STATE", SVC] p = run(state_cmd, check_result=Popen.ANY) if p.returncode != 0: # iscsi/initiator is not installed raise RuntimeError("%s not found - is it installed?" % SVC) # if the service is offline, enable it state = p.stdout.strip() if state == "offline": cmd = [SVCADM, "enable", "-s", SVC] run(cmd) # verify the service is now online p = run(state_cmd, check_result=Popen.ANY) state = p.stdout.strip() if state != "online": raise RuntimeError("Unable to start %s" % SVC) elif state != "online": # the service is in some other kind of state, so raise an error raise RuntimeError("%s requires manual servicing" % SVC) for iscsi in iscsi_list: # check iscsi.source for dhcp. If set, query dhcpinfo for the # iSCSI boot parameters and set the rest of the Iscsi object # attributes if iscsi.source == "dhcp": p = run([DHCPINFO, "Rootpath"]) # RFC 4173 defines the format of iSCSI boot parameters in DHCP # Rootpath as follows: # Rootpath=iscsi:<IP>:<protocol>:<port>:<LUN>:<target> iscsi_str = p.stdout.partition('=')[2] params = iscsi_str.split(':') iscsi.target_ip = params[1] iscsi.target_port = params[3] iscsi.target_lun = params[4] iscsi.target_name = params[5] if iscsi.target_name is not None: # set up static discovery of targets discovery_str = iscsi.target_name + "," + iscsi.target_ip if iscsi.target_port is not None: discovery_str += ":" + iscsi.target_port cmd = [ISCSIADM, "add", "static-config", discovery_str] run(cmd) cmd = [ISCSIADM, "modify", "discovery", "--static", "enable"] run(cmd) iscsi_list_cmd = [ ISCSIADM, "list", "target", "-S", discovery_str ] else: # set up discovery of sendtargets targets discovery_str = iscsi.target_ip if iscsi.target_port is not None: discovery_str += ":" + iscsi.target_port cmd = [ISCSIADM, "add", "discovery-address", discovery_str] run(cmd) cmd = [ ISCSIADM, "modify", "discovery", "--sendtargets", "enable" ] run(cmd) iscsi_list_cmd = [ISCSIADM, "list", "target", "-S"] # run devfsadm and wait for the iscsi devices to configure run([DEVFSADM, "-i", "iscsi"]) # list all the targets found iscsi_list = run(iscsi_list_cmd) # the output will look like: # # Target: <iqn string> # Alias: - # TPGT: 1 # ISID: 4000002a0000 # Connections: 1 # LUN: 1 # Vendor: SUN # Product: COMSTAR # OS Device Name: <ctd> # LUN: 0 # Vendor: SUN # Product: COMSTAR # OS Device Name: <ctd> # # The LUN number and ctd strings are the only values we're # interested in. iscsi_dict = dict() # walk the output from iscsiadm list target to create a mapping # between ctd and LUN number. for line in iscsi_list.stdout.splitlines(): line = line.lstrip() if line.startswith("LUN:"): lun_num = line.split(": ")[1] if line.startswith("OS Device Name:") and lun_num is not None: iscsi_ctd = line.rpartition("/")[2] iscsi_dict[iscsi_ctd] = lun_num # reset the lun_num for the next lun lun_num = None # try to map iscsi_lun back to iscsi.target_lun for iscsi_ctd, iscsi_lun in iscsi_dict.items(): if iscsi.target_lun is not None: if iscsi.target_lun == iscsi_lun: iscsi.parent.ctd = iscsi_ctd.partition("s2")[0] break else: iscsi.parent.ctd = iscsi_ctd.partition("s2")[0] break else: raise RuntimeError("target_lun: %s not found on target" % iscsi.target_lun) def execute(self, dry_run=False): """ primary execution checkpoint for Target Discovery """ self.dry_run = dry_run # setup iSCSI so that all iSCSI physical and logical devices can be # discovered self.setup_iscsi() # for sparc, check each disk to make sure there's a label if self.arch == "sparc": self.sparc_label_check() # check to see if the user specified a search_type if self.search_type == DISK_SEARCH_NAME: try: # check to see if the search name is either c#t#d# or c#d# if re.match(DISK_RE, self.search_name, re.I): dmd = diskmgt.descriptor_from_key(const.ALIAS, self.search_name) alias = diskmgt.DMAlias(dmd.value) drive = alias.drive else: dmd = diskmgt.descriptor_from_key(const.DRIVE, self.search_name) drive = diskmgt.DMDrive(dmd.value) except OSError as err: raise RuntimeError("Unable to look up %s - %s" % \ (self.search_name, err)) # insert the drive information into the tree new_disk = self.discover_disk(drive) if new_disk is not None: self.root.insert_children(new_disk) elif self.search_type == ZPOOL_SEARCH_NAME: self.discover_entire_system(add_physical=False) self.root.insert_children(self.discover_zpools(self.search_name)) # Add all Boot Environments that are contained in this zpool self.discover_BEs(self.search_name) else: self.discover_entire_system() # Add the discovered zpool objects self.root.insert_children(self.discover_zpools()) # Add all Boot Environments self.discover_BEs() # Add the root node to the DOC self.doc.persistent.insert_children(self.root)
class TestDiskSlice(unittest.TestCase): def setUp(self): self.engine = engine_test_utils.get_new_engine_instance() self.doc = self.engine.data_object_cache.volatile # create some DOC objects self.target = Target(Target.DESIRED) self.doc.insert_children(self.target) self.disk = Disk("disk") self.disk.ctd = "c8t1d0" self.disk.disk_prop = DiskProp() self.disk.disk_prop.dev_size = Size(str(200) + Size.gb_units) self.disk.disk_prop.blocksize = BLOCKSIZE self.disk.disk_prop.cylsize = CYLSIZE self.disk.disk_geometry = DiskGeometry() self.target.insert_children(self.disk) def tearDown(self): engine_test_utils.reset_engine() def test_update_vtoc(self): slice1 = Slice(1) slice1.action = "create" slice1.size = Size("4" + Size.sector_units) slice1.start_sector = 1 slice1.tag = const.V_BOOT slice1.flag = const.V_RONLY slice2 = Slice(2) slice2.action = "create" slice2.size = Size("8" + Size.sector_units) slice2.start_sector = 10 slice2.tag = const.V_BACKUP slice2.flag = const.V_RONLY slice3 = Slice(3) slice3.action = "preserve" slice3.size = Size("20" + Size.sector_units) slice3.start_sector = 20 slice3.tag = const.V_USR slice3.flag = const.V_UNMNT slices_list = [slice1, slice2, slice3] extvtocp = C.pointer(cstruct.extvtoc()) c = extvtocp.contents self.disk.geometry.ncly = 5 self.disk._update_vtoc_struct(extvtocp, slices_list, 10) self.failIf(\ c.v_part[int(slice1.name)].p_size != slice1.size.sectors or \ c.v_part[int(slice1.name)].p_start != slice1.start_sector or \ c.v_part[int(slice1.name)].p_tag != slice1.tag or \ c.v_part[int(slice1.name)].p_flag != slice1.flag) self.failIf(\ c.v_part[int(slice2.name)].p_size != slice2.size.sectors or \ c.v_part[int(slice2.name)].p_start != slice2.start_sector or \ c.v_part[int(slice2.name)].p_tag != slice2.tag or \ c.v_part[int(slice2.name)].p_flag != slice2.flag) self.failIf(\ c.v_part[int(slice3.name)].p_size != slice3.size.sectors or \ c.v_part[int(slice3.name)].p_start != slice3.start_sector or \ c.v_part[int(slice3.name)].p_tag != slice3.tag or \ c.v_part[int(slice3.name)].p_flag != slice3.flag) def test_slice_on_part(self): self.disk.geometry.nheads = 24 self.disk.geometry.nsectors = 848 self.disk.geometry.blocksize = 512 self.disk.geometry.ncyl = 14089 part = Partition(2) part.action = "create" part.start_sector = 0 part.size = Size("50" + Size.gb_units) part.part_type = "primary" part.bootid = Partition.ACTIVE self.disk.insert_children(part) slice1 = Slice(1) slice1.action = "create" slice1.size = Size(str(GBSECTOR) + Size.sector_units) slice1.start_sector = CYLSIZE slice1.tag = const.V_USR slice1.flag = 0 part.insert_children(slice1) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_swap_slices(self): self.disk.geometry.nheads = 24 self.disk.geometry.nsectors = 848 self.disk.geometry.blocksize = 512 self.disk.geometry.ncyl = 14089 part = Partition(2) part.action = "create" part.start_sector = 0 part.size = Size("50" + Size.gb_units) part.part_type = "primary" part.bootid = Partition.ACTIVE self.disk.insert_children(part) slice1 = Slice(1) slice1.action = "create" slice1.size = Size(str(GBSECTOR) + Size.sector_units) slice1.start_sector = CYLSIZE slice1.tag = const.V_SWAP slice1.is_swap = True slice2 = Slice(2) slice2.action = "create" slice2.size = Size(str(GBSECTOR) + Size.sector_units) slice2.start_sector = slice1.start_sector + slice1.size.sectors slice2.tag = const.V_SWAP slice2.is_swap = True part.insert_children([slice1, slice2]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err))
class TestDiskLabeling(unittest.TestCase): def setUp(self): self.engine = engine_test_utils.get_new_engine_instance() self.doc = self.engine.data_object_cache.volatile # create some DOC objects self.target = Target(Target.DESIRED) self.doc.insert_children(self.target) self.disk = Disk("disk") self.disk.ctd = "c8t1d0" self.disk.disk_prop = DiskProp() self.disk.disk_prop.blocksize = BLOCKSIZE self.disk.disk_prop.cylsize = CYLSIZE self.disk.disk_geometry = DiskGeometry() self.disk.disk_prop.dev_size = Size("500gb") self.target.insert_children(self.disk) def tearDown(self): engine_test_utils.reset_engine() def test_part_preserve(self): part = Partition(1) part.action = "preserve" part.part_type = "primary" part.bootid = Partition.ACTIVE part.size = Size("0b") part.start_sector = 0 part2 = Partition(2) part2.action = "preserve" part2.part_type = "primary" part2.bootid = 0 part2.size = Size("0b") part2.start_sector = 0 self.disk.insert_children([part, part2]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_slice_on_part_preserve(self): part = Partition(1) part.action = "preserve" part.type = "primary" part.bootid = Partition.ACTIVE part.start_sector = 0 part.size = Size("50" + Size.gb_units) part2 = Partition(2) part2.action = "preserve" part2.type = "primary" part2.bootid = 0 part2.size = Size("50" + Size.gb_units) part2.start_sector = 50 * GBSECTOR + 50 self.disk.insert_children([part, part2]) slice1 = Slice(1) slice1.action = "preserve" slice1.size = Size(str(GBSECTOR) + Size.sector_units) slice1.start_sector = CYLSIZE slice2 = Slice(2) slice2.action = "preserve" slice2.size = Size(str(GBSECTOR) + Size.sector_units) slice2.start_sector = CYLSIZE + GBSECTOR + 1 slice3 = Slice(3) slice3.action = "preserve" slice3.size = Size(str(GBSECTOR) + Size.sector_units) slice3.start_sector = CYLSIZE + (2 * GBSECTOR + 2) part.insert_children([slice1, slice2, slice3]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_slice_preserve(self): slice1 = Slice(1) slice1.action = "preserve" slice1.size = Size(str(GBSECTOR) + Size.sector_units) slice1.start_sector = CYLSIZE slice2 = Slice(2) slice2.action = "preserve" slice2.size = Size(str(GBSECTOR) + Size.sector_units) slice2.start_sector = CYLSIZE + GBSECTOR + 1 slice3 = Slice(3) slice3.action = "preserve" slice3.size = Size(str(GBSECTOR) + Size.sector_units) slice3.start_sector = CYLSIZE + (2 * GBSECTOR + 2) self.disk.insert_children([slice1, slice2, slice3]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_part_not_preserve(self): part = Partition(1) part.action = "create" part.part_type = "primary" part.bootid = Partition.ACTIVE part.size = Size("2gb") part2 = Partition(2) part2.action = "destroy" part2.part_type = "primary" part2.bootid = 0 part2.size = Size("2gb") self.disk.insert_children([part, part2]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_slice_on_part_not_preserve(self): part = Partition(1) part.action = "preserve" part.part_type = "primary" part.bootid = Partition.ACTIVE part.size = Size("50" + Size.gb_units) part.start_sector = 0 part2 = Partition(2) part2.action = "preserve" part2.part_type = "primary" part2.bootid = 0 part2.size = Size("50" + Size.gb_units) part2.start_sector = 50 * GBSECTOR + 50 self.disk.insert_children([part, part2]) slice1 = Slice(1) slice1.action = "create" slice1.size = Size(str(GBSECTOR) + Size.sector_units) slice1.start_sector = CYLSIZE slice2 = Slice(2) slice2.action = "create" slice2.size = Size(str(GBSECTOR) + Size.sector_units) slice2.start_sector = CYLSIZE + GBSECTOR + 1 slice3 = Slice(3) slice3.action = "destroy" slice3.size = Size(str(GBSECTOR) + Size.sector_units) slice3.start_sector = CYLSIZE + (2 * GBSECTOR + 2) part.insert_children([slice1, slice2, slice3]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_slice_not_preserve(self): slice1 = Slice(1) slice1.action = "create" slice1.size = Size(str(GBSECTOR) + Size.sector_units) slice1.start_sector = CYLSIZE slice2 = Slice(2) slice2.action = "create" slice2.size = Size(str(GBSECTOR) + Size.sector_units) slice2.start_sector = CYLSIZE + GBSECTOR + 1 slice3 = Slice(3) slice3.action = "destroy" slice3.size = Size(str(GBSECTOR) + Size.sector_units) slice3.start_sector = CYLSIZE + (2 * GBSECTOR + 2) self.disk.insert_children([slice1, slice2, slice3]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err))
class TestZpool(unittest.TestCase): def setUp(self): self.engine = engine_test_utils.get_new_engine_instance() self.doc = self.engine.data_object_cache.volatile # create DOC objects self.target = Target(Target.DESIRED) self.doc.insert_children(self.target) self.logical = Logical("logical") self.disk1 = Disk("disk") self.disk1.ctd = "c8t1d0" self.disk1.disk_prop = DiskProp() self.disk1.disk_prop.blocksize = 512 self.disk2 = Disk("disk2") self.disk2.ctd = "c8t2d0" self.disk2.disk_prop = DiskProp() self.disk2.disk_prop.blocksize = 512 def tearDown(self): self.target.delete_children() self.target.delete() engine_test_utils.reset_engine() def test_one_disk_zpool_create(self): self.disk1.in_zpool = "test_zpool" zpool = Zpool("test_zpool") zpool.action = "create" self.logical.insert_children(zpool) self.target.insert_children([self.disk1, self.logical]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_two_disk_zpool_create(self): self.disk1.in_zpool = "test_zpool" self.disk2.in_zpool = "test_zpool" zpool = Zpool("test_zpool") zpool.action = "create" self.logical.insert_children(zpool) self.target.insert_children([self.disk1, self.disk2, self.logical]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_whole_disk_zpool_create(self): self.disk1.in_zpool = "test_zpool" self.disk1.whole_disk = True self.disk2.in_zpool = "test_zpool" self.disk2.whole_disk = True zpool = Zpool("test_zpool") zpool.action = "create" self.logical.insert_children(zpool) self.target.insert_children([self.disk1, self.disk2, self.logical]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_empty_zpool_delete(self): zpool = Zpool("test_zpool") zpool.action = "delete" self.logical.insert_children(zpool) self.target.insert_children(self.logical) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_full_zpool_delete(self): zpool = Zpool("test_zpool") zpool.action = "delete" fs1 = Filesystem("test_zpool/fs1") fs2 = Filesystem("test_zpool/fs2") fs3 = Filesystem("test_zpool/fs3") zpool.insert_children([fs1, fs2, fs3]) self.logical.insert_children(zpool) self.target.insert_children(self.logical) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_empty_zpool_preserve(self): zpool = Zpool("test_zpool") zpool.action = "preserve" self.logical.insert_children(zpool) self.target.insert_children(self.logical) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_full_zpool_preserve(self): zpool = Zpool("test_zpool") zpool.action = "preserve" fs1 = Filesystem("test_zpool/fs1") fs2 = Filesystem("test_zpool/fs2") fs3 = Filesystem("test_zpool/fs3") zpool.insert_children([fs1, fs2, fs3]) self.logical.insert_children(zpool) self.target.insert_children(self.logical) self.doc.insert_children(self.target) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_filesystem_create(self): zpool = Zpool("test_zpool") zpool.action = "preserve" fs1 = Filesystem("test_zpool/fs1") fs1.action = "create" fs2 = Filesystem("test_zpool/fs2") fs2.action = "create" fs3 = Filesystem("test_zpool/fs3") fs3.action = "create" zpool.insert_children([fs1, fs2, fs3]) self.logical.insert_children(zpool) self.target.insert_children(self.logical) self.doc.insert_children(self.target) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_filesystem_create_and_delete(self): zpool = Zpool("test_zpool") zpool.action = "preserve" fs1 = Filesystem("test_zpool/fs1") fs1.action = "create" fs2 = Filesystem("test_zpool/fs2") fs2.action = "delete" fs3 = Filesystem("test_zpool/fs3") fs3.action = "create" zpool.insert_children([fs1, fs2, fs3]) self.logical.insert_children(zpool) self.target.insert_children(self.logical) self.doc.insert_children(self.target) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_zvol_create(self): zpool = Zpool("test_zpool") zpool.action = "preserve" fs1 = Filesystem("test_zpool/swap") fs1.action = "create" fs2 = Filesystem("test_zpool/dump") fs2.action = "create" zpool.insert_children([fs1, fs2]) self.logical.insert_children(zpool) self.target.insert_children(self.logical) self.doc.insert_children(self.target) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_zvol_create_and_delete(self): zpool = Zpool("test_zpool") zpool.action = "preserve" fs1 = Filesystem("test_zpool/swap") fs1.action = "delete" fs2 = Filesystem("test_zpool/dump") fs2.action = "create" zpool.insert_children([fs1, fs2]) self.logical.insert_children(zpool) self.target.insert_children(self.logical) self.doc.insert_children(self.target) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_full_zpool_create(self): zpool = Zpool("test_zpool") zpool.action = "create" fs1 = Filesystem("test_zpool/swap") fs1.action = "create" fs2 = Filesystem("test_zpool/dump") fs2.action = "create" zpool.insert_children([fs1, fs2]) self.logical.insert_children(zpool) self.target.insert_children(self.logical) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_pool_and_dataset_options(self): zpool = Zpool("test_zpool") zpool.action = "preserve" fs1 = Filesystem("test_zpool/fs1") fs1.action = "create" fs2 = Filesystem("test_zpool/fs2") fs2.action = "create" fs3 = Filesystem("test_zpool/fs3") fs3.action = "create" pool_options = PoolOptions("pool options", dict()) fs_options = DatasetOptions("fs options", dict()) pool_options.data_dict["autoexpand"] = "off" fs_options.data_dict["atime"] = "on" zpool.insert_children([fs1, fs2, fs3, pool_options, fs_options]) self.logical.insert_children(zpool) self.target.insert_children(self.logical) self.doc.insert_children(self.target) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_two_disk_vdev_create(self): self.disk1.in_zpool = "test_zpool" self.disk1.in_vdev = "test_mirror" self.disk2.in_zpool = "test_zpool" self.disk2.in_vdev = "test_mirror" zpool = Zpool("test_zpool") zpool.action = "create" vdev = Vdev("test_mirror") vdev.redundancy = "mirror" zpool.insert_children(vdev) self.logical.insert_children(zpool) self.target.insert_children([self.disk1, self.disk2, self.logical]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err)) def test_multi_disk_multi_vdev_create(self): self.disk1.in_zpool = "test_zpool" self.disk1.in_vdev = "test_mirror" self.disk2.in_zpool = "test_zpool" self.disk2.in_vdev = "test_mirror" self.disk3 = Disk("disk3") self.disk3.ctd = "c8t3d0" self.disk3.in_zpool = "test_zpool" self.disk3.in_vdev = "test_raidz" self.disk4 = Disk("disk4") self.disk4.ctd = "c8t4d0" self.disk4.in_zpool = "test_zpool" self.disk4.in_vdev = "test_raidz" self.disk5 = Disk("disk5") self.disk5.ctd = "c8t5d0" self.disk5.in_zpool = "test_zpool" self.disk5.in_vdev = "test_raidz" self.disk6 = Disk("disk6") self.disk6.ctd = "c8t6d0" self.disk6.in_zpool = "test_zpool" self.disk6.in_vdev = "test_spare" self.disk7 = Disk("disk7") self.disk7.ctd = "c8t7d0" self.disk7.in_zpool = "test_zpool" self.disk7.in_vdev = "test_log" zpool1 = Zpool("test_zpool") zpool1.action = "create" vdev1 = Vdev("test_mirror") vdev1.redundancy = "mirror" vdev2 = Vdev("test_raidz") vdev2.redundancy = "raidz" vdev3 = Vdev("test_log") vdev3.redundancy = "log" vdev4 = Vdev("test_spare") vdev4.redundancy = "spare" zpool1.insert_children([vdev1, vdev2, vdev3, vdev4]) self.logical.insert_children(zpool1) self.target.insert_children([self.disk1, self.disk2, self.disk3, \ self.disk4, self.disk5, self.disk6, self.disk7, self.logical]) t = instantiation.TargetInstantiation("test_ti") try: t.execute(dry_run=True) except Exception as err: self.fail(str(err))