summaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/devguide/index.rst364
1 files changed, 209 insertions, 155 deletions
diff --git a/docs/devguide/index.rst b/docs/devguide/index.rst
index 210774be6..cda38e0ed 100644
--- a/docs/devguide/index.rst
+++ b/docs/devguide/index.rst
@@ -301,7 +301,7 @@ page `[3]`_.
Overall Architecture
====================
-The Test result management in Brahmaputra can be summarized as follows::
+The Test result management can be summarized as follows::
+-------------+ +-------------+ +-------------+
| | | | | |
@@ -314,7 +314,7 @@ The Test result management in Brahmaputra can be summarized as follows::
+-----------------------------------------+
| |
| Test Rest API front end |
- | http://testresults.opnfv.org/testapi |
+ | http://testresults.opnfv.org/test |
| |
+-----------------------------------------+
A |
@@ -333,24 +333,16 @@ The Test result management in Brahmaputra can be summarized as follows::
| |
+----------------------+
-The Test dashboard URL is: TODO LF
-A alternate Test dashboard has been realized to provide a view per installer and
-per scenario for Brahmaputra release::
-
- http://testresults.opnfv.org/proto/brahma/
-
-This Dashboard consumes the results retrieved thanks to the Test API.
-
Test API description
====================
The Test API is used to declare pods, projects, test cases and test results. An
-additional method dashboard has been added to post-process the raw results. The
-data model is very basic, 4 objects are created:
+additional method dashboard has been added to post-process the raw results in release Brahmaputra.
+The data model is very basic, 4 objects are created:
* Pods
- * Test projects
- * Test cases
- * Test results
+ * Projects
+ * Testcases
+ * Results
Pods::
@@ -359,10 +351,11 @@ Pods::
"details": <URL description of the POD>,
"creation_date": YYYY-MM-DD HH:MM:SS ,
"name": <The POD Name>,
- "mode": <metal or virtual>
+ "mode": <metal or virtual>,
+ "role": <ci-pod or community-pod or single-node>
},
-Test project::
+Projects::
{
"id": <ID>,
@@ -371,185 +364,246 @@ Test project::
"description": <Short description>
},
-Test case::
+Testcases::
{
"id": <ID>,
"name":<Name of the test case>,
+ "project_name":<Name of belonged project>,
"creation_date": "YYYY-MM-DD HH:MM:SS",
"description": <short description>,
"url":<URL for longer description>
},
-Test results::
+Results::
{
"_id": <ID,
+ "case_name": <Reference to the test case>
"project_name": <Reference to project>,
"pod_name": <Reference to POD where the test was executed>,
- "version": <Scenario on which the test was executed>,
"installer": <Installer Apex or Compass or Fuel or Joid>,
- "description": <Short description>,
- "creation_date": "YYYY-MM-DD HH:MM:SS",
- "case_name": <Reference to the test case>
- "details":{
- <- the results to be put here ->
- }
-
+ "version": <master or Colorado or Brahmaputra>,
+ "start_date": "YYYY-MM-DD HH:MM:SS",
+ "stop_date": "YYYY-MM-DD HH:MM:SS",
+ "build_tag": <such as "jenkins-functest-fuel-baremetal-daily-master-108">,
+ "scenario": <Scenario on which the test was executed>,
+ "criteria": <PASS or FAILED>,
+ "trust_indicator": <0 ~ 1>
-For Brahmaputra, we got:
+The API can described as follows. For detailed information, please go to
+http://testresults.opnfv.org/test/swagger/spec.html
- * 16 pods
- * 18 projects
- * 101 test cases
+Authentication: opnfv/api@opnfv
-The projects and the test cases have been frozen in December.
-But all were not ready for Brahmaputra.
-
-
-
-The API can described as follows:
+Please notes that POST/DELETE/PUT operations for test or study purpose via
+swagger website is not allowed, because it will change the real data in
+the database.
Version:
+--------+--------------------------+-----------------------------------------+
| Method | Path | Description |
+========+==========================+=========================================+
- | GET | /version | Get API version |
+ | GET | /versions | Get all supported API versions |
+--------+--------------------------+-----------------------------------------+
Pods:
- +--------+--------------------------+-----------------------------------------+
- | Method | Path | Description |
- +========+==========================+=========================================+
- | GET | /pods | Get the list of declared Labs (PODs) |
- +--------+--------------------------+-----------------------------------------+
- | POST | /pods | Declare a new POD |
- | | | Content-Type: application/json |
- | | | { |
- | | | "name": "pod_foo", |
- | | | "creation_date": "YYYY-MM-DD HH:MM:SS" |
- | | | } |
- +--------+--------------------------+-----------------------------------------+
+ +--------+----------------------------+-----------------------------------------+
+ | Method | Path | Description |
+ +========+============================+=========================================+
+ | GET | /api/v1/pods | Get the list of declared Labs (PODs) |
+ +--------+----------------------------+-----------------------------------------+
+ | POST | /api/v1/pods | Declare a new POD |
+ | | | Content-Type: application/json |
+ | | | { |
+ | | | "name": "pod_foo", |
+ | | | "mode": "metal", |
+ | | | "role": "ci-pod", |
+ | | | "details": "it is a ci pod" |
+ | | | } |
+ +--------+----------------------------+-----------------------------------------+
+ | GET | /api/v1/pods/{pod_name} | Get a declared POD |
+ +--------+----------------------------+-----------------------------------------+
Projects:
- +--------+--------------------------+-----------------------------------------+
- | Method | Path | Description |
- +========+==========================+=========================================+
- | GET | /test_projects | Get the list of test projects |
- +--------+--------------------------+-----------------------------------------+
- | GET |/test_projects/{project} | Get details on {project} |
- | | | |
- +--------+--------------------------+-----------------------------------------+
- | POST | /test_projects | Add a new test project |
- | | | Content-Type: application/json |
- | | | { |
- | | | "name": "project_foo", |
- | | | "description": "whatever you want" |
- | | | } |
- +--------+--------------------------+-----------------------------------------+
- | PUT | /test_projects/{project} | Update a test project |
- | | | |
- | | | Content-Type: application/json |
- | | | { |
- | | | <the field(s) you want to modify> |
- | | | } |
- +--------+--------------------------+-----------------------------------------+
- | DELETE | /test_projects/{project} | Delete a test project |
- +--------+--------------------------+-----------------------------------------+
+ +--------+----------------------------+-----------------------------------------+
+ | Method | Path | Description |
+ +========+============================+=========================================+
+ | GET | /api/v1/projects | Get the list of declared projects |
+ +--------+----------------------------+-----------------------------------------+
+ | POST | /api/v1/projects | Declare a new test project |
+ | | | Content-Type: application/json |
+ | | | { |
+ | | | "name": "project_foo", |
+ | | | "description": "whatever you want" |
+ | | | } |
+ +--------+----------------------------+-----------------------------------------+
+ | DELETE | /api/v1/projects/{project} | Delete a test project |
+ +--------+----------------------------+-----------------------------------------+
+ | GET | /api/v1/projects/{project} | Get details on a {project} |
+ | | | |
+ +--------+----------------------------+-----------------------------------------+
+ | PUT | /api/v1/projects/{project} | Update a test project |
+ | | | |
+ | | | Content-Type: application/json |
+ | | | { |
+ | | | <the field(s) you want to modify> |
+ | | | } |
+ +--------+----------------------------+-----------------------------------------+
+
+
+Testcases:
+
+ +--------+----------------------------+-----------------------------------------+
+ | Method | Path | Description |
+ +========+============================+=========================================+
+ | GET | /api/v1/projects/{project}/| Get the list of testcases of {project} |
+ | | cases | |
+ +--------+----------------------------+-----------------------------------------+
+ | POST | /api/v1/projects/{project}/| Add a new test case to {project} |
+ | | cases | Content-Type: application/json |
+ | | | { |
+ | | | "name": "case_foo", |
+ | | | "description": "whatever you want" |
+ | | | "url": "whatever you want" |
+ | | | } |
+ +--------+----------------------------+-----------------------------------------+
+ | DELETE | /api/v1/projects/{project}/| Delete a test case |
+ | | cases/{case} | |
+ +--------+----------------------------+-----------------------------------------+
+ | GET | /api/v1/projects/{project}/| Get a declared test case |
+ | | cases/{case} | |
+ +--------+----------------------------+-----------------------------------------+
+ | PUT | /api/v1/projects/{project}?| Modify a test case of {project} |
+ | | cases/{case} | |
+ | | | Content-Type: application/json |
+ | | | { |
+ | | | <the field(s) you want to modify> |
+ | | | } |
+ +--------+----------------------------+-----------------------------------------+
+
+Results:
+
+ +--------+----------------------------+------------------------------------------+
+ | Method | Path | Description |
+ +========+============================+==========================================+
+ | GET | /api/v1/results | Get all the test results |
+ +--------+----------------------------+------------------------------------------+
+ | POST | /api/v1/results | Add a new test results |
+ | | | Content-Type: application/json |
+ | | | { |
+ | | | "project_name": "project_foo", |
+ | | | "scenario": "odl-l2", |
+ | | | "stop_date": "2016-05-28T14:42:58.384Z", |
+ | | | "trust_indicator": 0.5, |
+ | | | "case_name": "vPing", |
+ | | | "build_tag": "", |
+ | | | "version": "Colorado", |
+ | | | "pod_name": "pod_foo", |
+ | | | "criteria": "PASS", |
+ | | | "installer": "fuel", |
+ | | | "start_date": "2016-05-28T14:41:58.384Z",|
+ | | | "details": <your results> |
+ | | | } |
+ +--------+----------------------------+------------------------------------------+
+ | GET | /api/v1/results? | Get the test results of {case} |
+ | | case={case} | |
+ +--------+----------------------------+------------------------------------------+
+ | GET | /api/v1/results? | Get the test results of build_tag |
+ | | build_tag={tag} | {tag}. |
+ +--------+----------------------------+------------------------------------------+
+ | GET | /api/v1/results? | Get last {N} records of test results |
+ | | last={N} | |
+ +--------+----------------------------+------------------------------------------+
+ | GET | /api/v1/results? | Get the test results of scenario |
+ | | scenario={scenario} | {scenario}. |
+ +--------+----------------------------+------------------------------------------+
+ | GET | /api/v1/results? | Get the test results of trust_indicator |
+ | | trust_indicator={ind} | {ind}. |
+ +--------+----------------------------+------------------------------------------+
+ | GET | /api/v1/results? | Get the test results of last days |
+ | | period={period} | {period}. |
+ +--------+----------------------------+------------------------------------------+
+ | GET | /api/v1/results? | Get the test results of {project} |
+ | | project={project} | |
+ +--------+----------------------------+------------------------------------------+
+ | GET | /api/v1/results? | Get the test results of version |
+ | | version={version} | {version}. |
+ +--------+----------------------------+------------------------------------------+
+ | GET | /api/v1/results? | Get the test results of criteria |
+ | | criteria={criteria} | {criteria}. |
+ +--------+----------------------------+------------------------------------------+
+ | GET | /api/v1/results? | get the results on pod {pod} |
+ | | pod={pod} | |
+ +--------+----------------------------+------------------------------------------+
+ | GET | /api/v1/results? | Get the test results of installer {inst} |
+ | | installer={inst} | |
+ +--------+----------------------------+------------------------------------------+
+ | GET | /api/v1/results? | Get the results according to combined |
+ | | <query conditions> | query conditions supported above |
+ +--------+----------------------------+------------------------------------------+
+ | GET | /api/v1/results/{result_id}| Get the test result by result_id |
+ +--------+----------------------------+------------------------------------------+
-Test cases:
-
- +--------+--------------------------+-----------------------------------------+
- | Method | Path | Description |
- +========+==========================+=========================================+
- | GET | /test_projects/{project}/| Get the list of test cases of {project} |
- | | cases | |
- +--------+--------------------------+-----------------------------------------+
- | POST | /test_projects/{project}/| Add a new test case to {project} |
- | | cases | Content-Type: application/json |
- | | | { |
- | | | "name": "case_foo", |
- | | | "description": "whatever you want" |
- | | | "creation_date": "YYYY-MM-DD HH:MM:SS" |
- | | | "url": "whatever you want" |
- | | | } |
- +--------+--------------------------+-----------------------------------------+
- | PUT | /test_projects/{project}?| Modify a test case of {project} |
- | | case_name={case} | |
- | | | Content-Type: application/json |
- | | | { |
- | | | <the field(s) you want to modify> |
- | | | } |
- +--------+--------------------------+-----------------------------------------+
- | DELETE | /test_projects/{project}/| Delete a test case |
- | | case_name={case} | |
- +--------+--------------------------+-----------------------------------------+
-
-Test Results:
+Dashboard:
- +--------+--------------------------+-----------------------------------------+
- | Method | Path | Description |
- +========+==========================+=========================================+
- | GET |/results/project={project}| Get the test results of {project} |
- +--------+--------------------------+-----------------------------------------+
- | GET |/results/case={case} | Get the test results of {case} |
- +--------+--------------------------+-----------------------------------------+
- | GET |/results?pod={pod} | get the results on pod {pod} |
- +--------+--------------------------+-----------------------------------------+
- | GET |/results?installer={inst} | Get the test results of installer {inst}|
- +--------+--------------------------+-----------------------------------------+
- | GET |/results?version={version}| Get the test results of scenario |
- | | | {version}. Initially the version param |
- | | | was reflecting git version, in Functest |
- | | | it was decided to move to scenario |
- +--------+--------------------------+-----------------------------------------+
- | GET |/results?project={project}| Get all the results of the test case |
- | |&case={case} | {case} of the project {project} with |
- | |&version={scenario} | version {scenario} installed by |
- | |&installer={installer} | {installer} on POD {pod} stored since |
- | |&pod={pod} | {days} days |
- | | | {project_name} and {case_name} are |
- | |&period={days} | mandatory, the other parameters are |
- | | | optional. |
- +--------+--------------------------+-----------------------------------------+
- | POST | /results | Add a new test results |
- | | | Content-Type: application/json |
- | | | { |
- | | | "project_name": "project_foo", |
- | | | "case_name": "case_foo", |
- | | | "pod_name": "pod_foo", |
- | | | "installer": "installer_foo", |
- | | | "version": "scenario_foo", |
- | | | "details": <your results> |
- | | | } |
- +--------+--------------------------+-----------------------------------------+
+ +--------+----------------------------+-----------------------------------------+
+ | Method | Path | Description |
+ +========+============================+=========================================+
+ | GET |/dashboard/v1/results? | Get all the dashboard ready results of |
+ | |&project={project} | {case} of the project {project} |
+ | |&case={case} | |
+ +--------+----------------------------+-----------------------------------------+
+ | GET |/dashboard/v1/results? | Get all the dashboard ready results of |
+ | |&project={project} | {case} of the project {project} |
+ | |&case={case} | version {version} |
+ | |&version={version} | |
+ +--------+----------------------------+-----------------------------------------+
+ | GET |/dashboard/v1/results? | Get all the dashboard ready results of |
+ | |&project={project} | {case} of the project {project} |
+ | |&case={case} | since {days} days |
+ | |&period={days} | |
+ +--------+----------------------------+-----------------------------------------+
+ | GET |/dashboard/v1/results? | Get all the dashboard ready results of |
+ | |&project={project} | {case} of the project {project} |
+ | |&case={case} | installed by {installer} |
+ | |&installer={installer} | |
+ +--------+----------------------------+-----------------------------------------+
+ | GET |/dashboard/v1/results? | Get all the dashboard ready results of |
+ | |&project={project} | {case} of the project {project} |
+ | |&case={case} | on POD {pod} |
+ | |&pod={pod} | |
+ +--------+----------------------------+-----------------------------------------+
+ | GET |/dashboard/v1/results? | Get all the dashboard ready results of |
+ | |&project={project} | {case} of the project {project} |
+ | |&case={case} | and combined by other query conditions |
+ | |&<query conditions> | supported above. |
+ +--------+----------------------------+-----------------------------------------+
+ | GET |/dashboard/v1/projects? | Get all the dashboard ready projects |
+ +--------+----------------------------+-----------------------------------------+
+
+Dashboard description
+=====================
+The results with dashboard method are post-processed from raw results.
+Please note that dashboard results are not stored. Only raw results are stored.
-Dashboard:
+Release Brahmaputra
+-------------------
- +--------+--------------------------+-----------------------------------------+
- | Method | Path | Description |
- +========+==========================+=========================================+
- | GET |/dashboard? | Get all the dashboard ready results of |
- | |&project={project} | {case} of the project {project} |
- | |&case={case} | version {scenario} installed by |
- | |&version={scenario} | {installer} on POD {pod} stored since |
- | |&installer={installer} | {days} days |
- | |&pod={pod} | |
- | |&period={days} | {project_name} and {case_name} are |
- | | | mandatory, the other parameters are |
- | | | optional. |
- +--------+--------------------------+-----------------------------------------+
+Dashboard url: http://testresults.opnfv.org/dashboard/
+Release Colorado
+----------------
-The results with dashboard method are post-processed from raw results.
-Please note that dashboard results are not stored. Only raw results are stored.
+Dashboard url: http://testresults.opnfv.org/kibana_dashboards/
+Credentials for a guest account: opnfvuser/kibana
===============================================
How to push your results into the Test Database
>='full') self.assert_qmp(result, 'error/class', 'GenericError') def test_medium_not_found_blockdev_backup(self): if iotests.qemu_default_machine != 'pc': return result = self.vm.qmp('blockdev-backup', device='drive2', # CD-ROM target='drive1', sync='full') self.assert_qmp(result, 'error/class', 'GenericError') def test_image_not_found(self): result = self.vm.qmp('drive-backup', device='drive0', target=target_img, sync='full', mode='existing') self.assert_qmp(result, 'error/class', 'GenericError') def test_invalid_format(self): result = self.vm.qmp('drive-backup', device='drive0', target=target_img, sync='full', format='spaghetti-noodles') self.assert_qmp(result, 'error/class', 'GenericError') def do_test_device_not_found(self, cmd, **args): result = self.vm.qmp(cmd, **args) if cmd == 'drive-backup': self.assert_qmp(result, 'error/class', 'DeviceNotFound') else: self.assert_qmp(result, 'error/class', 'GenericError') def test_device_not_found(self): self.do_test_device_not_found('drive-backup', device='nonexistent', target=target_img, sync='full') self.do_test_device_not_found('blockdev-backup', device='nonexistent', target='drive0', sync='full') self.do_test_device_not_found('blockdev-backup', device='drive0', target='nonexistent', sync='full') self.do_test_device_not_found('blockdev-backup', device='nonexistent', target='nonexistent', sync='full') def test_target_is_source(self): result = self.vm.qmp('blockdev-backup', device='drive0', target='drive0', sync='full') self.assert_qmp(result, 'error/class', 'GenericError') class TestSetSpeed(iotests.QMPTestCase): image_len = 80 * 1024 * 1024 # MB def setUp(self): qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSetSpeed.image_len)) qemu_io('-f', iotests.imgfmt, '-c', 'write -P1 0 512', test_img) qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(TestSingleDrive.image_len)) self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img) self.vm.launch() def tearDown(self): self.vm.shutdown() os.remove(test_img) os.remove(blockdev_target_img) try: os.remove(target_img) except OSError: pass def do_test_set_speed(self, cmd, target): self.assert_no_active_block_jobs() self.vm.pause_drive('drive0') result = self.vm.qmp(cmd, device='drive0', target=target, sync='full') self.assert_qmp(result, 'return', {}) # Default speed is 0 result = self.vm.qmp('query-block-jobs') self.assert_qmp(result, 'return[0]/device', 'drive0') self.assert_qmp(result, 'return[0]/speed', 0) result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024) self.assert_qmp(result, 'return', {}) # Ensure the speed we set was accepted result = self.vm.qmp('query-block-jobs') self.assert_qmp(result, 'return[0]/device', 'drive0') self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024) event = self.cancel_and_wait(resume=True) self.assert_qmp(event, 'data/type', 'backup') # Check setting speed option works self.vm.pause_drive('drive0') result = self.vm.qmp(cmd, device='drive0', target=target, sync='full', speed=4*1024*1024) self.assert_qmp(result, 'return', {}) result = self.vm.qmp('query-block-jobs') self.assert_qmp(result, 'return[0]/device', 'drive0') self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024) event = self.cancel_and_wait(resume=True) self.assert_qmp(event, 'data/type', 'backup') def test_set_speed_drive_backup(self): self.do_test_set_speed('drive-backup', target_img) def test_set_speed_blockdev_backup(self): self.do_test_set_speed('blockdev-backup', 'drive1') def do_test_set_speed_invalid(self, cmd, target): self.assert_no_active_block_jobs() result = self.vm.qmp(cmd, device='drive0', target=target, sync='full', speed=-1) self.assert_qmp(result, 'error/class', 'GenericError') self.assert_no_active_block_jobs() self.vm.pause_drive('drive0') result = self.vm.qmp(cmd, device='drive0', target=target, sync='full') self.assert_qmp(result, 'return', {}) result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1) self.assert_qmp(result, 'error/class', 'GenericError') event = self.cancel_and_wait(resume=True) self.assert_qmp(event, 'data/type', 'backup') def test_set_speed_invalid_drive_backup(self): self.do_test_set_speed_invalid('drive-backup', target_img) def test_set_speed_invalid_blockdev_backup(self): self.do_test_set_speed_invalid('blockdev-backup', 'drive1') class TestSingleTransaction(iotests.QMPTestCase): image_len = 64 * 1024 * 1024 # MB def setUp(self): qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSingleTransaction.image_len)) qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x5d 0 64k', test_img) qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xd5 1M 32k', test_img) qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 32M 124k', test_img) qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 67043328 64k', test_img) qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(TestSingleDrive.image_len)) self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img) if iotests.qemu_default_machine == 'pc': self.vm.add_drive(None, 'media=cdrom', 'ide') self.vm.launch() def tearDown(self): self.vm.shutdown() os.remove(test_img) os.remove(blockdev_target_img) try: os.remove(target_img) except OSError: pass def do_test_cancel(self, cmd, target): self.assert_no_active_block_jobs() result = self.vm.qmp('transaction', actions=[{ 'type': cmd, 'data': { 'device': 'drive0', 'target': target, 'sync': 'full' }, } ]) self.assert_qmp(result, 'return', {}) event = self.cancel_and_wait() self.assert_qmp(event, 'data/type', 'backup') def test_cancel_drive_backup(self): self.do_test_cancel('drive-backup', target_img) def test_cancel_blockdev_backup(self): self.do_test_cancel('blockdev-backup', 'drive1') def do_test_pause(self, cmd, target, image): self.assert_no_active_block_jobs() self.vm.pause_drive('drive0') result = self.vm.qmp('transaction', actions=[{ 'type': cmd, 'data': { 'device': 'drive0', 'target': target, 'sync': 'full' }, } ]) self.assert_qmp(result, 'return', {}) result = self.vm.qmp('block-job-pause', device='drive0') self.assert_qmp(result, 'return', {}) self.vm.resume_drive('drive0') time.sleep(1) result = self.vm.qmp('query-block-jobs') offset = self.dictpath(result, 'return[0]/offset') time.sleep(1) result = self.vm.qmp('query-block-jobs') self.assert_qmp(result, 'return[0]/offset', offset) result = self.vm.qmp('block-job-resume', device='drive0') self.assert_qmp(result, 'return', {}) self.wait_until_completed() self.vm.shutdown() self.assertTrue(iotests.compare_images(test_img, image), 'target image does not match source after backup') def test_pause_drive_backup(self): self.do_test_pause('drive-backup', target_img, target_img) def test_pause_blockdev_backup(self): self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img) def do_test_medium_not_found(self, cmd, target): if iotests.qemu_default_machine != 'pc': return result = self.vm.qmp('transaction', actions=[{ 'type': cmd, 'data': { 'device': 'drive2', # CD-ROM 'target': target, 'sync': 'full' }, } ]) self.assert_qmp(result, 'error/class', 'GenericError') def test_medium_not_found_drive_backup(self): self.do_test_medium_not_found('drive-backup', target_img) def test_medium_not_found_blockdev_backup(self): self.do_test_medium_not_found('blockdev-backup', 'drive1') def test_image_not_found(self): result = self.vm.qmp('transaction', actions=[{ 'type': 'drive-backup', 'data': { 'device': 'drive0', 'mode': 'existing', 'target': target_img, 'sync': 'full' }, } ]) self.assert_qmp(result, 'error/class', 'GenericError') def test_device_not_found(self): result = self.vm.qmp('transaction', actions=[{ 'type': 'drive-backup', 'data': { 'device': 'nonexistent', 'mode': 'existing', 'target': target_img, 'sync': 'full' }, } ]) self.assert_qmp(result, 'error/class', 'DeviceNotFound') result = self.vm.qmp('transaction', actions=[{ 'type': 'blockdev-backup', 'data': { 'device': 'nonexistent', 'target': 'drive1', 'sync': 'full' }, } ]) self.assert_qmp(result, 'error/class', 'GenericError') result = self.vm.qmp('transaction', actions=[{ 'type': 'blockdev-backup', 'data': { 'device': 'drive0', 'target': 'nonexistent', 'sync': 'full' }, } ]) self.assert_qmp(result, 'error/class', 'GenericError') result = self.vm.qmp('transaction', actions=[{ 'type': 'blockdev-backup', 'data': { 'device': 'nonexistent', 'target': 'nonexistent', 'sync': 'full' }, } ]) self.assert_qmp(result, 'error/class', 'GenericError') def test_target_is_source(self): result = self.vm.qmp('transaction', actions=[{ 'type': 'blockdev-backup', 'data': { 'device': 'drive0', 'target': 'drive0', 'sync': 'full' }, } ]) self.assert_qmp(result, 'error/class', 'GenericError') def test_abort(self): result = self.vm.qmp('transaction', actions=[{ 'type': 'drive-backup', 'data': { 'device': 'nonexistent', 'mode': 'existing', 'target': target_img, 'sync': 'full' }, }, { 'type': 'Abort', 'data': {}, } ]) self.assert_qmp(result, 'error/class', 'GenericError') self.assert_no_active_block_jobs() result = self.vm.qmp('transaction', actions=[{ 'type': 'blockdev-backup', 'data': { 'device': 'nonexistent', 'target': 'drive1', 'sync': 'full' }, }, { 'type': 'Abort', 'data': {}, } ]) self.assert_qmp(result, 'error/class', 'GenericError') self.assert_no_active_block_jobs() result = self.vm.qmp('transaction', actions=[{ 'type': 'blockdev-backup', 'data': { 'device': 'drive0', 'target': 'nonexistent', 'sync': 'full' }, }, { 'type': 'Abort', 'data': {}, } ]) self.assert_qmp(result, 'error/class', 'GenericError') self.assert_no_active_block_jobs() if __name__ == '__main__': iotests.main(supported_fmts=['raw', 'qcow2'])