Adds service resource to shared file system

Introduce Service class with the list method to
shared file system storage service.

Change-Id: I6e2ed17ce1895dff806875a08fc914fe02a8f383
This commit is contained in:
Kafilat Adeleke 2021-06-21 07:54:59 +00:00 committed by Ashley Rodriguez
parent 0d5d48f65f
commit 104e8a3360
9 changed files with 347 additions and 0 deletions

View File

@ -192,3 +192,12 @@ the user that created the lock.
:noindex:
:members: resource_locks, get_resource_lock, update_resource_lock,
delete_resource_lock, create_resource_lock
Shared File System Services
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Interact with microservices supported by the Shared File Systems service.
.. autoclass:: openstack.shared_file_system.v2._proxy.Proxy
:noindex:
:members: services

View File

@ -7,6 +7,7 @@ Shared File System service resources
v2/availability_zone
v2/storage_pool
v2/limit
v2/service
v2/share
v2/share_instance
v2/share_network_subnet

View File

@ -0,0 +1,13 @@
openstack.shared_file_system.v2.service
=======================================
.. automodule:: openstack.shared_file_system.v2.service
The Service Class
-----------------
The ``Service`` class inherits from
:class:`~openstack.resource.Resource`.
.. autoclass:: openstack.shared_file_system.v2.service.Service
:members:

View File

@ -18,6 +18,7 @@ from openstack.shared_file_system.v2 import (
from openstack.shared_file_system.v2 import limit as _limit
from openstack.shared_file_system.v2 import quota_class_set as _quota_class_set
from openstack.shared_file_system.v2 import resource_locks as _resource_locks
from openstack.shared_file_system.v2 import service as _service
from openstack.shared_file_system.v2 import share as _share
from openstack.shared_file_system.v2 import share_group as _share_group
from openstack.shared_file_system.v2 import (
@ -60,6 +61,7 @@ class Proxy(proxy.Proxy):
"share_group_snapshot": _share_group_snapshot.ShareGroupSnapshot,
"resource_locks": _resource_locks.ResourceLock,
"quota_class_set": _quota_class_set.QuotaClassSet,
"service": _service.Service,
}
def availability_zones(self):
@ -1223,3 +1225,54 @@ class Proxy(proxy.Proxy):
return self._update(
_quota_class_set.QuotaClassSet, quota_class_name, **attrs
)
def services(self, **query):
"""Lists all services
:param kwargs query: Optional query parameters to be sent to limit
the services being returned. Available parameters include:
* host: The service host name.
* binary: The service binary name.
* zone: The availability zone.
* state: The current state of the service.A valid value is
up or down.
* status: The service status, which is enabled or disabled.
:returns: A generator of manila service resources.
:rtype: :class:`~openstack.shared_file_system.v2.
service.Service`
"""
return self._list(_service.Service, **query)
def disable_service(self, service):
"""Disable a service
:param service: Either the ID of a service or a
:class:`~openstack.shared_file_system.v2.
service.Service` instance.
:param str host: The host where service runs.
:param str name: The name of service.
:param str disabled_reason: The reason of force down a service.
:returns: Updated service instance
:rtype: class: `~openstack.shared_file_system.v2.
service.Service`
"""
service = self._get_resource(_service.Service, service)
return service.disable(self)
def enable_service(self, service):
"""Enable a service
:param service: Either the ID of a service or a
:class:`~openstack.shared_file_system.v2.
service.Service` instance.
:param str host: The host where service runs.
:param str name: The name of service.
:returns: Updated service instance
:rtype: :class:`~openstack.shared_file_system.v2.
service.Service`.
"""
service = self._get_resource(_service.Service, service)
return service.enable(self)

View File

@ -0,0 +1,81 @@
# 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
from openstack import utils
class Service(resource.Resource):
resource_key = "service"
resources_key = "services"
base_path = "/services"
# capabilities
allow_create = False
allow_fetch = False
allow_commit = True
allow_delete = False
allow_list = True
allow_head = False
_query_mapping = resource.QueryParameters(
'name',
'binary',
'host',
'state',
'status',
name='binary',
availability_zone='zone',
)
#: Properties
#: The availability zone of service
availability_zone = resource.Body("zone")
#: The service binary name.
binary = resource.Body("binary", type=str, aka="name")
#: The service host name.
host = resource.Body("host", type=str)
#: Service name
name = resource.Body('binary')
#: The current state of the service.
state = resource.Body("state", type=str)
#: The service status, which is enabled or disabled.
status = resource.Body("status", type=str)
#: The date and time stamp when the resource was
#: last updated within the services database.
updated_at = resource.Body("updated_at", type=str)
def _action(self, session, action, body, microversion=None):
if not microversion:
microversion = session.default_microversion
url = utils.urljoin(Service.base_path, action)
response = session.put(url, json=body, microversion=microversion)
self._translate_response(response)
return self
def enable(self, session):
"""Enable service."""
body = {
'host': self.host,
'binary': self.binary,
}
return self._action(session, 'enable', body)
def disable(self, session):
"""Disable service."""
body = {
'host': self.host,
'binary': self.binary,
}
return self._action(session, 'disable', body)

View File

@ -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.tests.functional.shared_file_system import base
class ServiceTest(base.BaseSharedFileSystemTest):
def test_service(self):
num_services = 0
services = self.operator_cloud.shared_file_system.services()
self.assertIsNotNone(services)
for service in services:
num_services += 1
for attribute in ('id', 'host', 'updated_at'):
self.assertTrue(hasattr(service, attribute))
self.assertGreater(num_services, 0)
def test_disable_enable(self):
services_modified = 0
for srv in self.operator_cloud.shared_file_system.services(
name='manila-data'
):
self.operator_cloud.shared_file_system.disable_service(
srv, srv.host, srv.name
)
self.operator_cloud.shared_file_system.enable_service(
srv, srv.host, srv.name
)
services_modified += 1
self.assertGreater(services_modified, 0)

View File

@ -15,6 +15,7 @@ from unittest import mock
from openstack.shared_file_system.v2 import _proxy
from openstack.shared_file_system.v2 import limit
from openstack.shared_file_system.v2 import resource_locks
from openstack.shared_file_system.v2 import service
from openstack.shared_file_system.v2 import share
from openstack.shared_file_system.v2 import share_access_rule
from openstack.shared_file_system.v2 import share_group
@ -593,3 +594,44 @@ class TestShareGroupResource(test_proxy_base.TestProxyBase):
share_group_snapshot.ShareGroupSnapshot,
True,
)
class TestServicesResource(test_proxy_base.TestProxyBase):
def setUp(self):
super(TestServicesResource, self).setUp()
self.proxy = _proxy.Proxy(self.session)
def test_services(self):
self.verify_list(self.proxy.services, service.Service)
def test_services_queried(self):
self.verify_list(
self.proxy.services,
service.Service,
method_kwargs={"name": "manila-share"},
expected_kwargs={"name": "manila-share"},
)
@mock.patch.object(service.Service, 'enable')
def test_service_enable(self, mock_enable):
result = self.proxy.enable_service(
service="value", host="host1", name="manila-share"
)
self.assertIs(result, mock_enable.return_value)
mock_enable.assert_called_once_with(
self.proxy,
"host1",
"manila-share",
)
@mock.patch.object(service.Service, 'disable')
def test_service_disable(self, mock_disable):
result = self.proxy.disable_service(
service="value", host="host1", name="manila-share"
)
self.assertIs(result, mock_disable.return_value)
mock_disable.assert_called_once_with(
self.proxy,
"host1",
"manila-share",
)

View File

@ -0,0 +1,104 @@
# 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 unittest import mock
from openstack.shared_file_system.v2 import service
from openstack.tests.unit import base
EXAMPLE = {
"status": "enabled",
"binary": "manila-share",
"zone": "nova",
"host": "manila2@generic1",
"updated_at": "2021-06-07T13:03:57.000000",
"state": "up",
"id": 1,
}
class TestServices(base.TestCase):
def setUp(self):
super(TestServices, self).setUp()
self.resp = mock.Mock()
self.resp.body = {'service': {}}
self.resp.json = mock.Mock(return_value=self.resp.body)
self.resp.status_code = 200
self.resp.headers = {}
self.sess = mock.Mock()
self.sess.put = mock.Mock(return_value=self.resp)
def test_basic(self):
services_resource = service.Service()
self.assertEqual('services', services_resource.resources_key)
self.assertEqual('/services', services_resource.base_path)
self.assertTrue(services_resource.allow_list)
self.assertFalse(services_resource.allow_create)
self.assertFalse(services_resource.allow_fetch)
self.assertTrue(services_resource.allow_commit)
self.assertFalse(services_resource.allow_delete)
self.assertFalse(services_resource.allow_head)
self.assertDictEqual(
{
'binary': 'binary',
'host': 'host',
'limit': 'limit',
'state': 'state',
'status': 'status',
'marker': 'marker',
'name': 'binary',
'availability_zone': 'zone',
},
services_resource._query_mapping._mapping,
)
def test_make_services(self):
services_resource = service.Service(**EXAMPLE)
self.assertEqual(EXAMPLE['id'], services_resource.id)
self.assertEqual(EXAMPLE['status'], services_resource.status)
self.assertEqual(EXAMPLE['binary'], services_resource.binary)
self.assertEqual(EXAMPLE['zone'], services_resource.availability_zone)
self.assertEqual(EXAMPLE['host'], services_resource.host)
self.assertEqual(EXAMPLE['updated_at'], services_resource.updated_at)
self.assertEqual(EXAMPLE['state'], services_resource.state)
def test_enable(self):
sot = service.Service(**EXAMPLE)
res = sot.enable(self.sess, 'host1', 'manila-share')
self.assertIsNotNone(res)
url = 'services/enable'
body = {
'binary': 'manila-share',
'host': 'host1',
}
self.sess.put.assert_called_with(
url, json=body, microversion=self.sess.default_microversion
)
def test_disable(self):
sot = service.Service(**EXAMPLE)
res = sot.disable(self.sess, 'host1', 'manila-share')
self.assertIsNotNone(res)
url = 'services/disable'
body = {
'binary': 'manila-share',
'host': 'host1',
}
self.sess.put.assert_called_with(
url, json=body, microversion=self.sess.default_microversion
)

View File

@ -0,0 +1,5 @@
---
features:
- |
Added support to list services associated with the
shared file system service.