Beispiel #1
0
    def test_destroy_async(self):
        """Test container destroy for asynchronous mode.

        Test only positive case. We don't test negative case because the API is
        implemented so that it returns the error code before executing the
        callback function, so if we try it as it is, the test hangs.

        :avocado: tags=all,full_regression,container,cont_destroy_async
        """
        self.add_pool()

        cbh = CallbackHandler()
        self.container.append(TestContainer(pool=self.pool))

        # We don't need to create asynchronously, so set the CallbackHandler
        # after creating it.
        self.container[0].create()
        self.container[0].cb_handler = cbh

        try:
            self.container[0].destroy()
            self.assertEqual(
                cbh.ret_code, RC_SUCCESS,
                "Async destroy failed! RC = {}".format(cbh.ret_code))
        except DaosApiError as excep:
            print(excep)
            print(traceback.format_exc())
Beispiel #2
0
    def test_create_async(self):
        """Test container create for asynchronous mode.

        Test both positive and negative cases. For negative case, RC is -1002,
        but we just check if it's something other than 0 to make the test
        robust.

        The negative case is more like a test of the API implementation rather
        than DAOS itself.

        :avocado: tags=all,full_regression,container,cont_create_async
        """
        self.add_pool()
        ph = self.pool.pool.handle

        cbh1 = CallbackHandler()
        cbh2 = CallbackHandler()
        self.container.append(TestContainer(pool=self.pool, cb_handler=cbh1))
        self.container.append(TestContainer(pool=self.pool))

        # We can't use TestContainer.create after the pool is destroyed, but we
        # can call DaosContainer.create to create the underlying DaosContainer,
        # so manually instantiate it and set it.
        self.container[1].container = DaosContainer(self.pool.context)

        try:
            self.container[0].create()
            self.assertEqual(
                cbh1.ret_code, RC_SUCCESS,
                "Async create failed! RC = {}".format(cbh1.ret_code))

            # Destroy pool and try to create the second container. TestContainer
            # calls wait, but we're using DaosContainer, so we need to manually
            # call it.
            self.pool.destroy(1)
            self.container[1].container.create(poh=ph,
                                               con_uuid=None,
                                               cb_func=cbh2.callback)
            cbh2.wait()
            self.assertTrue(
                cbh2.ret_code is not None and cbh2.ret_code != RC_SUCCESS,
                "Async create of non-existing container succeeded!")
        except DaosApiError as excep:
            print(excep)
            print(traceback.format_exc())
Beispiel #3
0
    def test_close_async(self):
        """Test container close for asynchronous mode.

        Test both positive and negative cases.

        :avocado: tags=all,full_regression,container,cont_close_async
        """
        self.add_pool()

        cbh1 = CallbackHandler()
        cbh2 = CallbackHandler()
        tc1 = TestContainer(pool=self.pool)
        tc2 = TestContainer(pool=self.pool)
        self.container.append(tc1)
        self.container.append(tc2)

        # We need to open to test close.
        tc1.create()
        tc1.open()
        tc1.cb_handler = cbh1

        # We'll test to close the non-existing container, so just instantiate
        # the underlying DaosContainer and set it.
        tc2.container = DaosContainer(self.pool.context)
        tc2.cb_handler = cbh2

        try:
            tc1.close()
            self.assertEqual(
                cbh1.ret_code, RC_SUCCESS,
                "Async close failed! RC = {}".format(cbh1.ret_code))

            # If we use TestContainer, it'll call the wait for us, but we're
            # using DaosContainer, so we need to manually call it.
            tc2.container.close(cb_func=cbh2.callback)
            cbh2.wait()
            self.assertTrue(
                cbh2.ret_code is not None and cbh2.ret_code != RC_SUCCESS,
                "Async close of non-existing container succeeded! " +
                "RC = {}".format(cbh2.ret_code))
        except DaosApiError as excep:
            print(excep)
            print(traceback.format_exc())
Beispiel #4
0
    def test_query_async(self):
        """Test container query for asynchronous mode.

        Test both positive and negative cases.

        :avocado: tags=all,full_regression,container,cont_query_async
        """
        self.add_pool()

        cbh1 = CallbackHandler()
        cbh2 = CallbackHandler()
        tc1 = TestContainer(pool=self.pool)
        tc2 = TestContainer(pool=self.pool)
        self.container.append(tc1)
        self.container.append(tc2)

        tc1.create()
        tc1.cb_handler = cbh1

        tc2.container = DaosContainer(self.pool.context)
        tc2.cb_handler = cbh2

        try:
            tc1.get_info()
            self.assertEqual(
                cbh1.ret_code, RC_SUCCESS,
                "Async query failed! RC = {}".format(cbh1.ret_code))

            tc2.container.query(cb_func=cbh2.callback)
            cbh2.wait()
            self.assertTrue(
                cbh2.ret_code is not None and cbh2.ret_code != RC_SUCCESS,
                "Async query of non-existing container succeeded! " +
                "RC = {}".format(cbh2.ret_code))
        except DaosApiError as excep:
            print(excep)
            print(traceback.format_exc())
Beispiel #5
0
    def test_destroy_async(self):
        """Destroy pool asynchronously.

        Create two server groups. Perform destroy asynchronously
        Expect the destroy to work on the server group where the pool was
        created and expect the destroy pool to fail on the second server.

        :avocado: tags=all,medium,full_regression
        :avocado: tags=pool,destroy,destroyasync
        """
        # Start two server groups
        group_names = [self.server_group + "_a", self.server_group + "_b"]
        group_hosts = {
            group_names[0]: self.hostlist_servers[:1],
            group_names[1]: self.hostlist_servers[1:2]
        }
        self.start_servers(group_hosts)

        self.add_pool(create=False)
        self.pool.name.value = group_names[0]
        self.pool.create()
        self.log.info("Pool UUID is %s on server_group %s", self.pool.uuid,
                      group_names[0])

        # Commented out due to DAOS-3836.
        # # Check that the pool was created on server_group_a
        # self.assertTrue(
        #    self.pool.check_files(group_hosts[group_names[0]]),
        #    "Pool data not detected on servers before destroy")

        # Commented out due to DAOS-3836.
        # # Check that the pool was not created on server_group_b
        # self.assertFalse(
        #    self.pool.check_files(group_hosts[group_names[1]]),
        #    "Pool data detected on servers before destroy")

        # Create callback handler
        cb_handler = CallbackHandler()

        # Destroy pool on server_group_a with callback
        self.log.info("Attempting to destroy pool")
        self.pool.pool.destroy(0, cb_handler.callback)
        cb_handler.wait()
        if cb_handler.ret_code != 0:
            self.fail("destroy-pool was expected to PASS")

        # Commented out due to DAOS-3836.
        # self.assertFalse(
        #    self.pool.check_files(group_hosts[group_names[0]]),
        #    "Pool data detected on {} after destroy".format(group_names[0]))

        # Destroy pool with callback while stopping other server
        # Create new pool on server_group_a
        self.add_pool(create=False)
        self.pool.name.value = group_names[0]
        self.pool.create()
        self.log.info("Pool UUID is %s on server_group %s", self.pool.uuid,
                      group_names[0])

        # Commented out due to DAOS-3836.
        # # Check that the pool was created on server_group_a
        # self.assertTrue(
        #    self.pool.check_files(group_hosts[group_names[0]]),
        #    "Pool data not detected on servers before destroy")

        # Commented out due to DAOS-3836.
        # # Check that the pool was not created on server_group_b
        # self.assertFalse(
        #    self.pool.check_files(group_hosts[group_names[1]]),
        #    "Pool data detected on servers before destroy")

        self.log.info("Stopping one server")
        try:
            self.server_managers[1].stop()
        except ServerFailed as error:
            self.fail("Error stopping daos server group '{}': {}".format(
                group_names[1], error))

        self.log.info("Attempting to destroy pool")
        self.pool.pool.destroy(0, cb_handler.callback)
        cb_handler.wait()
        if cb_handler.ret_code != 0:
            # Avoid attempting to destroy the pool again in tearDown()
            self.pool.pool = None
            self.fail("destroy-pool was expected to PASS")
Beispiel #6
0
    def test_pool_attribute_async(self):
        """Test pool set/get/list attribute with callback.

        Test ID: DAOS-1359

        Test Steps:
        1. Create a pool
        2. Call set_attr asynchronously.
        3. Call list_attr asynchronously and verify the returned list.
        4. Call get_attr asynchronously and verify the returned name and value.

        Return code from set_attr and get_attr. list_attr should always return 0.

        set_attr: (Valid is for long, special, and "Negative-Name".)
        Name     Value     RC
        Valid    Valid     0
        Valid    None      -1003
        None     Valid     -1003
        None     None      -1003

        get_attr:
        Name     Value     RC
        Valid    Valid     0
        Valid    None      -1005
        Wrong    Valid     -1005
        Wrong    None      -1005
        None     Valid     -1003
        None     None      -1003

        :avocado: tags=all,full_regression
        :avocado: tags=vm
        :avocado: tags=pool,pool_attribute
        :avocado: tags=async_pool_attribute
        """
        self.add_pool()

        expected_for_param = []

        name = self.params.get("name", '/run/attrtests/name_handles/*/')
        attr_name = name[0]
        expected_for_param.append(name[1])
        value = self.params.get("value", '/run/attrtests/value_handles/*/')
        attr_val = value[0]
        expected_for_param.append(value[1])

        expected_result = 'PASS'
        for result in expected_for_param:
            if result == 'FAIL':
                expected_result = 'FAIL'
                break

        # Convert any test yaml string to bytes
        if isinstance(attr_name, str):
            attr_name = attr_name.encode("utf-8")
        if isinstance(attr_val, str):
            attr_val = attr_val.encode("utf-8")

        attr_dict = {attr_name: attr_val}

        callback_handler = CallbackHandler()

        # Test set_attr()
        try:
            self.pool.pool.set_attr(data=attr_dict,
                                    cb_func=callback_handler.callback)
            callback_handler.wait()

            # Verify the return code.
            # One exception is when we use the "Negative-Name" and valid value. In this
            # case, the method works, but we consider it as failure during get_attr test,
            # so temporarily use "PASS" here.
            if attr_name and b"Negative" in attr_name and attr_val:
                set_exp_result = "PASS"
            else:
                set_exp_result = expected_result
            self.verify_async_return_code(ret_code=callback_handler.ret_code,
                                          expected_result=set_exp_result,
                                          method_name="set_attr")
        except DaosApiError as excep:
            print(excep)
            print(traceback.format_exc())
            if expected_result == 'PASS':
                self.fail(
                    "set_attr was supposed to work, but failed! name-value = {}"
                    .format(attr_dict))

        # Test list_attr()
        try:
            size, buf = self.pool.pool.list_attr(
                cb_func=callback_handler.callback)
            callback_handler.wait()

            # Verify the return code.
            ret_code = callback_handler.ret_code
            if ret_code != 0:
                self.fail("Unexpected RC after list_attr! {}".format(ret_code))
        except DaosApiError as excep:
            print(excep)
            print(traceback.format_exc())
            if expected_result == "PASS":
                self.fail("list_attr failed!")

        if expected_result == "PASS":
            # Verify the list output.
            self.verify_list_attr(attr_dict, size.value, buf)

        # Verify get_attr()
        results = {}
        if attr_name and b"Negative" in attr_name:
            attr_name = b"rubbish"

        try:
            (buff, sizes) = self.pool.pool.get_attr(
                attr_names=[attr_name], cb_func=callback_handler.callback)
            callback_handler.wait()

            # Construct the result dictionary from buff and sizes.
            results = {attr_name: buff[0][:sizes[0]]}

            # Verify the return code.
            self.verify_async_return_code(ret_code=callback_handler.ret_code,
                                          expected_result=expected_result,
                                          method_name="get_attr")
        except DaosApiError as excep:
            print(excep)
            print(traceback.format_exc())
            if expected_result == "PASS":
                self.fail("get_attr failed! name = {}".format(attr_name))

        if expected_result == "PASS":
            # Verify the get_attr output.
            self.verify_get_attr(attr_dict, results)
Beispiel #7
0
    def test_basic_attribute_async(self):
        """Test ID: DAOS-1359

        Test container set/list/get attribute asynchronously.

        :avocado: tags=all,full_regression
        :avocado: tags=vm
        :avocado: tags=container,container_attribute
        :avocado: tags=container_api_basic_attribute_async
        """
        self.prepare_attribute_test()

        callback_handler = CallbackHandler()

        # Test set_attr()
        try:
            self.container.container.set_attr(
                data=self.attr_dict,
                coh=None,
                cb_func=callback_handler.callback)
            callback_handler.wait()

            # Verify the return code.
            # One exception is when we use the "Negative-Name" and valid value. In this
            # case, the method works, but we consider it as failure during get_attr test,
            # so temporarily use "PASS" here.
            if self.attr_name and b"Negative" in self.attr_name and self.attr_val:
                set_exp_result = "PASS"
            else:
                set_exp_result = self.expected_result
            self.verify_async_return_code(ret_code=callback_handler.ret_code,
                                          expected_result=set_exp_result,
                                          method_name="set_attr")
        except DaosApiError as error:
            print(error)
            print(traceback.format_exc())
            if self.expected_result == "PASS":
                self.fail(
                    "set_attr was supposed to work, but failed! name-value = {}"
                    .format(self.attr_dict))

        # Test list_attr()
        try:
            size, buf = self.container.container.list_attr(
                cb_func=callback_handler.callback)
            callback_handler.wait()

            # Verify the return code.
            ret_code = callback_handler.ret_code
            if ret_code != 0:
                self.fail("Unexpected RC after list_attr! {}".format(ret_code))
        except DaosApiError as excep:
            print(excep)
            print(traceback.format_exc())
            self.fail("list_attr failed!")

        if self.expected_result == 'PASS':
            self.verify_list_attr(in_dict=self.attr_dict,
                                  out_size=size,
                                  out_buf=buf)

        # Test get_attr()
        # Request something that doesn't exist
        if self.attr_name and b"Negative" in self.attr_name:
            self.attr_name = b"rubbish"

        try:
            buff, sizes = self.container.container.get_attr(
                attr_names=[self.attr_name],
                coh=None,
                cb_func=callback_handler.callback)
            callback_handler.wait()

            # Construct the result dictionary from buff and sizes.
            results = {self.attr_name: buff[0][:sizes[0]]}

            # Verify the return code.
            self.verify_async_return_code(ret_code=callback_handler.ret_code,
                                          expected_result=self.expected_result,
                                          method_name="get_attr")
        except DaosApiError as excep:
            print(excep)
            print(traceback.format_exc())
            if self.expected_result == 'PASS':
                msg = "get_attr was supposed to work, but failed! attr_name = {}".format(
                    self.attr_name)
                self.fail(msg)

        if self.expected_result == "PASS":
            # Verify the get_attr output.
            self.verify_get_attr(indata=self.attr_dict, outdata=results)