Move get_compute_usage to use proxy
Address todo in compute cloud layer and move get_compute_usage to rely to the proxy layer. With this change method returns Usage object instead of munch. This also allows us to stop importing and inheriting from normalize class here. "attached" filter of the search_floating_ips is dopped since it is being pretty awkward. Change-Id: I3de1654fc35b2985e4a0658f7117bbe9db554dd3
This commit is contained in:
parent
1288359436
commit
dc6be6e906
@ -14,27 +14,23 @@
|
|||||||
# We can't just use list, because sphinx gets confused by
|
# We can't just use list, because sphinx gets confused by
|
||||||
# openstack.resource.Resource.list and openstack.resource2.Resource.list
|
# openstack.resource.Resource.list and openstack.resource2.Resource.list
|
||||||
import base64
|
import base64
|
||||||
import datetime
|
|
||||||
import functools
|
import functools
|
||||||
import operator
|
import operator
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import types # noqa
|
|
||||||
|
|
||||||
import iso8601
|
import iso8601
|
||||||
|
|
||||||
from openstack.cloud import _normalize
|
|
||||||
from openstack.cloud import _utils
|
from openstack.cloud import _utils
|
||||||
from openstack.cloud import exc
|
from openstack.cloud import exc
|
||||||
from openstack.cloud import meta
|
from openstack.cloud import meta
|
||||||
from openstack.compute.v2 import quota_set as _qs
|
from openstack.compute.v2 import quota_set as _qs
|
||||||
from openstack.compute.v2 import server as _server
|
from openstack.compute.v2 import server as _server
|
||||||
from openstack import exceptions
|
from openstack import exceptions
|
||||||
from openstack import proxy
|
|
||||||
from openstack import utils
|
from openstack import utils
|
||||||
|
|
||||||
|
|
||||||
class ComputeCloudMixin(_normalize.Normalizer):
|
class ComputeCloudMixin:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._servers = None
|
self._servers = None
|
||||||
@ -1688,7 +1684,6 @@ class ComputeCloudMixin(_normalize.Normalizer):
|
|||||||
name_or_id, ignore_missing=False)
|
name_or_id, ignore_missing=False)
|
||||||
self.compute.revert_quota_set(proj)
|
self.compute.revert_quota_set(proj)
|
||||||
|
|
||||||
# TODO(stephenfin): Convert to proxy methods
|
|
||||||
def get_compute_usage(self, name_or_id, start=None, end=None):
|
def get_compute_usage(self, name_or_id, start=None, end=None):
|
||||||
""" Get usage for a specific project
|
""" Get usage for a specific project
|
||||||
|
|
||||||
@ -1700,9 +1695,8 @@ class ComputeCloudMixin(_normalize.Normalizer):
|
|||||||
Defaults to now
|
Defaults to now
|
||||||
:raises: OpenStackCloudException if it's not a valid project
|
:raises: OpenStackCloudException if it's not a valid project
|
||||||
|
|
||||||
:returns: Munch object with the usage
|
:returns: A :class:`~openstack.compute.v2.usage.Usage` object
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def parse_date(date):
|
def parse_date(date):
|
||||||
try:
|
try:
|
||||||
return iso8601.parse_date(date)
|
return iso8601.parse_date(date)
|
||||||
@ -1716,43 +1710,17 @@ class ComputeCloudMixin(_normalize.Normalizer):
|
|||||||
" YYYY-MM-DDTHH:MM:SS".format(
|
" YYYY-MM-DDTHH:MM:SS".format(
|
||||||
date=date))
|
date=date))
|
||||||
|
|
||||||
def parse_datetime_for_nova(date):
|
if isinstance(start, str):
|
||||||
# Must strip tzinfo from the date- it breaks Nova. Also,
|
|
||||||
# Nova is expecting this in UTC. If someone passes in an
|
|
||||||
# ISO8601 date string or a datetime with timzeone data attached,
|
|
||||||
# strip the timezone data but apply offset math first so that
|
|
||||||
# the user's well formed perfectly valid date will be used
|
|
||||||
# correctly.
|
|
||||||
offset = date.utcoffset()
|
|
||||||
if offset:
|
|
||||||
date = date - datetime.timedelta(hours=offset)
|
|
||||||
return date.replace(tzinfo=None)
|
|
||||||
|
|
||||||
if not start:
|
|
||||||
start = parse_date('2010-07-06')
|
|
||||||
elif not isinstance(start, datetime.datetime):
|
|
||||||
start = parse_date(start)
|
start = parse_date(start)
|
||||||
if not end:
|
if isinstance(end, str):
|
||||||
end = datetime.datetime.utcnow()
|
|
||||||
elif not isinstance(start, datetime.datetime):
|
|
||||||
end = parse_date(end)
|
end = parse_date(end)
|
||||||
|
|
||||||
start = parse_datetime_for_nova(start)
|
|
||||||
end = parse_datetime_for_nova(end)
|
|
||||||
|
|
||||||
proj = self.get_project(name_or_id)
|
proj = self.get_project(name_or_id)
|
||||||
if not proj:
|
if not proj:
|
||||||
raise exc.OpenStackCloudException(
|
raise exc.OpenStackCloudException(
|
||||||
"project does not exist: {name}".format(name=proj.id))
|
"project does not exist: {name}".format(name=proj.id))
|
||||||
|
|
||||||
data = proxy._json_response(
|
return self.compute.get_usage(proj, start, end)
|
||||||
self.compute.get(
|
|
||||||
'/os-simple-tenant-usage/{project}'.format(project=proj.id),
|
|
||||||
params=dict(start=start.isoformat(), end=end.isoformat())),
|
|
||||||
error_message="Unable to get usage for project: {name}".format(
|
|
||||||
name=proj.id))
|
|
||||||
return self._normalize_compute_usage(
|
|
||||||
self._get_and_munchify('tenant_usage', data))
|
|
||||||
|
|
||||||
def _encode_server_userdata(self, userdata):
|
def _encode_server_userdata(self, userdata):
|
||||||
if hasattr(userdata, 'read'):
|
if hasattr(userdata, 'read'):
|
||||||
|
@ -1977,10 +1977,10 @@ class Proxy(proxy.Proxy):
|
|||||||
:returns: A list of compute ``Usage`` objects.
|
:returns: A list of compute ``Usage`` objects.
|
||||||
"""
|
"""
|
||||||
if start is not None:
|
if start is not None:
|
||||||
query['start'] = start
|
query['start'] = start.isoformat()
|
||||||
|
|
||||||
if end is not None:
|
if end is not None:
|
||||||
query['end'] = end
|
query['end'] = end.isoformat()
|
||||||
|
|
||||||
return self._list(_usage.Usage, **query)
|
return self._list(_usage.Usage, **query)
|
||||||
|
|
||||||
@ -1998,10 +1998,10 @@ class Proxy(proxy.Proxy):
|
|||||||
project = self._get_resource(_project.Project, project)
|
project = self._get_resource(_project.Project, project)
|
||||||
|
|
||||||
if start is not None:
|
if start is not None:
|
||||||
query['start'] = start
|
query['start'] = start.isoformat()
|
||||||
|
|
||||||
if end is not None:
|
if end is not None:
|
||||||
query['end'] = end
|
query['end'] = end.isoformat()
|
||||||
|
|
||||||
res = self._get_resource(_usage.Usage, project.id)
|
res = self._get_resource(_usage.Usage, project.id)
|
||||||
return res.fetch(self, **query)
|
return res.fetch(self, **query)
|
||||||
|
@ -485,6 +485,6 @@ class TestCompute(base.BaseFunctionalTest):
|
|||||||
self.add_info_on_exception('usage', usage)
|
self.add_info_on_exception('usage', usage)
|
||||||
self.assertIsNotNone(usage)
|
self.assertIsNotNone(usage)
|
||||||
self.assertIn('total_hours', usage)
|
self.assertIn('total_hours', usage)
|
||||||
self.assertIn('started_at', usage)
|
self.assertIn('start', usage)
|
||||||
self.assertEqual(start.isoformat(), usage['started_at'])
|
self.assertEqual(start.isoformat(), usage['start'])
|
||||||
self.assertIn('location', usage)
|
self.assertIn('location', usage)
|
||||||
|
@ -274,13 +274,7 @@ class TestFloatingIP(base.BaseFunctionalTest):
|
|||||||
|
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
fip_user['id'],
|
fip_user['id'],
|
||||||
[fip.id for fip in self.user_cloud.search_floating_ips(
|
[fip.id for fip in self.user_cloud.search_floating_ips()]
|
||||||
filters={"attached": False})]
|
|
||||||
)
|
|
||||||
self.assertNotIn(
|
|
||||||
fip_user['id'],
|
|
||||||
[fip.id for fip in self.user_cloud.search_floating_ips(
|
|
||||||
filters={"attached": True})]
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_get_floating_ip_by_id(self):
|
def test_get_floating_ip_by_id(self):
|
||||||
|
@ -25,6 +25,7 @@ class TestUsage(base.TestCase):
|
|||||||
start = end = datetime.datetime.now()
|
start = end = datetime.datetime.now()
|
||||||
|
|
||||||
self.register_uris([
|
self.register_uris([
|
||||||
|
self.get_nova_discovery_mock_dict(),
|
||||||
dict(method='GET',
|
dict(method='GET',
|
||||||
uri=self.get_mock_url(
|
uri=self.get_mock_url(
|
||||||
'compute', 'public',
|
'compute', 'public',
|
||||||
|
@ -1292,7 +1292,10 @@ class TestCompute(TestComputeProxy):
|
|||||||
self.proxy.usages,
|
self.proxy.usages,
|
||||||
usage.Usage,
|
usage.Usage,
|
||||||
method_kwargs={'start': start, 'end': end},
|
method_kwargs={'start': start, 'end': end},
|
||||||
expected_kwargs={'start': start, 'end': end},
|
expected_kwargs={
|
||||||
|
'start': start.isoformat(),
|
||||||
|
'end': end.isoformat()
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_get_usage(self):
|
def test_get_usage(self):
|
||||||
@ -1315,7 +1318,10 @@ class TestCompute(TestComputeProxy):
|
|||||||
method_args=['value'],
|
method_args=['value'],
|
||||||
method_kwargs={'start': start, 'end': end},
|
method_kwargs={'start': start, 'end': end},
|
||||||
expected_args=[self.proxy],
|
expected_args=[self.proxy],
|
||||||
expected_kwargs={'start': start, 'end': end},
|
expected_kwargs={
|
||||||
|
'start': start.isoformat(),
|
||||||
|
'end': end.isoformat()
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_create_server_remote_console(self):
|
def test_create_server_remote_console(self):
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
upgrade:
|
||||||
|
- |
|
||||||
|
cloud.get_compute_usage method return instance of compute.usage.Usage class
|
||||||
|
instead of munch.
|
Loading…
Reference in New Issue
Block a user