summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBin Yang <bin.yang@windriver.com>2019-04-01 09:46:31 +0000
committerBin Yang <bin.yang@windriver.com>2019-04-01 09:46:31 +0000
commit3176e57da097f2c238b134f18b1a4af00e105546 (patch)
tree66301d35a32927feed1fc277a3d06bb8eb87786b
parent4a7181a20f5eb9ad6bfbcb0945fa79ac0ddd620b (diff)
Update capacity check API
Query the AZinfo from the cache Relay on the background thread of AZcap Auditing Change-Id: I064dbc22c71ef25683145ef1c96274ce6ac74c3b Issue-ID: MULTICLOUD-542 Signed-off-by: Bin Yang <bin.yang@windriver.com>
-rw-r--r--share/newton_base/resource/capacity.py183
-rw-r--r--share/starlingx_base/registration/registration.py6
-rw-r--r--share/starlingx_base/resource/__init__.py10
-rw-r--r--share/starlingx_base/resource/capacity.py97
4 files changed, 204 insertions, 92 deletions
diff --git a/share/newton_base/resource/capacity.py b/share/newton_base/resource/capacity.py
index 1a08b9a5..c2fee361 100644
--- a/share/newton_base/resource/capacity.py
+++ b/share/newton_base/resource/capacity.py
@@ -35,112 +35,113 @@ class CapacityCheck(APIView):
self._logger.info("vimid, data> %s, %s" % (vimid, request.data))
self._logger.debug("META> %s" % request.META)
- hasEnoughResource = False
try:
- resource_demand = request.data
-
- tenant_name = None
- vim = VimDriverUtils.get_vim_info(vimid)
- sess = VimDriverUtils.get_session(vim, tenant_name)
-
- # get token:
- cloud_owner, regionid = extsys.decode_vim_id(vimid)
- interface = 'public'
- service = {'service_type': 'compute',
- 'interface': interface,
- 'region_name': vim['openstack_region_id']
- if vim.get('openstack_region_id')
- else vim['cloud_region_id']
- }
-
- # get limit for this tenant
- req_resouce = "/limits"
- self._logger.info("check limits> URI:%s" % req_resouce)
- resp = sess.get(req_resouce, endpoint_filter=service)
- self._logger.info("check limits> status:%s" % resp.status_code)
- content = resp.json()
- compute_limits = content['limits']['absolute']
- self._logger.debug("check limits> resp data:%s" % content)
-
- # get total resource of this cloud region
- try:
- req_resouce = "/os-hypervisors/statistics"
- self._logger.info("check os-hypervisors statistics> URI:%s" % req_resouce)
- resp = sess.get(req_resouce, endpoint_filter=service)
- self._logger.info("check os-hypervisors statistics> status:%s" % resp.status_code)
- content = resp.json()
- hypervisor_statistics = content['hypervisor_statistics']
- self._logger.debug("check os-hypervisors statistics> resp data:%s" % content)
- except HttpError as e:
- if e.http_status == status.HTTP_403_FORBIDDEN:
- # Due to non administrator account cannot get hypervisor data,
- # so construct enough resource data
- conVCPUS = int(resource_demand['vCPU'])
- conFreeRamMB = int(resource_demand['Memory'])
- conFreeDiskGB = int(resource_demand['Storage'])
- self._logger.info("Non administator forbidden to access hypervisor statistics data")
- hypervisor_statistics = {'vcpus_used': 0,
- 'vcpus': conVCPUS,
- 'free_ram_mb': conFreeRamMB,
- 'free_disk_gb': conFreeDiskGB}
- else:
- # non forbiden exeption will be redirected
- raise e
-
- # get storage limit for this tenant
- service['service_type'] = 'volumev2'
- req_resouce = "/limits"
- self._logger.info("check volumev2 limits> URI:%s" % req_resouce)
- resp = sess.get(req_resouce, endpoint_filter=service)
- self._logger.info("check volumev2> status:%s" % resp.status_code)
- content = resp.json()
- storage_limits = content['limits']['absolute']
- self._logger.debug("check volumev2> resp data:%s" % content)
-
- # compute actual available resource for this tenant
- remainVCPU = compute_limits['maxTotalCores'] - compute_limits['totalCoresUsed']
- remainHypervisorVCPU = hypervisor_statistics['vcpus'] - hypervisor_statistics['vcpus_used']
-
- if (remainVCPU > remainHypervisorVCPU):
- remainVCPU = remainHypervisorVCPU
-
- remainMEM = compute_limits['maxTotalRAMSize'] - compute_limits['totalRAMUsed']
- remainHypervisorMEM = hypervisor_statistics['free_ram_mb']
- if remainMEM > remainHypervisorMEM:
- remainMEM = remainHypervisorMEM
-
- remainStorage = storage_limits['maxTotalVolumeGigabytes'] - storage_limits['totalGigabytesUsed']
- remainHypervisorStorage = hypervisor_statistics['free_disk_gb']
- if (remainStorage > remainHypervisorStorage):
- remainStorage = remainHypervisorStorage
-
- # compare resource demanded with available
- if (int(resource_demand['vCPU']) > remainVCPU):
- hasEnoughResource = False
- elif (int(resource_demand['Memory']) > remainMEM):
- hasEnoughResource = False
- elif (int(resource_demand['Storage']) > remainStorage):
- hasEnoughResource = False
- else:
- hasEnoughResource = True
-
+ hasEnoughResource = self.get_tenant_cap_info(vimid, request.data)
self._logger.info("RESP with data> result:%s" % hasEnoughResource)
return Response(data={'result': hasEnoughResource}, status=status.HTTP_200_OK)
except VimDriverNewtonException as e:
self._logger.error("Plugin exception> status:%s,error:%s"
% (e.status_code, e.content))
- return Response(data={'result': hasEnoughResource,
+ return Response(data={'result': False,
'error': e.content}, status=e.status_code)
except HttpError as e:
self._logger.error("HttpError: status:%s, response:%s" % (e.http_status, e.response.json()))
resp = e.response.json()
- resp.update({'result': hasEnoughResource})
+ resp.update({'result': False})
return Response(data=e.response.json(), status=e.http_status)
except Exception as e:
self._logger.error(traceback.format_exc())
- return Response(data={'result': hasEnoughResource, 'error': str(e)},
+ return Response(data={'result': False, 'error': str(e)},
status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+ def get_tenant_cap_info(self, vimid, resource_demand):
+ hasEnoughResource = False
+ tenant_name = None
+ vim = VimDriverUtils.get_vim_info(vimid)
+ sess = VimDriverUtils.get_session(vim, tenant_name)
+
+ # get token:
+ # cloud_owner, regionid = extsys.decode_vim_id(vimid)
+ interface = 'public'
+ service = {'service_type': 'compute',
+ 'interface': interface,
+ 'region_name': vim['openstack_region_id']
+ if vim.get('openstack_region_id')
+ else vim['cloud_region_id']
+ }
+
+ # get limit for this tenant
+ req_resouce = "/limits"
+ self._logger.info("check limits> URI:%s" % req_resouce)
+ resp = sess.get(req_resouce, endpoint_filter=service)
+ self._logger.info("check limits> status:%s" % resp.status_code)
+ content = resp.json()
+ compute_limits = content['limits']['absolute']
+ self._logger.debug("check limits> resp data:%s" % content)
+
+ # get total resource of this cloud region
+ try:
+ req_resouce = "/os-hypervisors/statistics"
+ self._logger.info("check os-hypervisors statistics> URI:%s" % req_resouce)
+ resp = sess.get(req_resouce, endpoint_filter=service)
+ self._logger.info("check os-hypervisors statistics> status:%s" % resp.status_code)
+ content = resp.json()
+ hypervisor_statistics = content['hypervisor_statistics']
+ self._logger.debug("check os-hypervisors statistics> resp data:%s" % content)
+ except HttpError as e:
+ if e.http_status == status.HTTP_403_FORBIDDEN:
+ # Due to non administrator account cannot get hypervisor data,
+ # so construct enough resource data
+ conVCPUS = int(resource_demand['vCPU'])
+ conFreeRamMB = int(resource_demand['Memory'])
+ conFreeDiskGB = int(resource_demand['Storage'])
+ self._logger.info("Non administator forbidden to access hypervisor statistics data")
+ hypervisor_statistics = {'vcpus_used': 0,
+ 'vcpus': conVCPUS,
+ 'free_ram_mb': conFreeRamMB,
+ 'free_disk_gb': conFreeDiskGB}
+ else:
+ # non forbiden exeption will be redirected
+ raise e
+
+ # get storage limit for this tenant
+ service['service_type'] = 'volumev2'
+ req_resouce = "/limits"
+ self._logger.info("check volumev2 limits> URI:%s" % req_resouce)
+ resp = sess.get(req_resouce, endpoint_filter=service)
+ self._logger.info("check volumev2> status:%s" % resp.status_code)
+ content = resp.json()
+ storage_limits = content['limits']['absolute']
+ self._logger.debug("check volumev2> resp data:%s" % content)
+
+ # compute actual available resource for this tenant
+ remainVCPU = compute_limits['maxTotalCores'] - compute_limits['totalCoresUsed']
+ remainHypervisorVCPU = hypervisor_statistics['vcpus'] - hypervisor_statistics['vcpus_used']
+
+ if (remainVCPU > remainHypervisorVCPU):
+ remainVCPU = remainHypervisorVCPU
+
+ remainMEM = compute_limits['maxTotalRAMSize'] - compute_limits['totalRAMUsed']
+ remainHypervisorMEM = hypervisor_statistics['free_ram_mb']
+ if remainMEM > remainHypervisorMEM:
+ remainMEM = remainHypervisorMEM
+
+ remainStorage = storage_limits['maxTotalVolumeGigabytes'] - storage_limits['totalGigabytesUsed']
+ remainHypervisorStorage = hypervisor_statistics['free_disk_gb']
+ if (remainStorage > remainHypervisorStorage):
+ remainStorage = remainHypervisorStorage
+
+ # compare resource demanded with available
+ if (int(resource_demand['vCPU']) > remainVCPU):
+ hasEnoughResource = False
+ elif (int(resource_demand['Memory']) > remainMEM):
+ hasEnoughResource = False
+ elif (int(resource_demand['Storage']) > remainStorage):
+ hasEnoughResource = False
+ else:
+ hasEnoughResource = True
+
+ return hasEnoughResource
class APIv1CapacityCheck(CapacityCheck):
def __init__(self):
diff --git a/share/starlingx_base/registration/registration.py b/share/starlingx_base/registration/registration.py
index 7a85b29f..59074568 100644
--- a/share/starlingx_base/registration/registration.py
+++ b/share/starlingx_base/registration/registration.py
@@ -373,7 +373,8 @@ class InfraResourceAuditor(newton_registration.RegistryHelper):
continue
hypervisors_dict[h["hypervisor_hostname"]] = h
- az_pserver_info = {}
+ vimAzCacheKey = "cap_azlist_" + vimid
+ vimAzList = []
# cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid)
for az in self._get_list_resources(
"/os-availability-zone/detail", "compute", session,
@@ -393,6 +394,8 @@ class InfraResourceAuditor(newton_registration.RegistryHelper):
if azName == 'internal':
continue
+ vimAzList.append(azName)
+
# get list of host names
pservers_info = [k for (k, v) in az['hosts'].items()]
# set the association between az and pservers
@@ -456,6 +459,7 @@ class InfraResourceAuditor(newton_registration.RegistryHelper):
# update the cache
cache.set(azCapCacheKey, json.dumps(azCapInfoCache), 3600 * 24)
+ cache.set(vimAzCacheKey, vimAzList, 3600 * 24)
except Exception as e:
self._logger.error("azcap_audit raise exception: %s" % e)
pass
diff --git a/share/starlingx_base/resource/__init__.py b/share/starlingx_base/resource/__init__.py
new file mode 100644
index 00000000..825091ff
--- /dev/null
+++ b/share/starlingx_base/resource/__init__.py
@@ -0,0 +1,10 @@
+# Copyright (c) 2017-2019 Wind River Systems, Inc.
+#
+# 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.
diff --git a/share/starlingx_base/resource/capacity.py b/share/starlingx_base/resource/capacity.py
new file mode 100644
index 00000000..fc926d00
--- /dev/null
+++ b/share/starlingx_base/resource/capacity.py
@@ -0,0 +1,97 @@
+# Copyright (c) 2017-2019 Wind River Systems, Inc.
+#
+# 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 logging
+import traceback
+import json
+
+from django.core.cache import cache
+
+from newton_base.resource import capacity as newton_capacity
+from common.exceptions import VimDriverNewtonException
+from newton_base.util import VimDriverUtils
+
+from keystoneauth1.exceptions import HttpError
+from rest_framework import status
+from rest_framework.response import Response
+from rest_framework.views import APIView
+from common.msapi import extsys
+
+logger = logging.getLogger(__name__)
+
+
+class CapacityCheck(newton_capacity.CapacityCheck):
+ def __init__(self):
+ super(CapacityCheck, self).__init__()
+ self._logger = logger
+
+ def post(self, request, vimid=""):
+ self._logger.info("vimid, data> %s, %s" % (vimid, request.data))
+ self._logger.debug("META> %s" % request.META)
+
+ try:
+ hasEnoughResource = self.get_tenant_cap_info(vimid, request.data)
+ azCapInfo = self.get_az_cap_info(vimid)
+ self._logger.info("RESP with data> result:%s" % hasEnoughResource)
+ return Response(data={'result': hasEnoughResource, 'AZs': azCapInfo}, status=status.HTTP_200_OK)
+ except Exception as e:
+ self._logger.error(traceback.format_exc())
+ return Response(data={'result': False, 'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ def get_az_cap_info(self, vimid):
+ azCapInfo = []
+ viminfo = VimDriverUtils.get_vim_info(vimid)
+ if not viminfo:
+ self._logger.warn("azcap_audit no valid vimid: %s" % vimid)
+ return
+
+ session = VimDriverUtils.get_session(
+ viminfo,
+ tenant_name=viminfo['tenant']
+ )
+ try:
+ # get list of AZ
+ vimAzCacheKey = "cap_azlist_" + vimid
+ vimAzListCacheStr = cache.get(vimAzCacheKey)
+ vimAzListCache = json.loads(vimAzListCacheStr) if vimAzListCacheStr else []
+ for azName in vimAzListCache:
+ azCapCacheKey = "cap_" + vimid + "_" + azName
+ azCapInfoCacheStr = cache.get(azCapCacheKey)
+ azCapInfoCache = json.loads(azCapInfoCacheStr) if azCapInfoCacheStr else None
+
+ azCapInfo["availability-zone-name"] = azName
+ azCapInfo["vCPUAvail"] = azCapInfoCache.get("vcpus", 0) + azCapInfoCache.get("vcpus_used", 0)
+ azCapInfo["vCPUTotal"] = azCapInfoCache.get("vcpus", 0)
+ azCapInfo["MemoryAvail"] = azCapInfoCache.get("vcpus", 0)
+ azCapInfo["MemoryTotal"] = azCapInfoCache.get("vcpus", 0)
+ azCapInfo["StorageAvail"] = azCapInfoCache.get("vcpus", 0)
+ azCapInfo["StorageTotal"] = azCapInfoCache.get("vcpus", 0)
+
+ return azCapInfo
+ except Exception as e:
+ return azCapInfo
+ pass
+
+class APIv1CapacityCheck(CapacityCheck):
+ def __init__(self):
+ super(APIv1CapacityCheck, self).__init__()
+ # self._logger = logger
+
+ def post(self, request, cloud_owner="", cloud_region_id=""):
+ self._logger.info("vimid, data> %s,%s, %s" % (cloud_owner, cloud_region_id, request.data))
+ self._logger.debug("META> %s" % request.META)
+
+ vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id)
+ return super(APIv1CapacityCheck, self).post(request, vimid)