Moved gnocchi tempest tests under telemetry tempest plugin
* In order to achieve tempest plugin split goal, we have merged
aodh, panko, ceilometer and gnocchi tempest plugin into
telemetry tempest plugin
* gnocchi/tempest -> telemetry_tempest_plugin/gnocchi
* gnocchi/tests/functional_live -> telemetry_tempest_plugin/gnocchi
Change-Id: Icf6789afc143db3206af409c62a36e56edefd142
diff --git a/telemetry_tempest_plugin/config.py b/telemetry_tempest_plugin/config.py
index 87b50af..7fc17a8 100644
--- a/telemetry_tempest_plugin/config.py
+++ b/telemetry_tempest_plugin/config.py
@@ -27,6 +27,10 @@
cfg.BoolOpt("aodh_plugin",
default=True,
help="Whether or not Aodh is expected to be"
+ "available"),
+ cfg.BoolOpt('gnocchi',
+ default=True,
+ help="Whether or not Gnocchi is expected to be"
"available")]
telemetry_group = cfg.OptGroup(name='telemetry',
@@ -38,6 +42,9 @@
alarming_group = cfg.OptGroup(name='alarming_plugin',
title='Alarming Service Options')
+metric_group = cfg.OptGroup(name='metric',
+ title='Metric Service Options')
+
TelemetryGroup = [
cfg.IntOpt('notification_wait',
default=120,
@@ -75,3 +82,14 @@
'publicURL', 'adminURL', 'internalURL'],
help="The endpoint type to use for the alarming service."),
]
+
+metric_opts = [
+ cfg.StrOpt('catalog_type',
+ default='metric',
+ help="Catalog type of the Metric service."),
+ cfg.StrOpt('endpoint_type',
+ default='publicURL',
+ choices=['public', 'admin', 'internal',
+ 'publicURL', 'adminURL', 'internalURL'],
+ help="The endpoint type to use for the metric service."),
+]
diff --git a/telemetry_tempest_plugin/gnocchi/__init_.py b/telemetry_tempest_plugin/gnocchi/__init_.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/telemetry_tempest_plugin/gnocchi/__init_.py
diff --git a/telemetry_tempest_plugin/gnocchi/functional_live/__init__.py b/telemetry_tempest_plugin/gnocchi/functional_live/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/telemetry_tempest_plugin/gnocchi/functional_live/__init__.py
diff --git a/telemetry_tempest_plugin/gnocchi/functional_live/gabbits/live.yaml b/telemetry_tempest_plugin/gnocchi/functional_live/gabbits/live.yaml
new file mode 100644
index 0000000..d63cb09
--- /dev/null
+++ b/telemetry_tempest_plugin/gnocchi/functional_live/gabbits/live.yaml
@@ -0,0 +1,739 @@
+#
+# Confirmation tests to run against a live web server.
+#
+# These act as a very basic sanity check.
+
+defaults:
+ request_headers:
+ x-auth-token: $ENVIRON['GNOCCHI_SERVICE_TOKEN']
+ authorization: $ENVIRON['GNOCCHI_AUTHORIZATION']
+
+tests:
+ - name: check /
+ GET: /
+
+ # Fail to create archive policy
+ - name: wrong archive policy content type
+ desc: attempt to create archive policy with invalid content-type
+ POST: /v1/archive_policy
+ request_headers:
+ content-type: text/plain
+ status: 415
+ response_strings:
+ - Unsupported Media Type
+
+ - name: wrong method
+ desc: attempt to create archive policy with 'PUT' method
+ PUT: /v1/archive_policy
+ request_headers:
+ content-type: application/json
+ status: 405
+
+ - name: invalid authZ
+ desc: x-auth-token is invalid
+ POST: /v1/archive_policy
+ request_headers:
+ content-type: application/json
+ x-auth-token: 'hello'
+ authorization: 'basic hello:'
+ data:
+ name: medium
+ definition:
+ - granularity: 1 second
+ status: 401
+
+ - name: bad archive policy body
+ desc: archive policy contains invalid key 'cowsay'
+ POST: /v1/archive_policy
+ request_headers:
+ content-type: application/json
+ data:
+ cowsay: moo
+ status: 400
+ response_strings:
+ - "Invalid input: extra keys not allowed"
+
+ - name: missing definition
+ desc: archive policy is missing 'definition' keyword
+ POST: /v1/archive_policy
+ request_headers:
+ content-type: application/json
+ data:
+ name: medium
+ status: 400
+ response_strings:
+ - "Invalid input: required key not provided"
+
+ - name: empty definition
+ desc: empty definition for archive policy
+ POST: /v1/archive_policy
+ request_headers:
+ content-type: application/json
+ data:
+ name: medium
+ definition: []
+ status: 400
+ response_strings:
+ - "Invalid input: length of value must be at least 1"
+
+ - name: wrong value definition
+ desc: invalid type of 'definition' key
+ POST: /v1/archive_policy
+ request_headers:
+ content-type: application/json
+ data:
+ name: somename
+ definition: foobar
+ status: 400
+ response_strings:
+ - "Invalid input: expected a list"
+
+ - name: useless definition
+ desc: invalid archive policy definition
+ POST: /v1/archive_policy
+ request_headers:
+ content-type: application/json
+ data:
+ name: medium
+ definition:
+ - cowsay: moo
+ status: 400
+ response_strings:
+ - "Invalid input: extra keys not allowed"
+
+ #
+ # Create archive policy
+ #
+
+ - name: create archive policy
+ desc: create archve policy 'gabbilive' for live tests
+ POST: /v1/archive_policy
+ request_headers:
+ content-type: application/json
+ data:
+ name: gabbilive
+ back_window: 0
+ definition:
+ - granularity: 1 second
+ points: 60
+ - granularity: 2 second
+ timespan: 1 minute
+ - points: 5
+ timespan: 5 minute
+ aggregation_methods:
+ - mean
+ - min
+ - max
+ response_headers:
+ location: $SCHEME://$NETLOC/v1/archive_policy/gabbilive
+ status: 201
+
+ # Retrieve it correctly and then poorly
+
+ - name: get archive policy
+ desc: retrieve archive policy 'gabbilive' and asster its values
+ GET: $LOCATION
+ response_headers:
+ content-type: /application/json/
+ response_json_paths:
+ $.name: gabbilive
+ $.back_window: 0
+ $.definition[0].granularity: "0:00:01"
+ $.definition[0].points: 60
+ $.definition[0].timespan: "0:01:00"
+ $.definition[1].granularity: "0:00:02"
+ $.definition[1].points: 30
+ $.definition[1].timespan: "0:01:00"
+ $.definition[2].granularity: "0:01:00"
+ $.definition[2].points: 5
+ $.definition[2].timespan: "0:05:00"
+ response_json_paths:
+ $.aggregation_methods.`sorted`: ["max", "mean", "min"]
+
+ - name: get wrong accept
+ desc: invalid 'accept' header
+ GET: /v1/archive_policy/medium
+ request_headers:
+ accept: text/plain
+ status: 406
+
+ # Unexpected methods
+
+ - name: post single archive
+ desc: unexpected 'POST' request to archive policy
+ POST: /v1/archive_policy/gabbilive
+ status: 405
+
+ - name: put single archive
+ desc: unexpected 'PUT' request to archive policy
+ PUT: /v1/archive_policy/gabbilive
+ status: 405
+
+ # Duplicated archive policy names ain't allowed
+
+ - name: create duplicate archive policy
+ desc: create archve policy 'gabbilive' for live tests
+ POST: /v1/archive_policy
+ request_headers:
+ content-type: application/json
+ data:
+ name: gabbilive
+ definition:
+ - granularity: 30 second
+ points: 60
+ status: 409
+ response_strings:
+ - Archive policy gabbilive already exists
+
+ # Create a unicode named policy
+
+ - name: post unicode policy name
+ POST: /v1/archive_policy
+ request_headers:
+ content-type: application/json
+ data:
+ name: ✔éñ☃
+ definition:
+ - granularity: 1 minute
+ points: 20
+ status: 201
+ response_headers:
+ location: $SCHEME://$NETLOC/v1/archive_policy/%E2%9C%94%C3%A9%C3%B1%E2%98%83
+ response_json_paths:
+ name: ✔éñ☃
+
+ - name: retrieve unicode policy name
+ GET: $LOCATION
+ response_json_paths:
+ name: ✔éñ☃
+
+ - name: delete unicode archive policy
+ DELETE: /v1/archive_policy/%E2%9C%94%C3%A9%C3%B1%E2%98%83
+ status: 204
+
+ # It really is gone
+
+ - name: confirm delete
+ desc: assert deleted unicode policy is not available
+ GET: /v1/archive_policy/%E2%9C%94%C3%A9%C3%B1%E2%98%83
+ status: 404
+
+ # Fail to delete one that does not exist
+
+ - name: delete missing archive
+ desc: delete non-existent archive policy
+ DELETE: /v1/archive_policy/grandiose
+ status: 404
+ response_strings:
+ - Archive policy grandiose does not exist
+
+ # Attempt to create illogical policies
+
+ - name: create illogical policy
+ POST: /v1/archive_policy
+ request_headers:
+ content-type: application/json
+ data:
+ name: complex
+ definition:
+ - granularity: 1 second
+ points: 60
+ timespan: "0:01:01"
+ status: 400
+ response_strings:
+ - timespan ≠ granularity × points
+
+ - name: create identical granularities policy
+ POST: /v1/archive_policy
+ request_headers:
+ content-type: application/json
+ data:
+ name: complex
+ definition:
+ - granularity: 1 second
+ points: 60
+ - granularity: 1 second
+ points: 120
+ status: 400
+ response_strings:
+ - "More than one archive policy uses granularity `1.0'"
+
+ - name: policy invalid unit
+ desc: invalid unit for archive policy 'timespan' key
+ POST: /v1/archive_policy
+ request_headers:
+ content-type: application/json
+ data:
+ name: 227d0e1f-4295-4e4b-8515-c296c47d71d3
+ definition:
+ - granularity: 1 second
+ timespan: "1 shenanigan"
+ status: 400
+
+ #
+ # Archive policy rules
+ #
+
+ - name: create archive policy rule1
+ POST: /v1/archive_policy_rule
+ request_headers:
+ content-type: application/json
+ data:
+ name: gabbilive_rule
+ metric_pattern: "live.*"
+ archive_policy_name: gabbilive
+ status: 201
+ response_json_paths:
+ $.metric_pattern: "live.*"
+ $.archive_policy_name: gabbilive
+ $.name: gabbilive_rule
+
+ - name: create invalid archive policy rule
+ POST: /v1/archive_policy_rule
+ request_headers:
+ content-type: application/json
+ data:
+ name: test_rule
+ metric_pattern: "disk.foo.*"
+ status: 400
+
+ - name: missing auth archive policy rule
+ POST: /v1/archive_policy_rule
+ request_headers:
+ content-type: application/json
+ x-auth-token: 'hello'
+ authorization: 'basic hello:'
+ data:
+ name: test_rule
+ metric_pattern: "disk.foo.*"
+ archive_policy_name: low
+ status: 401
+
+ - name: wrong archive policy rule content type
+ POST: /v1/archive_policy_rule
+ request_headers:
+ content-type: text/plain
+ status: 415
+ response_strings:
+ - Unsupported Media Type
+
+ - name: bad archive policy rule body
+ POST: /v1/archive_policy_rule
+ request_headers:
+ content-type: application/json
+ data:
+ whaa: foobar
+ status: 400
+ response_strings:
+ - "Invalid input: extra keys not allowed"
+
+ # get an archive policy rules
+
+ - name: get all archive policy rules
+ GET: /v1/archive_policy_rule
+ status: 200
+ response_json_paths:
+ $[\name][0].name: "gabbilive_rule"
+ $[\name][0].metric_pattern: "live.*"
+ $[\name][0].archive_policy_name: "gabbilive"
+
+ - name: get unknown archive policy rule
+ GET: /v1/archive_policy_rule/foo
+ status: 404
+
+
+ - name: get archive policy rule
+ GET: /v1/archive_policy_rule/gabbilive_rule
+ status: 200
+ response_json_paths:
+ $.metric_pattern: "live.*"
+ $.archive_policy_name: "gabbilive"
+ $.name: "gabbilive_rule"
+
+ - name: delete archive policy in use
+ desc: fails due to https://bugs.launchpad.net/gnocchi/+bug/1569781
+ DELETE: /v1/archive_policy/gabbilive
+ status: 400
+
+ #
+ # Metrics
+ #
+
+
+ - name: get all metrics
+ GET: /v1/metric
+ status: 200
+
+ - name: create metric with name and rule
+ POST: /v1/metric
+ request_headers:
+ content-type: application/json
+ data:
+ name: "live.io.rate"
+ status: 201
+ response_json_paths:
+ $.archive_policy_name: gabbilive
+ $.name: live.io.rate
+
+ - name: assert metric is present in listing
+ GET: /v1/metric?id=$HISTORY['create metric with name and rule'].$RESPONSE['$.id']
+ response_json_paths:
+ $.`len`: 1
+
+ - name: assert metric is the only one with this policy
+ GET: /v1/metric?archive_policy_name=gabbilive
+ response_json_paths:
+ $.`len`: 1
+
+ - name: delete metric
+ DELETE: /v1/metric/$HISTORY['create metric with name and rule'].$RESPONSE['$.id']
+ status: 204
+
+ - name: assert metric is expunged
+ GET: $HISTORY['assert metric is present in listing'].$URL&status=delete
+ poll:
+ count: 360
+ delay: 1
+ response_json_paths:
+ $.`len`: 0
+
+ - name: create metric with name and policy
+ POST: /v1/metric
+ request_headers:
+ content-type: application/json
+ data:
+ name: "aagabbi.live.metric"
+ archive_policy_name: "gabbilive"
+ status: 201
+ response_json_paths:
+ $.archive_policy_name: gabbilive
+ $.name: "aagabbi.live.metric"
+
+ - name: get valid metric id
+ GET: $LOCATION
+ status: 200
+ response_json_paths:
+ $.archive_policy.name: gabbilive
+
+ - name: delete the metric
+ DELETE: /v1/metric/$RESPONSE['$.id']
+ status: 204
+
+ - name: ensure the metric is delete
+ GET: /v1/metric/$HISTORY['get valid metric id'].$RESPONSE['$.id']
+ status: 404
+
+ - name: create metric bad archive policy
+ POST: /v1/metric
+ request_headers:
+ content-type: application/json
+ data:
+ archive_policy_name: 2e2675aa-105e-4664-a30d-c407e6a0ea7f
+ status: 400
+ response_strings:
+ - Archive policy 2e2675aa-105e-4664-a30d-c407e6a0ea7f does not exist
+
+ - name: create metric bad content-type
+ POST: /v1/metric
+ request_headers:
+ content-type: plain/text
+ data: '{"archive_policy_name": "cookies"}'
+ status: 415
+
+
+ #
+ # Cleanup
+ #
+
+ - name: delete archive policy rule
+ DELETE: /v1/archive_policy_rule/gabbilive_rule
+ status: 204
+
+ - name: confirm delete archive policy rule
+ DELETE: /v1/archive_policy_rule/gabbilive_rule
+ status: 404
+
+
+ #
+ # Resources section
+ #
+
+ - name: root of resource
+ GET: /v1/resource
+ response_json_paths:
+ $.generic: $SCHEME://$NETLOC/v1/resource/generic
+
+ - name: typo of resource
+ GET: /v1/resoue
+ status: 404
+
+ - name: typo of resource extra
+ GET: /v1/resource/foobar
+ status: 404
+
+ - name: generic resource
+ GET: /v1/resource/generic
+ status: 200
+
+ - name: post resource type
+ POST: /v1/resource_type
+ request_headers:
+ content-type: application/json
+ data:
+ name: myresource
+ attributes:
+ display_name:
+ type: string
+ required: true
+ max_length: 5
+ min_length: 2
+ status: 201
+ response_headers:
+ location: $SCHEME://$NETLOC/v1/resource_type/myresource
+
+ - name: add an attribute
+ PATCH: /v1/resource_type/myresource
+ request_headers:
+ content-type: application/json-patch+json
+ data:
+ - op: "add"
+ path: "/attributes/awesome-stuff"
+ value: {"type": "bool", "required": false}
+ status: 200
+ response_json_paths:
+ $.name: myresource
+ $.attributes."awesome-stuff".type: bool
+ $.attributes.[*].`len`: 2
+
+ - name: remove an attribute
+ PATCH: /v1/resource_type/myresource
+ request_headers:
+ content-type: application/json-patch+json
+ data:
+ - op: "remove"
+ path: "/attributes/awesome-stuff"
+ status: 200
+ response_json_paths:
+ $.name: myresource
+ $.attributes.display_name.type: string
+ $.attributes.[*].`len`: 1
+
+ - name: myresource resource bad accept
+ desc: Expect 406 on bad accept type
+ request_headers:
+ accept: text/plain
+ GET: /v1/resource/myresource
+ status: 406
+ response_strings:
+ - 406 Not Acceptable
+
+ - name: myresource resource complex accept
+ desc: failover accept media type appropriately
+ request_headers:
+ accept: text/plain, application/json; q=0.8
+ GET: /v1/resource/myresource
+ status: 200
+
+ - name: post myresource resource
+ POST: /v1/resource/myresource
+ request_headers:
+ content-type: application/json
+ data:
+ id: 2ae35573-7f9f-4bb1-aae8-dad8dff5706e
+ user_id: 126204ef-989a-46fd-999b-ee45c8108f31
+ project_id: 98e785d7-9487-4159-8ab8-8230ec37537a
+ display_name: myvm
+ metrics:
+ vcpus:
+ archive_policy_name: gabbilive
+ status: 201
+ response_json_paths:
+ $.id: 2ae35573-7f9f-4bb1-aae8-dad8dff5706e
+ $.user_id: 126204ef-989a-46fd-999b-ee45c8108f31
+ $.project_id: 98e785d7-9487-4159-8ab8-8230ec37537a
+ $.display_name: "myvm"
+
+ - name: get myresource resource
+ GET: $LOCATION
+ status: 200
+ response_json_paths:
+ $.id: 2ae35573-7f9f-4bb1-aae8-dad8dff5706e
+ $.user_id: 126204ef-989a-46fd-999b-ee45c8108f31
+ $.project_id: 98e785d7-9487-4159-8ab8-8230ec37537a
+ $.display_name: "myvm"
+
+ - name: get vcpus metric
+ GET: /v1/metric/$HISTORY['get myresource resource'].$RESPONSE['$.metrics.vcpus']
+ status: 200
+ response_json_paths:
+ $.name: vcpus
+ $.resource.id: 2ae35573-7f9f-4bb1-aae8-dad8dff5706e
+
+ - name: search for myresource resource via user_id
+ POST: /v1/search/resource/myresource
+ request_headers:
+ content-type: application/json
+ data:
+ =:
+ user_id: "126204ef-989a-46fd-999b-ee45c8108f31"
+ response_json_paths:
+ $..id: 2ae35573-7f9f-4bb1-aae8-dad8dff5706e
+ $..user_id: 126204ef-989a-46fd-999b-ee45c8108f31
+ $..project_id: 98e785d7-9487-4159-8ab8-8230ec37537a
+ $..display_name: myvm
+
+ - name: search for myresource resource via user_id and 'generic' type
+ POST: /v1/search/resource/generic
+ request_headers:
+ content-type: application/json
+ data:
+ =:
+ id: "2ae35573-7f9f-4bb1-aae8-dad8dff5706e"
+ response_strings:
+ - '"user_id": "126204ef-989a-46fd-999b-ee45c8108f31"'
+
+ - name: search for myresource resource via user_id and project_id
+ POST: /v1/search/resource/generic
+ request_headers:
+ content-type: application/json
+ data:
+ and:
+ - =:
+ user_id: "126204ef-989a-46fd-999b-ee45c8108f31"
+ - =:
+ project_id: "98e785d7-9487-4159-8ab8-8230ec37537a"
+ response_strings:
+ - '"id": "2ae35573-7f9f-4bb1-aae8-dad8dff5706e"'
+
+ - name: patch myresource resource
+ PATCH: /v1/resource/myresource/2ae35573-7f9f-4bb1-aae8-dad8dff5706e
+ request_headers:
+ content-type: application/json
+ data:
+ display_name: myvm2
+ status: 200
+ response_json_paths:
+ display_name: myvm2
+
+ - name: post some measures to the metric on myresource
+ POST: /v1/resource/myresource/2ae35573-7f9f-4bb1-aae8-dad8dff5706e/metric/vcpus/measures
+ request_headers:
+ content-type: application/json
+ data:
+ - timestamp: "2015-03-06T14:33:57"
+ value: 2
+ - timestamp: "2015-03-06T14:34:12"
+ value: 2
+ status: 202
+
+ - name: get myresource measures with poll
+ GET: /v1/resource/myresource/2ae35573-7f9f-4bb1-aae8-dad8dff5706e/metric/vcpus/measures
+ # wait up to 60 seconds before policy is deleted
+ poll:
+ count: 60
+ delay: 1
+ response_json_paths:
+ $[0][2]: 2
+ $[1][2]: 2
+
+ - name: post some more measures to the metric on myresource
+ POST: /v1/resource/myresource/2ae35573-7f9f-4bb1-aae8-dad8dff5706e/metric/vcpus/measures
+ request_headers:
+ content-type: application/json
+ data:
+ - timestamp: "2015-03-06T14:34:15"
+ value: 5
+ - timestamp: "2015-03-06T14:34:20"
+ value: 5
+ status: 202
+
+ - name: get myresource measures with refresh
+ GET: /v1/resource/myresource/2ae35573-7f9f-4bb1-aae8-dad8dff5706e/metric/vcpus/measures?refresh=true
+ response_json_paths:
+ $[0][2]: 2
+ $[1][2]: 4
+ $[2][2]: 2
+ $[3][2]: 2
+ $[4][2]: 5
+ $[5][2]: 5
+
+ #
+ # Search for resources
+ #
+
+ - name: typo of search
+ POST: /v1/search/notexists
+ status: 404
+
+ - name: typo of search in resource
+ POST: /v1/search/resource/foobar
+ status: 404
+
+ - name: search with invalid uuid
+ POST: /v1/search/resource/generic
+ request_headers:
+ content-type: application/json
+ data:
+ =:
+ id: "cd9eef"
+ status: 200
+ response_json_paths:
+ $.`len`: 0
+
+ - name: assert vcpus metric exists in listing
+ GET: /v1/metric?id=$HISTORY['get myresource resource'].$RESPONSE['$.metrics.vcpus']
+ poll:
+ count: 360
+ delay: 1
+ response_json_paths:
+ $.`len`: 1
+
+ - name: delete myresource resource
+ DELETE: /v1/resource/myresource/2ae35573-7f9f-4bb1-aae8-dad8dff5706e
+ status: 204
+
+ # assert resource is really deleted
+ - name: assert resource resource is deleted
+ GET: /v1/resource/myresource/2ae35573-7f9f-4bb1-aae8-dad8dff5706e
+ status: 404
+
+ - name: assert vcpus metric is really expurged
+ GET: $HISTORY['assert vcpus metric exists in listing'].$URL&status=delete
+ poll:
+ count: 360
+ delay: 1
+ response_json_paths:
+ $.`len`: 0
+
+ - name: post myresource resource no data
+ POST: /v1/resource/myresource
+ request_headers:
+ content-type: application/json
+ status: 400
+
+ - name: assert no metrics have the gabbilive policy
+ GET: $HISTORY['assert metric is the only one with this policy'].$URL
+ response_json_paths:
+ $.`len`: 0
+
+ - name: assert no delete metrics have the gabbilive policy
+ GET: $HISTORY['assert metric is the only one with this policy'].$URL&status=delete
+ response_json_paths:
+ $.`len`: 0
+
+ - name: delete single archive policy cleanup
+ DELETE: /v1/archive_policy/gabbilive
+ poll:
+ count: 360
+ delay: 1
+ status: 204
+
+ # It really is gone
+
+ - name: delete our resource type
+ DELETE: /v1/resource_type/myresource
+ status: 204
+
+ - name: confirm delete of cleanup
+ GET: /v1/archive_policy/gabbilive
+ status: 404
diff --git a/telemetry_tempest_plugin/gnocchi/functional_live/gabbits/search-resource.yaml b/telemetry_tempest_plugin/gnocchi/functional_live/gabbits/search-resource.yaml
new file mode 100644
index 0000000..fe25478
--- /dev/null
+++ b/telemetry_tempest_plugin/gnocchi/functional_live/gabbits/search-resource.yaml
@@ -0,0 +1,275 @@
+#
+# Tests to confirm resources are searchable. Run against a live setup.
+# URL: http://gnocchi.xyz/rest.html#searching-for-resources
+#
+# Instance-ResourceID-1: a64ca14f-bc7c-45b0-aa85-42cd2179e1e2
+# Instance-ResourceID-2: 7ccccfa0-92ce-4225-80ca-3ac9cb122d6a
+# Instance-ResourceID-3: c442a47c-eb33-46ce-9665-f3aa0bef54e7
+#
+# UserID-1: 33ba83ca-2f12-4ad6-8fa2-bc8b55d36e07
+# UserID-2: 81d82ef3-4deb-499d-9270-9aeb5a3ec5fe
+#
+# ProjectID-1: c9a5f184-c0d0-4daa-83c3-af6fdc0879e6
+# ProjectID-2: 40eba01c-b348-49b8-803f-67123251a00a
+#
+# ImageID-1: 7ab2f7ae-7af5-4469-bdc8-3c0f6dfab75d
+# ImageID-2: b01f2588-89dc-46b2-897b-fffae1e10975
+#
+
+defaults:
+ request_headers:
+ x-auth-token: $ENVIRON['GNOCCHI_SERVICE_TOKEN']
+ authorization: $ENVIRON['GNOCCHI_AUTHORIZATION']
+
+tests:
+ #
+ # Setup resource types if don't exist
+ #
+
+ - name: create new resource type 'instance-like'
+ POST: /v1/resource_type
+ status: 201
+ request_headers:
+ content-type: application/json
+ data:
+ name: instance-like
+ attributes:
+ display_name:
+ type: string
+ required: True
+ flavor_id:
+ type: string
+ required: True
+ host:
+ type: string
+ required: True
+ image_ref:
+ type: string
+ required: False
+ server_group:
+ type: string
+ required: False
+
+ - name: create new resource type 'image-like'
+ POST: /v1/resource_type
+ status: 201
+ request_headers:
+ content-type: application/json
+ data:
+ name: image-like
+ attributes:
+ name:
+ type: string
+ required: True
+ disk_format:
+ type: string
+ required: True
+ container_format:
+ type: string
+ required: True
+
+ #
+ # Setup test resources
+ #
+ - name: helper. create instance-like resource-1
+ POST: /v1/resource/instance-like
+ request_headers:
+ content-type: application/json
+ data:
+ display_name: vm-gabbi-1
+ id: a64ca14f-bc7c-45b0-aa85-42cd2179e1e2
+ user_id: 33ba83ca-2f12-4ad6-8fa2-bc8b55d36e07
+ flavor_id: "1"
+ image_ref: 7ab2f7ae-7af5-4469-bdc8-3c0f6dfab75d
+ host: compute-0-gabbi.localdomain
+ project_id: c9a5f184-c0d0-4daa-83c3-af6fdc0879e6
+ status: 201
+
+ - name: helper. create instance-like resource-2
+ POST: /v1/resource/instance-like
+ request_headers:
+ content-type: application/json
+ data:
+ display_name: vm-gabbi-2
+ id: 7ccccfa0-92ce-4225-80ca-3ac9cb122d6a
+ user_id: 33ba83ca-2f12-4ad6-8fa2-bc8b55d36e07
+ flavor_id: "2"
+ image_ref: b01f2588-89dc-46b2-897b-fffae1e10975
+ host: compute-1-gabbi.localdomain
+ project_id: c9a5f184-c0d0-4daa-83c3-af6fdc0879e6
+ status: 201
+
+ - name: helper. create instance-like resource-3
+ POST: /v1/resource/instance-like
+ request_headers:
+ content-type: application/json
+ data:
+ display_name: vm-gabbi-3
+ id: c442a47c-eb33-46ce-9665-f3aa0bef54e7
+ user_id: 81d82ef3-4deb-499d-9270-9aeb5a3ec5fe
+ flavor_id: "2"
+ image_ref: b01f2588-89dc-46b2-897b-fffae1e10975
+ host: compute-1-gabbi.localdomain
+ project_id: 40eba01c-b348-49b8-803f-67123251a00a
+ status: 201
+
+ - name: helper. create image-like resource-1
+ POST: /v1/resource/image-like
+ request_headers:
+ content-type: application/json
+ data:
+ id: 7ab2f7ae-7af5-4469-bdc8-3c0f6dfab75d
+ container_format: bare
+ disk_format: qcow2
+ name: gabbi-image-1
+ user_id: 81d82ef3-4deb-499d-9270-9aeb5a3ec5fe
+ project_id: 40eba01c-b348-49b8-803f-67123251a00a
+ status: 201
+
+ #
+ # Actual tests
+ #
+
+ - name: search for all resources with a specific user_id
+ desc: search through all resource types
+ POST: /v1/search/resource/generic
+ request_headers:
+ content-type: application/json
+ data:
+ =:
+ user_id: 81d82ef3-4deb-499d-9270-9aeb5a3ec5fe
+ status: 200
+ response_json_paths:
+ $.`len`: 2
+ response_json_paths:
+ $.[0].type: instance-like
+ $.[1].type: image-like
+ $.[0].id: c442a47c-eb33-46ce-9665-f3aa0bef54e7
+ $.[1].id: 7ab2f7ae-7af5-4469-bdc8-3c0f6dfab75d
+
+ - name: search for all resources of instance-like type create by specific user_id
+ desc: all instances created by a specified user
+ POST: /v1/search/resource/generic
+ request_headers:
+ content-type: application/json
+ data:
+ and:
+ - =:
+ type: instance-like
+ - =:
+ user_id: 33ba83ca-2f12-4ad6-8fa2-bc8b55d36e07
+ status: 200
+ response_json_paths:
+ $.`len`: 2
+ response_strings:
+ - '"id": "a64ca14f-bc7c-45b0-aa85-42cd2179e1e2"'
+ - '"id": "7ccccfa0-92ce-4225-80ca-3ac9cb122d6a"'
+ response_json_paths:
+ $.[0].id: a64ca14f-bc7c-45b0-aa85-42cd2179e1e2
+ $.[1].id: 7ccccfa0-92ce-4225-80ca-3ac9cb122d6a
+ $.[0].type: instance-like
+ $.[1].type: instance-like
+ $.[0].metrics.`len`: 0
+ $.[1].metrics.`len`: 0
+
+ - name: search for all resources with a specific project_id
+ desc: search for all resources in a specific project
+ POST: /v1/search/resource/generic
+ request_headers:
+ content-type: application/json
+ data:
+ =:
+ project_id: c9a5f184-c0d0-4daa-83c3-af6fdc0879e6
+ status: 200
+ response_json_paths:
+ $.`len`: 2
+
+ - name: search for intances on a specific compute using "like" keyword
+ desc: search for vms hosted on a specific compute node
+ POST: /v1/search/resource/instance-like
+ request_headers:
+ content-type: application/json
+ data:
+ like:
+ host: 'compute-1-gabbi%'
+ response_json_paths:
+ $.`len`: 2
+ response_strings:
+ - '"project_id": "40eba01c-b348-49b8-803f-67123251a00a"'
+ - '"project_id": "c9a5f184-c0d0-4daa-83c3-af6fdc0879e6"'
+ - '"user_id": "33ba83ca-2f12-4ad6-8fa2-bc8b55d36e07"'
+ - '"user_id": "81d82ef3-4deb-499d-9270-9aeb5a3ec5fe"'
+ - '"display_name": "vm-gabbi-2"'
+ - '"display_name": "vm-gabbi-3"'
+
+ - name: search for instances using complex search with "like" keyword and user_id
+ desc: search for vms of specified user hosted on a specific compute node
+ POST: /v1/search/resource/instance-like
+ request_headers:
+ content-type: application/json
+ data:
+ and:
+ - like:
+ host: 'compute-%-gabbi%'
+ - =:
+ user_id: 33ba83ca-2f12-4ad6-8fa2-bc8b55d36e07
+ response_json_paths:
+ $.`len`: 2
+ response_strings:
+ - '"display_name": "vm-gabbi-1"'
+ - '"display_name": "vm-gabbi-2"'
+ - '"project_id": "c9a5f184-c0d0-4daa-83c3-af6fdc0879e6"'
+
+ - name: search for resources of instance-like or image-like type with specific user_id
+ desc: search for all image-like or instance-like resources created by a specific user
+ POST: /v1/search/resource/generic
+ request_headers:
+ content-type: application/json
+ data:
+ and:
+ - =:
+ user_id: 81d82ef3-4deb-499d-9270-9aeb5a3ec5fe
+
+ - or:
+ - =:
+ type: instance-like
+
+ - =:
+ type: image-like
+ status: 200
+ response_json_paths:
+ $.`len`: 2
+ response_strings:
+ - '"type": "image-like"'
+ - '"type": "instance-like"'
+ - '"id": "7ab2f7ae-7af5-4469-bdc8-3c0f6dfab75d"'
+ - '"id": "c442a47c-eb33-46ce-9665-f3aa0bef54e7"'
+
+ #
+ # Tear down resources
+ #
+
+ - name: helper. delete instance-like resource-1
+ DELETE: /v1/resource/instance-like/a64ca14f-bc7c-45b0-aa85-42cd2179e1e2
+ status: 204
+
+ - name: helper. delete instance-like resource-2
+ DELETE: /v1/resource/instance-like/7ccccfa0-92ce-4225-80ca-3ac9cb122d6a
+ status: 204
+
+ - name: helper. delete instance-like resource-3
+ DELETE: /v1/resource/instance-like/c442a47c-eb33-46ce-9665-f3aa0bef54e7
+ status: 204
+
+ - name: helper. delete image-like resource
+ DELETE: /v1/resource/image-like/7ab2f7ae-7af5-4469-bdc8-3c0f6dfab75d
+ status: 204
+
+ - name: helper. delete resource-type instance-like
+ DELETE: /v1/resource_type/instance-like
+ status: 204
+
+ - name: helper. delete resource-type image-like
+ DELETE: /v1/resource_type/image-like
+ status: 204
+
diff --git a/telemetry_tempest_plugin/gnocchi/scenario/__init__.py b/telemetry_tempest_plugin/gnocchi/scenario/__init__.py
new file mode 100644
index 0000000..3ad1239
--- /dev/null
+++ b/telemetry_tempest_plugin/gnocchi/scenario/__init__.py
@@ -0,0 +1,110 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from __future__ import absolute_import
+
+import os
+import unittest
+
+from gabbi import runner
+from gabbi import suitemaker
+from gabbi import utils
+import six.moves.urllib.parse as urlparse
+from tempest import config
+import tempest.test
+
+CONF = config.CONF
+
+TEST_DIR = os.path.join(os.path.dirname(__file__), '..',
+ 'gnocchi', 'functional_live', 'gabbits')
+
+
+class GnocchiGabbiTest(tempest.test.BaseTestCase):
+ credentials = ['admin']
+
+ TIMEOUT_SCALING_FACTOR = 5
+
+ @classmethod
+ def skip_checks(cls):
+ super(GnocchiGabbiTest, cls).skip_checks()
+ if not CONF.service_available.gnocchi:
+ raise cls.skipException("Gnocchi support is required")
+
+ def _do_test(self, filename):
+ token = self.os_admin.auth_provider.get_token()
+ url = self.os_admin.auth_provider.base_url(
+ {'service': CONF.metric.catalog_type,
+ 'endpoint_type': CONF.metric.endpoint_type})
+
+ parsed_url = urlparse.urlsplit(url)
+ prefix = parsed_url.path.rstrip('/') # turn it into a prefix
+ if parsed_url.scheme == 'https':
+ port = 443
+ require_ssl = True
+ else:
+ port = 80
+ require_ssl = False
+ host = parsed_url.hostname
+ if parsed_url.port:
+ port = parsed_url.port
+
+ os.environ["GNOCCHI_SERVICE_TOKEN"] = token
+ os.environ["GNOCCHI_AUTHORIZATION"] = "not used"
+
+ with open(os.path.join(TEST_DIR, filename)) as f:
+ suite_dict = utils.load_yaml(f)
+ suite_dict.setdefault('defaults', {})['ssl'] = require_ssl
+ test_suite = suitemaker.test_suite_from_dict(
+ loader=unittest.defaultTestLoader,
+ test_base_name="gabbi",
+ suite_dict=suite_dict,
+ test_directory=TEST_DIR,
+ host=host, port=port,
+ fixture_module=None,
+ intercept=None,
+ prefix=prefix,
+ handlers=runner.initialize_handlers([]),
+ test_loader_name="tempest")
+
+ # NOTE(sileht): We hide stdout/stderr and reraise the failure
+ # manually, tempest will print it itself.
+ with open(os.devnull, 'w') as stream:
+ result = unittest.TextTestRunner(
+ stream=stream, verbosity=0, failfast=True,
+ ).run(test_suite)
+
+ if not result.wasSuccessful():
+ failures = (result.errors + result.failures +
+ result.unexpectedSuccesses)
+ if failures:
+ test, bt = failures[0]
+ name = test.test_data.get('name', test.id())
+ msg = 'From test "%s" :\n%s' % (name, bt)
+ self.fail(msg)
+
+ self.assertTrue(result.wasSuccessful())
+
+
+def test_maker(name, filename):
+ def test(self):
+ self._do_test(filename)
+ test.__name__ = name
+ return test
+
+
+# Create one scenario per yaml file
+for filename in os.listdir(TEST_DIR):
+ if not filename.endswith('.yaml'):
+ continue
+ name = "test_%s" % filename[:-5].lower().replace("-", "_")
+ setattr(GnocchiGabbiTest, name,
+ test_maker(name, filename))
diff --git a/telemetry_tempest_plugin/plugin.py b/telemetry_tempest_plugin/plugin.py
index 0d8fdfd..2f2861e 100644
--- a/telemetry_tempest_plugin/plugin.py
+++ b/telemetry_tempest_plugin/plugin.py
@@ -43,6 +43,9 @@
config.register_opt_group(
conf, tempest_config.alarming_group,
tempest_config.AlarmingGroup)
+ config.register_opt_group(
+ conf, tempest_config.metric_group,
+ tempest_config.metric_opts)
def get_opt_lists(self):
return [(tempest_config.telemetry_group.name,
@@ -52,4 +55,6 @@
(config.service_available_group.name,
tempest_config.service_option),
(tempest_config.alarming_group.name,
- tempest_config.AlarmingGroup)]
+ tempest_config.AlarmingGroup),
+ (tempest_config.metric_group.name,
+ tempest_config.metric_opts)]