summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHaibin Huang <haibin.huang@intel.com>2020-02-24 17:01:11 +0800
committerHaibin Huang <haibin.huang@intel.com>2020-02-26 15:24:32 +0800
commit64fb0384e373bf68b558179c6b74bdc0974f21fb (patch)
tree10d14e9e7fd4f3327f6354f7df108bf44e1f0028
parent1ad876471ad26419b3f92972ffabc42060a66733 (diff)
Call hpa driver
Issue-ID: MULTICLOUD-694 Signed-off-by: Haibin Huang <haibin.huang@intel.com> Change-Id: Ifb585a5446e3337522cbd0f947076d9f8a9d4451
-rw-r--r--pike/pike/registration/views/registration.py2
-rw-r--r--pike/requirements.txt1
-rw-r--r--share/newton_base/registration/registration_driver.py1141
3 files changed, 1143 insertions, 1 deletions
diff --git a/pike/pike/registration/views/registration.py b/pike/pike/registration/views/registration.py
index fc6a6799..b21d2d4f 100644
--- a/pike/pike/registration/views/registration.py
+++ b/pike/pike/registration/views/registration.py
@@ -19,7 +19,7 @@ import logging
from django.conf import settings
-from newton_base.registration import registration as newton_registration
+from newton_base.registration import registration_driver as newton_registration
from common.msapi import extsys
LOGGER = logging.getLogger(__name__)
diff --git a/pike/requirements.txt b/pike/requirements.txt
index 6fbbf07a..ddbbd956 100644
--- a/pike/requirements.txt
+++ b/pike/requirements.txt
@@ -35,3 +35,4 @@ python-memcached
# for onap logging
onappylog>=1.0.9
+onaphpadriver>=1.0
diff --git a/share/newton_base/registration/registration_driver.py b/share/newton_base/registration/registration_driver.py
new file mode 100644
index 00000000..26954273
--- /dev/null
+++ b/share/newton_base/registration/registration_driver.py
@@ -0,0 +1,1141 @@
+# Copyright (c) 2020 Intel 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 uuid
+import traceback
+
+from keystoneauth1.exceptions import HttpError
+from rest_framework import status
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+from common.exceptions import VimDriverNewtonException
+from common.msapi import extsys
+from common.msapi.helper import MultiCloudThreadHelper
+from common.msapi.helper import MultiCloudAAIHelper
+from common.utils import restcall
+from newton_base.util import VimDriverUtils
+from django.conf import settings
+from hpa import hpa_discovery
+
+logger = logging.getLogger(__name__)
+
+
+class Registry(APIView):
+
+ def __init__(self):
+ # logger.debug("Registry __init__: %s" % traceback.format_exc())
+ if not hasattr(self, "_logger"):
+ self._logger = logger
+
+ if not hasattr(self, "register_thread"):
+ # dedicate thread to offload vim registration process
+ self.register_thread = MultiCloudThreadHelper("vimupdater")
+
+ if not hasattr(self, "register_helper") or not self.register_helper:
+ if not hasattr(self, "proxy_prefix"):
+ self.proxy_prefix = "multicloud"
+ if not hasattr(self, "AAI_BASE_URL"):
+ self.AAI_BASE_URL = "127.0.0.1"
+ self.register_helper = RegistryHelper(
+ self.proxy_prefix or "multicloud",
+ self.AAI_BASE_URL or "127.0.0.1")
+
+ def post(self, request, vimid=""):
+ self._logger.info("registration with vimid: %s" % vimid)
+ self._logger.debug("with data: %s" % request.data)
+
+ try:
+ # Get the specified tenant id
+ specified_project_idorname = request.META.get("Project", None)
+
+ # compose the one time backlog item
+ backlog_item = {
+ "id": vimid,
+ "worker": self.register_helper.registryV0,
+ "payload": (vimid, specified_project_idorname),
+ "repeat": 0,
+ "status": (1,
+ "The registration is on progress")
+ }
+ self.register_thread.add(backlog_item)
+ if 0 == self.register_thread.state():
+ self.register_thread.start()
+
+ return Response(status=status.HTTP_202_ACCEPTED)
+
+ 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):
+ try:
+ backlog_item = self.register_thread.get(vimid)
+ if backlog_item:
+ return Response(
+ data={'status': backlog_item.get(
+ "status", "Status not available, vimid: %s" % vimid)},
+ status=status.HTTP_200_OK)
+ else:
+ return Response(
+ data={
+ 'error': "Registration process for "
+ "Cloud Region not found: %s"
+ % vimid
+ },
+ status=status.HTTP_404_NOT_FOUND)
+ except Exception as e:
+ self._logger.error(traceback.format_exc())
+ return Response(
+ data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ def delete(self, request, vimid=""):
+ self._logger.debug("Registration--delete::data> %s" % request.data)
+ self._logger.debug("Registration--delete::vimid > %s"% vimid)
+ try:
+
+ # compose the one time backlog item
+ backlog_item = {
+ "id": vimid,
+ "worker": self.register_helper.unregistryV0,
+ "payload": (vimid,), # important to add , at the end
+ "repeat": 0,
+ "status": (1, "The de-registration is in progress")
+ }
+ self.register_thread.add(backlog_item)
+ if 0 == self.register_thread.state():
+ self.register_thread.start()
+
+ return Response(
+ status=status.HTTP_204_NO_CONTENT
+ )
+ 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)
+
+
+
+class RegistryHelper(MultiCloudAAIHelper):
+ '''
+ Helper code to discover and register a cloud region's resource
+ '''
+
+ def __init__(self, multicloud_prefix, aai_base_url):
+ # logger.debug("RegistryHelper __init__: %s" % traceback.format_exc())
+ self.proxy_prefix = multicloud_prefix
+ self.aai_base_url = aai_base_url
+ self._logger = logger
+ super(RegistryHelper, self).__init__(multicloud_prefix, aai_base_url)
+
+ def registryV1(self, cloud_owner, cloud_region_id):
+ # cloud_owner = payload.get("cloud-owner", None)
+ # cloud_region_id = payload.get("cloud-region-id", None)
+ vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id)
+ return self.registryV0(vimid)
+
+ def registryV0(self, vimid, project_idorname=None):
+ # populate proxy identity url
+ self._update_proxy_identity_endpoint(vimid)
+
+ # prepare request resource to vim instance
+ # get token:
+ viminfo = VimDriverUtils.get_vim_info(vimid)
+ sess = None
+ if not viminfo:
+ return (
+ 10,
+ "Cloud Region not found in AAI: %s" % vimid
+ )
+ if project_idorname:
+ try:
+ # check if specified with tenant id
+ sess = VimDriverUtils.get_session(
+ viminfo, tenant_name=None,
+ tenant_id=project_idorname
+ )
+ except Exception as e:
+ pass
+
+ if not sess:
+ try:
+ # check if specified with tenant name
+ sess = VimDriverUtils.get_session(
+ viminfo, tenant_name=project_idorname,
+ tenant_id=None
+ )
+ except Exception as e:
+ pass
+
+ if not sess:
+ # set the default tenant since there is no tenant info in the VIM yet
+ sess = VimDriverUtils.get_session(
+ viminfo, tenant_name=viminfo.get('tenant', None))
+
+ # step 1. discover all projects and populate into AAI
+ retcode, status = self._discover_tenants(vimid, sess, viminfo)
+ # if 0 != retcode:
+ # return (
+ # retcode, status
+ # )
+
+ # discover all flavors
+ retcode, status = self._discover_flavors(vimid, sess, viminfo)
+ # if 0 != retcode:
+ # return (
+ # retcode, status
+ # )
+
+ # discover all images
+ retcode, status = self._discover_images(vimid, sess, viminfo)
+ # if 0 != retcode:
+ # return (
+ # retcode, status
+ # )
+
+ # discover all az
+ retcode, status = self._discover_availability_zones(vimid, sess, viminfo)
+ # if 0 != retcode:
+ # return (
+ # retcode, status
+ # )
+
+ # discover all vg
+ #self._discover_volumegroups(vimid, sess, viminfo)
+ # if 0 != retcode:
+ # return (
+ # retcode, status
+ # )
+
+ # discover all snapshots
+ #self._discover_snapshots(vimid, sess, viminfo)
+ # if 0 != retcode:
+ # return retcode, status
+
+ # discover all server groups
+ #self.discover_servergroups(request, vimid, sess, viminfo)
+ # if 0 != retcode:
+ # return retcode, status
+
+ # discover all pservers
+ #self._discover_pservers(vimid, sess, viminfo)
+ # if 0 != retcode:
+ # return retcode, status
+
+ return (
+ 0,
+ "Registration finished for Cloud Region: %s" % vimid
+ )
+
+ def unregistryV1(self, cloud_owner, cloud_region_id):
+ # cloud_owner = payload.get("cloud-owner", None)
+ # cloud_region_id = payload.get("cloud-region-id", None)
+ vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id)
+ return self.unregistryV0(vimid)
+
+ def unregistryV0(self, vimid):
+ # prepare request resource to vim instance
+ # get token:
+ viminfo = VimDriverUtils.get_vim_info(vimid)
+ if not viminfo:
+ return (
+ 10,
+ "Cloud Region not found:" % vimid
+ )
+
+ cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid)
+
+ # get the resource first
+ resource_url = ("/cloud-infrastructure/cloud-regions/"
+ "cloud-region/%(cloud_owner)s/%(cloud_region_id)s?depth=all"
+ % {
+ "cloud_owner": cloud_owner,
+ "cloud_region_id": cloud_region_id,
+ })
+
+ # get cloud-region
+ retcode, content, status_code = \
+ restcall.req_to_aai(resource_url, "GET", nocache=True)
+
+ # add resource-version
+ cloudregiondata = {}
+ if retcode == 0 and content:
+ cloudregiondata = json.JSONDecoder().decode(content)
+ else:
+ return (
+ 10,
+ "Cloud Region not found: %s, %s" % (cloud_owner, cloud_region_id)
+ )
+
+ # step 1. remove all tenants
+ tenants = cloudregiondata.get("tenants", None)
+ for tenant in tenants.get("tenant", []) if tenants else []:
+ # common prefix
+ aai_cloud_region = \
+ "/cloud-infrastructure/cloud-regions/cloud-region/%s/%s/tenants/tenant/%s" \
+ % (cloud_owner, cloud_region_id, tenant['tenant-id'])
+
+ # remove all vservers
+ try:
+ # get list of vservers
+ vservers = tenant.get('vservers', {}).get('vserver', [])
+ for vserver in vservers:
+ try:
+ # iterate vport, except will be raised if no l-interface exist
+ for vport in vserver['l-interfaces']['l-interface']:
+ # delete vport
+ vport_delete_url =\
+ aai_cloud_region + \
+ "/vservers/vserver/%s/l-interfaces/l-interface/%s?resource-version=%s" \
+ % (vserver['vserver-id'], vport['interface-name'],
+ vport['resource-version'])
+ restcall.req_to_aai(vport_delete_url, "DELETE")
+ except Exception as e:
+ pass
+
+ try:
+ # delete vserver
+ vserver_delete_url =\
+ aai_cloud_region +\
+ "/vservers/vserver/%s?resource-version=%s" \
+ % (vserver['vserver-id'],
+ vserver['resource-version'])
+ restcall.req_to_aai(vserver_delete_url, "DELETE")
+ except Exception as e:
+ continue
+
+ except Exception:
+ self._logger.error(traceback.format_exc())
+ pass
+
+ resource_url = ("/cloud-infrastructure/cloud-regions/"
+ "cloud-region/%(cloud_owner)s/%(cloud_region_id)s/"
+ "%(resource_type)ss/%(resource_type)s/%(resource_id)s/"
+ "?resource-version=%(resource-version)s"
+ % {
+ "cloud_owner": cloud_owner,
+ "cloud_region_id": cloud_region_id,
+ "resource_type": "tenant",
+ "resource_id": tenant["tenant-id"],
+ "resource-version": tenant["resource-version"]
+ })
+ # remove tenant
+ retcode, content, status_code = \
+ restcall.req_to_aai(resource_url, "DELETE")
+
+ # remove all flavors
+ flavors = cloudregiondata.get("flavors", None)
+ for flavor in flavors.get("flavor", []) if flavors else []:
+ # iterate hpa-capabilities
+ hpa_capabilities = flavor.get("hpa-capabilities", None)
+ for hpa_capability in hpa_capabilities.get("hpa-capability", [])\
+ if hpa_capabilities else []:
+ resource_url = ("/cloud-infrastructure/cloud-regions/"
+ "cloud-region/%(cloud_owner)s/%(cloud_region_id)s/"
+ "%(resource_type)ss/%(resource_type)s/%(resource_id)s/"
+ "hpa-capabilities/hpa-capability/%(hpa-capability-id)s/"
+ "?resource-version=%(resource-version)s"
+ % {
+ "cloud_owner": cloud_owner,
+ "cloud_region_id": cloud_region_id,
+ "resource_type": "flavor",
+ "resource_id": flavor["flavor-id"],
+ "hpa-capability-id": hpa_capability["hpa-capability-id"],
+ "resource-version": hpa_capability["resource-version"]
+ })
+ # remove hpa-capability
+ retcode, content, status_code = \
+ restcall.req_to_aai(resource_url, "DELETE")
+
+ # remove flavor
+ resource_url = ("/cloud-infrastructure/cloud-regions/"
+ "cloud-region/%(cloud_owner)s/%(cloud_region_id)s/"
+ "%(resource_type)ss/%(resource_type)s/%(resource_id)s/"
+ "?resource-version=%(resource-version)s"
+ % {
+ "cloud_owner": cloud_owner,
+ "cloud_region_id": cloud_region_id,
+ "resource_type": "flavor",
+ "resource_id": flavor["flavor-id"],
+ "resource-version": flavor["resource-version"]
+ })
+
+ retcode, content, status_code = \
+ restcall.req_to_aai(resource_url, "DELETE")
+
+ # remove all images
+ images = cloudregiondata.get("images", None)
+ for image in images.get("image", []) if images else []:
+ resource_url = ("/cloud-infrastructure/cloud-regions/"
+ "cloud-region/%(cloud_owner)s/%(cloud_region_id)s/"
+ "%(resource_type)ss/%(resource_type)s/%(resource_id)s/"
+ "?resource-version=%(resource-version)s"
+ % {
+ "cloud_owner": cloud_owner,
+ "cloud_region_id": cloud_region_id,
+ "resource_type": "image",
+ "resource_id": image["image-id"],
+ "resource-version": image["resource-version"]
+ })
+ # remove image
+ retcode, content, status_code = \
+ restcall.req_to_aai(resource_url, "DELETE")
+
+ # remove all az
+ azs = cloudregiondata.get("availability-zones", None)
+ for az in azs.get("availability-zone", []) if azs else []:
+ # delete az relationship first
+ resource_url = ("/cloud-infrastructure/cloud-regions/"
+ "cloud-region/%(cloud_owner)s/%(cloud_region_id)s/"
+ "%(resource_type)ss/%(resource_type)s/%(resource_id)s"
+ % {
+ "cloud_owner": cloud_owner,
+ "cloud_region_id": cloud_region_id,
+ "resource_type": "availability-zone",
+ "resource_id": az["availability-zone-name"]
+ })
+
+ rs = az.get("relationship-list", []).get("relationship", [])
+ for r in rs:
+ retcode, content, status_code = \
+ restcall.req_to_aai(
+ resource_url+"/relationship-list/relationship",
+ "DELETE", content=r)
+
+ # delete az
+ resource_url2 = (resource_url + "?resource-version=%(resource-version)s"
+ % {"resource-version": az["resource-version"]})
+ retcode, content, status_code = \
+ restcall.req_to_aai(resource_url2, "DELETE")
+
+
+ # remove all vg
+
+ # remove all snapshots
+ snapshots = cloudregiondata.get("snapshots", None)
+ for snapshot in snapshots.get("snapshot", []) if snapshots else []:
+ resource_url = ("/cloud-infrastructure/cloud-regions/"
+ "cloud-region/%(cloud_owner)s/%(cloud_region_id)s/"
+ "%(resource_type)ss/%(resource_type)s/%(resource_id)s/"
+ "?resource-version=%(resource-version)s"
+ % {
+ "cloud_owner": cloud_owner,
+ "cloud_region_id": cloud_region_id,
+ "resource_type": "snapshot",
+ "resource_id": snapshot["snapshot-id"],
+ "resource-version": snapshot["resource-version"]
+ })
+ # remove snapshot
+ retcode, content, status_code = \
+ restcall.req_to_aai(resource_url, "DELETE")
+
+ # remove all server groups
+
+ # remove all pservers
+
+ # remove cloud region itself
+ resource_url = ("/cloud-infrastructure/cloud-regions/"
+ "cloud-region/%(cloud_owner)s/%(cloud_region_id)s"
+ "?resource-version=%(resource-version)s"
+ % {
+ "cloud_owner": cloud_owner,
+ "cloud_region_id": cloud_region_id,
+ "resource-version": cloudregiondata["resource-version"]
+ })
+ # remove cloud region
+ retcode, content, status_code = \
+ restcall.req_to_aai(resource_url, "DELETE")
+
+ return retcode, content
+
+ def _discover_tenants(self, vimid="", session=None, viminfo=None):
+ 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")
+ return 0, "succeed"
+ except VimDriverNewtonException as e:
+ self._logger.error(
+ "VimDriverNewtonException: status:%s, response:%s"
+ % (e.http_status, e.content))
+ return (
+ e.http_status, e.content
+ )
+ except HttpError as e:
+ if e.http_status == status.HTTP_403_FORBIDDEN:
+ ### get the tenant information from the token response
+ try:
+ ### get tenant info from the session
+ tmp_auth_state = VimDriverUtils.get_auth_state(session)
+ tmp_auth_info = json.loads(tmp_auth_state)
+ tmp_auth_data = tmp_auth_info['body']
+ tenant = tmp_auth_data['token']['project']
+ tenant_info = {
+ 'tenant-id': tenant['id'],
+ 'tenant-name': tenant['name'],
+ }
+
+ self._update_resoure(
+ cloud_owner, cloud_region_id, tenant['id'],
+ tenant_info, "tenant")
+
+ return 0, "succeed"
+
+ except Exception as ex:
+ self._logger.error(traceback.format_exc())
+ return (
+ 11,
+ str(ex)
+ )
+ else:
+ self._logger.error(
+ "HttpError: status:%s, response:%s"
+ % (e.http_status, e.response.json()))
+ return (
+ e.http_status, e.response.json()
+ )
+ except Exception as e:
+ self._logger.error(traceback.format_exc())
+ return (
+ 11,
+ str(e)
+ )
+
+ def _discover_flavors(self, vimid="", session=None, viminfo=None):
+ 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('links') and len(flavor['links']) > 0:
+ flavor_info['flavor-selflink'] =\
+ flavor['links'][0]['href'] or 'http://0.0.0.0'
+ else:
+ flavor_info['flavor-selflink'] = 'http://0.0.0.0'
+
+ # add hpa capabilities
+ if (flavor['name'].find('onap.') == 0):
+ req_resouce = "/flavors/%s/os-extra_specs" % flavor['id']
+ extraResp = self._get_list_resources(
+ req_resouce, "compute", session,
+ viminfo, vimid, "extra_specs")
+
+ vimtype = viminfo['version']
+ hpa = hpa_discovery.HPADiscovery()
+ for extra_spec in extraResp:
+ data = {"flavor": flavor, "extra_specs": extraResp, "viminfo": viminfo, "vimtype": vimtype}
+ hpa_capability = hpa.get_hpa_capabilities(data)
+ hpa_capabilities.append(hpa_capability)
+
+ flavor_info['hpa-capabilities'] = \
+ {'hpa-capability': hpa_capabilities}
+ logger.debug("hpa_capabilities:%s" % hpa_capabilities)
+
+ retcode, content = self._update_resoure(
+ cloud_owner, cloud_region_id, flavor['id'],
+ flavor_info, "flavor")
+
+ return (0, "succeed")
+ except VimDriverNewtonException as e:
+ self._logger.error(
+ "VimDriverNewtonException: status:%s, response:%s" %
+ (e.http_status, e.content))
+ return (
+ e.http_status, e.content
+ )
+ except HttpError as e:
+ self._logger.error("HttpError: status:%s, response:%s" %
+ (e.http_status, e.response.json()))
+ return (
+ e.http_status, e.response.json()
+ )
+ except Exception as e:
+ self._logger.error(traceback.format_exc())
+ return (
+ 11, str(e)
+ )
+
+ def _discover_images(self, vimid="", session=None, viminfo=None):
+ 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_name': viminfo['openstack_region_id']
+ if viminfo.get('openstack_region_id')
+ else viminfo['cloud_region_id']
+ }
+
+ self._logger.info("making request with URI:%s" %
+ req_resource)
+ resp = session.get(req_resource, endpoint_filter=service)
+ self._logger.info("request returns with status %s" %
+ resp.status_code)
+ if resp.status_code == status.HTTP_200_OK:
+ self._logger.debug("with content:%s" %
+ resp.json())
+ pass
+ content = resp.json()
+
+ # if resp.status_code == status.HTTP_200_OK:
+ # parse the schema? TBD
+ # self.update_image(cloud_owner, cloud_region_id, image_info)
+ #metadata_info = {}
+ return (0, "succeed")
+ except VimDriverNewtonException as e:
+ self._logger.error("VimDriverNewtonException:"
+ " status:%s, response:%s" %
+ (e.http_status, e.content))
+ return (
+ e.http_status, e.content
+ )
+ except HttpError as e:
+ self._logger.error("HttpError: status:%s, response:%s" %
+ (e.http_status, e.response.json()))
+ return (
+ e.http_status, e.response.json()
+ )
+ except Exception as e:
+ self._logger.error(traceback.format_exc())
+ return (
+ 11, str(e)
+ )
+
+ def _discover_availability_zones(self, vimid="", session=None,
+ viminfo=None):
+ try:
+ az_pserver_info = {}
+ 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': '',
+ }
+ # filter out the default az: "internal" and "nova"
+ azName = az.get('zoneName', None)
+ # comment it for test the registration process only
+ # if azName == 'nova':
+ # continue
+ if azName == 'internal':
+ continue
+
+ # get list of host names
+ pservers_info = [k for (k, v) in list(az['hosts'].items())]
+ # set the association between az and pservers
+ az_pserver_info[azName] = pservers_info
+
+ az_info['hypervisor-type'] = 'QEMU' # default for OpenStack
+
+ ret, content = 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))
+ # return (
+ # ret,
+ # "fail to popluate az info into AAI:%s" % content
+ # )
+ continue
+
+ # populate pservers:
+ for hostname in pservers_info:
+ if hostname == "":
+ continue
+
+ pservername = vimid+"_"+hostname
+ selflink = ""
+ # if self.proxy_prefix[3:] == "/v1":
+ # selflink = "%s/%s/%s/compute/os-hypervisors/detail?hypervisor_hostname_pattern=%s"%\
+ # (self.proxy_prefix, cloud_owner, cloud_region_id , hostname)
+ # else:
+ # selflink = "%s/%s/compute/os-hypervisors/detail?hypervisor_hostname_pattern=%s" % \
+ # (self.proxy_prefix, vimid, hostname)
+
+ pinfo = {
+ "hostname": pservername,
+ "server-selflink": selflink,
+ "pserver-id": hostname
+ }
+ self._update_pserver(cloud_owner, cloud_region_id, pinfo)
+ self._update_pserver_relation_az(cloud_owner, cloud_region_id, pinfo, azName)
+ self._update_pserver_relation_cloudregion(cloud_owner, cloud_region_id, pinfo)
+
+ return (0, az_pserver_info)
+ except VimDriverNewtonException as e:
+ self._logger.error(
+ "VimDriverNewtonException: status:%s,"
+ " response:%s" % (e.http_status, e.content))
+ return (
+ e.http_status, e.content
+ )
+ except HttpError as e:
+ self._logger.error(
+ "HttpError: status:%s, response:%s" %
+ (e.http_status, e.response.json()))
+ return (
+ e.http_status, e.response.json()
+ )
+ except Exception as e:
+ self._logger.error(traceback.format_exc())
+ return (
+ 11, str(e)
+ )
+
+ # def _discover_volumegroups(self, vimid="", session=None, viminfo=None):
+ # cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid)
+ # for cg in self._get_list_resources(
+ # "/consistencygroups/detail", "volumev3", session,
+ # viminfo, vimid,
+ # "consistencygroups"):
+ # vg_info = {
+ # 'volume-group-id': cg['id'],
+ # 'volume-group-name': cg['name'],
+ # 'vnf-type': '',
+ # }
+ #
+ # ret = self._update_resoure(
+ # cloud_owner, cloud_region_id, cg['id'], vg_info,
+ # "volume-group")
+ # if ret != 0:
+ # # failed to update image
+ # self._logger.debug("failed to populate volumegroup info into AAI: %s, volume-group-id: %s, ret:%s"
+ # % (vimid, vg_info['volume-group-id'], ret))
+
+ def _discover_snapshots(self, vimid="", session=None, viminfo=None):
+ 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, content = 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))
+ return (
+ ret,
+ "fail to populate snapshot into AAI:%s" % content
+ )
+ return 0, "Succeed"
+ except VimDriverNewtonException as e:
+ self._logger.error("VimDriverNewtonException: status:%s, response:%s" % (e.http_status, e.content))
+ return (
+ e.http_status, e.content
+ )
+ except HttpError as e:
+ self._logger.error("HttpError: status:%s, response:%s" % (e.http_status, e.response.json()))
+ return (
+ e.http_status, e.response.json()
+ )
+ except Exception as e:
+ self._logger.error(traceback.format_exc())
+ return (
+ 11, str(e)
+ )
+
+ # def _discover_servergroups(self, vimid="", session=None, viminfo=None):
+ # for sg in self._get_list_resources(
+ # "/os-server-groups", "compute", session,
+ # viminfo, vimid,
+ # "security groups"):
+
+ def _update_pserver_relation_az(self, cloud_owner, cloud_region_id, pserverinfo, azName):
+ related_link = \
+ "/aai/%s/cloud-infrastructure/cloud-regions/"\
+ "cloud-region/%s/%s/"\
+ "availability-zones/availability-zone/%s" % (
+ settings.AAI_SCHEMA_VERSION, cloud_owner,
+ cloud_region_id, azName)
+
+ relationship_data = \
+ {
+ 'related-to': 'availability-zone',
+ 'related-link': related_link,
+ 'relationship-data': [
+ {
+ 'relationship-key': 'availability-zone.availability-zone-name',
+ 'relationship-value': azName
+ }
+ ],
+ "related-to-property": [
+ {
+ "property-key": "availability-zone.availability-zone-name"
+ }
+ ]
+ }
+
+ retcode, content, status_code = \
+ restcall.req_to_aai("/cloud-infrastructure/pservers/pserver/%s"
+ "/relationship-list/relationship"
+ % (pserverinfo['hostname']), "PUT",
+ content=relationship_data)
+
+ self._logger.debug("update_pserver_az_relation,vimid:%s_%s, "
+ "az:%s req_to_aai: %s, return %s, %s, %s"
+ % (cloud_owner, cloud_region_id, azName,
+ pserverinfo['hostname'], retcode, content,
+ status_code))
+ return (
+ 0,
+ "succeed"
+ )
+
+ def _update_pserver_relation_cloudregion(
+ self,
+ cloud_owner,
+ cloud_region_id,
+ pserverinfo
+ ):
+ related_link = \
+ "/aai/%s/cloud-infrastructure/cloud-regions/"\
+ "cloud-region/%s/%s" % (
+ settings.AAI_SCHEMA_VERSION, cloud_owner,
+ cloud_region_id)
+
+ relationship_data = \
+ {
+ 'related-to': 'cloud-region',
+ 'related-link': related_link,
+ 'relationship-data': [
+ {
+ 'relationship-key': 'cloud-region.cloud-owner',
+ 'relationship-value': cloud_owner
+ },
+ {
+ 'relationship-key': 'cloud-region.cloud-region-id',
+ 'relationship-value': cloud_region_id
+ }
+ ],
+ "related-to-property": [
+ {
+ "property-key": "cloud-region.cloud-owner"
+ },
+ {
+ "property-key": "cloud-region.cloud-region-id"
+ }
+ ]
+ }
+
+ retcode, content, status_code = \
+ restcall.req_to_aai("/cloud-infrastructure/pservers/pserver"
+ "/%s/relationship-list/relationship"
+ % (pserverinfo['hostname']), "PUT",
+ content=relationship_data)
+
+ self._logger.debug("update_pserver_cloudregion_relation,vimid:%s_%s"
+ " req_to_aai: %s, return %s, %s, %s"
+ % (cloud_owner, cloud_region_id,
+ pserverinfo['hostname'], retcode, content,
+ status_code))
+ return (
+ 0,
+ "succeed"
+ )
+
+ def _update_pserver(self, cloud_owner, cloud_region_id, pserverinfo):
+ '''
+ populate pserver into AAI
+ :param cloud_owner:
+ :param cloud_region_id:
+ :param pserverinfo:
+ hostname: string
+ in-maint: boolean
+
+ pserver-name2: string
+ pserver-id: string
+ ptnii-equip-name: string
+ number-of-cpus: integer
+ disk-in-gigabytes: integer
+ ram-in-megabytes: integer
+ equip-type: string
+ equip-vendor: string
+ equip-model: string
+ fqdn: string
+ pserver-selflink: string
+ ipv4-oam-address: string
+ serial-number: string
+ ipaddress-v4-loopback-0: string
+ ipaddress-v6-loopback-0: string
+ ipaddress-v4-aim: string
+ ipaddress-v6-aim: string
+ ipaddress-v6-oam: string
+ inv-status: string
+ internet-topology: string
+ purpose: string
+ prov-status: string
+ management-option: string
+ host-profile: string
+
+ :return:
+ '''
+
+ 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", nocache=True)
+
+ # 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(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))
+
+ return retcode, content
+ else:
+ # unknown cloud owner,region_id
+ return (
+ 10,
+ "Cloud Region not found: %s,%s"
+ % (cloud_owner, cloud_region_id)
+ )
+
+ def _discover_pservers(self, vimid="", session=None, viminfo=None):
+ 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'):
+ 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, content = 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))
+ return ret, "fail to update pserver to AAI:%s" % content
+
+ return 0, "succeed"
+ except VimDriverNewtonException as e:
+ self._logger.error(
+ "VimDriverNewtonException: status:%s, response:%s"
+ % (e.http_status, e.content))
+ return (
+ e.http_status, e.content
+ )
+ except HttpError as e:
+ self._logger.error(
+ "HttpError: status:%s, response:%s"
+ % (e.http_status, e.response.json()))
+ return (
+ e.http_status, e.response.json()
+ )
+ except Exception as e:
+ self._logger.error(traceback.format_exc())
+ return (
+ 11, str(e)
+ )
+
+ def _update_proxy_identity_endpoint(self, vimid):
+ '''
+ update cloud_region's identity url
+ :param cloud_owner:
+ :param cloud_region_id:
+ :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)
+
+ # get cloud-region
+ retcode, content, status_code = \
+ restcall.req_to_aai(resource_url, "GET", nocache=True)
+
+ # add resource-version to url
+ if retcode == 0 and content:
+ viminfo = json.JSONDecoder().decode(content)
+ viminfo['identity-url'] =\
+ self.proxy_prefix + "/%s/identity/v2.0" % vimid \
+ if self.proxy_prefix[-3:] == "/v0" \
+ else self.proxy_prefix +\
+ "/%s/%s/identity/v2.0"\
+ % extsys.decode_vim_id(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)
+
+ 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))
+ return 0, "succeed"
+ else:
+ self._logger.debug(
+ "failure: update_proxy_identity_endpoint,vimid:"
+ "%s req_to_aai: return %s, %s, %s"
+ % (vimid, retcode, content, status_code))
+ return retcode, content
+ else:
+ return (
+ 10,
+ "Cloud Region not found: %s" % vimid
+ )
+
+ except VimDriverNewtonException as e:
+ self._logger.error(
+ "VimDriverNewtonException: status:%s, response:%s"
+ % (e.http_status, e.content))
+ return (
+ e.http_status, e.content
+ )
+ except HttpError as e:
+ self._logger.error(
+ "HttpError: status:%s, response:%s"
+ % (e.http_status, e.response.json()))
+ return (
+ e.http_status, e.response.json()
+ )
+ except Exception as e:
+ self._logger.error(traceback.format_exc())
+ return (
+ 11, str(e)
+ )
+