diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | newton/newton/proxy/urls.py | 3 | ||||
-rw-r--r-- | newton/newton/proxy/views/dnsaasdelegate.py | 191 | ||||
-rw-r--r-- | newton/newton/proxy/views/identityV3.py | 13 | ||||
-rw-r--r-- | newton/newton/proxy/views/proxy_utils.py | 45 | ||||
-rw-r--r-- | newton/newton/registration/tests/test_registration.py | 6 | ||||
-rw-r--r-- | newton/newton/registration/views/registration.py | 560 | ||||
-rw-r--r-- | newton/tox.ini | 6 | ||||
-rw-r--r-- | ocata/ocata/registration/tests/test_registration.py | 6 | ||||
-rw-r--r-- | ocata/tox.ini | 5 | ||||
-rw-r--r-- | windriver/titanium_cloud/registration/tests/test_registration.py | 6 | ||||
-rw-r--r-- | windriver/tox.ini | 6 |
12 files changed, 620 insertions, 228 deletions
@@ -10,3 +10,4 @@ logs/*.log htmlcov/ .idea/ mydatabase +.DS_Store diff --git a/newton/newton/proxy/urls.py b/newton/newton/proxy/urls.py index 556cc4e6..0e0ca52a 100644 --- a/newton/newton/proxy/urls.py +++ b/newton/newton/proxy/urls.py @@ -17,6 +17,7 @@ from rest_framework.urlpatterns import format_suffix_patterns from newton.proxy.views import identityV3 from newton.proxy.views import services +from newton.proxy.views import dnsaasdelegate urlpatterns = [ # url(r'^identity/v2)$', @@ -29,6 +30,8 @@ urlpatterns = [ identityV3.TokensV2.as_view()), url(r'^identity/v2.0/tenants/?$', services.GetTenants.as_view()), + url(r'dns-delegate/(?P<requri>[0-9a-zA-Z./_-]*)$', + dnsaasdelegate.DnsaasDelegate.as_view()), url(r'^(?P<servicetype>[0-9a-zA-Z_-]{,18})/(?P<requri>[0-9a-zA-Z./_-]*)$', services.Services.as_view()), ] diff --git a/newton/newton/proxy/views/dnsaasdelegate.py b/newton/newton/proxy/views/dnsaasdelegate.py new file mode 100644 index 00000000..bce24dff --- /dev/null +++ b/newton/newton/proxy/views/dnsaasdelegate.py @@ -0,0 +1,191 @@ +# Copyright (c) 2017 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 json +import traceback + +from keystoneauth1.exceptions import HttpError +import re +from rest_framework.permissions import BasePermission +from rest_framework.response import Response +from rest_framework import status +from rest_framework.views import APIView + +from newton.proxy.views.services import Services + +from newton.proxy.views.proxy_utils import ProxyUtils +from newton.pub.exceptions import VimDriverNewtonException +from newton.pub.msapi import extsys +from newton.requests.views.util import VimDriverUtils + + +logger = logging.getLogger(__name__) + +DEBUG=True + +class DnsaasDelegate(Services): + ''' + DNSaaS delegate service + ''' + + def __init__(self): + self._logger = logger + + + def _do_action(self, action, request, vim_id, servicetype, requri): + tmp_auth_token = self._get_token(request) + try: + # fetch the auth_state out of cache + auth_state_str, metadata_catalog_str = VimDriverUtils.get_token_cache(tmp_auth_token) + + if not auth_state_str: + #invalid token + return Response(data={'error': "request token %s is not valid" % (tmp_auth_token)}, + status=status.HTTP_404_NOT_FOUND) + + # get project name from auth_state + auth_state = json.loads(auth_state_str) + if not auth_state: + # invalid token + return Response(data={'error': "request token %s is broken" % (tmp_auth_token)}, + status=status.HTTP_404_NOT_FOUND) + + tenant_name = auth_state['body']['token']['project']['name'] + + #find out the delegated DNSaaS provider + viminfo = VimDriverUtils.get_vim_info(vim_id) + if not viminfo: + return Response(data={'error': "vimid %s is not found" % (vim_id)}, + status=status.HTTP_404_NOT_FOUND) + + cloud_dns_delegate_info = None + cloud_extra_info_str = viminfo.get('cloud_extra_info') + if cloud_extra_info_str: + cloud_extra_info = json.loads(cloud_extra_info_str) + cloud_dns_delegate_info = cloud_extra_info.get("dns-delegate") + + if not cloud_dns_delegate_info \ + or not cloud_dns_delegate_info.get("cloud-owner") \ + or not cloud_dns_delegate_info.get("cloud-region-id"): + return Response(data={'error': "dns-delegate for vimid %s is not configured" + % (vim_id)}, + status=status.HTTP_404_NOT_FOUND) + + vimid_delegate = cloud_dns_delegate_info.get("cloud-owner") \ + + "_" \ + + cloud_dns_delegate_info.get("cloud-region-id") + + + #now forward request to delegated DNS service endpoint + vim = VimDriverUtils.get_vim_info(vimid_delegate) + if not vim: + return Response(data={'error': "vimid %s is not found" % (vimid_delegate)}, + status=status.HTTP_404_NOT_FOUND) + + sess = VimDriverUtils.get_session(vim, tenantname=tenant_name, auth_state=None) + + cloud_owner, regionid = extsys.decode_vim_id(vimid_delegate) + interface = 'public' + service = { + 'service_type': servicetype, + 'interface': interface, + 'region_id': regionid + } + + req_resource = requri + querystr = VimDriverUtils.get_query_part(request) + if querystr: + req_resource += "?" + querystr + + self._logger.debug("service " + action + " request uri %s" % (req_resource)) + if(action == "get"): + resp = sess.get(req_resource, endpoint_filter=service, + headers={"Content-Type": "application/json", + "Accept": "application/json"}) + elif(action == "post"): + resp = sess.post(req_resource, data=json.JSONEncoder().encode(request.data), + endpoint_filter=service, + headers={"Content-Type": "application/json", + "Accept": "application/json"}) + elif(action == "put"): + resp = sess.put(req_resource, data=json.JSONEncoder().encode(request.data), + endpoint_filter=service, + headers={"Content-Type": "application/json", + "Accept": "application/json"}) + elif(action == "patch"): + resp = sess.patch(req_resource, data=json.JSONEncoder().encode(request.data), + endpoint_filter=service, + headers={"Content-Type": "application/json", + "Accept": "application/json"}) + elif (action == "delete"): + resp = sess.delete(req_resource, endpoint_filter=service, + headers={"Content-Type": "application/json", + "Accept": "application/json"}) + content = resp.json() if resp.content else None + self._logger.debug("service " + action + " response: %s, %s" % (resp.status_code, content)) + + if (action != "delete"): + return Response(headers={'X-Subject-Token': tmp_auth_token}, data=content, status=resp.status_code) + return Response(headers={'X-Subject-Token': tmp_auth_token}, status=resp.status_code) + except VimDriverNewtonException as e: + return Response(data={'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())) + return Response(data=e.response.json(), status=e.http_status) + except Exception as e: + self._logger.error(traceback.format_exc()) + return Response(data={'error': str(e)}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + def get(self, request, vimid="", servicetype="dns-delegate", requri=""): + self._logger.debug("DnsaasDelegate--get::META> %s" % request.META) + self._logger.debug("DnsaasDelegate--get::data> %s" % request.data) + self._logger.debug("DnsaasDelegate--get::vimid, servicetype, requri> %s,%s,%s" + % (vimid, servicetype, requri)) + return self._do_action("get", request, vimid, "dns", requri) + + def head(self, request, vimid="", servicetype="dns-delegate", requri=""): + self._logger.debug("DnsaasDelegate--get::META> %s" % request.META) + self._logger.debug("DnsaasDelegate--get::data> %s" % request.data) + self._logger.debug("DnsaasDelegate--get::vimid, servicetype, requri> %s,%s,%s" + % (vimid, servicetype, requri)) + return self._do_action("head", request, vimid, "dns", requri) + + def post(self, request, vimid="", servicetype="dns-delegate", requri=""): + self._logger.debug("DnsaasDelegate--get::META> %s" % request.META) + self._logger.debug("DnsaasDelegate--get::data> %s" % request.data) + self._logger.debug("DnsaasDelegate--get::vimid, servicetype, requri> %s,%s,%s" + % (vimid, servicetype, requri)) + return self._do_action("post", request, vimid, "dns", requri) + + def put(self, request, vimid="", servicetype="dns-delegate", requri=""): + self._logger.debug("DnsaasDelegate--get::META> %s" % request.META) + self._logger.debug("DnsaasDelegate--get::data> %s" % request.data) + self._logger.debug("DnsaasDelegate--get::vimid, servicetype, requri> %s,%s,%s" + % (vimid, servicetype, requri)) + return self._do_action("put", request, vimid, "dns", requri) + + def patch(self, request, vimid="", servicetype="dns-delegate", requri=""): + self._logger.debug("DnsaasDelegate--get::META> %s" % request.META) + self._logger.debug("DnsaasDelegate--get::data> %s" % request.data) + self._logger.debug("DnsaasDelegate--get::vimid, servicetype, requri> %s,%s,%s" + % (vimid, servicetype, requri)) + return self._do_action("patch", request, vimid, "dns", requri) + + def delete(self, request, vimid="", servicetype="dns-delegate", requri=""): + self._logger.debug("DnsaasDelegate--get::META> %s" % request.META) + self._logger.debug("DnsaasDelegate--get::data> %s" % request.data) + self._logger.debug("DnsaasDelegate--get::vimid, servicetype, requri> %s,%s,%s" + % (vimid, servicetype, requri)) + return self._do_action("delete", request, vimid, "dns", requri) diff --git a/newton/newton/proxy/views/identityV3.py b/newton/newton/proxy/views/identityV3.py index 048d5a0f..bc2b06e9 100644 --- a/newton/newton/proxy/views/identityV3.py +++ b/newton/newton/proxy/views/identityV3.py @@ -80,10 +80,17 @@ class Tokens(APIView): #set expiring in 1 hour #update the catalog - tmp_auth_data['token']['catalog'], tmp_metadata_catalog = ProxyUtils.update_catalog(vimid, tmp_auth_data['token']['catalog'], self.proxy_prefix) - tmp_auth_token = VimDriverUtils.update_token_cache(vim, sess, tmp_auth_token, tmp_auth_state, json.dumps(tmp_metadata_catalog)) + tmp_auth_data['token']['catalog'], tmp_metadata_catalog = ProxyUtils.update_catalog( + vimid, tmp_auth_data['token']['catalog'], self.proxy_prefix) - resp = Response(headers={'X-Subject-Token': tmp_auth_token}, data=tmp_auth_data, status=status.HTTP_201_CREATED) + tmp_auth_token = VimDriverUtils.update_token_cache( + vim, sess, tmp_auth_token, tmp_auth_state, json.dumps(tmp_metadata_catalog)) + + tmp_auth_data['token']['catalog'] = ProxyUtils.update_catalog_dnsaas( + vimid,tmp_auth_data['token']['catalog'], self.proxy_prefix, vim) + + resp = Response(headers={'X-Subject-Token': tmp_auth_token}, + data=tmp_auth_data, status=status.HTTP_201_CREATED) return resp except VimDriverNewtonException as e: diff --git a/newton/newton/proxy/views/proxy_utils.py b/newton/newton/proxy/views/proxy_utils.py index 89a49286..c80b9680 100644 --- a/newton/newton/proxy/views/proxy_utils.py +++ b/newton/newton/proxy/views/proxy_utils.py @@ -15,6 +15,8 @@ import logging import json import traceback import re +import uuid + from rest_framework import status from newton.pub.exceptions import VimDriverNewtonException @@ -128,4 +130,47 @@ class ProxyUtils(object): return None + @staticmethod + def update_catalog_dnsaas(vimid, catalog, multicould_namespace, viminfo): + ''' + append DNSaaS delegate endpoints to catalog + :param vimid: + :param catalog: service catalog to be updated + :param multicould_namespace: multicloud namespace prefix to replace the real one in catalog endpoints url + :param viminfo: vim information + :return:updated catalog + ''' + + try: + cloud_dns_delegate_info = None + cloud_extra_info_str = viminfo.get('cloud_extra_info') + if cloud_extra_info_str: + cloud_extra_info = json.loads(cloud_extra_info_str) + cloud_dns_delegate_info = cloud_extra_info.get("dns-delegate") + + if not cloud_dns_delegate_info\ + or not cloud_dns_delegate_info.get("cloud-owner") \ + or not cloud_dns_delegate_info.get("cloud-region-id"): + #DNSaaS deleget was not configured yet + return catalog + + dns_catalog = { + "name":"dns-delegate", + "type":"dns", + "id": str(uuid.uuid1()), + "endpoints": { + "interface": "public", + "region": cloud_dns_delegate_info.get("cloud-region-id"), + "region_id": cloud_dns_delegate_info.get("cloud-region-id"), + "id": str(uuid.uuid1()), + "url": multicould_namespace + "/%s/dns-delegate" % vimid, + } + } + catalog.append(dns_catalog) + + return catalog + + except Exception as e: + logger.error(traceback.format_exc()) + return catalog diff --git a/newton/newton/registration/tests/test_registration.py b/newton/newton/registration/tests/test_registration.py index d765eeb2..40c729d7 100644 --- a/newton/newton/registration/tests/test_registration.py +++ b/newton/newton/registration/tests/test_registration.py @@ -103,11 +103,7 @@ MOCK_GET_HYPERVISOR_RESPONSE = { "hypervisor_hostname": "testing", "state": "ACTIVE", "id": 1, "local_gb": 256, "memory_mb": 1024, "hypervisor_links": "link", "host_ip": "127.0.0.1", - "cpu_info": { - "topology": { - "cores": 8, "threads": 16, "sockets": 4 - } - } + "cpu_info": u'{"topology": {"cores": 8, "threads": 16, "sockets": 4}}' }, { "hypervisor_hostname": "testing2", "state": "XXX", diff --git a/newton/newton/registration/views/registration.py b/newton/newton/registration/views/registration.py index 883f0d68..0a9f7f8e 100644 --- a/newton/newton/registration/views/registration.py +++ b/newton/newton/registration/views/registration.py @@ -55,13 +55,20 @@ class Registry(APIView): def _update_resoure(self, cloud_owner, cloud_region_id, resoure_id, resource_info, resource_type): if cloud_owner and cloud_region_id: - #get the resource first + self._logger.debug( + ("_update_resoure,vimid:%(cloud_owner)s" + "_%(cloud_region_id)s req_to_aai: %(resoure_id)s, " + "%(resource_type)s, %(resource_info)s") + % { + "cloud_owner": cloud_owner, + "cloud_region_id": cloud_region_id, + "resoure_id": resoure_id, + "resource_type": resource_type, + "resource_info": resource_info, + }) - #add resource - #then update the resource - retcode, content, status_code = \ - restcall.req_to_aai( - ("/cloud-infrastructure/cloud-regions/" + #get the resource first + resource_url = ("/cloud-infrastructure/cloud-regions/" "cloud-region/%(cloud_owner)s/%(cloud_region_id)s/" "%(resource_type)ss/%(resource_type)s/%(resoure_id)s" % { @@ -70,10 +77,24 @@ class Registry(APIView): "resoure_id": resoure_id, "resource_type": resource_type, }) - , "PUT", content=resource_info) + + # get cloud-region + retcode, content, status_code = \ + restcall.req_to_aai(resource_url, "GET") + + # add resource-version + if retcode == 0 and content: + content = json.JSONDecoder().decode(content) + #resource_info["resource-version"] = content["resource-version"] + content.update(resource_info) + resource_info = content + + #then update the resource + retcode, content, status_code = \ + restcall.req_to_aai(resource_url, "PUT", content=resource_info) self._logger.debug( - ("update_tenant,vimid:%(cloud_owner)s" + ("_update_resoure,vimid:%(cloud_owner)s" "_%(cloud_region_id)s req_to_aai: %(resoure_id)s, " "return %(retcode)s, %(content)s, %(status_code)s") % { @@ -88,42 +109,66 @@ class Registry(APIView): return 1 # unknown cloud owner,region_id def _discover_tenants(self, vimid="", session=None, viminfo=None): - # iterate all projects and populate them into AAI - cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) - for tenant in self._get_list_resources( - "projects", "identity", session, viminfo, vimid, - "projects"): - tenant_info = { - 'tenant-id': tenant['id'], - 'tenant-name': tenant['name'], - } - self._update_resoure( - cloud_owner, cloud_region_id, tenant['id'], - tenant_info, "tenant") + try: + # iterate all projects and populate them into AAI + cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) + for tenant in self._get_list_resources( + "projects", "identity", session, viminfo, vimid, + "projects"): + tenant_info = { + 'tenant-id': tenant['id'], + 'tenant-name': tenant['name'], + } + self._update_resoure( + cloud_owner, cloud_region_id, tenant['id'], + tenant_info, "tenant") + + except VimDriverNewtonException as e: + self._logger.error("VimDriverNewtonException: status:%s, response:%s" % (e.http_status, e.content)) + return + except HttpError as e: + self._logger.error("HttpError: status:%s, response:%s" % (e.http_status, e.response.json())) + return + except Exception as e: + self._logger.error(traceback.format_exc()) + return def _discover_flavors(self, vimid="", session=None, viminfo=None): - cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) - for flavor in self._get_list_resources( - "/flavors/detail", "compute", session, viminfo, vimid, - "flavors"): - flavor_info = { - 'flavor-id': flavor['id'], - 'flavor-name': flavor['name'], - 'flavor-vcpus': flavor['vcpus'], - 'flavor-ram': flavor['ram'], - 'flavor-disk': flavor['disk'], - 'flavor-ephemeral': flavor['OS-FLV-EXT-DATA:ephemeral'], - 'flavor-swap': flavor['swap'], - 'flavor-is-public': flavor['os-flavor-access:is_public'], - 'flavor-disabled': flavor['OS-FLV-DISABLED:disabled'], - } - - if flavor.get('link') and len(flavor['link']) > 0: - flavor_info['flavor-selflink'] = flavor['link'][0]['href'], - - self._update_resoure( - cloud_owner, cloud_region_id, flavor['id'], - flavor_info, "flavor") + try: + cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) + for flavor in self._get_list_resources( + "/flavors/detail", "compute", session, viminfo, vimid, + "flavors"): + flavor_info = { + 'flavor-id': flavor['id'], + 'flavor-name': flavor['name'], + 'flavor-vcpus': flavor['vcpus'], + 'flavor-ram': flavor['ram'], + 'flavor-disk': flavor['disk'], + 'flavor-ephemeral': flavor['OS-FLV-EXT-DATA:ephemeral'], + 'flavor-swap': flavor['swap'], + 'flavor-is-public': flavor['os-flavor-access:is_public'], + 'flavor-disabled': flavor['OS-FLV-DISABLED:disabled'], + } + + if flavor.get('link') and len(flavor['link']) > 0: + flavor_info['flavor-selflink'] = flavor['link'][0]['href'] or 'http://0.0.0.0', + else: + flavor_info['flavor-selflink'] = 'http://0.0.0.0', + + self._update_resoure( + cloud_owner, cloud_region_id, flavor['id'], + flavor_info, "flavor") + + except VimDriverNewtonException as e: + self._logger.error("VimDriverNewtonException: status:%s, response:%s" % (e.http_status, e.content)) + return + except HttpError as e: + self._logger.error("HttpError: status:%s, response:%s" % (e.http_status, e.response.json())) + return + except Exception as e: + self._logger.error(traceback.format_exc()) + return # def update_image_metadata(self, cloud_owner, cloud_region_id, image_id, metadatainfo): # ''' @@ -152,85 +197,106 @@ class Registry(APIView): # return 1 def _discover_images(self, vimid="", session=None, viminfo=None): - - cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) - for image in self._get_list_resources( - "/v2/images", "image", session, viminfo, vimid, - "images"): - image_info = { - 'image-id': image['id'], - 'image-name': image['name'], - 'image-selflink': image['self'], - - 'image-os-distro': image.get('os_distro'), - 'image-os-version': image.get('os_version'), - 'application': image.get('application'), - 'application-vendor': image.get('application_vendor'), - 'application-version': image.get('application_version'), - 'image-architecture': image.get('architecture'), - } - - ret = self._update_resoure( - cloud_owner, cloud_region_id, image['id'], image_info, - "image") - if ret != 0: - # failed to update image - self._logger.debug("failed to populate image info into AAI: %s, image id: %s, ret:%s" - % (vimid, image_info['image-id'], ret)) - continue - - schema = image['schema'] - if schema: - req_resource = schema - service = {'service_type': "image", - 'interface': 'public', - 'region_id': viminfo['cloud_region_id']} - resp = session.get(req_resource, endpoint_filter=service) - content = resp.json() - - self._logger.debug("vimid: %s, req: %s,resp code: %s, body: %s" - % (vimid, req_resource, resp.status_code, content)) - # if resp.status_code == status.HTTP_200_OK: - # parse the schema? TBD - # self.update_image(cloud_owner, cloud_region_id, image_info) - #metadata_info = {} - - def _discover_availability_zones(self, vimid="", session=None, - viminfo=None): - cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) - for az in self._get_list_resources( - "/os-availability-zone/detail", "compute", session, - viminfo, vimid, - "availabilityZoneInfo"): - az_info = { - 'availability-zone-name': az['zoneName'], - 'operational-status': az['zoneState']['available'] - if az.get('zoneState') else '', - 'hypervisor-type': '', - } - if az.get('hosts'): - for (k, v) in az['hosts'].items(): - req_resource = "/os-hypervisors/detail?hypervisor_hostname_pattern=%s" % k - service = {'service_type': "compute", + try: + cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) + for image in self._get_list_resources( + "/v2/images", "image", session, viminfo, vimid, + "images"): + image_info = { + 'image-id': image['id'], + 'image-name': image['name'], + 'image-selflink': image['self'], + + 'image-os-distro': image.get('os_distro') or 'Unknown', + 'image-os-version': image.get('os_version') or 'Unknown', + 'application': image.get('application'), + 'application-vendor': image.get('application_vendor'), + 'application-version': image.get('application_version'), + 'image-architecture': image.get('architecture'), + } + + ret = self._update_resoure( + cloud_owner, cloud_region_id, image['id'], image_info, + "image") + if ret != 0: + # failed to update image + self._logger.debug("failed to populate image info into AAI: %s, image id: %s, ret:%s" + % (vimid, image_info['image-id'], ret)) + continue + + schema = image['schema'] + if schema: + req_resource = schema + service = {'service_type': "image", 'interface': 'public', 'region_id': viminfo['cloud_region_id']} resp = session.get(req_resource, endpoint_filter=service) content = resp.json() + self._logger.debug("vimid: %s, req: %s,resp code: %s, body: %s" % (vimid, req_resource, resp.status_code, content)) - if resp.status_code != status.HTTP_200_OK and not content[0]: - continue - az_info['hypervisor-type'] = content['hypervisors'][0]['hypervisor_type']\ - if len(content.get('hypervisors')) else '' - - break - ret = self._update_resoure( - cloud_owner, cloud_region_id, az['zoneName'], az_info, - "availability-zone") - if ret != 0: - # failed to update image - self._logger.debug("failed to populate az info into AAI: %s, az name: %s, ret:%s" - % (vimid, az_info['availability-zone-name'], ret)) + # if resp.status_code == status.HTTP_200_OK: + # parse the schema? TBD + # self.update_image(cloud_owner, cloud_region_id, image_info) + #metadata_info = {} + + except VimDriverNewtonException as e: + self._logger.error("VimDriverNewtonException: status:%s, response:%s" % (e.http_status, e.content)) + return + except HttpError as e: + self._logger.error("HttpError: status:%s, response:%s" % (e.http_status, e.response.json())) + return + except Exception as e: + self._logger.error(traceback.format_exc()) + return + + def _discover_availability_zones(self, vimid="", session=None, + viminfo=None): + try: + cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) + for az in self._get_list_resources( + "/os-availability-zone/detail", "compute", session, + viminfo, vimid, + "availabilityZoneInfo"): + az_info = { + 'availability-zone-name': az['zoneName'], + 'operational-status': az['zoneState']['available'] + if az.get('zoneState') else '', + 'hypervisor-type': '', + } + if az.get('hosts'): + for (k, v) in az['hosts'].items(): + req_resource = "/os-hypervisors/detail?hypervisor_hostname_pattern=%s" % k + service = {'service_type': "compute", + 'interface': 'public', + 'region_id': viminfo['cloud_region_id']} + resp = session.get(req_resource, endpoint_filter=service) + content = resp.json() + self._logger.debug("vimid: %s, req: %s,resp code: %s, body: %s" + % (vimid, req_resource, resp.status_code, content)) + if resp.status_code != status.HTTP_200_OK and not content[0]: + continue + az_info['hypervisor-type'] = content['hypervisors'][0]['hypervisor_type']\ + if len(content.get('hypervisors')) else '' + + break + ret = self._update_resoure( + cloud_owner, cloud_region_id, az['zoneName'], az_info, + "availability-zone") + if ret != 0: + # failed to update image + self._logger.debug("failed to populate az info into AAI: %s, az name: %s, ret:%s" + % (vimid, az_info['availability-zone-name'], ret)) + + except VimDriverNewtonException as e: + self._logger.error("VimDriverNewtonException: status:%s, response:%s" % (e.http_status, e.content)) + return + except HttpError as e: + self._logger.error("HttpError: status:%s, response:%s" % (e.http_status, e.response.json())) + return + except Exception as e: + self._logger.error(traceback.format_exc()) + return # def _discover_volumegroups(self, vimid="", session=None, viminfo=None): # cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) @@ -253,32 +319,43 @@ class Registry(APIView): # % (vimid, vg_info['volume-group-id'], ret)) def _discover_snapshots(self, vimid="", session=None, viminfo=None): - cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) - for ss in self._get_list_resources( - "/snapshots/detail", "volumev3", session, - viminfo, vimid, - "snapshots"): - snapshot_info = { - 'snapshot-id': ss['id'], - 'snapshot-name': ss['name'], - } - if ss.get('metadata'): - snapshot_info['snapshot-architecture'] = ss['metadata'].get('architecture') - snapshot_info['application'] = ss['metadata'].get('architecture') - snapshot_info['snapshot-os-distro'] = ss['metadata'].get('os-distro') - snapshot_info['snapshot-os-version'] = ss['metadata'].get('os-version') - snapshot_info['application-vendor'] = ss['metadata'].get('vendor') - snapshot_info['application-version'] = ss['metadata'].get('version') - snapshot_info['snapshot-selflink'] = ss['metadata'].get('selflink') - snapshot_info['prev-snapshot-id'] = ss['metadata'].get('prev-snapshot-id') - - ret = self._update_resoure( - cloud_owner, cloud_region_id, ss['id'], snapshot_info, - "snapshot") - if ret != 0: - # failed to update image - self._logger.debug("failed to populate snapshot info into AAI: %s, snapshot-id: %s, ret:%s" - % (vimid, snapshot_info['snapshot-id'], ret)) + try: + cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) + for ss in self._get_list_resources( + "/snapshots/detail", "volumev3", session, + viminfo, vimid, + "snapshots"): + snapshot_info = { + 'snapshot-id': ss['id'], + 'snapshot-name': ss['name'], + } + if ss.get('metadata'): + snapshot_info['snapshot-architecture'] = ss['metadata'].get('architecture') + snapshot_info['application'] = ss['metadata'].get('architecture') + snapshot_info['snapshot-os-distro'] = ss['metadata'].get('os-distro') + snapshot_info['snapshot-os-version'] = ss['metadata'].get('os-version') + snapshot_info['application-vendor'] = ss['metadata'].get('vendor') + snapshot_info['application-version'] = ss['metadata'].get('version') + snapshot_info['snapshot-selflink'] = ss['metadata'].get('selflink') + snapshot_info['prev-snapshot-id'] = ss['metadata'].get('prev-snapshot-id') + + ret = self._update_resoure( + cloud_owner, cloud_region_id, ss['id'], snapshot_info, + "snapshot") + if ret != 0: + # failed to update image + self._logger.debug("failed to populate snapshot info into AAI: %s, snapshot-id: %s, ret:%s" + % (vimid, snapshot_info['snapshot-id'], ret)) + + except VimDriverNewtonException as e: + self._logger.error("VimDriverNewtonException: status:%s, response:%s" % (e.http_status, e.content)) + return + except HttpError as e: + self._logger.error("HttpError: status:%s, response:%s" % (e.http_status, e.response.json())) + return + except Exception as e: + self._logger.error(traceback.format_exc()) + return # def _discover_servergroups(self, vimid="", session=None, viminfo=None): # for sg in self._get_list_resources( @@ -324,9 +401,23 @@ class Registry(APIView): ''' if cloud_owner and cloud_region_id: + resource_url = "/cloud-infrastructure/pservers/pserver/%s" \ + % (pserverinfo['hostname']) + + # get cloud-region + retcode, content, status_code = \ + restcall.req_to_aai(resource_url, "GET") + + # add resource-version to url + if retcode == 0 and content: + content = json.JSONDecoder().decode(content) + #pserverinfo["resource-version"] = content["resource-version"] + content.update(pserverinfo) + pserverinfo = content + + retcode, content, status_code = \ - restcall.req_to_aai("/cloud-infrastructure/pservers/pserver/%s" - % (pserverinfo['hostname']), "PUT", content=pserverinfo) + restcall.req_to_aai(resource_url, "PUT", content=pserverinfo) self._logger.debug("update_snapshot,vimid:%s_%s req_to_aai: %s, return %s, %s, %s" % (cloud_owner,cloud_region_id, pserverinfo['hostname'], retcode, content, status_code)) @@ -375,34 +466,51 @@ class Registry(APIView): return 1 # unknown cloud owner,region_id def _discover_pservers(self, vimid="", session=None, viminfo=None): - cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) - for hypervisor in self._get_list_resources( - "/os-hypervisors/detail", "compute", session, - viminfo, vimid, - "hypervisors"): - hypervisor_info = { - 'hostname': hypervisor['hypervisor_hostname'], - 'in-maint': hypervisor['state'], - - 'pserver-id': hypervisor.get('id'), - 'ptnii-equip-name': hypervisor.get('id'), - 'disk-in-gigabytes': hypervisor.get('local_gb'), - 'ram-in-megabytes': hypervisor.get('memory_mb'), - 'pserver-selflink': hypervisor.get('hypervisor_links'), - 'ipv4-oam-address': hypervisor.get('host_ip'), - } - - if hypervisor.get('cpu_info') and hypervisor.get('cpu_info').get('topology'): - cputopo = hypervisor.get('cpu_info').get('topology') - n_cpus = cputopo['cores'] * cputopo['threads'] * cputopo['sockets'] - hypervisor_info['number-of-cpus'] = n_cpus - - ret = self._update_pserver(cloud_owner, cloud_region_id, - hypervisor_info) - if ret != 0: - # failed to update image - self._logger.debug("failed to populate pserver info into AAI: %s, hostname: %s, ret:%s" - % (vimid, hypervisor_info['hostname'], ret)) + try: + cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) + for hypervisor in self._get_list_resources( + "/os-hypervisors/detail", "compute", session, + viminfo, vimid, + "hypervisors"): + hypervisor_info = { + 'hostname': hypervisor['hypervisor_hostname'], + 'in-maint': hypervisor['state'], + + 'pserver-id': hypervisor.get('id'), + 'ptnii-equip-name': hypervisor.get('id'), + 'disk-in-gigabytes': hypervisor.get('local_gb'), + 'ram-in-megabytes': hypervisor.get('memory_mb'), + 'pserver-selflink': hypervisor.get('hypervisor_links'), + 'ipv4-oam-address': hypervisor.get('host_ip'), + } + + # if hypervisor.get('cpu_info') and hypervisor['cpu_info'].get('topology'): + # cputopo = hypervisor['cpu_info'].get('topology') + # n_cpus = cputopo['cores'] * cputopo['threads'] * cputopo['sockets'] + # hypervisor_info['number-of-cpus'] = n_cpus + if hypervisor.get('cpu_info'): + cpu_info = json.loads(hypervisor['cpu_info']) + if cpu_info.get('topology'): + cputopo = cpu_info.get('topology') + n_cpus = cputopo['cores'] * cputopo['threads'] * cputopo['sockets'] + hypervisor_info['number-of-cpus'] = n_cpus + + ret = self._update_pserver(cloud_owner, cloud_region_id, + hypervisor_info) + if ret != 0: + # failed to update image + self._logger.debug("failed to populate pserver info into AAI: %s, hostname: %s, ret:%s" + % (vimid, hypervisor_info['hostname'], ret)) + + except VimDriverNewtonException as e: + self._logger.error("VimDriverNewtonException: status:%s, response:%s" % (e.http_status, e.content)) + return + except HttpError as e: + self._logger.error("HttpError: status:%s, response:%s" % (e.http_status, e.response.json())) + return + except Exception as e: + self._logger.error(traceback.format_exc()) + return def _update_epa_caps(self, cloud_owner, cloud_region_id, epa_caps_info): ''' @@ -419,9 +527,23 @@ class Registry(APIView): } if cloud_owner and cloud_region_id: + resource_url = "/cloud-infrastructure/cloud-regions/cloud-region/%s/%s" \ + % (cloud_owner, cloud_region_id) + + # get cloud-region retcode, content, status_code = \ - restcall.req_to_aai("/cloud-infrastructure/cloud-regions/cloud-region/%s/%s/" - % (cloud_owner, cloud_region_id, ), "PUT", content=cloud_epa_caps) + restcall.req_to_aai(resource_url, "GET") + + #add resource-version to url + if retcode == 0 and content: + content = json.JSONDecoder().decode(content) + #cloud_epa_caps["resource-version"] = content["resource-version"] + content.update(cloud_epa_caps) + cloud_epa_caps = content + + #update cloud-region + retcode, content, status_code = \ + restcall.req_to_aai(resource_url, "PUT", content=cloud_epa_caps) self._logger.debug( "update_epa_caps,vimid:%s_%s req_to_aai: update cloud-epa-caps, return %s, %s, %s" @@ -431,20 +553,32 @@ class Registry(APIView): return 1 # unknown cloud owner,region_id def _discover_epa_resources(self, vimid="", viminfo=None): - cloud_epa_caps_info = {} - cloud_extra_info = viminfo.get('cloud_extra_info') - if cloud_extra_info: - cloud_epa_caps_info.update(json.loads(cloud_extra_info)) - - cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) - ret = self._update_epa_caps(cloud_owner, cloud_region_id, - cloud_epa_caps_info) - if ret != 0: - # failed to update image - self._logger.debug("failed to populate EPA CAPs info into AAI: %s, ret:%s" - % (vimid, ret)) - - def _update_proxy_identity_endpoint(self, viminfo): + try: + cloud_epa_caps_info = {} + cloud_extra_info_str = viminfo.get('cloud_extra_info') + if cloud_extra_info_str: + cloud_extra_info = json.loads(cloud_extra_info_str) + cloud_epa_caps_info.update(cloud_extra_info.get("epa-caps")) + + cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) + ret = self._update_epa_caps(cloud_owner, cloud_region_id, + cloud_epa_caps_info) + if ret != 0: + # failed to update image + self._logger.debug("failed to populate EPA CAPs info into AAI: %s, ret:%s" + % (vimid, ret)) + + except VimDriverNewtonException as e: + self._logger.error("VimDriverNewtonException: status:%s, response:%s" % (e.http_status, e.content)) + return + except HttpError as e: + self._logger.error("HttpError: status:%s, response:%s" % (e.http_status, e.response.json())) + return + except Exception as e: + self._logger.error(traceback.format_exc()) + return + + def _update_proxy_identity_endpoint(self, vimid): ''' update cloud_region's identity url :param cloud_owner: @@ -452,17 +586,41 @@ class Registry(APIView): :param url: :return: ''' + try: + cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) + if cloud_owner and cloud_region_id: + resource_url = "/cloud-infrastructure/cloud-regions/cloud-region/%s/%s" \ + % (cloud_owner, cloud_region_id) - vimid = viminfo['vimId'] - cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) - if cloud_owner and cloud_region_id: - viminfo['identity-url'] = self.proxy_prefix + "/%s/identity/v3" % vimid - retcode, content, status_code = \ - restcall.req_to_aai("/cloud-infrastructure/cloud-regions/cloud-region/%s/%s" - % (cloud_owner, cloud_region_id), "PUT", content=viminfo) + # get cloud-region + retcode, content, status_code = \ + restcall.req_to_aai(resource_url, "GET") + + # add resource-version to url + if retcode == 0 and content: + viminfo = json.JSONDecoder().decode(content) + # cloud_epa_caps["resource-version"] = content["resource-version"] + viminfo['identity-url'] = self.proxy_prefix + "/%s/identity/v3" % vimid - self._logger.debug("update_proxy_identity_endpoint,vimid:%s req_to_aai: %s, return %s, %s, %s" - % (vimid, viminfo['identity-url'], retcode, content, status_code)) + retcode, content, status_code = \ + restcall.req_to_aai("/cloud-infrastructure/cloud-regions/cloud-region/%s/%s" + % (cloud_owner, cloud_region_id), "PUT", content=viminfo) + + self._logger.debug("update_proxy_identity_endpoint,vimid:%s req_to_aai: %s, return %s, %s, %s" + % (vimid, viminfo['identity-url'], retcode, content, status_code)) + else: + self._logger.debug("failure: update_proxy_identity_endpoint,vimid:%s req_to_aai: return %s, %s, %s" + % (vimid, retcode, content, status_code)) + + except VimDriverNewtonException as e: + self._logger.error("VimDriverNewtonException: status:%s, response:%s" % (e.http_status, e.content)) + return + except HttpError as e: + self._logger.error("HttpError: status:%s, response:%s" % (e.http_status, e.response.json())) + return + except Exception as e: + self._logger.error(traceback.format_exc()) + return def post(self, request, vimid=""): self._logger.debug("Registration--post::data> %s" % request.data) @@ -470,17 +628,15 @@ class Registry(APIView): try: # populate proxy identity url + self._update_proxy_identity_endpoint(vimid) + + # prepare request resource to vim instance + # get token: viminfo = VimDriverUtils.get_vim_info(vimid) if not viminfo: raise VimDriverNewtonException( "There is no cloud-region with {cloud-owner}_{cloud-region-id}=%s in AAI" % vimid) - #cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) - self._update_proxy_identity_endpoint(viminfo) - - # prepare request resource to vim instance - # get token: - viminfo = VimDriverUtils.get_vim_info(vimid) # set the default tenant since there is no tenant info in the VIM yet sess = VimDriverUtils.get_session( viminfo, tenantname=viminfo['tenant']) diff --git a/newton/tox.ini b/newton/tox.ini index ee15e4b0..71a8ff75 100644 --- a/newton/tox.ini +++ b/newton/tox.ini @@ -7,6 +7,6 @@ downloadcache = ~/cache/pip [testenv] deps = -r{toxinidir}/requirements.txt -commands = coverage run --branch manage.py test newton - coverage html --omit=".tox*,*test*,*__init__.py" -d htmlcov - +commands = + coverage run --branch manage.py test + coverage report --omit=".tox/*,*tests*,*__init__.py" --fail-under=30 diff --git a/ocata/ocata/registration/tests/test_registration.py b/ocata/ocata/registration/tests/test_registration.py index 4f68bf46..e3fe352e 100644 --- a/ocata/ocata/registration/tests/test_registration.py +++ b/ocata/ocata/registration/tests/test_registration.py @@ -103,11 +103,7 @@ MOCK_GET_HYPERVISOR_RESPONSE = { "hypervisor_hostname": "testing", "state": "ACTIVE", "id": 1, "local_gb": 256, "memory_mb": 1024, "hypervisor_links": "link", "host_ip": "127.0.0.1", - "cpu_info": { - "topology": { - "cores": 8, "threads": 16, "sockets": 4 - } - } + "cpu_info": u'{"topology": {"cores": 8, "threads": 16, "sockets": 4}}' }, { "hypervisor_hostname": "testing2", "state": "XXX", diff --git a/ocata/tox.ini b/ocata/tox.ini index 05ef3c70..dcd7033e 100644 --- a/ocata/tox.ini +++ b/ocata/tox.ini @@ -9,6 +9,7 @@ downloadcache = ~/cache/pip setenv = PYTHONPATH = {toxinidir}/../newton deps = -r{toxinidir}/requirements.txt -commands = coverage run --branch manage.py test ocata - coverage html --omit=".tox*,*test*,*__init__.py" -d htmlcov +commands = + coverage run --branch manage.py test + coverage report --omit=".tox/*,*tests*,*__init__.py,*newton*" --fail-under=30 diff --git a/windriver/titanium_cloud/registration/tests/test_registration.py b/windriver/titanium_cloud/registration/tests/test_registration.py index 041d2ec0..4c20edee 100644 --- a/windriver/titanium_cloud/registration/tests/test_registration.py +++ b/windriver/titanium_cloud/registration/tests/test_registration.py @@ -103,11 +103,7 @@ MOCK_GET_HYPERVISOR_RESPONSE = { "hypervisor_hostname": "testing", "state": "ACTIVE", "id": 1, "local_gb": 256, "memory_mb": 1024, "hypervisor_links": "link", "host_ip": "127.0.0.1", - "cpu_info": { - "topology": { - "cores": 8, "threads": 16, "sockets": 4 - } - } + "cpu_info": u'{"topology": {"cores": 8, "threads": 16, "sockets": 4}}' }, { "hypervisor_hostname": "testing2", "state": "XXX", diff --git a/windriver/tox.ini b/windriver/tox.ini index 764cf01c..90357d66 100644 --- a/windriver/tox.ini +++ b/windriver/tox.ini @@ -9,6 +9,6 @@ downloadcache = ~/cache/pip setenv = PYTHONPATH = {toxinidir}/../newton deps = -r{toxinidir}/requirements.txt -commands = coverage run --branch manage.py test titanium_cloud - coverage html --omit=".tox*,*test*,*__init__.py" -d htmlcov - +commands = + coverage run --branch manage.py test titanium_cloud + coverage report --omit=".tox/*,*tests*,*__init__.py,*newton*" --fail-under=30 |