gce-api/gceapi/api/instance_disk_api.py
Andrey Pavlov 75905790e5 update gce api to current OpenStack
- add devstack plugin
- update openstack common
- move unit tests to unit folder
- update infrastructural files

Change-Id: Id72006f70110dbd1762f42b582470ac5f3439f2a
2015-09-03 17:16:30 +03:00

205 lines
7.6 KiB
Python

# Copyright 2014
# The Cloudscaling Group, 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 string
from oslo_log import log as logging
from gceapi.api import base_api
from gceapi.api import clients
from gceapi.api import disk_api
from gceapi.api import operation_api
from gceapi.api import operation_util
from gceapi.api import utils
from gceapi import exception
from gceapi.i18n import _
LOG = logging.getLogger(__name__)
GB = 1024 ** 3
class API(base_api.API):
"""GCE Attached disk API."""
KIND = "attached_disk"
PERSISTENT_ATTRIBUTES = ["id", "instance_name", "volume_id", "name",
"auto_delete"]
def __init__(self, *args, **kwargs):
super(API, self).__init__(*args, **kwargs)
operation_api.API().register_get_progress_method(
"attached_disk-delete",
self._get_delete_item_progress)
def _get_type(self):
return self.KIND
def _get_persistent_attributes(self):
return self.PERSISTENT_ATTRIBUTES
def get_item(self, context, instance_name, name):
items = self._get_db_items(context)
items = [i for i in items
if i["instance_name"] == instance_name and i["name"] == name]
if len(items) != 1:
raise exception.NotFound
return items[0]
def get_items(self, context, instance_name):
items = self._get_db_items(context)
for item in items:
item.setdefault("auto_delete", False)
return [i for i in items if i["instance_name"] == instance_name]
def add_item(self, context, instance_name, params, source, name,
auto_delete, scope):
# NOTE(apavlov): name is a 'device_name' here
if not name:
msg = _("There is no name to assign.")
raise exception.InvalidRequest(msg)
nova_client = clients.nova(context)
instances = nova_client.servers.list(
search_opts={"name": instance_name})
if not instances or len(instances) != 1:
raise exception.NotFound
instance = instances[0]
devices = list()
volumes_client = nova_client.volumes
for server_volume in volumes_client.get_server_volumes(instance.id):
devices.append(server_volume.device)
device_name = None
for letter in string.ascii_lowercase[1:]:
device_name = "vd" + letter
for device in devices:
if device_name in device:
break
else:
break
else:
raise exception.OverQuota
context.operation_data["device_name"] = device_name
if source:
volume_name = utils._extract_name_from_url(source)
if not volume_name:
msg = _("There is no volume to assign.")
raise exception.NotFound(msg)
volume = disk_api.API().get_item(context, volume_name, scope)
context.operation_data["volume_id"] = volume["id"]
elif params:
params.setdefault("diskName", instance_name)
context.operation_data["params"] = params
context.operation_data["scope"] = scope
else:
msg = _('Disk config must contain either "source" or '
'"initializeParams".')
raise exception.InvalidRequest(msg)
context.operation_data["instance_id"] = instance.id
context.operation_data["register_args"] = [instance_name, name,
auto_delete]
operation_util.start_operation(
context, base_api.API._get_complex_operation_progress)
operation_util.continue_operation(
context, lambda: self._attach_volume(context), timeout=0)
def _attach_volume(self, context):
params = context.operation_data.get("params")
if params:
scope = context.operation_data["scope"]
context.operation_data.pop("params")
body = {"sizeGb": params.get("diskSizeGb"),
"sourceImage": params["sourceImage"]}
volume = disk_api.API().add_item(context, params.get("diskName"),
body, scope=scope)
context.operation_data["disk"] = volume
return None
disk = context.operation_data.get("disk")
if disk:
volume_id = disk["id"]
item_progress = disk_api.API()._get_add_item_progress(context,
volume_id)
if not operation_util.is_final_progress(item_progress):
return None
context.operation_data.pop("disk")
context.operation_data["volume_id"] = volume_id
instance_id = context.operation_data["instance_id"]
device_name = context.operation_data["device_name"]
volume_id = context.operation_data["volume_id"]
volumes_client = clients.nova(context).volumes
volumes_client.create_server_volume(
instance_id, volume_id, "/dev/" + device_name)
args = context.operation_data["register_args"]
self.register_item(context, args[0], volume_id, args[1], args[2])
return operation_util.get_final_progress()
def register_item(self, context, instance_name, volume_id, name,
auto_delete):
if not name:
msg = _("There is no name to assign.")
raise exception.InvalidRequest(msg)
if not volume_id:
msg = _("There is no volume_id to assign.")
raise exception.InvalidRequest(msg)
new_item = {
"id": instance_name + "-" + volume_id,
"instance_name": instance_name,
"volume_id": volume_id,
"name": name,
"auto_delete": auto_delete
}
new_item = self._add_db_item(context, new_item)
return new_item
def delete_item(self, context, instance_name, name):
item = self.get_item(context, instance_name, name)
volume_id = item["volume_id"]
nova_client = clients.nova(context)
instances = nova_client.servers.list(
search_opts={"name": instance_name})
if not instances or len(instances) != 1:
raise exception.NotFound
instance = instances[0]
operation_util.start_operation(context,
self._get_delete_item_progress,
item["id"])
nova_client.volumes.delete_server_volume(instance.id, volume_id)
self._delete_db_item(context, item)
def set_disk_auto_delete(self, context, instance_name, name, auto_delete):
item = self.get_item(context, instance_name, name)
item["auto_delete"] = auto_delete
self._update_db_item(context, item)
def unregister_item(self, context, instance_name, name):
item = self.get_item(context, instance_name, name)
self._delete_db_item(context, item)
def _get_add_item_progress(self, context, dummy_id):
return operation_util.get_final_progress()
def _get_delete_item_progress(self, context, dummy_id):
return operation_util.get_final_progress()