blob: 168681b943687572dbe5231414a8be0b6d892a10 [file] [log] [blame]
#########
# Copyright (c) 2014 GigaSpaces Technologies Ltd. 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 time
from cloudify import ctx
from cloudify.decorators import operation
from cloudify import exceptions as cfy_exc
from openstack_plugin_common import (delete_resource_and_runtime_properties,
with_cinder_client,
get_resource_id,
transform_resource_name,
use_external_resource,
validate_resource,
COMMON_RUNTIME_PROPERTIES_KEYS,
OPENSTACK_AZ_PROPERTY,
OPENSTACK_ID_PROPERTY,
OPENSTACK_TYPE_PROPERTY,
OPENSTACK_NAME_PROPERTY)
from glance_plugin.image import handle_image_from_relationship
VOLUME_STATUS_CREATING = 'creating'
VOLUME_STATUS_DELETING = 'deleting'
VOLUME_STATUS_AVAILABLE = 'available'
VOLUME_STATUS_IN_USE = 'in-use'
VOLUME_STATUS_ERROR = 'error'
VOLUME_STATUS_ERROR_DELETING = 'error_deleting'
VOLUME_ERROR_STATUSES = (VOLUME_STATUS_ERROR, VOLUME_STATUS_ERROR_DELETING)
# Note: The 'device_name' property should actually be a property of the
# relationship between a server and a volume; It'll move to that
# relationship type once relationship properties are better supported.
DEVICE_NAME_PROPERTY = 'device_name'
VOLUME_OPENSTACK_TYPE = 'volume'
RUNTIME_PROPERTIES_KEYS = COMMON_RUNTIME_PROPERTIES_KEYS
@operation
@with_cinder_client
def create(cinder_client, status_attempts, status_timeout, args, **kwargs):
if use_external_resource(ctx, cinder_client, VOLUME_OPENSTACK_TYPE,
'name'):
return
name = get_resource_id(ctx, VOLUME_OPENSTACK_TYPE)
volume_dict = {'name': name}
volume_dict.update(ctx.node.properties['volume'], **args)
handle_image_from_relationship(volume_dict, 'imageRef', ctx)
volume_dict['name'] = transform_resource_name(
ctx, volume_dict['name'])
v = cinder_client.volumes.create(**volume_dict)
ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = v.id
ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \
VOLUME_OPENSTACK_TYPE
ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = \
volume_dict['name']
wait_until_status(cinder_client=cinder_client,
volume_id=v.id,
status=VOLUME_STATUS_AVAILABLE,
num_tries=status_attempts,
timeout=status_timeout,
)
ctx.instance.runtime_properties[OPENSTACK_AZ_PROPERTY] = \
v.availability_zone
@operation
@with_cinder_client
def delete(cinder_client, **kwargs):
delete_resource_and_runtime_properties(ctx, cinder_client,
RUNTIME_PROPERTIES_KEYS)
@with_cinder_client
def wait_until_status(cinder_client, volume_id, status, num_tries,
timeout):
for _ in range(num_tries):
volume = cinder_client.volumes.get(volume_id)
if volume.status in VOLUME_ERROR_STATUSES:
raise cfy_exc.NonRecoverableError(
"Volume {0} is in error state".format(volume_id))
if volume.status == status:
return volume, True
time.sleep(timeout)
ctx.logger.warning("Volume {0} current state: '{1}', "
"expected state: '{2}'".format(volume_id,
volume.status,
status))
return volume, False
@with_cinder_client
def get_attachment(cinder_client, volume_id, server_id):
volume = cinder_client.volumes.get(volume_id)
for attachment in volume.attachments:
if attachment['server_id'] == server_id:
return attachment
@operation
@with_cinder_client
def creation_validation(cinder_client, **kwargs):
validate_resource(ctx, cinder_client, VOLUME_OPENSTACK_TYPE,
'name')