Beispiel #1
0
    def setUp(self):
        """
        set up method
        """
        super(Snapshot, self).setUp()
        self.log.info("==In setUp, self.context= %s", self.context)

        # initialize a python pool object then create the underlying
        # daos storage and connect to it
        self.prepare_pool()

        try:
            # create a container
            self.container = DaosContainer(self.context)
            self.container.create(self.pool.pool.handle)

        except DaosApiError as error:
            self.log.info("Error detected in DAOS pool container setup: %s",
                          str(error))
            self.log.info(traceback.format_exc())
            self.fail("##Test failed on setUp, before snapshot taken")

        # now open it
        self.container.open()

        # do a query and compare the UUID returned from create with
        # that returned by query
        self.container.query()

        if self.container.get_uuid_str() != c_uuid_to_str(
                self.container.info.ci_uuid):
            self.fail("##Container UUID did not match the one in info.")
Beispiel #2
0
    def check_container_info(self, ci_uuid=None, ci_nsnapshots=None):
        # pylint: disable=unused-argument
        """Check the container info attributes.

        Note:
            Arguments may also be provided as a string with a number preceded
            by '<', '<=', '>', or '>=' for other comparisons besides the
            default '=='.

        Args:
            ci_uuid (str, optional): container uuid. Defaults to None.
            ci_nsnapshots (int, optional): number of snapshots.
                Defaults to None.

        Note:
            Arguments may also be provided as a string with a number preceded
            by '<', '<=', '>', or '>=' for other comparisons besides the
            default '=='.

        Returns:
            bool: True if at least one expected value is specified and all the
                specified values match; False otherwise

        """
        self.get_info()
        checks = [(key, c_uuid_to_str(getattr(self.info, key))
                   if key == "ci_uuid" else getattr(self.info, key), val)
                  for key, val in locals().items()
                  if key != "self" and val is not None]
        return self._check_info(checks)
Beispiel #3
0
    def setUp(self):
        """
        set up method
        """
        super(Snapshot, self).setUp()
        # get parameters from yaml file, set default
        createmode = self.params.get("mode", '/run/poolparams/createmode/',
                                     511)
        createuid = os.geteuid()
        creategid = os.getegid()
        createsetid = self.params.get("setname", '/run/poolparams/createset/')
        createsize = self.params.get("size", '/run/poolparams/createsize/')
        self.log.info("==In setUp, self.context= %s", self.context)

        try:

            # initialize a python pool object then create the underlying
            # daos storage
            self.pool = DaosPool(self.context)
            self.pool.create(createmode, createuid, creategid, createsize,
                             createsetid, None)

            # need a connection to the pool with rw permission
            #    DAOS_PC_RO = int(1 << 0)
            #    DAOS_PC_RW = int(1 << 1)
            #    DAOS_PC_EX = int(1 << 2)
            self.pool.connect(1 << 1)

            # create a container
            self.container = DaosContainer(self.context)
            self.container.create(self.pool.handle)

        except DaosApiError as error:
            self.log.info("Error detected in DAOS pool container setup: %s",
                          str(error))
            self.log.info(traceback.format_exc())
            self.fail("##Test failed on setUp, before snapshot taken")

        # now open it
        self.container.open()

        # do a query and compare the UUID returned from create with
        # that returned by query
        self.container.query()

        if self.container.get_uuid_str() != c_uuid_to_str(
                self.container.info.ci_uuid):
            self.fail("##Container UUID did not match the one in info.")
Beispiel #4
0
    def check_pool_info(self,
                        pi_uuid=None,
                        pi_ntargets=None,
                        pi_nnodes=None,
                        pi_ndisabled=None,
                        pi_map_ver=None,
                        pi_leader=None,
                        pi_bits=None):
        # pylint: disable=unused-argument
        """Check the pool info attributes.

        Note:
            Arguments may also be provided as a string with a number preceded
            by '<', '<=', '>', or '>=' for other comparisons besides the
            default '=='.

        Args:
            pi_uuid (str, optional): pool uuid. Defaults to None.
            pi_ntargets (int, optional): number of targets. Defaults to None.
            pi_nnodes (int, optional): number of nodes. Defaults to None.
            pi_ndisabled (int, optional): number of disabled. Defaults to None.
            pi_map_ver (int, optional): pool map version. Defaults to None.
            pi_leader (int, optional): pool leader. Defaults to None.
            pi_bits (int, optional): pool bits. Defaults to None.

        Note:
            Arguments may also be provided as a string with a number preceded
            by '<', '<=', '>', or '>=' for other comparisons besides the
            default '=='.

        Returns:
            bool: True if at least one expected value is specified and all the
                specified values match; False otherwise

        """
        self.get_info()
        checks = [(key, c_uuid_to_str(getattr(self.info, key))
                   if key == "pi_uuid" else getattr(self.info, key), val)
                  for key, val in list(locals().items())
                  if key != "self" and val is not None]
        return self._check_info(checks)
    def test_container_basics(self):
        """
        Test basic container create/destroy/open/close/query.

        :avocado: tags=all,container,pr,medium,basecont
        """
        try:
            # Parameters used in pool create
            pool_mode = self.params.get("mode", '/run/pool/createmode/')
            pool_name = self.params.get("setname", '/run/pool/createset/')
            pool_size = self.params.get("size", '/run/pool/createsize/')

            # Create pool and connect
            self.pool = get_pool(self.context, pool_mode, pool_size, pool_name,
                                 1, self.d_log)

            # Create a container and open
            self.container = get_container(self.context, self.pool, self.d_log)

            # Query and compare the UUID returned from create with
            # that returned by query
            self.container.query()

            if self.container.get_uuid_str() != c_uuid_to_str(
                    self.container.info.ci_uuid):
                self.fail("Container UUID did not match the one in info'n")

            self.container.close()

            # Wait and destroy
            time.sleep(5)
            self.container.destroy()

        except DaosApiError as excep:
            print(excep)
            print(traceback.format_exc())
            self.fail("Test was expected to pass but it failed.\n")
        except Exception as excep:
            self.fail("Daos code segfaulted most likely, error: %s" % excep)
Beispiel #6
0
    def test_tx_basics(self):
        """
        Perform I/O to an object in a container in 2 different transactions,
        verifying basic I/O and transactions in particular.

        NOTE: this was an epoch test and all I did was get it working with tx
        Not a good test at this point, need to redesign when tx is fully
        working.

        :avocado: tags=all,container,tx,small,smoke,pr,basictx
        """
        self.pool = None

        try:
            # parameters used in pool create
            createmode = self.params.get("mode", '/run/poolparams/createmode/')
            createuid = os.geteuid()
            creategid = os.getegid()
            createsetid = self.params.get("setname",
                                          '/run/poolparams/createset/')
            createsize = self.params.get("size", '/run/poolparams/createsize/')

            # initialize a python pool object then create the underlying
            # daos storage
            self.pool = DaosPool(self.context)
            self.pool.create(createmode, createuid, creategid,
                             createsize, createsetid, None)

            # need a connection to create container
            self.pool.connect(1 << 1)

            # create a container
            container = DaosContainer(self.context)
            container.create(self.pool.handle)

            # now open it
            container.open()

            # do a query and compare the UUID returned from create with
            # that returned by query
            container.query()

            if container.get_uuid_str() != c_uuid_to_str(
                    container.info.ci_uuid):
                self.fail("Container UUID did not match the one in info\n")

            # create an object and write some data into it
            thedata = "a string that I want to stuff into an object"
            thedatasize = 45
            dkey = "this is the dkey"
            akey = "this is the akey"

            oid, txn = container.write_an_obj(thedata, thedatasize,
                                              dkey, akey, None, None, 2)

            # read the data back and make sure its correct
            thedata2 = container.read_an_obj(thedatasize, dkey, akey,
                                             oid, txn)
            if thedata != thedata2.value:
                print("thedata>" + thedata)
                print("thedata2>" + thedata2.value)
                self.fail("Write data 1, read it back, didn't match\n")

            # repeat above, but know that the write_an_obj call is advancing
            # the epoch so the original copy remains and the new copy is in
            # a new epoch.
            thedata3 = "a different string"
            thedatasize2 = 19
            # note using the same keys so writing to the same spot
            dkey = "this is the dkey"
            akey = "this is the akey"

            oid, tx2 = container.write_an_obj(thedata3, thedatasize2,
                                              dkey, akey, oid, None, 2)

            # read the data back and make sure its correct
            thedata4 = container.read_an_obj(thedatasize2, dkey, akey,
                                             oid, tx2)
            if thedata3 != thedata4.value:
                self.fail("Write data 2, read it back, didn't match\n")

            # transactions generally don't work this way but need to explore
            # an alternative to below code once model is complete, maybe
            # read from a snapshot or read from TX_NONE etc.

            # the original data should still be there too
            #thedata5 = container.read_an_obj(thedatasize, dkey, akey,
            #                                 oid, transaction)
            #if thedata != thedata5.value:
            #    self.fail("Write data 3, read it back, didn't match\n")

            container.close()

            # wait a few seconds and then destroy
            time.sleep(5)
            container.destroy()

        except DaosApiError as excep:
            print(excep)
            print(traceback.format_exc())
            self.fail("Test was expected to pass but it failed.\n")
Beispiel #7
0
    def test_array_obj(self):
        """
        Test ID: DAOS-961

        Test Description: Writes an array to an object and then reads it
        back and verifies it.

        :avocado: tags=all,smoke,pr,object,tiny,basicobject
        """
        self.prepare_pool()

        try:
            # create a container
            container = DaosContainer(self.context)
            container.create(self.pool.pool.handle)
            self.plog.info("Container %s created.", container.get_uuid_str())

            # now open it
            container.open()

            # do a query and compare the UUID returned from create with
            # that returned by query
            container.query()

            if container.get_uuid_str() != c_uuid_to_str(
                    container.info.ci_uuid):
                self.fail("Container UUID did not match the one in info\n")

            # create an object and write some data into it
            thedata = []
            thedata.append("data string one")
            thedata.append("data string two")
            thedata.append("data string tre")
            dkey = "this is the dkey"
            akey = "this is the akey"

            self.plog.info("writing array to dkey >%s< akey >%s<.", dkey, akey)
            oid = container.write_an_array_value(thedata,
                                                 dkey,
                                                 akey,
                                                 obj_cls=3)

            # read the data back and make sure its correct
            length = len(thedata[0])
            thedata2 = container.read_an_array(len(thedata), length + 1, dkey,
                                               akey, oid)
            if thedata[0][0:length - 1] != thedata2[0][0:length - 1]:
                self.plog.error("Data mismatch")
                self.plog.error("Wrote: >%s<", thedata[0])
                self.plog.error("Read: >%s<", thedata2[0])
                self.fail("Write data, read it back, didn't match\n")

            if thedata[2][0:length - 1] != thedata2[2][0:length - 1]:
                self.plog.error("Data mismatch")
                self.plog.error("Wrote: >%s<", thedata[2])
                self.plog.error("Read: >%s<", thedata2[2])
                self.fail("Write data, read it back, didn't match\n")

            container.close()

            # wait a few seconds and then destroy
            time.sleep(5)
            container.destroy()

            self.plog.info("Test Complete")

        except DaosApiError as excep:
            self.plog.error("Test Failed, exception was thrown.")
            print(excep)
            print(traceback.format_exc())
            self.fail("Test was expected to pass but it failed.\n")
Beispiel #8
0
    def test_evict(self):
        """
        Test evicting a client from a pool.

        Test creates 2 pools on 4 target (pool_tgt [0,1,2,3])
        and 1 pool on 2 targets (pool_tgt_ut [0,1]).  The pools are connected
        to and a container with data is created on all 3.
        The evict is done on connection to the pool with 2 targets.
        The handle is removed.
        The test verifies that the other two pools were not affected
        by the evict
        :avocado: tags=all,pr,daily_regression,full_regression
        :avocado: tags=small
        :avocado: tags=pool,poolevict
        :avocado: tags=DAOS_5610
        """
        pool = []
        container = []
        # non_pool_servers = []
        # Target list is configured so that the pools are across all servers
        # except the pool under test is created on half of the servers
        pool_tgt = list(range(len(self.hostlist_servers)))
        pool_tgt_ut = list(range(int(len(self.hostlist_servers) / 2)))
        tlist = [pool_tgt, pool_tgt, pool_tgt_ut]
        pool_servers = [self.hostlist_servers[:len(tgt)] for tgt in tlist]
        # non_pool_servers = [self.hostlist_servers[len(tgt):] for tgt in tlist]
        # Create Connected TestPool
        for count, target_list in enumerate(tlist):
            pool.append(self.connected_pool(pool_servers[count], target_list))
            # Commented out due to DAOS-3836.
            # if len(non_pool_servers[count]) > 0:
            #    self.assertFalse(
            #        pool[count].check_files(non_pool_servers[count]),
            #        "Pool # {} data detected on non pool servers {} ".format(
            #            count+1, non_pool_servers[count]))

            self.log.info("Pool # %s is connected with handle %s", count + 1,
                          pool[count].pool.handle.value)

            container.append(TestContainer(pool[count]))
            container[count].get_params(self)
            container[count].create()
            container[count].write_objects(target_list[-1])

        try:
            self.log.info(
                "Attempting to evict clients from pool with UUID: %s",
                pool[-1].uuid)
            # Evict the last pool in the list
            pool[-1].dmg.pool_evict(pool=pool[-1].pool.get_uuid_str())
        except CommandFailure as result:
            self.fail("Detected exception while evicting a client {}".format(
                str(result)))

        for count in range(len(tlist)):
            # Commented out due to DAOS-3836.
            # # Check that all pool files still exist
            # if pool[count].check_files(pool_servers[count]):
            #    self.log.info(
            #        "Pool # %s with UUID %s still exists",
            #        count+1, pool[count].uuid)
            # else:
            #    self.fail(
            #        "Pool # {} with UUID {} does not exists".format(
            #            count+1, pool[count].uuid))

            # Verify connection to pools with pool_query; pool that was evicted
            # should fail the pool query because the handle was removed
            try:
                # Call daos api directly to avoid connecting to pool
                pool_info = pool[count].pool.pool_query()
            except DaosApiError as error:
                # expected error for evicted pool
                if count == len(tlist) - 1 and "-1002" in str(error):
                    self.log.info(
                        "Pool # %s was unable to query pool info due to "
                        "expected invalid handle error (-1002):\n\t%s",
                        count + 1, error)
                # unexpected error from pool_query
                else:
                    self.fail("Pool # {} failed pool query: {}".format(
                        count + 1, error))

                pool_info = None
            # Check that UUID of valid pools still exists
            if pool_info:
                if c_uuid_to_str(pool_info.pi_uuid) == pool[count].uuid:
                    self.log.info(
                        "Pool # %s UUID matches pool_info.pi_uuid %s",
                        count + 1, pool[count].uuid)
                else:
                    self.fail(
                        "Pool # {} UUID does not matches pool_info.pi_uuid:  "
                        "{} != {}".format(count + 1, pool[count].uuid,
                                          c_uuid_to_str(pool_info.pi_uuid)))
Beispiel #9
0
    def test_array_obj(self):
        """
        Test ID: DAOS-961

        Test Description: Writes an array to an object and then reads it
        back and verifies it.

        :avocado: tags=all,smoke,pr,object,tiny,basicobject
        """
        try:
            # parameters used in pool create
            createmode = self.params.get("mode",
                                         '/run/pool_params/createmode/')
            createsetid = self.params.get("setname",
                                          '/run/pool_params/createset/')
            createsize = self.params.get("size",
                                         '/run/pool_params/createsize/')
            createuid = os.geteuid()
            creategid = os.getegid()

            # initialize a python pool object then create the underlying
            # daos storage
            pool = DaosPool(self.context)
            pool.create(createmode, createuid, creategid, createsize,
                        createsetid, None)
            self.plog.info("Pool %s created.", pool.get_uuid_str())

            # need a connection to create container
            pool.connect(1 << 1)

            # create a container
            container = DaosContainer(self.context)
            container.create(pool.handle)
            self.plog.info("Container %s created.", container.get_uuid_str())

            # now open it
            container.open()

            # do a query and compare the UUID returned from create with
            # that returned by query
            container.query()

            if container.get_uuid_str() != c_uuid_to_str(
                    container.info.ci_uuid):
                self.fail("Container UUID did not match the one in info\n")

            # create an object and write some data into it
            thedata = []
            thedata.append("data string one")
            thedata.append("data string two")
            thedata.append("data string tre")
            dkey = "this is the dkey"
            akey = "this is the akey"

            self.plog.info("writing array to dkey >%s< akey >%s<.", dkey, akey)
            oid, epoch = container.write_an_array_value(thedata,
                                                        dkey,
                                                        akey,
                                                        obj_cls=3)

            # read the data back and make sure its correct
            length = len(thedata[0])
            thedata2 = container.read_an_array(len(thedata), length + 1, dkey,
                                               akey, oid, epoch)
            if thedata[0][0:length - 1] != thedata2[0][0:length - 1]:
                self.plog.error("Data mismatch")
                self.plog.error("Wrote: >%s<", thedata[0])
                self.plog.error("Read: >%s<", thedata2[0])
                self.fail("Write data, read it back, didn't match\n")

            if thedata[2][0:length - 1] != thedata2[2][0:length - 1]:
                self.plog.error("Data mismatch")
                self.plog.error("Wrote: >%s<", thedata[2])
                self.plog.error("Read: >%s<", thedata2[2])
                self.fail("Write data, read it back, didn't match\n")

            container.close()

            # wait a few seconds and then destroy
            time.sleep(5)
            container.destroy()

            # cleanup the pool
            pool.disconnect()
            pool.destroy(1)
            self.plog.info("Test Complete")

        except DaosApiError as excep:
            self.plog.error("Test Failed, exception was thrown.")
            print(excep)
            print(traceback.format_exc())
            self.fail("Test was expected to pass but it failed.\n")
Beispiel #10
0
Datei: evict.py Projekt: liw/daos
    def test_evict(self):
        """
        Test Steps:
        1. Create 2 pools on all server ranks.
        2. Create another pool on half of the ranks.
        3. After creating each pool, create a container and write objects.
        4. Verify that the pool file exists in /mnt/daos.
        5. Verify that the third pool's file doesn't exist on the half of the hosts that
        this pool wasn't created on.
        6. Evict the third pool on the half of the ranks.
        7. Verify that the pool file still exists in /mnt/daos for all three pools. i.e.,
        verify that the evict didn't cause the ill effect to the pool file.
        8. For all pools, call pool_query() over API. The first two pools should
        succeed. The last pool should fail because it was evicted.
        9. For all pools, write objects to the container. The first two pools should
        succeed. The last pool should fail because it was evicted.
        10. For the first two pools, check the UUID obtained from the pool_query() in
        the previous step and verify that the evict on the third pool didn't have ill
        effect.

        :avocado: tags=all,pr,daily_regression
        :avocado: tags=vm
        :avocado: tags=pool,pool_evict
        :avocado: tags=pool_evict_basic
        """
        # Do not use self.pool. It will cause -1002 error when disconnecting.
        pools = []
        containers = []

        host_count = len(self.hostlist_servers)
        all_ranks = list(range(host_count))
        first_half_count = int(host_count / 2)
        # half_ranks_with is the half of the all ranks that we'll create the third pool
        # on.
        half_ranks_with = list(range(first_half_count))
        # half_ranks_without is the half of the all ranks that we will not create a pool.
        half_ranks_without = list(range(first_half_count, host_count))

        # all_hosts is the list of hosts that maps to the all_ranks. e.g.,
        # rank 0: wolf-1
        # rank 1: wolf-4
        # rank 2: wolf-3
        # rank 3: wolf-2
        # then all_hosts would be ["wolf-1", "wolf-4", "wolf-3", "wolf-2"]. (Order
        # doesn't matter.)
        all_hosts = self.get_host_list(ranks=all_ranks)
        # Same idea as all_hosts. i.e., ["wolf-1", "wolf-4"] in above example.
        half_hosts_with = self.get_host_list(ranks=half_ranks_with)
        half_hosts_without = self.get_host_list(ranks=half_ranks_without)

        # Step 1 to 4. Create two pools, container, and write data.
        for _ in range(2):
            # Create a pool over all of the hosts, check the pool file, and connect.
            pools.append(self.connected_pool(hostlist=all_hosts, targets=all_ranks))
            # Create a container and write data to it.
            containers.append(self.get_container(pool=pools[-1]))
            containers[-1].write_objects()

        # Create a pool over the half of the hosts, check the pool file, and connect.
        pools.append(self.connected_pool(
            hostlist=half_hosts_with, targets=half_ranks_with))
        # Create a container and write data to it.
        containers.append(self.get_container(pool=pools[-1]))
        containers[-1].write_objects()

        # Step 5. Verify that the third pool's file doesn't exist on the half of the
        # hosts that this pool wasn't created on.
        if pools[-1].check_files(half_hosts_without):
            self.fail("Pool # 2 with UUID {} exists".format(pools[-1].uuid))
        else:
            self.log.info("Pool # 2 with UUID %s does not exist", pools[-1].uuid)

        # 6. Evict the third pool.
        self.verify_pool_evict(pool=pools[-1])

        # 7. Verify that the pool file still exists in /mnt/daos for all three pools.
        for index, pool in enumerate(pools):
            # Get the hostnames to search the pool file.
            if index in (0, 1):
                hosts = all_hosts
                failure_expected = False
            else:
                hosts = half_hosts_with
                failure_expected = True

            if pool.check_files(hosts):
                self.log.info(
                    "Pool # %d with UUID %s still exists", index, pool.uuid)
            else:
                self.fail(
                    "Pool # {} with UUID {} does not exist".format(index, pool.uuid))

            # 8. Verify connection to pools with pool_query(); pool that was evicted
            # should fail because the handle was removed.
            try:
                # Call daos api directly to avoid connecting to pool.
                pool_info = pool.pool.pool_query()
                if failure_expected:
                    self.fail(
                        "Pool # {} was evicted, but pool_query worked!".format(index))
            except DaosApiError as error:
                # Expected error for evicted pool.
                if failure_expected and "-1002" in str(error):
                    self.log.info(
                        "Pool # %d was unable to query pool info due to "
                        "expected invalid handle error (-1002):\n\t%s",
                        index, error)
                # unexpected error from pool_query
                else:
                    self.fail(
                        "Pool # {} failed pool query: {}".format(index, error))

                pool_info = None

            # 9. Try to write object to the container. It should fail for the evicted pool
            # and should work for other pools.
            try:
                containers[index].write_objects()
                if failure_expected:
                    self.fail(
                        "Pool {} was evicted, but write_objects worked!".format(index))
            except TestFail as error:
                if failure_expected and "-1002" in str(error):
                    msg = "Pool # {}: write_objects failed as expected.\n\t{}".format(
                        index, error)
                    self.log.info(msg)
                else:
                    self.fail("Pool # {} write_objects failed! {}".format(index, error))

            # 10. Check that we were able to obtain the UUID of the non-evicted pools.
            if pool_info:
                pool.connected = False
                if c_uuid_to_str(pool_info.pi_uuid) == pool.uuid:
                    self.log.info(
                        "Pool # %d UUID matches pool_info.pi_uuid %s", index, pool.uuid)
                else:
                    self.fail(
                        "Pool # {} UUID does not match pool_info.pi_uuid: "
                        "{} != {}".format(
                            index, pool.uuid, c_uuid_to_str(pool_info.pi_uuid)))