コード例 #1
0
    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()
コード例 #2
0
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
コード例 #3
0
ファイル: test_distro_const.py プロジェクト: alhazred/caiman
    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)
コード例 #4
0
    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")
コード例 #5
0
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))
コード例 #6
0
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))
コード例 #7
0
    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)
コード例 #8
0
    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)
コード例 #9
0
    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")
コード例 #10
0
    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)
コード例 #11
0
    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
コード例 #12
0
ファイル: ti_full.py プロジェクト: alhazred/caiman
    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)
コード例 #13
0
    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)
コード例 #14
0
    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
コード例 #15
0
    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)
コード例 #16
0
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))
コード例 #17
0
ファイル: test_distro_const.py プロジェクト: alhazred/caiman
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)
コード例 #18
0
    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)
コード例 #19
0
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
コード例 #20
0
ファイル: ti_full.py プロジェクト: SynetoStorageOS/caiman
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))
コード例 #21
0
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)
コード例 #22
0
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))
コード例 #23
0
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)
コード例 #24
0
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))
コード例 #25
0
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)
コード例 #26
0
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))
コード例 #27
0
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))
コード例 #28
0
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)
コード例 #29
0
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))
コード例 #30
0
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))
コード例 #31
0
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))