Merge remote-tracking branch 'origin/master' into feature/r1
Change-Id: I2f4dda93652fb0800d89ce4a9e6d9b67e696bbd6
This commit is contained in:
commit
4e730f4dff
28
.pre-commit-config.yaml
Normal file
28
.pre-commit-config.yaml
Normal file
@ -0,0 +1,28 @@
|
||||
---
|
||||
default_language_version:
|
||||
# force all unspecified python hooks to run python3
|
||||
python: python3
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v3.4.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: mixed-line-ending
|
||||
args: ['--fix', 'lf']
|
||||
exclude: '.*\.(svg)$'
|
||||
- id: check-byte-order-marker
|
||||
- id: check-executables-have-shebangs
|
||||
- id: check-merge-conflict
|
||||
- id: debug-statements
|
||||
- id: check-yaml
|
||||
files: .*\.(yaml|yml)$
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: flake8
|
||||
name: flake8
|
||||
additional_dependencies:
|
||||
- hacking>=3.0.1,<3.1.0
|
||||
language: python
|
||||
entry: flake8
|
||||
files: '^.*\.py$'
|
||||
exclude: '^(doc|releasenotes|tools)/.*$'
|
@ -249,9 +249,9 @@
|
||||
IRONIC_CALLBACK_TIMEOUT: 600
|
||||
IRONIC_DEPLOY_DRIVER: ipmi
|
||||
IRONIC_RAMDISK_TYPE: tinyipa
|
||||
IRONIC_VM_COUNT: 6
|
||||
IRONIC_VM_COUNT: 2
|
||||
IRONIC_VM_LOG_DIR: '{{ devstack_base_dir }}/ironic-bm-logs'
|
||||
IRONIC_VM_SPECS_RAM: 512
|
||||
IRONIC_VM_SPECS_RAM: 1024
|
||||
devstack_plugins:
|
||||
ironic: https://opendev.org/openstack/ironic
|
||||
devstack_services:
|
||||
@ -376,7 +376,7 @@
|
||||
- project:
|
||||
templates:
|
||||
- check-requirements
|
||||
- openstack-python3-ussuri-jobs
|
||||
- openstack-python3-xena-jobs
|
||||
- openstacksdk-functional-tips
|
||||
- openstacksdk-tox-tips
|
||||
- os-client-config-tox-tips
|
||||
|
@ -194,6 +194,35 @@ class Proxy(proxy.Proxy):
|
||||
"""
|
||||
return self._get(_driver.Driver, driver)
|
||||
|
||||
def list_driver_vendor_passthru(self, driver):
|
||||
"""Get driver's vendor_passthru methods.
|
||||
|
||||
:param driver: The value can be the name of a driver or a
|
||||
:class:`~openstack.baremetal.v1.driver.Driver` instance.
|
||||
|
||||
:returns: One :dict: of vendor methods with corresponding usages
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound` when no
|
||||
driver matching the name could be found.
|
||||
"""
|
||||
driver = self.get_driver(driver)
|
||||
return driver.list_vendor_passthru(self)
|
||||
|
||||
def call_driver_vendor_passthru(self, driver,
|
||||
verb: str, method: str, body=None):
|
||||
"""Call driver's vendor_passthru method.
|
||||
|
||||
:param driver: The value can be the name of a driver or a
|
||||
:class:`~openstack.baremetal.v1.driver.Driver` instance.
|
||||
:param verb: One of GET, POST, PUT, DELETE,
|
||||
depending on the driver and method.
|
||||
:param method: Name of vendor method.
|
||||
:param body: passed to the vendor function as json body.
|
||||
|
||||
:returns: Server response
|
||||
"""
|
||||
driver = self.get_driver(driver)
|
||||
return driver.call_vendor_passthru(self, verb, method, body)
|
||||
|
||||
def nodes(self, details=False, **query):
|
||||
"""Retrieve a generator of nodes.
|
||||
|
||||
|
@ -10,7 +10,10 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.baremetal.v1 import _common
|
||||
from openstack import exceptions
|
||||
from openstack import resource
|
||||
from openstack import utils
|
||||
|
||||
|
||||
class Driver(resource.Resource):
|
||||
@ -117,3 +120,60 @@ class Driver(resource.Resource):
|
||||
#: Enabled vendor interface implementations.
|
||||
#: Introduced in API microversion 1.30.
|
||||
enabled_vendor_interfaces = resource.Body("enabled_vendor_interfaces")
|
||||
|
||||
def list_vendor_passthru(self, session):
|
||||
"""Fetch vendor specific methods exposed by driver
|
||||
|
||||
:param session: The session to use for making this request.
|
||||
:returns: A dict of the available vendor passthru methods for driver.
|
||||
Method names keys and corresponding usages in dict form as values
|
||||
Usage dict properties:
|
||||
* ``async``: bool # Is passthru function invoked asynchronously
|
||||
* ``attach``: bool # Is return value attached to response object
|
||||
* ``description``: str # Description of what the method does
|
||||
* ``http_methods``: list # List of HTTP methods supported
|
||||
"""
|
||||
session = self._get_session(session)
|
||||
request = self._prepare_request()
|
||||
request.url = utils.urljoin(
|
||||
request.url, 'vendor_passthru', 'methods')
|
||||
response = session.get(request.url, headers=request.headers)
|
||||
|
||||
msg = ("Failed to list list vendor_passthru methods for {driver_name}"
|
||||
.format(driver_name=self.name))
|
||||
exceptions.raise_from_response(response, error_message=msg)
|
||||
return response.json()
|
||||
|
||||
def call_vendor_passthru(self, session,
|
||||
verb: str, method: str, body: dict = None):
|
||||
"""Call a vendor specific passthru method
|
||||
|
||||
Contents of body are params passed to the hardware driver
|
||||
function. Validation happens there. Missing parameters, or
|
||||
excess parameters will cause the request to be rejected
|
||||
|
||||
:param session: The session to use for making this request.
|
||||
:param method: Vendor passthru method name.
|
||||
:param verb: One of GET, POST, PUT, DELETE,
|
||||
depending on the driver and method.
|
||||
:param body: passed to the vendor function as json body.
|
||||
:raises: :exc:`ValueError` if :data:`verb` is not one of
|
||||
GET, POST, PUT, DELETE
|
||||
:returns: response of method call.
|
||||
"""
|
||||
if verb.upper() not in ['GET', 'PUT', 'POST', 'DELETE']:
|
||||
raise ValueError('Invalid verb: {}'.format(verb))
|
||||
|
||||
session = self._get_session(session)
|
||||
request = self._prepare_request()
|
||||
request.url = utils.urljoin(
|
||||
request.url, f'vendor_passthru?method={method}')
|
||||
call = getattr(session, verb.lower())
|
||||
response = call(
|
||||
request.url, json=body, headers=request.headers,
|
||||
retriable_status_codes=_common.RETRIABLE_STATUS_CODES)
|
||||
|
||||
msg = ("Failed call to method {method} on driver {driver_name}"
|
||||
.format(method=method, driver_name=self.name))
|
||||
exceptions.raise_from_response(response, error_message=msg)
|
||||
return response
|
||||
|
@ -14,6 +14,7 @@ from openstack.block_storage import _base_proxy
|
||||
from openstack.block_storage.v3 import availability_zone
|
||||
from openstack.block_storage.v3 import backup as _backup
|
||||
from openstack.block_storage.v3 import capabilities as _capabilities
|
||||
from openstack.block_storage.v3 import group_type as _group_type
|
||||
from openstack.block_storage.v3 import limits as _limits
|
||||
from openstack.block_storage.v3 import resource_filter as _resource_filter
|
||||
from openstack.block_storage.v3 import snapshot as _snapshot
|
||||
@ -549,6 +550,101 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
|
||||
|
||||
return self._list(availability_zone.AvailabilityZone)
|
||||
|
||||
def get_group_type(self, group_type):
|
||||
"""Get a specific group type
|
||||
|
||||
:param group_type: The value can be the ID of a group type
|
||||
or a :class:`~openstack.block_storage.v3.group_type.GroupType`
|
||||
instance.
|
||||
|
||||
:returns: One :class:
|
||||
`~openstack.block_storage.v3.group_type.GroupType` instance.
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound` when no
|
||||
resource can be found.
|
||||
"""
|
||||
return self._get(_group_type.GroupType, group_type)
|
||||
|
||||
def find_group_type(self, name_or_id, ignore_missing=True):
|
||||
"""Find a single group type
|
||||
|
||||
:param name_or_id: The name or ID of a group type.
|
||||
:param bool ignore_missing: When set to ``False``
|
||||
:class:`~openstack.exceptions.ResourceNotFound` will be raised
|
||||
when the group type does not exist.
|
||||
|
||||
:returns: One :class:`~openstack.block_storage.v3.group_type
|
||||
.GroupType'
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound`
|
||||
when no resource can be found.
|
||||
"""
|
||||
return self._find(
|
||||
_group_type.GroupType, name_or_id, ignore_missing=ignore_missing)
|
||||
|
||||
def group_types(self, **query):
|
||||
"""Retrive a generator of group types
|
||||
|
||||
:param dict query: Optional query parameters to be sent to limit the
|
||||
resources being returned:
|
||||
|
||||
* sort: Comma-separated list of sort keys and optional sort
|
||||
directions in the form of <key> [:<direction>]. A valid
|
||||
direction is asc (ascending) or desc (descending).
|
||||
* limit: Requests a page size of items. Returns a number of items
|
||||
up to a limit value. Use the limit parameter to make an
|
||||
initial limited request and use the ID of the last-seen item
|
||||
from the response as the marker parameter value in a
|
||||
subsequent limited request.
|
||||
* offset: Used in conjunction with limit to return a slice of
|
||||
items. Is where to start in the list.
|
||||
* marker: The ID of the last-seen item.
|
||||
|
||||
:returns: A generator of group type objects.
|
||||
"""
|
||||
return self._list(_group_type.GroupType, **query)
|
||||
|
||||
def create_group_type(self, **attrs):
|
||||
"""Create a group type
|
||||
|
||||
:param dict attrs: Keyword arguments which will be used to create
|
||||
a :class:`~openstack.block_storage.v3.group_type.GroupType'
|
||||
comprised of the properties on the GroupType class.
|
||||
|
||||
:returns: The results of group type creation.
|
||||
:rtype: :class:`~openstack.block_storage.v3.group_type.GroupTye'.
|
||||
"""
|
||||
return self._create(_group_type.GroupType, **attrs)
|
||||
|
||||
def delete_group_type(self, group_type, ignore_missing=True):
|
||||
"""Delete a group type
|
||||
|
||||
:param group_type: The value can be the ID of a group type
|
||||
or a :class:`~openstack.block_storage.v3.group_type.GroupType`
|
||||
instance.
|
||||
:param bool ignore_missing: When set to ``False``
|
||||
:class:`~openstack.exceptions.ResourceNotFound` will be raised when
|
||||
the zone does not exist.
|
||||
When set to ``True``, no exception will be set when attempting to
|
||||
delete a nonexistent zone.
|
||||
|
||||
:returns: ''None''
|
||||
"""
|
||||
self._delete(
|
||||
_group_type.GroupType, group_type, ignore_missing=ignore_missing)
|
||||
|
||||
def update_group_type(self, group_type, **attrs):
|
||||
"""Update a group_type
|
||||
|
||||
:param group_type: The value can be the ID of a group type or a
|
||||
:class:`~openstack.block_storage.v3.group_type.GroupType`
|
||||
instance.
|
||||
:param dict attrs: The attributes to update on the group type.
|
||||
|
||||
:returns: The updated group type.
|
||||
:rtype: :class:`~openstack.block_storage.v3.group_type.GroupType`
|
||||
"""
|
||||
return self._update(
|
||||
_group_type.GroupType, group_type, **attrs)
|
||||
|
||||
def wait_for_status(self, res, status='ACTIVE', failures=None,
|
||||
interval=2, wait=120):
|
||||
"""Wait for a resource to be in a particular status.
|
||||
|
36
openstack/block_storage/v3/group_type.py
Normal file
36
openstack/block_storage/v3/group_type.py
Normal file
@ -0,0 +1,36 @@
|
||||
# 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 openstack import resource
|
||||
|
||||
|
||||
class GroupType(resource.Resource):
|
||||
resource_key = "group_type"
|
||||
resources_key = "group_types"
|
||||
base_path = "/group_types"
|
||||
|
||||
# capabilities
|
||||
allow_fetch = True
|
||||
allow_create = True
|
||||
allow_delete = True
|
||||
allow_commit = True
|
||||
allow_list = True
|
||||
|
||||
_max_microversion = "3.11"
|
||||
|
||||
#: Properties
|
||||
#: The group type description.
|
||||
description = resource.Body("description")
|
||||
#: Contains the specifications for a group type.
|
||||
group_specs = resource.Body("group_specs", type=dict)
|
||||
#: Whether the group type is publicly visible.
|
||||
is_public = resource.Body("is_public", type=bool)
|
@ -141,8 +141,12 @@ class Server(resource.Resource, metadata.MetadataMixin, resource.TagMixin):
|
||||
launch_index = resource.Body('OS-EXT-SRV-ATTR:launch_index', type=int)
|
||||
#: The timestamp when the server was launched.
|
||||
launched_at = resource.Body('OS-SRV-USG:launched_at')
|
||||
#: The maximum number of servers to create.
|
||||
max_count = resource.Body('max_count')
|
||||
#: Metadata stored for this server. *Type: dict*
|
||||
metadata = resource.Body('metadata', type=dict)
|
||||
#: The minimum number of servers to create.
|
||||
min_count = resource.Body('min_count')
|
||||
#: A networks object. Required parameter when there are multiple
|
||||
#: networks defined for the tenant. When you do not specify the
|
||||
#: networks parameter, the server attaches to the only network
|
||||
|
@ -37,7 +37,7 @@ class Image(resource.Resource, resource.TagMixin, _download.DownloadMixin):
|
||||
"member_status", "owner",
|
||||
"status", "size_min", "size_max",
|
||||
"protected", "is_hidden",
|
||||
"sort_key", "sort_dir", "sort", "tags",
|
||||
"sort_key", "sort_dir", "sort", "tag",
|
||||
"created_at", "updated_at",
|
||||
is_hidden="os_hidden")
|
||||
|
||||
|
@ -214,12 +214,12 @@ class Proxy(adapter.Adapter):
|
||||
key = '.'.join(
|
||||
[self._statsd_prefix, self.service_type, method]
|
||||
+ name_parts)
|
||||
if response is not None:
|
||||
duration = int(response.elapsed.total_seconds() * 1000)
|
||||
self._statsd_client.timing(key, duration)
|
||||
self._statsd_client.incr(key)
|
||||
elif exc is not None:
|
||||
self._statsd_client.incr('%s.failed' % key)
|
||||
with self._statsd_client.pipeline() as pipe:
|
||||
if response is not None:
|
||||
pipe.timing(key, response.elapsed)
|
||||
pipe.incr(key)
|
||||
elif exc is not None:
|
||||
pipe.incr('%s.failed' % key)
|
||||
|
||||
def _report_stats_prometheus(self, response, url=None, method=None,
|
||||
exc=None):
|
||||
|
@ -0,0 +1,39 @@
|
||||
# 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 openstack.block_storage.v3 import group_type as _group_type
|
||||
from openstack.tests.functional.block_storage.v3 import base
|
||||
|
||||
|
||||
class TestGroupType(base.BaseBlockStorageTest):
|
||||
|
||||
def setUp(self):
|
||||
super(TestGroupType, self).setUp()
|
||||
|
||||
self.GROUP_TYPE_NAME = self.getUniqueString()
|
||||
self.GROUP_TYPE_ID = None
|
||||
|
||||
group_type = self.conn.block_storage.create_group_type(
|
||||
name=self.GROUP_TYPE_NAME)
|
||||
self.assertIsInstance(group_type, _group_type.GroupType)
|
||||
self.assertEqual(self.GROUP_TYPE_NAME, group_type.name)
|
||||
self.GROUP_TYPE_ID = group_type.id
|
||||
|
||||
def tearDown(self):
|
||||
group_type = self.conn.block_storage.delete_group_type(
|
||||
self.GROUP_TYPE_ID, ignore_missing=False)
|
||||
self.assertIsNone(group_type)
|
||||
super(TestGroupType, self).tearDown()
|
||||
|
||||
def test_get(self):
|
||||
group_type = self.conn.block_storage.get_group_type(self.GROUP_TYPE_ID)
|
||||
self.assertEqual(self.GROUP_TYPE_NAME, group_type.name)
|
@ -10,7 +10,13 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from keystoneauth1 import adapter
|
||||
|
||||
from openstack.baremetal.v1 import _common
|
||||
from openstack.baremetal.v1 import driver
|
||||
from openstack import exceptions
|
||||
from openstack.tests.unit import base
|
||||
|
||||
|
||||
@ -63,3 +69,63 @@ class TestDriver(base.TestCase):
|
||||
self.assertEqual(FAKE['hosts'], sot.hosts)
|
||||
self.assertEqual(FAKE['links'], sot.links)
|
||||
self.assertEqual(FAKE['properties'], sot.properties)
|
||||
|
||||
@mock.patch.object(exceptions, 'raise_from_response', mock.Mock())
|
||||
def test_list_vendor_passthru(self):
|
||||
self.session = mock.Mock(spec=adapter.Adapter)
|
||||
sot = driver.Driver(**FAKE)
|
||||
fake_vendor_passthru_info = {
|
||||
'fake_vendor_method': {
|
||||
'async': True,
|
||||
'attach': False,
|
||||
'description': "Fake function that does nothing in background",
|
||||
'http_methods': ['GET', 'PUT', 'POST', 'DELETE']
|
||||
}
|
||||
}
|
||||
self.session.get.return_value.json.return_value = (
|
||||
fake_vendor_passthru_info)
|
||||
result = sot.list_vendor_passthru(self.session)
|
||||
self.session.get.assert_called_once_with(
|
||||
'drivers/{driver_name}/vendor_passthru/methods'.format(
|
||||
driver_name=FAKE["name"]),
|
||||
headers=mock.ANY)
|
||||
self.assertEqual(result, fake_vendor_passthru_info)
|
||||
|
||||
@mock.patch.object(exceptions, 'raise_from_response', mock.Mock())
|
||||
def test_call_vendor_passthru(self):
|
||||
self.session = mock.Mock(spec=adapter.Adapter)
|
||||
sot = driver.Driver(**FAKE)
|
||||
# GET
|
||||
sot.call_vendor_passthru(self.session, 'GET', 'fake_vendor_method')
|
||||
self.session.get.assert_called_once_with(
|
||||
'drivers/{}/vendor_passthru?method={}'.format(
|
||||
FAKE["name"], 'fake_vendor_method'),
|
||||
json=None,
|
||||
headers=mock.ANY,
|
||||
retriable_status_codes=_common.RETRIABLE_STATUS_CODES)
|
||||
# PUT
|
||||
sot.call_vendor_passthru(self.session, 'PUT', 'fake_vendor_method',
|
||||
body={"fake_param_key": "fake_param_value"})
|
||||
self.session.put.assert_called_once_with(
|
||||
'drivers/{}/vendor_passthru?method={}'.format(
|
||||
FAKE["name"], 'fake_vendor_method'),
|
||||
json={"fake_param_key": "fake_param_value"},
|
||||
headers=mock.ANY,
|
||||
retriable_status_codes=_common.RETRIABLE_STATUS_CODES)
|
||||
# POST
|
||||
sot.call_vendor_passthru(self.session, 'POST', 'fake_vendor_method',
|
||||
body={"fake_param_key": "fake_param_value"})
|
||||
self.session.post.assert_called_once_with(
|
||||
'drivers/{}/vendor_passthru?method={}'.format(
|
||||
FAKE["name"], 'fake_vendor_method'),
|
||||
json={"fake_param_key": "fake_param_value"},
|
||||
headers=mock.ANY,
|
||||
retriable_status_codes=_common.RETRIABLE_STATUS_CODES)
|
||||
# DELETE
|
||||
sot.call_vendor_passthru(self.session, 'DELETE', 'fake_vendor_method')
|
||||
self.session.delete.assert_called_once_with(
|
||||
'drivers/{}/vendor_passthru?method={}'.format(
|
||||
FAKE["name"], 'fake_vendor_method'),
|
||||
json=None,
|
||||
headers=mock.ANY,
|
||||
retriable_status_codes=_common.RETRIABLE_STATUS_CODES)
|
||||
|
46
openstack/tests/unit/block_storage/v3/test_group_type.py
Normal file
46
openstack/tests/unit/block_storage/v3/test_group_type.py
Normal file
@ -0,0 +1,46 @@
|
||||
# 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 openstack.block_storage.v3 import group_type
|
||||
from openstack.tests.unit import base
|
||||
|
||||
GROUP_TYPE = {
|
||||
"id": "6685584b-1eac-4da6-b5c3-555430cf68ff",
|
||||
"name": "grp-type-001",
|
||||
"description": "group type 001",
|
||||
"is_public": True,
|
||||
"group_specs": {
|
||||
"consistent_group_snapshot_enabled": "<is> False"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TestGroupType(base.TestCase):
|
||||
|
||||
def test_basic(self):
|
||||
resource = group_type.GroupType()
|
||||
self.assertEqual("group_type", resource.resource_key)
|
||||
self.assertEqual("group_types", resource.resources_key)
|
||||
self.assertEqual("/group_types", resource.base_path)
|
||||
self.assertTrue(resource.allow_create)
|
||||
self.assertTrue(resource.allow_fetch)
|
||||
self.assertTrue(resource.allow_delete)
|
||||
self.assertTrue(resource.allow_commit)
|
||||
self.assertTrue(resource.allow_list)
|
||||
|
||||
def test_make_resource(self):
|
||||
resource = group_type.GroupType(**GROUP_TYPE)
|
||||
self.assertEqual(GROUP_TYPE["id"], resource.id)
|
||||
self.assertEqual(GROUP_TYPE["name"], resource.name)
|
||||
self.assertEqual(GROUP_TYPE["description"], resource.description)
|
||||
self.assertEqual(GROUP_TYPE["is_public"], resource.is_public)
|
||||
self.assertEqual(GROUP_TYPE["group_specs"], resource.group_specs)
|
@ -14,6 +14,7 @@ from unittest import mock
|
||||
from openstack.block_storage.v3 import _proxy
|
||||
from openstack.block_storage.v3 import backup
|
||||
from openstack.block_storage.v3 import capabilities
|
||||
from openstack.block_storage.v3 import group_type
|
||||
from openstack.block_storage.v3 import limits
|
||||
from openstack.block_storage.v3 import resource_filter
|
||||
from openstack.block_storage.v3 import snapshot
|
||||
@ -245,3 +246,26 @@ class TestVolumeProxy(test_proxy_base.TestProxyBase):
|
||||
def test_resource_filters(self):
|
||||
self.verify_list(self.proxy.resource_filters,
|
||||
resource_filter.ResourceFilter)
|
||||
|
||||
def test_group_type_get(self):
|
||||
self.verify_get(self.proxy.get_group_type, group_type.GroupType)
|
||||
|
||||
def test_group_type_find(self):
|
||||
self.verify_find(self.proxy.find_group_type, group_type.GroupType)
|
||||
|
||||
def test_group_types(self):
|
||||
self.verify_list(self.proxy.group_types, group_type.GroupType)
|
||||
|
||||
def test_group_type_create(self):
|
||||
self.verify_create(self.proxy.create_group_type, group_type.GroupType)
|
||||
|
||||
def test_group_type_delete(self):
|
||||
self.verify_delete(
|
||||
self.proxy.delete_group_type, group_type.GroupType, False)
|
||||
|
||||
def test_group_type_delete_ignore(self):
|
||||
self.verify_delete(
|
||||
self.proxy.delete_group_type, group_type.GroupType, True)
|
||||
|
||||
def test_group_type_update(self):
|
||||
self.verify_update(self.proxy.update_group_type, group_type.GroupType)
|
||||
|
@ -592,7 +592,9 @@ class TestNormalize(base.TestCase):
|
||||
'region_name': u'RegionOne',
|
||||
'zone': u'ca-ymq-2'},
|
||||
'locked': True,
|
||||
'max_count': None,
|
||||
'metadata': {u'group': u'irc', u'groups': u'irc,enabled'},
|
||||
'min_count': None,
|
||||
'name': u'mordred-irc',
|
||||
'networks': {
|
||||
u'public': [
|
||||
@ -625,6 +627,8 @@ class TestNormalize(base.TestCase):
|
||||
'OS-SRV-USG:terminated_at': None,
|
||||
'host_status': None,
|
||||
'locked': True,
|
||||
'max_count': None,
|
||||
'min_count': None,
|
||||
'os-extended-volumes:volumes_attached': [],
|
||||
'trusted_image_certificates': None},
|
||||
'public_v4': None,
|
||||
@ -1175,6 +1179,8 @@ class TestStrictNormalize(base.TestCase):
|
||||
'properties': {
|
||||
'host_status': None,
|
||||
'locked': True,
|
||||
'max_count': None,
|
||||
'min_count': None,
|
||||
'trusted_image_certificates': None
|
||||
},
|
||||
'public_v4': None,
|
||||
|
@ -10,9 +10,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.compute import version
|
||||
from openstack.tests.unit import base
|
||||
|
||||
from openstack.compute import version
|
||||
|
||||
IDENTIFIER = 'IDENTIFIER'
|
||||
EXAMPLE = {
|
||||
|
@ -10,9 +10,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.compute.v2 import availability_zone as az
|
||||
from openstack.tests.unit import base
|
||||
|
||||
from openstack.compute.v2 import availability_zone as az
|
||||
|
||||
IDENTIFIER = 'IDENTIFIER'
|
||||
BASIC_EXAMPLE = {
|
||||
|
@ -10,9 +10,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.compute.v2 import extension
|
||||
from openstack.tests.unit import base
|
||||
|
||||
from openstack.compute.v2 import extension
|
||||
|
||||
IDENTIFIER = 'IDENTIFIER'
|
||||
EXAMPLE = {
|
||||
|
@ -9,13 +9,14 @@
|
||||
# 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 unittest import mock
|
||||
|
||||
from keystoneauth1 import adapter
|
||||
|
||||
from openstack.compute.v2 import flavor
|
||||
from openstack.tests.unit import base
|
||||
|
||||
from openstack.compute.v2 import flavor
|
||||
|
||||
IDENTIFIER = 'IDENTIFIER'
|
||||
BASIC_EXAMPLE = {
|
||||
|
@ -9,15 +9,16 @@
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
from unittest import mock
|
||||
|
||||
from keystoneauth1 import adapter
|
||||
|
||||
from openstack.compute.v2 import hypervisor
|
||||
from openstack import exceptions
|
||||
from openstack.tests.unit import base
|
||||
|
||||
from openstack.compute.v2 import hypervisor
|
||||
|
||||
EXAMPLE = {
|
||||
"cpu_info": {
|
||||
|
@ -10,9 +10,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.compute.v2 import image
|
||||
from openstack.tests.unit import base
|
||||
|
||||
from openstack.compute.v2 import image
|
||||
|
||||
IDENTIFIER = 'IDENTIFIER'
|
||||
|
||||
|
@ -10,9 +10,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.compute.v2 import keypair
|
||||
from openstack.tests.unit import base
|
||||
|
||||
from openstack.compute.v2 import keypair
|
||||
|
||||
EXAMPLE = {
|
||||
'created_at': 'some_time',
|
||||
|
@ -9,6 +9,7 @@
|
||||
# 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 unittest import mock
|
||||
|
||||
from openstack.compute.v2 import _proxy
|
||||
|
@ -257,7 +257,7 @@ class TestServer(base.TestCase):
|
||||
hints = {"hint": 3}
|
||||
|
||||
sot = server.Server(id=1, availability_zone=zone, user_data=data,
|
||||
scheduler_hints=hints)
|
||||
scheduler_hints=hints, min_count=2, max_count=3)
|
||||
request = sot._prepare_request()
|
||||
|
||||
self.assertNotIn("OS-EXT-AZ:availability_zone",
|
||||
@ -274,6 +274,9 @@ class TestServer(base.TestCase):
|
||||
request.body[sot.resource_key])
|
||||
self.assertEqual(request.body["OS-SCH-HNT:scheduler_hints"], hints)
|
||||
|
||||
self.assertEqual(2, request.body[sot.resource_key]['min_count'])
|
||||
self.assertEqual(3, request.body[sot.resource_key]['max_count'])
|
||||
|
||||
def test_change_password(self):
|
||||
sot = server.Server(**EXAMPLE)
|
||||
|
||||
|
@ -10,9 +10,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.compute.v2 import server_diagnostics
|
||||
from openstack.tests.unit import base
|
||||
|
||||
from openstack.compute.v2 import server_diagnostics
|
||||
|
||||
IDENTIFIER = 'IDENTIFIER'
|
||||
EXAMPLE = {
|
||||
|
@ -10,9 +10,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.compute.v2 import server_group
|
||||
from openstack.tests.unit import base
|
||||
|
||||
from openstack.compute.v2 import server_group
|
||||
|
||||
EXAMPLE = {
|
||||
'id': 'IDENTIFIER',
|
||||
|
@ -10,9 +10,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.compute.v2 import server_interface
|
||||
from openstack.tests.unit import base
|
||||
|
||||
from openstack.compute.v2 import server_interface
|
||||
|
||||
IDENTIFIER = 'IDENTIFIER'
|
||||
EXAMPLE = {
|
||||
|
@ -14,9 +14,9 @@ from unittest import mock
|
||||
|
||||
from keystoneauth1 import adapter
|
||||
|
||||
from openstack.compute.v2 import server_remote_console
|
||||
from openstack.tests.unit import base
|
||||
|
||||
from openstack.compute.v2 import server_remote_console
|
||||
|
||||
IDENTIFIER = 'IDENTIFIER'
|
||||
EXAMPLE = {
|
||||
|
@ -12,8 +12,8 @@
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from openstack import exceptions
|
||||
from openstack.compute.v2 import service
|
||||
from openstack import exceptions
|
||||
from openstack.tests.unit import base
|
||||
|
||||
IDENTIFIER = 'IDENTIFIER'
|
||||
|
@ -10,9 +10,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.compute.v2 import volume_attachment
|
||||
from openstack.tests.unit import base
|
||||
|
||||
from openstack.compute.v2 import volume_attachment
|
||||
|
||||
EXAMPLE = {
|
||||
'device': '1',
|
||||
|
@ -154,7 +154,7 @@ class TestImage(base.TestCase):
|
||||
'sort_dir': 'sort_dir',
|
||||
'sort_key': 'sort_key',
|
||||
'status': 'status',
|
||||
'tags': 'tags',
|
||||
'tag': 'tag',
|
||||
'updated_at': 'updated_at',
|
||||
'visibility': 'visibility'
|
||||
},
|
||||
|
@ -12,10 +12,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.tests.unit import base
|
||||
import uuid
|
||||
|
||||
from openstack.load_balancer.v2 import amphora
|
||||
from openstack.tests.unit import base
|
||||
|
||||
|
||||
IDENTIFIER = uuid.uuid4()
|
||||
LB_ID = uuid.uuid4()
|
||||
|
@ -11,10 +11,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.tests.unit import base
|
||||
import uuid
|
||||
|
||||
from openstack.load_balancer.v2 import availability_zone
|
||||
from openstack.tests.unit import base
|
||||
|
||||
|
||||
AVAILABILITY_ZONE_PROFILE_ID = uuid.uuid4()
|
||||
EXAMPLE = {
|
||||
|
@ -11,10 +11,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.tests.unit import base
|
||||
import uuid
|
||||
|
||||
from openstack.load_balancer.v2 import availability_zone_profile
|
||||
from openstack.tests.unit import base
|
||||
|
||||
|
||||
IDENTIFIER = uuid.uuid4()
|
||||
EXAMPLE = {
|
||||
|
@ -12,10 +12,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.tests.unit import base
|
||||
import uuid
|
||||
|
||||
from openstack.load_balancer.v2 import flavor
|
||||
from openstack.tests.unit import base
|
||||
|
||||
|
||||
IDENTIFIER = uuid.uuid4()
|
||||
FLAVOR_PROFILE_ID = uuid.uuid4()
|
||||
|
@ -12,10 +12,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.tests.unit import base
|
||||
import uuid
|
||||
|
||||
from openstack.load_balancer.v2 import flavor_profile
|
||||
from openstack.tests.unit import base
|
||||
|
||||
|
||||
IDENTIFIER = uuid.uuid4()
|
||||
EXAMPLE = {
|
||||
|
@ -11,10 +11,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.tests.unit import base
|
||||
import uuid
|
||||
|
||||
from openstack.load_balancer.v2 import health_monitor
|
||||
from openstack.tests.unit import base
|
||||
|
||||
|
||||
EXAMPLE = {
|
||||
'admin_state_up': True,
|
||||
|
@ -10,10 +10,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.tests.unit import base
|
||||
import uuid
|
||||
|
||||
from openstack.load_balancer.v2 import l7_policy
|
||||
from openstack.tests.unit import base
|
||||
|
||||
|
||||
EXAMPLE = {
|
||||
'action': 'REJECT',
|
||||
|
@ -10,10 +10,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.tests.unit import base
|
||||
import uuid
|
||||
|
||||
from openstack.load_balancer.v2 import l7_rule
|
||||
from openstack.tests.unit import base
|
||||
|
||||
|
||||
EXAMPLE = {
|
||||
'admin_state_up': True,
|
||||
|
@ -10,10 +10,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.tests.unit import base
|
||||
import uuid
|
||||
|
||||
from openstack.load_balancer.v2 import listener
|
||||
from openstack.tests.unit import base
|
||||
|
||||
|
||||
IDENTIFIER = 'IDENTIFIER'
|
||||
EXAMPLE = {
|
||||
|
@ -10,10 +10,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.tests.unit import base
|
||||
import uuid
|
||||
|
||||
from openstack.load_balancer.v2 import member
|
||||
from openstack.tests.unit import base
|
||||
|
||||
|
||||
IDENTIFIER = 'IDENTIFIER'
|
||||
EXAMPLE = {
|
||||
|
@ -10,10 +10,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.tests.unit import base
|
||||
import uuid
|
||||
|
||||
from openstack.load_balancer.v2 import pool
|
||||
from openstack.tests.unit import base
|
||||
|
||||
|
||||
IDENTIFIER = 'IDENTIFIER'
|
||||
EXAMPLE = {
|
||||
|
@ -12,9 +12,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.load_balancer.v2 import provider
|
||||
from openstack.tests.unit import base
|
||||
|
||||
from openstack.load_balancer.v2 import provider
|
||||
|
||||
EXAMPLE = {
|
||||
'name': 'best',
|
||||
|
@ -10,8 +10,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import uuid
|
||||
from unittest import mock
|
||||
import uuid
|
||||
|
||||
from openstack.load_balancer.v2 import _proxy
|
||||
from openstack.load_balancer.v2 import amphora
|
||||
|
@ -13,9 +13,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.load_balancer.v2 import quota
|
||||
from openstack.tests.unit import base
|
||||
|
||||
from openstack.load_balancer.v2 import quota
|
||||
|
||||
IDENTIFIER = 'IDENTIFIER'
|
||||
EXAMPLE = {
|
||||
|
@ -10,9 +10,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.load_balancer import version
|
||||
from openstack.tests.unit import base
|
||||
|
||||
from openstack.load_balancer import version
|
||||
|
||||
IDENTIFIER = 'IDENTIFIER'
|
||||
EXAMPLE = {
|
||||
|
@ -10,9 +10,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.message import version
|
||||
from openstack.tests.unit import base
|
||||
|
||||
from openstack.message import version
|
||||
|
||||
IDENTIFIER = 'IDENTIFIER'
|
||||
EXAMPLE = {
|
||||
|
@ -17,7 +17,6 @@ import hashlib
|
||||
import logging
|
||||
import sys
|
||||
from unittest import mock
|
||||
from unittest import skipIf
|
||||
|
||||
import fixtures
|
||||
import os_service_types
|
||||
@ -359,8 +358,6 @@ class Test_md5(base.TestCase):
|
||||
digest = test_md5.hexdigest()
|
||||
self.assertEqual(digest, self.md5_digest)
|
||||
|
||||
@skipIf(sys.version_info.major == 2,
|
||||
"hashlib.md5 does not raise TypeError here in py2")
|
||||
def test_string_data_raises_type_error(self):
|
||||
if not self.fips_enabled:
|
||||
self.assertRaises(TypeError, hashlib.md5, u'foo')
|
||||
|
@ -11,9 +11,9 @@
|
||||
# under the License.
|
||||
|
||||
from openstack.tests.unit import base
|
||||
|
||||
from openstack.workflow.v2 import execution
|
||||
|
||||
|
||||
FAKE_INPUT = {
|
||||
'cluster_id': '8c74607c-5a74-4490-9414-a3475b1926c2',
|
||||
'node_id': 'fba2cc5d-706f-4631-9577-3956048d13a2',
|
||||
|
@ -11,9 +11,9 @@
|
||||
# under the License.
|
||||
|
||||
from openstack.tests.unit import base
|
||||
|
||||
from openstack.workflow import version
|
||||
|
||||
|
||||
IDENTIFIER = 'IDENTIFIER'
|
||||
EXAMPLE = {
|
||||
'id': IDENTIFIER,
|
||||
|
@ -11,7 +11,6 @@
|
||||
# under the License.
|
||||
|
||||
from openstack.tests.unit import base
|
||||
|
||||
from openstack.workflow.v2 import workflow
|
||||
|
||||
|
||||
|
4
tox.ini
4
tox.ini
@ -129,10 +129,6 @@ per-file-ignores =
|
||||
openstack/tests/unit/identity/*:H306,I100,I201,I202
|
||||
openstack/tests/unit/accelerator/*:H306,I100,I201,I202
|
||||
openstack/tests/unit/config/*:H306,I100,I201,I202
|
||||
openstack/tests/unit/workflow/*:H306,I100,I201,I202
|
||||
openstack/tests/unit/message/*:H306,I100,I201,I202
|
||||
openstack/tests/unit/load_balancer/*:H306,I100,I201,I202
|
||||
openstack/tests/unit/compute/*:H306,I100,I201,I202
|
||||
|
||||
[flake8:local-plugins]
|
||||
extension =
|
||||
|
Loading…
Reference in New Issue
Block a user