167 lines
4.7 KiB
Python
167 lines
4.7 KiB
Python
# coding=utf-8
|
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
|
|
#
|
|
# Copyright (c) 2012, Intel Performance Learning Solutions Ltd.
|
|
#
|
|
# 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.
|
|
|
|
"""
|
|
Storage related glue :-)
|
|
"""
|
|
|
|
import random
|
|
|
|
from nova import exception
|
|
from nova import volume
|
|
from nova.image import glance
|
|
|
|
from cinder import exception as cinder_ex
|
|
|
|
from occi import exceptions
|
|
|
|
# Connection to the nova APIs
|
|
from occi_os_api.nova_glue import vm
|
|
|
|
VOLUME_API = volume.API()
|
|
|
|
IMAGE_API = glance.get_default_image_service()
|
|
|
|
|
|
def create_storage(size, context, name=None, description=None):
|
|
"""
|
|
Create a storage instance.
|
|
|
|
size -- Size of the storage. ('occi.storage.size')
|
|
context -- The os context.
|
|
name -- defaults to a random number if needed.
|
|
description -- defaults to the name
|
|
"""
|
|
# L8R: A blueprint?
|
|
# OpenStack deals with size in terms of integer.
|
|
# Need to convert float to integer for now and only if the float
|
|
# can be losslessly converted to integer
|
|
# e.g. See nova/quota.py:allowed_volumes(...)
|
|
if not float(size).is_integer:
|
|
raise AttributeError('Volume sizes cannot be specified as fractional'
|
|
' floats.')
|
|
size = int(float(size))
|
|
|
|
disp_name = ''
|
|
if name is not None:
|
|
disp_name = name
|
|
else:
|
|
disp_name = str(random.randrange(0, 99999999)) + '-storage.occi-wg.org'
|
|
if description is not None:
|
|
disp_descr = description
|
|
else:
|
|
disp_descr = disp_name
|
|
|
|
try:
|
|
return VOLUME_API.create(context,
|
|
size,
|
|
disp_name,
|
|
disp_descr)
|
|
except cinder_ex.VolumeSizeExceedsAvailableQuota:
|
|
raise AttributeError('The volume size quota has been reached!')
|
|
except cinder_ex.VolumeLimitExceeded:
|
|
raise AttributeError('The # of volumes quota has been reached!')
|
|
|
|
|
|
def delete_storage_instance(uid, context):
|
|
"""
|
|
Delete a storage instance.
|
|
|
|
uid -- Id of the volume.
|
|
context -- The os context.
|
|
"""
|
|
try:
|
|
instance = get_storage(uid, context)
|
|
VOLUME_API.delete(context, instance)
|
|
except cinder_ex.InvalidVolume:
|
|
raise AttributeError('Volume is in wrong state or still attached!')
|
|
|
|
|
|
def snapshot_storage_instance(uid, name, description, context):
|
|
"""
|
|
Snapshots an storage instance.
|
|
|
|
uid -- Id of the volume.
|
|
context -- The os context.
|
|
"""
|
|
try:
|
|
instance = get_storage(uid, context)
|
|
VOLUME_API.create_snapshot(context, instance, name, description)
|
|
except cinder_ex.InvalidVolume:
|
|
raise AttributeError('Volume is in wrong state!')
|
|
|
|
|
|
def get_image(uid, context):
|
|
"""
|
|
Return details on an image.
|
|
"""
|
|
try:
|
|
return IMAGE_API.show(context, uid)
|
|
except exception.ImageNotFound as err:
|
|
raise AttributeError(str(err))
|
|
|
|
|
|
def get_image_architecture(uid, context):
|
|
"""
|
|
Extract architecture from either:
|
|
- image name, title or metadata. The architecture is sometimes
|
|
encoded in the image's name
|
|
- db::glance::image_properties could be used reliably so long as the
|
|
information is supplied when registering an image with glance.
|
|
- else return a default of x86
|
|
|
|
uid -- id of the instance!
|
|
context -- The os context.
|
|
"""
|
|
instance = vm.get_vm(uid, context)
|
|
|
|
arch = ''
|
|
uid = instance['image_ref']
|
|
img = IMAGE_API.show(context, uid)
|
|
img_properties = img['properties']
|
|
if 'arch' in img_properties:
|
|
arch = img['properties']['arch']
|
|
elif 'architecture' in img_properties:
|
|
arch = img['properties']['architecture']
|
|
|
|
if arch == '':
|
|
# if all attempts fail set it to a default value
|
|
arch = 'x86'
|
|
return arch
|
|
|
|
|
|
def get_storage(uid, context):
|
|
"""
|
|
Retrieve an Volume instance from nova.
|
|
|
|
uid -- id of the instance
|
|
context -- the os context
|
|
"""
|
|
try:
|
|
instance = VOLUME_API.get(context, uid)
|
|
except exception.NotFound:
|
|
raise exceptions.HTTPError(404, 'Volume not found!')
|
|
return instance
|
|
|
|
|
|
def get_storage_volumes(context):
|
|
"""
|
|
Retrieve all storage entities from user.
|
|
"""
|
|
return VOLUME_API.get_all(context)
|