gce-api/gceapi/api/instance_disk_api.py

147 lines
5.2 KiB
Python

# Copyright 2013 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 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.openstack.common.gettextutils import _
from gceapi.openstack.common import log as logging
LOG = logging.getLogger(__name__)
class API(base_api.API):
"""GCE Attached disk API."""
KIND = "attached_disk"
PERSISTENT_ATTRIBUTES = ["id", "instance_name", "volume_id", "name"]
def __init__(self, *args, **kwargs):
super(API, self).__init__(*args, **kwargs)
operation_api.API().register_get_progress_method(
"attached_disk-add",
self._get_add_item_progress)
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)
return [i for i in items if i["instance_name"] == instance_name]
def add_item(self, context, instance_name, source, name):
if not name:
msg = _("There is no name to assign.")
raise exception.InvalidRequest(msg)
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, None)
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
operation_util.start_operation(context, self._get_add_item_progress)
volumes_client.create_server_volume(
instance.id, volume["id"], "/dev/" + device_name)
item = self.register_item(context, instance_name, volume["id"], name)
operation_util.set_item_id(context, item["id"])
def register_item(self, context, instance_name, volume_id, name):
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,
}
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 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_api.gef_final_progress()
def _get_delete_item_progress(self, context, dummy_id):
return operation_api.gef_final_progress()