337 lines
12 KiB
Python
Raw Normal View History

# Copyright 2014 OpenStack Foundation
# All Rights Reserved.
#
# 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 six
from six.moves.urllib import parse
import warlock
from glanceclient.common import utils
from glanceclient.openstack.common import strutils
DEFAULT_PAGE_SIZE = 20
class NamespaceController(object):
def __init__(self, http_client, model):
self.http_client = http_client
self.model = model
def create(self, **kwargs):
"""Create a namespace.
:param kwargs: Unpacked namespace object.
"""
url = '/v2/metadefs/namespaces'
try:
namespace = self.model(kwargs)
except (warlock.InvalidOperation, ValueError) as e:
raise TypeError(utils.exception_to_str(e))
resp, body = self.http_client.post(url, data=namespace)
body.pop('self', None)
return self.model(**body)
def update(self, namespace_name, **kwargs):
"""Update a namespace.
:param namespace_name: Name of a namespace (old one).
:param kwargs: Unpacked namespace object.
"""
namespace = self.get(namespace_name)
for (key, value) in six.iteritems(kwargs):
try:
setattr(namespace, key, value)
except warlock.InvalidOperation as e:
raise TypeError(utils.exception_to_str(e))
# Remove read-only parameters.
read_only = ['schema', 'updated_at', 'created_at']
for elem in read_only:
if elem in namespace:
del namespace[elem]
url = '/v2/metadefs/namespaces/{0}'.format(namespace_name)
self.http_client.put(url, data=namespace)
return self.get(namespace.namespace)
def get(self, namespace, **kwargs):
"""Get one namespace."""
query_params = parse.urlencode(kwargs)
if kwargs:
query_params = '?%s' % query_params
url = '/v2/metadefs/namespaces/{0}{1}'.format(namespace, query_params)
resp, body = self.http_client.get(url)
#NOTE(bcwaldon): remove 'self' for now until we have an elegant
# way to pass it into the model constructor without conflict
body.pop('self', None)
return self.model(**body)
def list(self, **kwargs):
"""Retrieve a listing of Namespace objects
:param page_size: Number of namespaces to request in each request
:returns generator over list of Namespaces
"""
ori_validate_fun = self.model.validate
empty_fun = lambda *args, **kwargs: None
def paginate(url):
resp, body = self.http_client.get(url)
for namespace in body['namespaces']:
# NOTE(bcwaldon): remove 'self' for now until we have
# an elegant way to pass it into the model constructor
# without conflict.
namespace.pop('self', None)
yield self.model(**namespace)
# NOTE(zhiyan): In order to resolve the performance issue
# of JSON schema validation for image listing case, we
# don't validate each image entry but do it only on first
# image entry for each page.
self.model.validate = empty_fun
# NOTE(zhiyan); Reset validation function.
self.model.validate = ori_validate_fun
try:
next_url = body['next']
except KeyError:
return
else:
for namespace in paginate(next_url):
yield namespace
filters = kwargs.get('filters', {})
filters = {} if filters is None else filters
if not kwargs.get('page_size'):
filters['limit'] = DEFAULT_PAGE_SIZE
else:
filters['limit'] = kwargs['page_size']
for param, value in six.iteritems(filters):
if isinstance(value, list):
filters[param] = strutils.safe_encode(','.join(value))
elif isinstance(value, six.string_types):
filters[param] = strutils.safe_encode(value)
url = '/v2/metadefs/namespaces?%s' % parse.urlencode(filters)
for namespace in paginate(url):
yield namespace
def delete(self, namespace):
"""Delete a namespace."""
url = '/v2/metadefs/namespaces/{0}'.format(namespace)
self.http_client.delete(url)
class ResourceTypeController(object):
def __init__(self, http_client, model):
self.http_client = http_client
self.model = model
def associate(self, namespace, **kwargs):
"""Associate a resource type with a namespace."""
try:
res_type = self.model(kwargs)
except (warlock.InvalidOperation, ValueError) as e:
raise TypeError(utils.exception_to_str(e))
url = '/v2/metadefs/namespaces/{0}/resource_types'.format(namespace,
res_type)
resp, body = self.http_client.post(url, data=res_type)
body.pop('self', None)
return self.model(**body)
def deassociate(self, namespace, resource):
"""Deasociate a resource type with a namespace."""
url = '/v2/metadefs/namespaces/{0}/resource_types/{1}'. \
format(namespace, resource)
self.http_client.delete(url)
def list(self):
"""Retrieve a listing of available resource types
:returns generator over list of resource_types
"""
url = '/v2/metadefs/resource_types'
resp, body = self.http_client.get(url)
for resource_type in body['resource_types']:
yield self.model(**resource_type)
def get(self, namespace):
url = '/v2/metadefs/namespaces/{0}/resource_types'.format(namespace)
resp, body = self.http_client.get(url)
body.pop('self', None)
for resource_type in body['resource_type_associations']:
yield self.model(**resource_type)
class PropertyController(object):
def __init__(self, http_client, model):
self.http_client = http_client
self.model = model
def create(self, namespace, **kwargs):
"""Create a property.
:param namespace: Name of a namespace the property will belong.
:param kwargs: Unpacked property object.
"""
try:
prop = self.model(kwargs)
except (warlock.InvalidOperation, ValueError) as e:
raise TypeError(utils.exception_to_str(e))
url = '/v2/metadefs/namespaces/{0}/properties'.format(namespace)
resp, body = self.http_client.post(url, data=prop)
body.pop('self', None)
return self.model(**body)
def update(self, namespace, prop_name, **kwargs):
"""Update a property.
:param namespace: Name of a namespace the property belongs.
:param prop_name: Name of a property (old one).
:param kwargs: Unpacked property object.
"""
prop = self.get(namespace, prop_name)
for (key, value) in kwargs.items():
try:
setattr(prop, key, value)
except warlock.InvalidOperation as e:
raise TypeError(utils.exception_to_str(e))
url = '/v2/metadefs/namespaces/{0}/properties/{1}'.format(namespace,
prop_name)
self.http_client.put(url, data=prop)
return self.get(namespace, prop.name)
def get(self, namespace, prop_name):
url = '/v2/metadefs/namespaces/{0}/properties/{1}'.format(namespace,
prop_name)
resp, body = self.http_client.get(url)
body.pop('self', None)
body['name'] = prop_name
return self.model(**body)
def list(self, namespace, **kwargs):
"""Retrieve a listing of metadata properties
:returns generator over list of objects
"""
url = '/v2/metadefs/namespaces/{0}/properties'.format(namespace)
resp, body = self.http_client.get(url)
for key, value in body['properties'].items():
value['name'] = key
yield self.model(value)
def delete(self, namespace, prop_name):
"""Delete a property."""
url = '/v2/metadefs/namespaces/{0}/properties/{1}'.format(namespace,
prop_name)
self.http_client.delete(url)
def delete_all(self, namespace):
"""Delete all properties in a namespace."""
url = '/v2/metadefs/namespaces/{0}/properties'.format(namespace)
self.http_client.delete(url)
class ObjectController(object):
def __init__(self, http_client, model):
self.http_client = http_client
self.model = model
def create(self, namespace, **kwargs):
"""Create an object.
:param namespace: Name of a namespace the object belongs.
:param kwargs: Unpacked object.
"""
try:
obj = self.model(kwargs)
except (warlock.InvalidOperation, ValueError) as e:
raise TypeError(utils.exception_to_str(e))
url = '/v2/metadefs/namespaces/{0}/objects'.format(namespace)
resp, body = self.http_client.post(url, data=obj)
body.pop('self', None)
return self.model(**body)
def update(self, namespace, object_name, **kwargs):
"""Update an object.
:param namespace: Name of a namespace the object belongs.
:param prop_name: Name of an object (old one).
:param kwargs: Unpacked object.
"""
obj = self.get(namespace, object_name)
for (key, value) in kwargs.items():
try:
setattr(obj, key, value)
except warlock.InvalidOperation as e:
raise TypeError(utils.exception_to_str(e))
# Remove read-only parameters.
read_only = ['schema', 'updated_at', 'created_at']
for elem in read_only:
if elem in namespace:
del namespace[elem]
url = '/v2/metadefs/namespaces/{0}/objects/{1}'.format(namespace,
object_name)
self.http_client.put(url, data=obj)
return self.get(namespace, obj.name)
def get(self, namespace, object_name):
url = '/v2/metadefs/namespaces/{0}/objects/{1}'.format(namespace,
object_name)
resp, body = self.http_client.get(url)
body.pop('self', None)
return self.model(**body)
def list(self, namespace, **kwargs):
"""Retrieve a listing of metadata objects
:returns generator over list of objects
"""
url = '/v2/metadefs/namespaces/{0}/objects'.format(namespace,)
resp, body = self.http_client.get(url)
for obj in body['objects']:
yield self.model(obj)
def delete(self, namespace, object_name):
"""Delete an object."""
url = '/v2/metadefs/namespaces/{0}/objects/{1}'.format(namespace,
object_name)
self.http_client.delete(url)
def delete_all(self, namespace):
"""Delete all objects in a namespace."""
url = '/v2/metadefs/namespaces/{0}/objects'.format(namespace)
self.http_client.delete(url)