Start to make placement client
This patch starts to prepare base methods for placement client in a new class, ``BlazarPlacementClient``. Change-Id: I58712bd9dd243daed0e616792e0ba11b80cd680b Blueprint: placement-api
This commit is contained in:
parent
c31dd15ac2
commit
c86e2414b0
39
blazar/tests/fake_requests.py
Normal file
39
blazar/tests/fake_requests.py
Normal 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.
|
||||||
|
"""Fakes relating to the `requests` module."""
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
class FakeResponse(requests.Response):
|
||||||
|
def __init__(self, status_code, content=None, headers=None):
|
||||||
|
"""A requests.Response that can be used as a mock return_value.
|
||||||
|
|
||||||
|
A key feature is that the instance will evaluate to True or False like
|
||||||
|
a real Response, based on the status_code.
|
||||||
|
|
||||||
|
Properties like ok, status_code, text, and content, and methods like
|
||||||
|
json(), work as expected based on the inputs.
|
||||||
|
|
||||||
|
:param status_code: Integer HTTP response code (200, 404, etc.)
|
||||||
|
:param content: String supplying the payload content of the response.
|
||||||
|
Using a json-encoded string will make the json() method
|
||||||
|
behave as expected.
|
||||||
|
:param headers: Dict of HTTP header values to set.
|
||||||
|
"""
|
||||||
|
super(FakeResponse, self).__init__()
|
||||||
|
self.status_code = status_code
|
||||||
|
if content:
|
||||||
|
self._content = content.encode('utf-8')
|
||||||
|
self.encoding = 'utf-8'
|
||||||
|
if headers:
|
||||||
|
self.headers = headers
|
93
blazar/tests/utils/openstack/test_placement.py
Normal file
93
blazar/tests/utils/openstack/test_placement.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
|
from blazar import tests
|
||||||
|
from blazar.tests import fake_requests
|
||||||
|
from blazar.utils.openstack import placement
|
||||||
|
|
||||||
|
from oslo_config import cfg
|
||||||
|
from oslo_config import fixture as conf_fixture
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
PLACEMENT_MICROVERSION = 1.29
|
||||||
|
|
||||||
|
|
||||||
|
class TestPlacementClient(tests.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestPlacementClient, self).setUp()
|
||||||
|
self.cfg = self.useFixture(conf_fixture.Config(CONF))
|
||||||
|
self.cfg.config(os_auth_host='foofoo')
|
||||||
|
self.cfg.config(os_auth_port='8080')
|
||||||
|
self.cfg.config(os_auth_prefix='identity')
|
||||||
|
self.cfg.config(os_auth_version='v3')
|
||||||
|
self.client = placement.BlazarPlacementClient()
|
||||||
|
|
||||||
|
def test_client_auth_url(self):
|
||||||
|
self.assertEqual("http://foofoo:8080/identity/v3",
|
||||||
|
self.client._client.session.auth.auth_url)
|
||||||
|
|
||||||
|
@mock.patch('keystoneauth1.session.Session.request')
|
||||||
|
def test_get(self, kss_req):
|
||||||
|
kss_req.return_value = fake_requests.FakeResponse(200)
|
||||||
|
url = '/resource_providers'
|
||||||
|
resp = self.client.get(url)
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
kss_req.assert_called_once_with(
|
||||||
|
url, 'GET',
|
||||||
|
endpoint_filter={'service_type': 'placement',
|
||||||
|
'interface': 'public'},
|
||||||
|
headers={'accept': 'application/json'},
|
||||||
|
microversion=PLACEMENT_MICROVERSION, raise_exc=False)
|
||||||
|
|
||||||
|
@mock.patch('keystoneauth1.session.Session.request')
|
||||||
|
def test_post(self, kss_req):
|
||||||
|
kss_req.return_value = fake_requests.FakeResponse(200)
|
||||||
|
url = '/resource_providers'
|
||||||
|
data = {'name': 'unicorn'}
|
||||||
|
resp = self.client.post(url, data)
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
kss_req.assert_called_once_with(
|
||||||
|
url, 'POST', json=data,
|
||||||
|
endpoint_filter={'service_type': 'placement',
|
||||||
|
'interface': 'public'},
|
||||||
|
headers={'accept': 'application/json'},
|
||||||
|
microversion=PLACEMENT_MICROVERSION, raise_exc=False)
|
||||||
|
|
||||||
|
@mock.patch('keystoneauth1.session.Session.request')
|
||||||
|
def test_put(self, kss_req):
|
||||||
|
kss_req.return_value = fake_requests.FakeResponse(200)
|
||||||
|
url = '/resource_providers'
|
||||||
|
data = {'name': 'unicorn'}
|
||||||
|
resp = self.client.put(url, data)
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
kss_req.assert_called_once_with(
|
||||||
|
url, 'PUT', json=data,
|
||||||
|
endpoint_filter={'service_type': 'placement',
|
||||||
|
'interface': 'public'},
|
||||||
|
headers={'accept': 'application/json'},
|
||||||
|
microversion=PLACEMENT_MICROVERSION, raise_exc=False)
|
||||||
|
|
||||||
|
@mock.patch('keystoneauth1.session.Session.request')
|
||||||
|
def test_delete(self, kss_req):
|
||||||
|
kss_req.return_value = fake_requests.FakeResponse(200)
|
||||||
|
url = '/resource_providers'
|
||||||
|
resp = self.client.delete(url)
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
kss_req.assert_called_once_with(
|
||||||
|
url, 'DELETE',
|
||||||
|
endpoint_filter={'service_type': 'placement',
|
||||||
|
'interface': 'public'},
|
||||||
|
headers={'accept': 'application/json'},
|
||||||
|
microversion=PLACEMENT_MICROVERSION, raise_exc=False)
|
93
blazar/utils/openstack/placement.py
Normal file
93
blazar/utils/openstack/placement.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
# 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 keystoneauth1 import adapter
|
||||||
|
from keystoneauth1.identity import v3
|
||||||
|
from keystoneauth1 import session
|
||||||
|
|
||||||
|
from oslo_config import cfg
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
PLACEMENT_MICROVERSION = 1.29
|
||||||
|
|
||||||
|
|
||||||
|
class BlazarPlacementClient(object):
|
||||||
|
"""Client class for updating placement."""
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
"""Initialize the report client.
|
||||||
|
|
||||||
|
If a prepared keystoneauth1 adapter for API communication is
|
||||||
|
specified, it is used.
|
||||||
|
|
||||||
|
Otherwise creates it via _create_client() function.
|
||||||
|
"""
|
||||||
|
adapter = kwargs.pop('adapter', None)
|
||||||
|
self._client = adapter or self._create_client(**kwargs)
|
||||||
|
|
||||||
|
def _create_client(self, **kwargs):
|
||||||
|
"""Create the HTTP session accessing the placement service."""
|
||||||
|
username = kwargs.pop('username',
|
||||||
|
CONF.os_admin_username)
|
||||||
|
user_domain_name = kwargs.pop('user_domain_name',
|
||||||
|
CONF.os_admin_user_domain_name)
|
||||||
|
project_name = kwargs.pop('project_name',
|
||||||
|
CONF.os_admin_project_name)
|
||||||
|
password = kwargs.pop('password',
|
||||||
|
CONF.os_admin_password)
|
||||||
|
|
||||||
|
project_domain_name = kwargs.pop('project_domain_name',
|
||||||
|
CONF.os_admin_project_domain_name)
|
||||||
|
auth_url = kwargs.pop('auth_url', None)
|
||||||
|
|
||||||
|
if auth_url is None:
|
||||||
|
auth_url = "%s://%s:%s/%s/%s" % (CONF.os_auth_protocol,
|
||||||
|
CONF.os_auth_host,
|
||||||
|
CONF.os_auth_port,
|
||||||
|
CONF.os_auth_prefix,
|
||||||
|
CONF.os_auth_version)
|
||||||
|
|
||||||
|
auth = v3.Password(auth_url=auth_url,
|
||||||
|
username=username,
|
||||||
|
password=password,
|
||||||
|
project_name=project_name,
|
||||||
|
user_domain_name=user_domain_name,
|
||||||
|
project_domain_name=project_domain_name)
|
||||||
|
sess = session.Session(auth=auth)
|
||||||
|
# Set accept header on every request to ensure we notify placement
|
||||||
|
# service of our response body media type preferences.
|
||||||
|
headers = {'accept': 'application/json'}
|
||||||
|
client = adapter.Adapter(session=sess,
|
||||||
|
service_type='placement',
|
||||||
|
interface='public',
|
||||||
|
additional_headers=headers)
|
||||||
|
return client
|
||||||
|
|
||||||
|
def get(self, url, microversion=PLACEMENT_MICROVERSION):
|
||||||
|
return self._client.get(url, raise_exc=False,
|
||||||
|
microversion=microversion)
|
||||||
|
|
||||||
|
def post(self, url, data, microversion=PLACEMENT_MICROVERSION):
|
||||||
|
return self._client.post(url, json=data, raise_exc=False,
|
||||||
|
microversion=microversion)
|
||||||
|
|
||||||
|
def put(self, url, data, microversion=PLACEMENT_MICROVERSION):
|
||||||
|
return self._client.put(url, json=data, raise_exc=False,
|
||||||
|
microversion=microversion)
|
||||||
|
|
||||||
|
def delete(self, url, microversion=PLACEMENT_MICROVERSION):
|
||||||
|
return self._client.delete(url, raise_exc=False,
|
||||||
|
microversion=microversion)
|
@ -8,6 +8,7 @@ Babel!=2.4.0,>=2.3.4 # BSD
|
|||||||
eventlet!=0.18.3,!=0.20.1,>=0.18.2 # MIT
|
eventlet!=0.18.3,!=0.20.1,>=0.18.2 # MIT
|
||||||
Flask!=0.11,>=0.10 # BSD
|
Flask!=0.11,>=0.10 # BSD
|
||||||
iso8601>=0.1.11 # MIT
|
iso8601>=0.1.11 # MIT
|
||||||
|
keystoneauth1>=3.4.0 # Apache-2.0
|
||||||
keystonemiddleware>=4.17.0 # Apache-2.0
|
keystonemiddleware>=4.17.0 # Apache-2.0
|
||||||
kombu!=4.0.2,>=4.0.0 # BSD
|
kombu!=4.0.2,>=4.0.0 # BSD
|
||||||
oslo.concurrency>=3.26.0 # Apache-2.0
|
oslo.concurrency>=3.26.0 # Apache-2.0
|
||||||
@ -26,6 +27,7 @@ netaddr>=0.7.18 # BSD
|
|||||||
python-keystoneclient>=3.8.0 # Apache-2.0
|
python-keystoneclient>=3.8.0 # Apache-2.0
|
||||||
pecan!=1.0.2,!=1.0.3,!=1.0.4,!=1.2,>=1.0.0 # BSD
|
pecan!=1.0.2,!=1.0.3,!=1.0.4,!=1.2,>=1.0.0 # BSD
|
||||||
sqlalchemy-migrate>=0.11.0 # Apache-2.0
|
sqlalchemy-migrate>=0.11.0 # Apache-2.0
|
||||||
|
requests>=2.18.4 # Apache-2.0
|
||||||
Routes>=2.3.1 # MIT
|
Routes>=2.3.1 # MIT
|
||||||
six>=1.10.0 # MIT
|
six>=1.10.0 # MIT
|
||||||
SQLAlchemy!=1.1.5,!=1.1.6,!=1.1.7,!=1.1.8,>=1.0.10 # MIT
|
SQLAlchemy!=1.1.5,!=1.1.6,!=1.1.7,!=1.1.8,>=1.0.10 # MIT
|
||||||
|
Loading…
Reference in New Issue
Block a user