Add Cinder support for GCE
Supported operations: 1. Create/delete a volume 2. Snapshot a volume 3. Create a volume from snapshot 4. Attach/detach volume to an instance Change-Id: I5b2a9ee964fc239153d6de9886cc5e4a8e743c17 Signed-off-by: Sanket <sanket@infracloud.io>
This commit is contained in:
parent
e4fd7a04f5
commit
1de5c3778c
2
cinder/requirements-gce.txt
Normal file
2
cinder/requirements-gce.txt
Normal file
@ -0,0 +1,2 @@
|
||||
google-api-python-client
|
||||
oslo.service>=1.19.0
|
0
cinder/volume/drivers/gce/__init__.py
Normal file
0
cinder/volume/drivers/gce/__init__.py
Normal file
135
cinder/volume/drivers/gce/driver.py
Normal file
135
cinder/volume/drivers/gce/driver.py
Normal file
@ -0,0 +1,135 @@
|
||||
# Copyright 2017 Platform9 Systems Inc.(http://www.platform9.com)
|
||||
#
|
||||
# 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.
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from cinder.i18n import _LI
|
||||
from cinder.volume.driver import BaseVD
|
||||
from cinder.volume.drivers.gce import gceconf
|
||||
from cinder.volume.drivers.gce import gceutils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GceDriver(BaseVD):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(GceDriver, self).__init__(*args, **kwargs)
|
||||
self.VERSION = '0.0.1'
|
||||
self.gce_zone = gceconf.zone
|
||||
self.gce_region = gceconf.region
|
||||
self.gce_project = gceconf.project_id
|
||||
self.gce_svc_key = gceconf.service_key_path
|
||||
|
||||
def do_setup(self, context):
|
||||
self.gce_svc = gceutils.get_gce_service(self.gce_svc_key)
|
||||
self.set_initialized()
|
||||
LOG.info(
|
||||
_LI("Gce volume driver init with %s project, %s zone") %
|
||||
(self.gce_project, self.gce_zone))
|
||||
|
||||
def _gce_volume_name(self, volume):
|
||||
return 'vol-' + volume.id
|
||||
|
||||
def _gce_snapshot_name(self, snapshot):
|
||||
return 'snap-' + snapshot.id
|
||||
|
||||
def create_volume(self, volume):
|
||||
compute, project, zone = self.gce_svc, self.gce_project, self.gce_zone
|
||||
name = self._gce_volume_name(volume)
|
||||
size = volume['size']
|
||||
operation = gceutils.create_disk(compute, project, zone, name, size)
|
||||
gceutils.wait_for_operation(compute, project, operation)
|
||||
|
||||
def delete_volume(self, volume):
|
||||
compute, project, zone = self.gce_svc, self.gce_project, self.gce_zone
|
||||
name = self._gce_volume_name(volume)
|
||||
operation = gceutils.delete_disk(compute, project, zone, name)
|
||||
gceutils.wait_for_operation(compute, project, operation)
|
||||
|
||||
def check_for_setup_error(self):
|
||||
pass
|
||||
|
||||
def create_export(self, context, volume, connector):
|
||||
pass
|
||||
|
||||
def ensure_export(self, context, volume):
|
||||
pass
|
||||
|
||||
def remove_export(self, context, volume):
|
||||
pass
|
||||
|
||||
def initialize_connection(self, volume, connector, initiator_data=None):
|
||||
compute, project, zone = self.gce_svc, self.gce_project, self.gce_zone
|
||||
name = self._gce_volume_name(volume)
|
||||
gce_volume = gceutils.get_disk(compute, project, zone, name)
|
||||
return dict(data=gce_volume)
|
||||
|
||||
def terminate_connection(self, volume, connector, **kwargs):
|
||||
pass
|
||||
|
||||
def _update_volume_stats(self):
|
||||
data = dict()
|
||||
data['volume_backend_name'] = 'gce'
|
||||
data['vendor_name'] = 'Google, Inc.'
|
||||
data['driver_version'] = '0.0.1'
|
||||
data['storage_protocol'] = 'iscsi'
|
||||
pool = dict(pool_name=gceconf.gce_pool_name,
|
||||
free_capacity_gb=gceconf.gce_free_capacity_gb,
|
||||
total_capacity_gb=gceconf.gce_free_capacity_gb,
|
||||
provisioned_capacity_gb=0, reserved_percentage=0,
|
||||
location_info=dict(), QoS_support=False,
|
||||
max_over_subscription_ratio=1.0,
|
||||
thin_provisioning_support=False,
|
||||
thick_provisioning_support=True, total_volumes=0)
|
||||
data['pools'] = [pool]
|
||||
self._stats = data
|
||||
|
||||
def get_volume_stats(self, refresh=False):
|
||||
if refresh:
|
||||
self._update_volume_stats()
|
||||
return self._stats
|
||||
|
||||
def create_snapshot(self, snapshot):
|
||||
compute, project, zone = self.gce_svc, self.gce_project, self.gce_zone
|
||||
volume_name = self._gce_volume_name(snapshot.volume)
|
||||
name = self._gce_snapshot_name(snapshot)
|
||||
operation = gceutils.snapshot_disk(compute, project, zone, volume_name,
|
||||
name)
|
||||
gceutils.wait_for_operation(compute, project, operation)
|
||||
|
||||
def delete_snapshot(self, snapshot):
|
||||
compute, project = self.gce_svc, self.gce_project
|
||||
name = self._gce_snapshot_name(snapshot)
|
||||
operation = gceutils.delete_snapshot(compute, project, name)
|
||||
gceutils.wait_for_operation(compute, project, operation)
|
||||
|
||||
def create_volume_from_snapshot(self, volume, snapshot):
|
||||
compute, project, zone = self.gce_svc, self.gce_project, self.gce_zone
|
||||
name = self._gce_volume_name(volume)
|
||||
snapshot_name = self._gce_snapshot_name(snapshot)
|
||||
operation = gceutils.create_disk_from_snapshot(compute, project, zone,
|
||||
name, snapshot_name)
|
||||
gceutils.wait_for_operation(compute, project, operation)
|
||||
|
||||
def copy_image_to_volume(self, context, volume, image_service, image_id):
|
||||
raise NotImplementedError()
|
||||
|
||||
def copy_volume_to_image(self, context, volume, image_service, image_meta):
|
||||
raise NotImplementedError()
|
||||
|
||||
def migrate_volume(self, context, volume, host):
|
||||
raise NotImplementedError()
|
||||
|
||||
def copy_volume_data(self, context, src_vol, dest_vol, remote=None):
|
||||
raise NotImplementedError()
|
43
cinder/volume/drivers/gce/gceconf.py
Normal file
43
cinder/volume/drivers/gce/gceconf.py
Normal file
@ -0,0 +1,43 @@
|
||||
# Copyright 2017 Platform9 Systems Inc.(http://www.platform9.com)
|
||||
#
|
||||
# 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.
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
gce_group = cfg.OptGroup(name='GCE',
|
||||
title='Options to connect to Google cloud')
|
||||
|
||||
gce_opts = [
|
||||
cfg.StrOpt('service_key_path', help='Service key of GCE account',
|
||||
secret=True),
|
||||
cfg.StrOpt('zone', help='GCE zone'),
|
||||
cfg.StrOpt('region', help='GCE region'),
|
||||
cfg.StrOpt('project_id', help='GCE project id'),
|
||||
cfg.StrOpt('gce_pool_name', help='Storage pool name'),
|
||||
cfg.IntOpt('gce_free_capacity_gb',
|
||||
help='Free space available on GCE storage pool', default=1024),
|
||||
cfg.IntOpt('gce_total_capacity_gb',
|
||||
help='Total space available on GCE storage pool', default=1024)
|
||||
] # yapf:disable
|
||||
|
||||
cfg.CONF.register_group(gce_group)
|
||||
cfg.CONF.register_opts(gce_opts, group=gce_group)
|
||||
|
||||
service_key_path = cfg.CONF.GCE.service_key_path
|
||||
zone = cfg.CONF.GCE.zone
|
||||
region = cfg.CONF.GCE.region
|
||||
project_id = cfg.CONF.GCE.project_id
|
||||
|
||||
gce_pool_name = cfg.CONF.GCE.gce_pool_name
|
||||
gce_free_capacity_gb = cfg.CONF.GCE.gce_free_capacity_gb
|
||||
gce_total_capacity_gb = cfg.CONF.GCE.gce_total_capacity_gb
|
180
cinder/volume/drivers/gce/gceutils.py
Normal file
180
cinder/volume/drivers/gce/gceutils.py
Normal file
@ -0,0 +1,180 @@
|
||||
# Copyright (c) 2017 Platform9 Systems 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 expressed or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from googleapiclient.discovery import build
|
||||
from oauth2client.client import GoogleCredentials
|
||||
from oslo_log import log as logging
|
||||
|
||||
from cinder.i18n import _LI
|
||||
from oslo_service import loopingcall
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GceOperationError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def wait_for_operation(compute, project, operation, interval=1, timeout=60):
|
||||
"""Wait for GCE operation to complete, raise error if operation failure
|
||||
:param compute: GCE compute resource object using googleapiclient.discovery
|
||||
:param project: string, GCE Project Id
|
||||
:param zone: string, GCE Name of zone
|
||||
:param operation: object, Operation resource obtained by calling GCE API
|
||||
:param interval: int, Time period(seconds) between two GCE operation checks
|
||||
:param timeout: int, Absoulte time period(seconds) to monitor GCE operation
|
||||
"""
|
||||
|
||||
def watch_operation(name, request):
|
||||
result = request.execute()
|
||||
if result['status'] == 'DONE':
|
||||
LOG.info(
|
||||
_LI("Operation %s status is %s") % (name, result['status']))
|
||||
if 'error' in result:
|
||||
raise GceOperationError(result['error'])
|
||||
raise loopingcall.LoopingCallDone()
|
||||
|
||||
operation_name = operation['name']
|
||||
|
||||
if 'zone' in operation:
|
||||
zone = operation['zone'].split('/')[-1]
|
||||
monitor_request = compute.zoneOperations().get(
|
||||
project=project, zone=zone, operation=operation_name)
|
||||
elif 'region' in operation:
|
||||
region = operation['region'].split('/')[-1]
|
||||
monitor_request = compute.regionOperations().get(
|
||||
project=project, region=region, operation=operation_name)
|
||||
else:
|
||||
monitor_request = compute.globalOperations().get(
|
||||
project=project, operation=operation_name)
|
||||
|
||||
timer = loopingcall.FixedIntervalWithTimeoutLoopingCall(
|
||||
watch_operation, operation_name, monitor_request)
|
||||
timer.start(interval=interval, timeout=timeout).wait()
|
||||
|
||||
|
||||
def get_gce_service(service_key):
|
||||
"""Returns GCE compute resource object for interacting with GCE API
|
||||
:param service_key: string, Path of service key obtained from
|
||||
https://console.cloud.google.com/apis/credentials
|
||||
:return: :class:`Resource <Resource>` object
|
||||
:rtype: googleapiclient.discovery.Resource
|
||||
"""
|
||||
credentials = GoogleCredentials.from_stream(service_key)
|
||||
service = build('compute', 'v1', credentials=credentials)
|
||||
return service
|
||||
|
||||
|
||||
def create_disk(compute, project, zone, name, size):
|
||||
"""Create disk in GCE
|
||||
:param compute: GCE compute resource object using googleapiclient.discovery
|
||||
:param project: string, GCE Project Id
|
||||
:param zone: string, GCE Name of zone
|
||||
:param name: string, GCE disk name
|
||||
:param size: int, size of disk inn Gb
|
||||
:return: Operation information
|
||||
:rtype: dict
|
||||
"""
|
||||
body = {
|
||||
"name": name,
|
||||
"zone": "projects/%s/zones/%s" % (project, zone),
|
||||
"type": "projects/%s/zones/%s/diskTypes/pd-standard" % (project, zone),
|
||||
"sizeGb": size
|
||||
}
|
||||
return compute.disks().insert(project=project, zone=zone, body=body,
|
||||
sourceImage=None).execute()
|
||||
|
||||
|
||||
def delete_disk(compute, project, zone, name):
|
||||
"""Delete disk in GCE
|
||||
:param compute: GCE compute resource object using googleapiclient.discovery
|
||||
:param project: string, GCE Project Id
|
||||
:param zone: string, GCE Name of zone
|
||||
:param name: string, GCE disk name
|
||||
:return: Operation information
|
||||
:rtype: dict
|
||||
"""
|
||||
return compute.disks().delete(project=project, zone=zone,
|
||||
disk=name).execute()
|
||||
|
||||
|
||||
def get_disk(compute, project, zone, name):
|
||||
"""Get info of disk in GCE
|
||||
:param compute: GCE compute resource object using googleapiclient.discovery
|
||||
:param project: string, GCE Project Id
|
||||
:param zone: string, GCE Name of zone
|
||||
:param name: string, GCE disk name
|
||||
:return: GCE disk information
|
||||
:rtype: dict
|
||||
"""
|
||||
return compute.disks().get(project=project, zone=zone, disk=name).execute()
|
||||
|
||||
|
||||
def snapshot_disk(compute, project, zone, name, snapshot_name):
|
||||
"""Create snapshot of disk in GCE
|
||||
:param compute: GCE compute resource object using googleapiclient.discovery
|
||||
:param project: string, GCE Project Id
|
||||
:param zone: string, GCE Name of zone
|
||||
:param name: string, GCE disk name
|
||||
:param snapshot_name: string, GCE snapshot name
|
||||
:return: Operation information
|
||||
:rtype: dict
|
||||
"""
|
||||
body = {"name": snapshot_name}
|
||||
return compute.disks().createSnapshot(project=project, zone=zone,
|
||||
disk=name, body=body).execute()
|
||||
|
||||
|
||||
def get_snapshot(compute, project, name):
|
||||
"""Get info of snapshot in GCE
|
||||
:param compute: GCE compute resource object using googleapiclient.discovery
|
||||
:param project: string, GCE Project Id
|
||||
:param name: string, GCE snapshot name
|
||||
:return: GCE snapshot information
|
||||
:rtype: dict
|
||||
"""
|
||||
return compute.snapshots().get(project=project, snapshot=name).execute()
|
||||
|
||||
|
||||
def delete_snapshot(compute, project, name):
|
||||
"""Delete snapshot in GCE
|
||||
:param compute: GCE compute resource object using googleapiclient.discovery
|
||||
:param project: string, GCE Project Id
|
||||
:param name: string, GCE snapshot name
|
||||
:return: Operation information
|
||||
:rtype: dict
|
||||
"""
|
||||
return compute.snapshots().delete(project=project, snapshot=name).execute()
|
||||
|
||||
|
||||
def create_disk_from_snapshot(compute, project, zone, name, snapshot_name):
|
||||
"""Create disk from snapshot in GCE
|
||||
:param compute: GCE compute resource object using googleapiclient.discovery
|
||||
:param project: string, GCE Project Id
|
||||
:param zone: string, GCE Name of zone
|
||||
:param name: string, GCE disk name
|
||||
:param snapshot_name: string, GCE snapshot name
|
||||
:return: Operation information
|
||||
:rtype: dict
|
||||
"""
|
||||
gce_snapshot = get_snapshot(compute, project, snapshot_name)
|
||||
body = {
|
||||
"name": name,
|
||||
"zone": "projects/%s/zones/%s" % (project, zone),
|
||||
"type": "projects/%s/zones/%s/diskTypes/pd-standard" % (project, zone),
|
||||
"sourceSnapshot": gce_snapshot["selfLink"],
|
||||
"sizeGb": gce_snapshot["diskSizeGb"]
|
||||
}
|
||||
return compute.disks().insert(project=project, zone=zone, body=body,
|
||||
sourceImage=None).execute()
|
@ -18,6 +18,7 @@ import uuid
|
||||
|
||||
import nova.conf
|
||||
from nova import exception
|
||||
from nova.i18n import _LI
|
||||
from nova.virt import driver, hardware
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
@ -115,8 +116,9 @@ class GCEDriver(driver.ComputeDriver):
|
||||
self.gce_svc = gceutils.get_gce_service(self.gce_svc_key)
|
||||
self.gce_flavor_info = gceutils.get_machines_info(
|
||||
self.gce_svc, self.gce_project, self.gce_zone)
|
||||
LOG.info("GCE driver init with %s project, %s region" %
|
||||
(self.gce_project, self.gce_zone))
|
||||
LOG.info(
|
||||
_LI("GCE driver init with %s project, %s region") %
|
||||
(self.gce_project, self.gce_zone))
|
||||
if '_GCE_NODES' not in globals():
|
||||
set_nodes([CONF.host])
|
||||
|
||||
@ -192,6 +194,15 @@ class GCEDriver(driver.ComputeDriver):
|
||||
|
||||
return network_interfaces
|
||||
|
||||
def _process_ssh_keys(self, instance):
|
||||
key_name, key_data = instance.key_name, instance.key_data
|
||||
if key_name is None or key_data is None:
|
||||
return {}
|
||||
return {
|
||||
'key': 'ssh-keys',
|
||||
'value': '{0}:{1}'.format(key_name, key_data)
|
||||
}
|
||||
|
||||
def spawn(self, context, instance, image_meta, injected_files,
|
||||
admin_password, network_info=None, block_device_info=None):
|
||||
"""Create a new instance/VM/domain on the virtualization platform.
|
||||
@ -218,7 +229,8 @@ class GCEDriver(driver.ComputeDriver):
|
||||
compute, project, zone = self.gce_svc, self.gce_project, self.gce_zone
|
||||
# TODO: Use instance id as instance name
|
||||
instance_name = instance.display_name
|
||||
LOG.info("Creating instance %s as %s on GCE." % (instance.display_name,
|
||||
LOG.info(
|
||||
_LI("Creating instance %s as %s on GCE.") % (instance.display_name,
|
||||
instance_name))
|
||||
# Image Info
|
||||
image_link = instance.system_metadata['image_gce_link']
|
||||
@ -236,13 +248,18 @@ class GCEDriver(driver.ComputeDriver):
|
||||
instance_name)
|
||||
# Update GCE info in openstack instance metadata
|
||||
instance.metadata.update({'gce_id': gce_instance['name']})
|
||||
gce_metadata = [
|
||||
{
|
||||
'key': 'openstack_id',
|
||||
'value': instance.uuid
|
||||
},
|
||||
]
|
||||
ssh_keys = self._process_ssh_keys(instance)
|
||||
if ssh_keys:
|
||||
gce_metadata.append(ssh_keys)
|
||||
operation = gceutils.set_instance_metadata(
|
||||
compute, project, zone, gce_instance['name'], [
|
||||
{
|
||||
'key': 'openstack_id',
|
||||
'value': instance.uuid
|
||||
},
|
||||
], operation='add')
|
||||
compute, project, zone, gce_instance['name'], gce_metadata,
|
||||
operation='add')
|
||||
gceutils.wait_for_operation(compute, project, zone, operation)
|
||||
self._uuid_to_gce_instance[instance.uuid] = gceutils.get_instance(
|
||||
compute, project, zone, instance_name)
|
||||
@ -284,22 +301,22 @@ class GCEDriver(driver.ComputeDriver):
|
||||
block_device_info=None):
|
||||
compute, project, zone = self.gce_svc, self.gce_project, self.gce_zone
|
||||
gce_id = self._get_gce_id_from_instance(instance)
|
||||
LOG.info('Stopping instance %s' % instance.uuid)
|
||||
LOG.info(_LI('Stopping instance %s') % instance.uuid)
|
||||
operation = gceutils.stop_instance(compute, project, zone, gce_id)
|
||||
gceutils.wait_for_operation(compute, project, zone, operation)
|
||||
LOG.info('Starting instance %s' % instance.uuid)
|
||||
LOG.info(_LI('Starting instance %s') % instance.uuid)
|
||||
operation = gceutils.start_instance(compute, project, zone, gce_id)
|
||||
gceutils.wait_for_operation(compute, project, zone, operation)
|
||||
LOG.info('Soft Reboot Complete for instance %s' % instance.uuid)
|
||||
LOG.info(_LI('Soft Reboot Complete for instance %s') % instance.uuid)
|
||||
|
||||
def _hard_reboot(self, context, instance, network_info,
|
||||
block_device_info=None):
|
||||
compute, project, zone = self.gce_svc, self.gce_project, self.gce_zone
|
||||
gce_id = self._get_gce_id_from_instance(instance)
|
||||
LOG.info('Resetting instance %s' % instance.uuid)
|
||||
LOG.info(_LI('Resetting instance %s') % instance.uuid)
|
||||
operation = gceutils.reset_instance(compute, project, zone, gce_id)
|
||||
gceutils.wait_for_operation(compute, project, zone, operation)
|
||||
LOG.info('Hard Reboot Complete %s' % instance.uuid)
|
||||
LOG.info(_LI('Hard Reboot Complete %s') % instance.uuid)
|
||||
|
||||
@staticmethod
|
||||
def get_host_ip_addr():
|
||||
@ -351,23 +368,23 @@ class GCEDriver(driver.ComputeDriver):
|
||||
"""
|
||||
compute, project, zone = self.gce_svc, self.gce_project, self.gce_zone
|
||||
gce_id = self._get_gce_id_from_instance(instance)
|
||||
LOG.info('Stopping instance %s' % instance.uuid)
|
||||
LOG.info(_LI('Stopping instance %s') % instance.uuid)
|
||||
operation = gceutils.stop_instance(compute, project, zone, gce_id)
|
||||
gceutils.wait_for_operation(compute, project, zone, operation)
|
||||
LOG.info('Power off complete %s' % instance.uuid)
|
||||
LOG.info(_LI('Power off complete %s') % instance.uuid)
|
||||
|
||||
def power_on(self, context, instance, network_info, block_device_info):
|
||||
"""Power on the specified instance."""
|
||||
compute, project, zone = self.gce_svc, self.gce_project, self.gce_zone
|
||||
gce_id = self._get_gce_id_from_instance(instance)
|
||||
LOG.info('Starting instance %s' % instance.uuid)
|
||||
LOG.info(_LI('Starting instance %s') % instance.uuid)
|
||||
operation = gceutils.start_instance(compute, project, zone, gce_id)
|
||||
gceutils.wait_for_operation(compute, project, zone, operation)
|
||||
LOG.info("Power on Complete %s" % instance.uuid)
|
||||
LOG.info(_LI("Power on Complete %s") % instance.uuid)
|
||||
|
||||
def soft_delete(self, instance):
|
||||
"""Deleting the specified instance"""
|
||||
LOG.info("Soft delete instance %s" % instance.uuid)
|
||||
LOG.info(_LI("Soft delete instance %s") % instance.uuid)
|
||||
self.destroy(instance)
|
||||
|
||||
def restore(self, instance):
|
||||
@ -380,7 +397,7 @@ class GCEDriver(driver.ComputeDriver):
|
||||
instance.
|
||||
:param instance: nova.objects.instance.Instance
|
||||
"""
|
||||
LOG.info("Pause instance %s" % instance.uuid)
|
||||
LOG.info(_LI("Pause instance %s") % instance.uuid)
|
||||
self.power_off(instance)
|
||||
|
||||
def unpause(self, instance):
|
||||
@ -390,7 +407,7 @@ class GCEDriver(driver.ComputeDriver):
|
||||
instance. and powering on such an instance in this method.
|
||||
:param instance: nova.objects.instance.Instance
|
||||
"""
|
||||
LOG.info("Unpause instance %s" % instance.uuid)
|
||||
LOG.info(_LI("Unpause instance %s") % instance.uuid)
|
||||
self.power_on(context=None, instance=instance, network_info=None,
|
||||
block_device_info=None)
|
||||
|
||||
@ -401,7 +418,7 @@ class GCEDriver(driver.ComputeDriver):
|
||||
instance.
|
||||
:param instance: nova.objects.instance.Instance
|
||||
"""
|
||||
LOG.info("Suspending instance %s" % instance.uuid)
|
||||
LOG.info(_LI("Suspending instance %s") % instance.uuid)
|
||||
self.power_off(instance)
|
||||
|
||||
def resume(self, context, instance, network_info, block_device_info=None):
|
||||
@ -411,7 +428,7 @@ class GCEDriver(driver.ComputeDriver):
|
||||
instance.
|
||||
:param instance: nova.objects.instance.Instance
|
||||
"""
|
||||
LOG.info("Resuming instance %s" % instance.uuid)
|
||||
LOG.info(_LI("Resuming instance %s") % instance.uuid)
|
||||
self.power_on(context, instance, network_info, block_device_info)
|
||||
|
||||
def destroy(self, context, instance, network_info, block_device_info=None,
|
||||
@ -433,22 +450,41 @@ class GCEDriver(driver.ComputeDriver):
|
||||
"""
|
||||
compute, project, zone = self.gce_svc, self.gce_project, self.gce_zone
|
||||
gce_id = self._get_gce_id_from_instance(instance)
|
||||
LOG.info('Deleting instance %s' % instance.uuid)
|
||||
LOG.info(_LI('Deleting instance %s') % instance.uuid)
|
||||
operation = gceutils.delete_instance(compute, project, zone, gce_id)
|
||||
gceutils.wait_for_operation(compute, project, zone, operation)
|
||||
LOG.info("Destroy Complete %s" % instance.uuid)
|
||||
LOG.info(_LI("Destroy Complete %s") % instance.uuid)
|
||||
|
||||
def attach_volume(self, context, connection_info, instance, mountpoint,
|
||||
disk_bus=None, device_type=None, encryption=None):
|
||||
"""Attach the disk to the instance at mountpoint using info.
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
compute, project, zone = self.gce_svc, self.gce_project, self.gce_zone
|
||||
gce_id = self._get_gce_id_from_instance(instance)
|
||||
gce_volume = connection_info['data']
|
||||
disk_name = gce_volume['name'],
|
||||
disk_link = gce_volume['selfLink']
|
||||
operation = gceutils.attach_disk(compute, project, zone, gce_id,
|
||||
disk_name, disk_link)
|
||||
gceutils.wait_for_operation(compute, project, zone, operation)
|
||||
LOG.info(
|
||||
_LI("Volume %s attached to instace %s") % (disk_name,
|
||||
instance.uuid))
|
||||
|
||||
def detach_volume(self, connection_info, instance, mountpoint,
|
||||
encryption=None):
|
||||
"""Detach the disk attached to the instance.
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
compute, project, zone = self.gce_svc, self.gce_project, self.gce_zone
|
||||
gce_id = self._get_gce_id_from_instance(instance)
|
||||
gce_volume = connection_info['data']
|
||||
disk_name = gce_volume['name']
|
||||
operation = gceutils.detach_disk(compute, project, zone, gce_id,
|
||||
disk_name)
|
||||
gceutils.wait_for_operation(compute, project, zone, operation)
|
||||
LOG.info(
|
||||
_LI("Volume %s detached from instace %s") % (disk_name,
|
||||
instance.uuid))
|
||||
|
||||
def swap_volume(self, old_connection_info, new_connection_info, instance,
|
||||
mountpoint, resize_to):
|
||||
|
@ -297,3 +297,43 @@ def get_network(compute, project, name):
|
||||
"""
|
||||
result = compute.networks().get(project=project, network=name).execute()
|
||||
return result
|
||||
|
||||
|
||||
def attach_disk(compute, project, zone, instance_name, disk_name, disk_link):
|
||||
"""Attach disk to instance
|
||||
:param compute: GCE compute resource object using googleapiclient.discovery
|
||||
:param project: string, GCE Project Id
|
||||
:param zone: string, GCE Name of zone
|
||||
:param instance_name: string, GCE instance name
|
||||
:param disk_name: string, GCE disk name
|
||||
:param disk_link: url, GCE disk link
|
||||
:return: Operation information
|
||||
:rtype: dict
|
||||
"""
|
||||
body = {
|
||||
"type": "PERSISTENT",
|
||||
"mode": "READ_WRITE",
|
||||
"source": disk_link,
|
||||
"deviceName": disk_name,
|
||||
"boot": False,
|
||||
"autoDelete": False,
|
||||
"interface": "SCSI"
|
||||
}
|
||||
return compute.instances().attachDisk(project=project, zone=zone,
|
||||
instance=instance_name,
|
||||
body=body).execute()
|
||||
|
||||
|
||||
def detach_disk(compute, project, zone, instance_name, disk_name):
|
||||
"""Detach disk from instance
|
||||
:param compute: GCE compute resource object using googleapiclient.discovery
|
||||
:param project: string, GCE Project Id
|
||||
:param zone: string, GCE Name of zone
|
||||
:param instance_name: string, GCE instance name
|
||||
:param disk_name: string, GCE disk name
|
||||
:return: Operation information
|
||||
:rtype: dict
|
||||
"""
|
||||
return compute.instances().detachDisk(project=project, zone=zone,
|
||||
instance=instance_name,
|
||||
deviceName=disk_name).execute()
|
||||
|
Loading…
x
Reference in New Issue
Block a user