graffiti/graffiti/drivers/modules/glance.py

262 lines
11 KiB
Python

# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from glanceclient import Client
from graffiti.api.model.v1.capability import Capability
from graffiti.api.model.v1.property import Property
from graffiti.api.model.v1.resource import Resource
from graffiti.common import exception
from graffiti.common import utils
from graffiti.drivers import base
import keystoneclient.v2_0.client as ksclient
from oslo.config import cfg
class GlanceResourceDriver(base.ResourceInterface):
def __init__(self):
super(GlanceResourceDriver, self).__init__()
self.separator = "."
self.service_type = 'image'
self.endpoint_type = 'publicURL'
self.default_namespace_postfix = "::Default"
self.unknown_properties_type = "AdditionalProperties"
def get_resource(self, resource_type, resource_id, auth_token,
endpoint_id=None, **kwargs):
"""Retrieve the resource detail
:param resource_type: resource_type set for this call
:param resource_id: unique resource identifier
:param auth_token: keystone auth_token of request user
:param endpoint_id: id for locating the cloud resource provider
:param **kwargs: Include additional info required by the driver,
:returns resource detail
"""
# glance_image_properties = {
# "GLANCE.MySQL.Port": "3605",
# "GLANCE.MySQL.Home": "/opt/mysql",
# "GLANCE.Apache.Port": "8080",
# "GLANCE.Apache.docroot": "/var/apache/static"
# }
glance_client = self.__get_glance_client(endpoint_id, auth_token)
image = glance_client.images.get(resource_id)
image_resource = self.transform_image_to_resource(resource_type, image)
return image_resource
def update_resource(self, resource_type, resource_id, resource, auth_token,
endpoint_id=None, **kwargs):
"""Update resource
:param resource_type: resource_type set for this call
:param resource_id: unique resource identifier
:param resource: resource detail
:type param: graffiti.api.model.v1.resource.Resource
:param auth_token: keystone auth_token of request user
:param endpoint_id: id for locating the cloud resource provider
:param **kwargs: Include additional info required by the driver,
"""
glance_client = self.__get_glance_client(endpoint_id, auth_token)
image_properties = {}
for capability in resource.capabilities:
if capability.capability_type_namespace \
== resource_type + self.default_namespace_postfix \
and capability.capability_type \
== self.unknown_properties_type:
# For unknown properties, just directly set property name.
for property_name, property_value in \
capability.properties.iteritems():
image_properties[property_name] = property_value
else:
properties = capability.properties
#capability_type = self.replace_colon_from_name(
# capability.capability_type
#)
#capability_type_namespace = self.replace_colon_from_name(
# capability.capability_type_namespace
#)
for property_name, property_value in properties.iteritems():
#prop_name = capability_type_namespace + \
# self.separator + \
# capability_type + \
# self.separator + \
# self.replace_colon_from_name(property_name)
prop_name = self.replace_colon_from_name(property_name)
image_properties[prop_name] = property_value
# if capability doesnt have properties add capability as TAG
if not properties:
tag_name = capability.capability_type
image_properties[tag_name] = utils.TAG_IDENTIFIER
image = glance_client.images.get(resource.id)
image.update(properties=image_properties, purge_props=True)
def find_resources(self, resource_query, auth_token,
endpoint_id=None, **kwargs):
"""Find resources matching the query
:param resource_query: query object. Includes resource type(s)
:param auth_token: keystone auth_token of request user
:param endpoint_id: id for locating the cloud resource provider
:param **kwargs: Include additional info required by the driver,
:returns list of resources
"""
resource_list = dict()
if resource_query:
glance_client = self.__get_glance_client(
endpoint_id,
auth_token
)
images = glance_client.images.list()
for image in list(images):
#Filter based on requested resource types
glance_image_properties = image.properties
image_type = "OS::Glance::Image"
if "image_type" in glance_image_properties.keys():
image_type = glance_image_properties['image_type']
if image_type and image_type.lower() == "snapshot":
image_type = "OS::Glance::Snapshot"
if image_type in resource_query.resource_types:
resource = self.transform_image_to_resource(
image_type,
image
)
resource_list[resource.id] = resource
return resource_list
def create_resource(self, resource_type, resource, auth_token,
endpoint_id=None, **kwargs):
"""Create resource
:param resource_type: resource_type set for this call
:param resource: resource detail
:param auth_token: keystone auth_token of request user
:param endpoint_id: id for locating the cloud resource provider
:param **kwargs: Include additional info required by the driver,
"""
raise exception.MethodNotSupported(method="create_resource")
def delete_resource(self, resource_type, resource_id, auth_token,
endpoint_id=None, **kwargs):
"""Delete resource
:param resource_type: resource_type set for this call
:param resource_id: unique resource identifier
:param auth_token: keystone auth_token of request user
:param endpoint_id: id for locating the cloud resource provider
:param **kwargs: Include additional info required by the driver,
"""
raise exception.MethodNotSupported(method="delete_resource")
def __get_glance_client(self, endpoint_id, auth_token):
keystone = ksclient.Client(
auth_url=cfg.CONF.keystone.auth_url,
username=cfg.CONF.keystone.username,
password=cfg.CONF.keystone.password,
tenant_name=cfg.CONF.keystone.tenant_name
)
glance_public_url = None
if endpoint_id:
for entry in keystone.service_catalog.catalog.get(
'serviceCatalog'):
for endpoint in entry['endpoints']:
if endpoint['id'] == endpoint_id:
glance_public_url = endpoint['publicURL']
break
if glance_public_url:
break
else:
glance_public_url = keystone.service_catalog.url_for(
service_type=self.service_type,
endpoint_type=self.endpoint_type
)
glance_client = Client(
'1',
endpoint=glance_public_url,
token=auth_token
)
return glance_client
def transform_image_to_resource(self, resource_type, image):
glance_image_properties = image.properties
image_resource = Resource()
image_capabilities = []
image_resource.capabilities = image_capabilities
image_resource.id = image.id
image_resource.type = resource_type
image_resource.name = image.name
for key in glance_image_properties:
if key.count(self.separator) == 2:
(namespace, capability_type, prop_name) = key.split(".")
namespace = self.replace_hash_from_name(namespace)
capability_type = self.replace_hash_from_name(capability_type)
prop_name = self.replace_hash_from_name(prop_name)
else:
prop_name = key
capability_type = None
namespace = None
cap_and_namespace = utils.get_qualifier(
key,
glance_image_properties[key]
)
if cap_and_namespace:
capability_type = cap_and_namespace.name
namespace = cap_and_namespace.namespace
else:
namespace = resource_type + self.default_namespace_postfix
capability_type = self.unknown_properties_type
image_property = Property()
image_property.name = prop_name
image_property.value = glance_image_properties[key]
image_capability = None
for capability in image_resource.capabilities:
if capability.capability_type_namespace == namespace and \
capability.capability_type == capability_type:
image_capability = capability
if not image_capability:
image_capability = Capability()
image_capability.properties = {}
image_resource.capabilities.append(image_capability)
image_capability.capability_type_namespace = namespace
image_capability.capability_type = capability_type
image_capability.properties[image_property.name] = \
image_property.value
return image_resource
def replace_colon_from_name(self, name):
if name:
return name.replace(':', '#')
return
def replace_hash_from_name(self, name):
if name:
return name.replace('#', ':')
return