Reorganize scenario testing.
* This moves all scenarios in scenarios directory.
* factorized code between two scenarios in utils.py
* remove unused tempest-heat-plugin
Change-Id: Ifd2e1ad1453484e6af4ae09dedb6e96d96f42b52
diff --git a/telemetry_tempest_plugin/scenario/gnocchi_gabbits/live.yaml b/telemetry_tempest_plugin/scenario/gnocchi_gabbits/live.yaml
new file mode 100644
index 0000000..6d15d61
--- /dev/null
+++ b/telemetry_tempest_plugin/scenario/gnocchi_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: $ENVIRON['GNOCCHI_SERVICE_URL']/
+
+ # Fail to create archive policy
+ - name: wrong archive policy content type
+ desc: attempt to create archive policy with invalid content-type
+ POST: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/archive_policy
+ request_headers:
+ content-type: application/json
+ status: 405
+
+ - name: invalid authZ
+ desc: x-auth-token is invalid
+ POST: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/archive_policy/gabbilive
+ status: 405
+
+ - name: put single archive
+ desc: unexpected 'PUT' request to archive policy
+ PUT: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/archive_policy/grandiose
+ status: 404
+ response_strings:
+ - Archive policy grandiose does not exist
+
+ # Attempt to create illogical policies
+
+ - name: create illogical policy
+ POST: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/archive_policy_rule
+ request_headers:
+ content-type: text/plain
+ status: 415
+ response_strings:
+ - Unsupported Media Type
+
+ - name: bad archive policy rule body
+ POST: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/archive_policy_rule/foo
+ status: 404
+
+
+ - name: get archive policy rule
+ GET: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/archive_policy/gabbilive
+ status: 400
+
+ #
+ # Metrics
+ #
+
+
+ - name: get all metrics
+ GET: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/metric
+ status: 200
+
+ - name: create metric with name and rule
+ POST: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/metric?archive_policy_name=gabbilive
+ response_json_paths:
+ $.`len`: 1
+
+ - name: delete metric
+ DELETE: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/metric/$RESPONSE['$.id']
+ status: 204
+
+ - name: ensure the metric is delete
+ GET: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/metric/$HISTORY['get valid metric id'].$RESPONSE['$.id']
+ status: 404
+
+ - name: create metric bad archive policy
+ POST: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/metric
+ request_headers:
+ content-type: plain/text
+ data: '{"archive_policy_name": "cookies"}'
+ status: 415
+
+
+ #
+ # Cleanup
+ #
+
+ - name: delete archive policy rule
+ DELETE: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/archive_policy_rule/gabbilive_rule
+ status: 204
+
+ - name: confirm delete archive policy rule
+ DELETE: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/archive_policy_rule/gabbilive_rule
+ status: 404
+
+
+ #
+ # Resources section
+ #
+
+ - name: root of resource
+ GET: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/resource
+ response_json_paths:
+ $.generic: $SCHEME://$NETLOC/v1/resource/generic
+
+ - name: typo of resource
+ GET: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/resoue
+ status: 404
+
+ - name: typo of resource extra
+ GET: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/resource/foobar
+ status: 404
+
+ - name: generic resource
+ GET: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/resource/generic
+ status: 200
+
+ - name: post resource type
+ POST: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/resource/myresource
+ status: 200
+
+ - name: post myresource resource
+ POST: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/search/notexists
+ status: 404
+
+ - name: typo of search in resource
+ POST: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/search/resource/foobar
+ status: 404
+
+ - name: search with invalid uuid
+ POST: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/resource/myresource/2ae35573-7f9f-4bb1-aae8-dad8dff5706e
+ status: 204
+
+ # assert resource is really deleted
+ - name: assert resource resource is deleted
+ GET: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/archive_policy/gabbilive
+ poll:
+ count: 360
+ delay: 1
+ status: 204
+
+ # It really is gone
+
+ - name: delete our resource type
+ DELETE: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/resource_type/myresource
+ status: 204
+
+ - name: confirm delete of cleanup
+ GET: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/archive_policy/gabbilive
+ status: 404
diff --git a/telemetry_tempest_plugin/scenario/gnocchi_gabbits/search-resource.yaml b/telemetry_tempest_plugin/scenario/gnocchi_gabbits/search-resource.yaml
new file mode 100644
index 0000000..8febac6
--- /dev/null
+++ b/telemetry_tempest_plugin/scenario/gnocchi_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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/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: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/resource/instance-like/a64ca14f-bc7c-45b0-aa85-42cd2179e1e2
+ status: 204
+
+ - name: helper. delete instance-like resource-2
+ DELETE: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/resource/instance-like/7ccccfa0-92ce-4225-80ca-3ac9cb122d6a
+ status: 204
+
+ - name: helper. delete instance-like resource-3
+ DELETE: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/resource/instance-like/c442a47c-eb33-46ce-9665-f3aa0bef54e7
+ status: 204
+
+ - name: helper. delete image-like resource
+ DELETE: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/resource/image-like/7ab2f7ae-7af5-4469-bdc8-3c0f6dfab75d
+ status: 204
+
+ - name: helper. delete resource-type instance-like
+ DELETE: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/resource_type/instance-like
+ status: 204
+
+ - name: helper. delete resource-type image-like
+ DELETE: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/resource_type/image-like
+ status: 204
+
diff --git a/telemetry_tempest_plugin/scenario/telemetry_integration_gabbits/aodh-gnocchi-threshold-alarm.yaml b/telemetry_tempest_plugin/scenario/telemetry_integration_gabbits/aodh-gnocchi-threshold-alarm.yaml
new file mode 100644
index 0000000..9349295
--- /dev/null
+++ b/telemetry_tempest_plugin/scenario/telemetry_integration_gabbits/aodh-gnocchi-threshold-alarm.yaml
@@ -0,0 +1,309 @@
+#
+# Tests for gnocchi-threshold-alarm
+#
+# user_id : c8ecb587-d38c-426f-a58d-22b8d4a9a1d3
+# project_id : 709f6ed6-bfb3-4649-b303-0019a7f6aef2
+# alarm name : gabbi-gnocchi-threshold-resource-alarm
+# resource_id : gabbi-mock-resource
+# archive policy : gabbiliveceph
+#
+
+defaults:
+ request_headers:
+ x-auth-token: $ENVIRON['ADMIN_TOKEN']
+
+tests:
+ #
+ # Setup gnocchi archive policy/resource type/resource/metrics
+ #
+
+ - name: SETUP. create archive policy gabbiliveceph
+ desc: create archve policy 'gabbiliveceph' for tests
+ POST: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/archive_policy
+ status: 201
+ request_headers:
+ content-type: application/json
+ data:
+ name: gabbiliveceph
+ back_window: 0
+ definition:
+ - granularity: 1 second
+ points: 60
+ - granularity: 20 second
+ timespan: 1 minute
+ - points: 5
+ timespan: 5 minute
+ aggregation_methods:
+ - mean
+ - min
+ - max
+ response_json_paths:
+ $.name: gabbiliveceph
+ $.back_window: 0
+ $.aggregation_methods.`len`: 3
+
+ - name: create resource type ceph_account
+ desc: needed to create a resource
+ POST: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/resource_type
+ status: 201 || 409
+ request_headers:
+ content-type: application/json
+ data:
+ name: ceph_account
+
+ - name: create resource of ceph_account type
+ POST: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/resource/ceph_account
+ request_headers:
+ content-type: application/json
+ data:
+ id: 662e46f3-8c06-430c-8a9c-adcaedd1272c
+ user_id: 27e342e4-4489-424f-a7e4-ba8ed9ad729c
+ project_id: d6d32769-c351-4758-b0a2-458fa1a065a3
+ metrics:
+ radosgw.objects:
+ archive_policy_name: gabbiliveceph
+ radosgw.objects.size:
+ archive_policy_name: gabbiliveceph
+ radosgw.objects.containers:
+ archive_policy_name: gabbiliveceph
+ radosgw.api.request:
+ archive_policy_name: gabbiliveceph
+ radosgw.containers.objects:
+ archive_policy_name: gabbiliveceph
+ radosgw.containers.objects.size:
+ archive_policy_name: gabbiliveceph
+ status: 201
+ response_json_paths:
+ $.user_id: 27e342e4-4489-424f-a7e4-ba8ed9ad729c
+ $.project_id: d6d32769-c351-4758-b0a2-458fa1a065a3
+ $.metrics.`len`: 6
+
+ #
+ # Actual tests
+ #
+
+ - name: search 'gabbi-gnocchi-threshold-resource-alarm' alarm doesnt exist
+ desc: search for alarm using user_id, project_id, alarm_name
+ GET: $ENVIRON['AODH_SERVICE_URL']/v2/alarms
+ query_parameters:
+ q.field:
+ - user_id
+ - project_id
+ - name
+ q.op:
+ - eq
+ - eq
+ - eq
+ q.value:
+ - c8ecb587-d38c-426f-a58d-22b8d4a9a1d3
+ - 709f6ed6-bfb3-4649-b303-0019a7f6aef2
+ - gabbi-gnocchi-threshold-resource-alarm
+ method: GET
+ response_json_paths:
+ $.`len`: 0
+
+ - name: create alarm 'gabbi-gnocchi-threshold-resource-alarm'
+ desc: create a threshold alarm gabbi-gnocchi-threshold-resource-alarm
+ POST: $ENVIRON['AODH_SERVICE_URL']/v2/alarms
+ request_headers:
+ content-type: application/json
+ data:
+ alarm_actions:
+ - "http://site:8000/gnocchi-threshold-resource"
+ alarm_id: null
+ description: An gabbilive threshold based alarm
+ enabled: true
+ insufficient_data_actions:
+ - "http://site:8000/nodata-gnocchi-threshold-resource"
+ name: "gabbi-gnocchi-threshold-resource-alarm"
+ ok_actions:
+ - "http://site:8000/ok-gnocchi-threshold-resource"
+ project_id: 709f6ed6-bfb3-4649-b303-0019a7f6aef2
+ repeat_actions: false
+ severity: moderate
+ state: "insufficient data"
+ type: gnocchi_resources_threshold
+ gnocchi_resources_threshold_rule:
+ evaluation_periods: 3
+ metric: "radosgw.objects.size"
+ resource_id: "662e46f3-8c06-430c-8a9c-adcaedd1272c"
+ aggregation_method: "mean"
+ granularity: 60
+ threshold: 5.0
+ comparison_operator: "ge"
+ resource_type: ceph_account
+ user_id: c8ecb587-d38c-426f-a58d-22b8d4a9a1d3
+ status: 201
+ response_json_paths:
+ $.name: gabbi-gnocchi-threshold-resource-alarm
+ $.type: gnocchi_resources_threshold
+ $.user_id: c8ecb587-d38c-426f-a58d-22b8d4a9a1d3
+ $.project_id: 709f6ed6-bfb3-4649-b303-0019a7f6aef2
+ $.severity: moderate
+
+ - name: retrieve history about 'gabbi-gnocchi-threshold-resource-alarm' creation
+ desc: get history about alarm creation
+ GET: $ENVIRON['AODH_SERVICE_URL']/v2/alarms/$RESPONSE['$.alarm_id']/history
+ request_headers:
+ content-type: application/json
+ poll:
+ count: 5
+ delay: 2
+ response_json_paths:
+ $.`len`: 1
+ $.[0].type: creation
+ $.[0].alarm_id: $RESPONSE['$.alarm_id']
+
+ - name: update severity for alarm 'gabbi-gnocchi-threshold-resource-alarm'
+ desc: update severity for alarm gabbi-gnocchi-threshold-resource-alarm
+ PUT: $ENVIRON['AODH_SERVICE_URL']/v2/alarms/$RESPONSE['$.[0].alarm_id']
+ status: 200
+ request_headers:
+ content-type: application/json
+ data:
+ alarm_actions:
+ - "http://site:8000/gnocchi-threshold-resource"
+ alarm_id: null
+ description: An gabbilive threshold based alarm
+ enabled: true
+ insufficient_data_actions:
+ - "http://site:8000/nodata-gnocchi-threshold-resource"
+ name: "gabbi-gnocchi-threshold-resource-alarm"
+ ok_actions:
+ - "http://site:8000/ok-gnocchi-threshold-resource"
+ project_id: 709f6ed6-bfb3-4649-b303-0019a7f6aef2
+ repeat_actions: false
+ severity: low
+ state: "insufficient data"
+ type: gnocchi_resources_threshold
+ gnocchi_resources_threshold_rule:
+ evaluation_periods: 3
+ metric: "radosgw.objects.size"
+ resource_id: "662e46f3-8c06-430c-8a9c-adcaedd1272c"
+ aggregation_method: "mean"
+ granularity: 60
+ threshold: 5.0
+ comparison_operator: "ge"
+ resource_type: ceph_account
+ user_id: c8ecb587-d38c-426f-a58d-22b8d4a9a1d3
+ response_json_paths:
+ $.name: gabbi-gnocchi-threshold-resource-alarm
+ $.type: gnocchi_resources_threshold
+ $.user_id: c8ecb587-d38c-426f-a58d-22b8d4a9a1d3
+ $.project_id: 709f6ed6-bfb3-4649-b303-0019a7f6aef2
+ $.severity: low
+ $.state: "insufficient data"
+
+ - name: retrieve history for 'gabbi-gnocchi-threshold-resource-alarm'
+ desc: get history for rule_change
+ GET: $ENVIRON['AODH_SERVICE_URL']/v2/alarms/$RESPONSE['$.alarm_id']/history
+ request_headers:
+ content-type: application/json
+ poll:
+ count: 5
+ delay: 2
+ response_json_paths:
+ $.`len`: 2
+ $.[0].type: rule change
+ $.[0].alarm_id: $RESPONSE['$.alarm_id']
+ $.[0].detail: '{"severity": "low"}'
+
+ - name: update alarm state for 'gabbi-gnocchi-threshold-resource-alarm'
+ desc: update state for alarm
+ PUT: $ENVIRON['AODH_SERVICE_URL']/v2/alarms/$RESPONSE['$.[0].alarm_id']/state
+ request_headers:
+ content-type: application/json
+ data: '"ok"'
+ status: 200
+ response_strings:
+ - "ok"
+
+ - name: get alarm state for 'gabbi-gnocchi-threshold-resource-alarm'
+ desc: get state for alarm
+ GET: $URL
+ request_headers:
+ content-type: application/json
+ status: 200
+ response_strings:
+ - "ok"
+
+ - name: search 'gabbi-gnocchi-threshold-resource-alarm' alarm exist
+ desc: search for alarm using user_id, project_id, alarm_name
+ GET: $ENVIRON['AODH_SERVICE_URL']/v2/alarms
+ query_parameters:
+ q.field:
+ - user_id
+ - project_id
+ - name
+ q.op:
+ - eq
+ - eq
+ - eq
+ q.value:
+ - c8ecb587-d38c-426f-a58d-22b8d4a9a1d3
+ - 709f6ed6-bfb3-4649-b303-0019a7f6aef2
+ - gabbi-gnocchi-threshold-resource-alarm
+ poll:
+ count: 5
+ delay: 2
+ response_json_paths:
+ $.`len`: 1
+
+ - name: get info about 'gabbi-gnocchi-threshold-resource-alarm' alarm
+ desc: access alarm using its ID
+ GET: $ENVIRON['AODH_SERVICE_URL']/v2/alarms/$RESPONSE['$.[0].alarm_id']
+ response_json_paths:
+ $.alarm_id: $RESPONSE['$.[0].alarm_id']
+ $.alarm_actions: ["http://site:8000/gnocchi-threshold-resource"]
+ $.name: gabbi-gnocchi-threshold-resource-alarm
+ $.gnocchi_resources_threshold_rule.resource_id: "662e46f3-8c06-430c-8a9c-adcaedd1272c"
+ $.gnocchi_resources_threshold_rule.metric: "radosgw.objects.size"
+ $.gnocchi_resources_threshold_rule.resource_type: "ceph_account"
+ $.user_id: c8ecb587-d38c-426f-a58d-22b8d4a9a1d3
+
+ #
+ # Teardown
+ #
+
+ - name: CLEANUP. search 'gabbi-gnocchi-threshold-resource' alarm exist
+ desc: Find alarm id using user_id, project_id, alarm_name
+ GET: $ENVIRON['AODH_SERVICE_URL']/v2/alarms
+ query_parameters:
+ q.field:
+ - user_id
+ - project_id
+ - name
+ q.op:
+ - eq
+ - eq
+ - eq
+ q.value:
+ - c8ecb587-d38c-426f-a58d-22b8d4a9a1d3
+ - 709f6ed6-bfb3-4649-b303-0019a7f6aef2
+ - gabbi-gnocchi-threshold-resource-alarm
+ response_json_paths:
+ $.`len`: 1
+
+ - name: CLEANUP. delete threshold alarm 'gabbi-gnocchi-threshold-resource'
+ DELETE: $ENVIRON['AODH_SERVICE_URL']/v2/alarms/$RESPONSE['$.[0].alarm_id']
+ status: 204
+
+ - name: CLEANUP. Get resource by name '662e46f3-8c06-430c-8a9c-adcaedd1272c'
+ desc: retrieve resource by 662e46f3-8c06-430c-8a9c-adcaedd1272c to get its ID
+ GET: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/resource/generic/662e46f3-8c06-430c-8a9c-adcaedd1272c
+ status: 200
+
+ - name: CLEANUP. delete test ceph_resource '662e46f3-8c06-430c-8a9c-adcaedd1272c'
+ desc: delete ceph_account resource 662e46f3-8c06-430c-8a9c-adcaedd1272c
+ DELETE: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/resource/generic/$RESPONSE['$.id']
+ status: 204
+
+ - name: CLEANUP. delete resource type ceph_account
+ DELETE: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/resource_type/ceph_account
+ status: 204
+
+ - name: CLEANUP. delete archive
+ DELETE: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/archive_policy/gabbiliveceph
+ status: 204
+ xfail: True
+
diff --git a/telemetry_tempest_plugin/scenario/telemetry_integration_gabbits/autoscaling.yaml b/telemetry_tempest_plugin/scenario/telemetry_integration_gabbits/autoscaling.yaml
new file mode 100644
index 0000000..8eac9d0
--- /dev/null
+++ b/telemetry_tempest_plugin/scenario/telemetry_integration_gabbits/autoscaling.yaml
@@ -0,0 +1,175 @@
+defaults:
+ request_headers:
+ x-auth-token: $ENVIRON['USER_TOKEN']
+
+tests:
+ - name: list alarms none
+ desc: Lists alarms, none yet exist
+ url: $ENVIRON['AODH_SERVICE_URL']/v2/alarms
+ method: GET
+ response_strings:
+ - "[]"
+
+ - name: list servers none
+ desc: List servers, none yet exists
+ url: $ENVIRON['NOVA_SERVICE_URL']/servers
+ method: GET
+ response_strings:
+ - "[]"
+
+ - name: create stack
+ desc: Create an autoscaling stack
+ url: $ENVIRON['HEAT_SERVICE_URL']/stacks
+ method: POST
+ request_headers:
+ content-type: application/json
+ data: <@create_stack.json
+ status: 201
+
+ - name: control stack status
+ desc: Checks the stack have been created successfully
+ url: $ENVIRON['HEAT_SERVICE_URL']/stacks/integration_test
+ redirects: true
+ method: GET
+ status: 200
+ poll:
+ count: 300
+ delay: 1
+ response_json_paths:
+ $.stack.stack_status: "CREATE_COMPLETE"
+
+ - name: list servers grow
+ desc: Wait the autoscaling stack grow to two servers
+ url: $ENVIRON['NOVA_SERVICE_URL']/servers/detail
+ method: GET
+ poll:
+ count: 600
+ delay: 1
+ response_json_paths:
+ $.servers[0].metadata.'metering.server_group': $RESPONSE['$.stack.id']
+ $.servers[1].metadata.'metering.server_group': $RESPONSE['$.stack.id']
+ $.servers[0].status: ACTIVE
+ $.servers[1].status: ACTIVE
+ $.servers.`len`: 2
+
+ - name: check gnocchi resources
+ desc: Check the gnocchi resources for this two servers exists
+ url: $ENVIRON['GNOCCHI_SERVICE_URL']/v1/resource/instance
+ method: GET
+ poll:
+ count: 30
+ delay: 1
+ response_strings:
+ - '"id": "$RESPONSE["$.servers[0].id"]"'
+ - '"id": "$RESPONSE["$.servers[1].id"]"'
+
+ - name: check event
+ desc: Check panko for new instance.create.end event
+ url: $ENVIRON['PANKO_SERVICE_URL']/v2/events
+ method: GET
+ request_headers:
+ content-type: application/json
+ data:
+ q:
+ - field: event_type
+ op: eq
+ type: string
+ value: compute.instance.create.end
+ - field: resource_id
+ op: eq
+ type: string
+ value: $HISTORY['list servers grow'].$RESPONSE['$.servers[0].id']
+ poll:
+ count: 30
+ delay: 1
+ response_json_paths:
+ $.`len`: 1
+ $[0].event_type: compute.instance.create.end
+ $[0].traits[?(@.name='resource_id')].value: $HISTORY['list servers grow'].$RESPONSE['$.servers[0].id']
+
+ - name: check alarm
+ desc: Check the aodh alarm and its state
+ url: $ENVIRON['AODH_SERVICE_URL']/v2/alarms
+ method: GET
+ poll:
+ count: 30
+ delay: 1
+ response_strings:
+ - "integration_test-cpu_alarm_high-"
+ response_json_paths:
+ $[0].state: alarm
+
+ - name: get stack location for update
+ desc: Get the stack location
+ url: $ENVIRON['HEAT_SERVICE_URL']/stacks/integration_test
+ method: GET
+ status: 302
+
+ - name: update stack
+ desc: Update an autoscaling stack
+ url: $LOCATION
+ method: PUT
+ request_headers:
+ content-type: application/json
+ data: <@update_stack.json
+ status: 202
+
+ - name: control stack status
+ desc: Checks the stack have been created successfully
+ url: $ENVIRON['HEAT_SERVICE_URL']/stacks/integration_test
+ redirects: true
+ method: GET
+ status: 200
+ poll:
+ count: 300
+ delay: 1
+ response_json_paths:
+ $.stack.stack_status: "UPDATE_COMPLETE"
+
+ - name: list servers shrink
+ desc: Wait the autoscaling stack shrink to one server
+ url: $ENVIRON['NOVA_SERVICE_URL']/servers/detail
+ method: GET
+ poll:
+ count: 600
+ delay: 1
+ response_json_paths:
+ $.servers[0].metadata.'metering.server_group': $RESPONSE['$.stack.id']
+ $.servers[0].status: ACTIVE
+ $.servers.`len`: 1
+
+ - name: get stack location
+ desc: Get the stack location
+ url: $ENVIRON['HEAT_SERVICE_URL']/stacks/integration_test
+ method: GET
+ status: 302
+
+ - name: delete stack
+ desc: Delete the stack
+ url: $LOCATION
+ method: DELETE
+ status: 204
+
+ - name: get deleted stack
+ desc: Check the stack have been deleted
+ url: $ENVIRON['HEAT_SERVICE_URL']/stacks/integration_test
+ redirects: true
+ method: GET
+ poll:
+ count: 300
+ delay: 1
+ status: 404
+
+ - name: list alarms deleted
+ desc: List alarms, no more exist
+ url: $ENVIRON['AODH_SERVICE_URL']/v2/alarms
+ method: GET
+ response_strings:
+ - "[]"
+
+ - name: list servers deleted
+ desc: List servers, no more exists
+ url: $ENVIRON['NOVA_SERVICE_URL']/servers
+ method: GET
+ response_strings:
+ - "[]"
diff --git a/telemetry_tempest_plugin/scenario/telemetry_integration_gabbits/create_stack.json b/telemetry_tempest_plugin/scenario/telemetry_integration_gabbits/create_stack.json
new file mode 100644
index 0000000..57a6366
--- /dev/null
+++ b/telemetry_tempest_plugin/scenario/telemetry_integration_gabbits/create_stack.json
@@ -0,0 +1,74 @@
+{
+ "stack_name": "integration_test",
+ "template": {
+ "heat_template_version": "2013-05-23",
+ "description": "Integration Test AutoScaling with heat+ceilometer+gnocchi+aodh",
+ "resources": {
+ "asg": {
+ "type": "OS::Heat::AutoScalingGroup",
+ "properties": {
+ "min_size": 1,
+ "max_size": 2,
+ "resource": {
+ "type": "OS::Nova::Server",
+ "properties": {
+ "networks": [{ "network": "$ENVIRON['NEUTRON_NETWORK']" }],
+ "flavor": "$ENVIRON['NOVA_FLAVOR_REF']",
+ "image": "$ENVIRON['GLANCE_IMAGE_NAME']",
+ "metadata": {
+ "metering.server_group": { "get_param": "OS::stack_id" }
+ },
+ "user_data_format": "RAW",
+ "user_data": {"Fn::Join": ["", [
+ "#!/bin/sh\n",
+ "echo 'Loading CPU'\n",
+ "set -v\n",
+ "cat /dev/urandom > /dev/null\n"
+ ]]}
+ }
+ }
+ }
+ },
+ "web_server_scaleup_policy": {
+ "type": "OS::Heat::ScalingPolicy",
+ "properties": {
+ "adjustment_type": "change_in_capacity",
+ "auto_scaling_group_id": { "get_resource": "asg" },
+ "cooldown": 2,
+ "scaling_adjustment": 1
+ }
+ },
+ "cpu_alarm_high": {
+ "type": "OS::Ceilometer::GnocchiAggregationByResourcesAlarm",
+ "properties": {
+ "description": "Scale-up if the mean CPU > 10% on 1 minute",
+ "metric": "cpu_util",
+ "aggregation_method": "mean",
+ "granularity": $ENVIRON["AODH_GRANULARITY"],
+ "evaluation_periods": 1,
+ "threshold": 10,
+ "comparison_operator": "gt",
+ "alarm_actions": [
+ {
+ "str_replace": {
+ "template": "trust+url",
+ "params": {
+ "url": { "get_attr": [ "web_server_scaleup_policy", "signal_url" ] }
+ }
+ }
+ }
+ ],
+ "resource_type": "instance",
+ "query": {
+ "str_replace": {
+ "template": "{\"and\": [{\"=\": {\"server_group\": \"stack_id\"}}, {\"=\": {\"ended_at\": null}}]}",
+ "params": {
+ "stack_id": { "get_param": "OS::stack_id" }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/telemetry_tempest_plugin/scenario/telemetry_integration_gabbits/update_stack.json b/telemetry_tempest_plugin/scenario/telemetry_integration_gabbits/update_stack.json
new file mode 100644
index 0000000..54f8e29
--- /dev/null
+++ b/telemetry_tempest_plugin/scenario/telemetry_integration_gabbits/update_stack.json
@@ -0,0 +1,73 @@
+{
+ "template": {
+ "heat_template_version": "2013-05-23",
+ "description": "Integration Test AutoScaling with heat+ceilometer+gnocchi+aodh",
+ "resources": {
+ "asg": {
+ "type": "OS::Heat::AutoScalingGroup",
+ "properties": {
+ "min_size": 1,
+ "max_size": 2,
+ "resource": {
+ "type": "OS::Nova::Server",
+ "properties": {
+ "networks": [{ "network": "$ENVIRON['NEUTRON_NETWORK']" }],
+ "flavor": "$ENVIRON['NOVA_FLAVOR_REF']",
+ "image": "$ENVIRON['GLANCE_IMAGE_NAME']",
+ "metadata": {
+ "metering.server_group": { "get_param": "OS::stack_id" }
+ },
+ "user_data_format": "RAW",
+ "user_data": {"Fn::Join": ["", [
+ "#!/bin/sh\n",
+ "echo 'Loading CPU'\n",
+ "set -v\n",
+ "cat /dev/urandom > /dev/null\n"
+ ]]}
+ }
+ }
+ }
+ },
+ "web_server_scaledown_policy": {
+ "type": "OS::Heat::ScalingPolicy",
+ "properties": {
+ "adjustment_type": "change_in_capacity",
+ "auto_scaling_group_id": { "get_resource": "asg" },
+ "cooldown": 2,
+ "scaling_adjustment": -1
+ }
+ },
+ "cpu_alarm_high": {
+ "type": "OS::Ceilometer::GnocchiAggregationByResourcesAlarm",
+ "properties": {
+ "description": "Scale-down if the mean CPU > 10% on 1 minute",
+ "metric": "cpu_util",
+ "aggregation_method": "mean",
+ "granularity": $ENVIRON["AODH_GRANULARITY"],
+ "evaluation_periods": 1,
+ "threshold": 10,
+ "comparison_operator": "gt",
+ "alarm_actions": [
+ {
+ "str_replace": {
+ "template": "trust+url",
+ "params": {
+ "url": { "get_attr": [ "web_server_scaledown_policy", "signal_url" ] }
+ }
+ }
+ }
+ ],
+ "resource_type": "instance",
+ "query": {
+ "str_replace": {
+ "template": "{\"and\": [{\"=\": {\"server_group\": \"stack_id\"}}, {\"=\": {\"ended_at\": null}}]}",
+ "params": {
+ "stack_id": { "get_param": "OS::stack_id" }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/telemetry_tempest_plugin/scenario/test_gnocchi.py b/telemetry_tempest_plugin/scenario/test_gnocchi.py
new file mode 100644
index 0000000..e283d2f
--- /dev/null
+++ b/telemetry_tempest_plugin/scenario/test_gnocchi.py
@@ -0,0 +1,52 @@
+# 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
+
+from tempest import config
+import tempest.test
+
+from telemetry_tempest_plugin.scenario import utils
+
+CONF = config.CONF
+
+TEST_DIR = os.path.join(os.path.dirname(__file__), 'gnocchi_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 _prep_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,
+ 'region': CONF.identity.region})
+
+ os.environ.update({
+ "GNOCCHI_SERVICE_URL": url,
+ "GNOCCHI_SERVICE_TOKEN": token,
+ "GNOCCHI_AUTHORIZATION": "not used",
+ })
+
+
+utils.generate_tests(GnocchiGabbiTest, TEST_DIR)
diff --git a/telemetry_tempest_plugin/scenario/test_telemetry_integration.py b/telemetry_tempest_plugin/scenario/test_telemetry_integration.py
index df527c0..22155dd 100644
--- a/telemetry_tempest_plugin/scenario/test_telemetry_integration.py
+++ b/telemetry_tempest_plugin/scenario/test_telemetry_integration.py
@@ -11,16 +11,14 @@
# under the License.
import os
-import unittest
-from gabbi import runner
-from gabbi import suitemaker
-from gabbi import utils
from tempest import config
from tempest.scenario import manager
-TEST_DIR = os.path.join(os.path.dirname(__file__), '..',
- 'integration', 'gabbi', 'gabbits-live')
+from telemetry_tempest_plugin.scenario import utils
+
+TEST_DIR = os.path.join(os.path.dirname(__file__),
+ 'telemetry_integration_gabbits')
class TestTelemetryIntegration(manager.ScenarioTest):
@@ -75,7 +73,7 @@
opt_section.catalog_type)
return endpoints[0]['endpoints'][0][endpoint_type]
- def _do_test(self, filename):
+ def _prep_test(self, filename):
admin_auth = self.os_admin.auth_provider.get_auth()
auth = self.os_primary.auth_provider.get_auth()
networks = self.os_primary.networks_client.list_networks(
@@ -96,48 +94,5 @@
"NEUTRON_NETWORK": networks[0].get('id'),
})
- with open(os.path.join(TEST_DIR, filename)) as f:
- test_suite = suitemaker.test_suite_from_dict(
- loader=unittest.defaultTestLoader,
- test_base_name="gabbi",
- suite_dict=utils.load_yaml(f),
- test_directory=TEST_DIR,
- host="example.com", port=None,
- fixture_module=None,
- intercept=None,
- 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(TestTelemetryIntegration, name,
- test_maker(name, filename))
+utils.generate_tests(TestTelemetryIntegration, TEST_DIR)
diff --git a/telemetry_tempest_plugin/scenario/utils.py b/telemetry_tempest_plugin/scenario/utils.py
new file mode 100644
index 0000000..90b4d6b
--- /dev/null
+++ b/telemetry_tempest_plugin/scenario/utils.py
@@ -0,0 +1,78 @@
+# 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
+from oslo_log import log as logging
+
+LOG = logging.getLogger(__name__)
+
+
+def run_test(test_class_instance, test_dir, filename):
+ d = utils.load_yaml(yaml_file=os.path.join(test_dir, filename))
+ test_suite = suitemaker.test_suite_from_dict(
+ loader=unittest.defaultTestLoader,
+ test_base_name="gabbi",
+ suite_dict=d,
+ test_directory=test_dir,
+ host='example.com', port=None,
+ fixture_module=None,
+ intercept=None,
+ handlers=runner.initialize_handlers([]),
+ test_loader_name="tempest")
+
+ # NOTE(sileht): We hide stdout/stderr and reraise the failure
+ # manually, tempest will print it ittest_class.
+ with open(os.devnull, 'w') as stream:
+ result = unittest.TextTestRunner(
+ stream=stream, verbosity=0, failfast=True,
+ ).run(test_suite)
+
+ return
+
+ 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)
+ test_class_instance.fail(msg)
+
+ test_class_instance.assertTrue(result.wasSuccessful())
+
+
+def test_maker(test_dir, filename, name):
+ def test(self):
+ self._prep_test(filename)
+ run_test(self, test_dir, filename)
+ test.__name__ = name
+ return test
+
+
+def generate_tests(test_class, test_dir):
+ # Create one scenario per yaml file
+ filenames = os.listdir(test_dir)
+ if not filenames:
+ raise RuntimeError("%s is empty" % test_dir)
+ for filename in filenames:
+ if not filename.endswith('.yaml'):
+ continue
+ name = "test_%s" % filename[:-5].lower().replace("-", "_")
+ setattr(test_class, name,
+ test_maker(test_dir, filename, name))