Implement resize volume method
Trove use Cinder as volume backend default and Cinder requires that volume must in "available" status if wish to resize. So we should stop db firstly, then detach volume from instance and resize volume. Finally, restart db in ease. If resize volume failed, the instance may stuck into "RESIZE" status. Because we have no idea to rescue the volume which is in "error_extending" by Cinder. implement bp implement-volume-extend Change-Id: Iff3b302a705917e0e27cd70edf6e1be1639f62d5
This commit is contained in:
parent
1467437f83
commit
6956868753
@ -456,36 +456,50 @@ class BuiltInstanceTasks(BuiltInstance, NotifyMixin, ConfigurationMixin):
|
||||
deleted_at=timeutils.isotime(deleted_at),
|
||||
server=old_server)
|
||||
|
||||
def resize_volume(self, new_size):
|
||||
old_volume_size = self.volume_size
|
||||
new_size = int(new_size)
|
||||
LOG.debug("%s: Resizing volume for instance: %s from %s to %r GB"
|
||||
% (greenthread.getcurrent(), self.server.id,
|
||||
old_volume_size, new_size))
|
||||
def _resize_active_volume(self, new_size):
|
||||
try:
|
||||
LOG.debug("Instance %s calling stop_db..." % self.server.id)
|
||||
self.guest.stop_db()
|
||||
|
||||
LOG.debug("Detach volume %s from instance %s" % (self.volume_id,
|
||||
self.server.id))
|
||||
self.volume_client.volumes.detach(self.volume_id)
|
||||
|
||||
utils.poll_until(
|
||||
lambda: self.volume_client.volumes.get(self.volume_id),
|
||||
lambda volume: volume.status == 'available',
|
||||
sleep_time=2,
|
||||
time_out=CONF.volume_time_out)
|
||||
|
||||
LOG.debug("Successfully detach volume %s" % self.volume_id)
|
||||
except Exception as e:
|
||||
LOG.error("Failed to detach volume %s instance %s: %s" % (
|
||||
self.volume_id, self.server.id, str(e)))
|
||||
self.restart()
|
||||
raise
|
||||
|
||||
self._do_resize(new_size)
|
||||
self.volume_client.volumes.attach(self.server.id, self.volume_id)
|
||||
|
||||
self.restart()
|
||||
|
||||
def _do_resize(self, new_size):
|
||||
try:
|
||||
self.volume_client.volumes.extend(self.volume_id, new_size)
|
||||
except cinder_exceptions.ClientException:
|
||||
self.update_db(task_status=inst_models.InstanceTasks.NONE)
|
||||
LOG.exception("Error encountered trying to rescan or resize the "
|
||||
"attached volume filesystem for volume: "
|
||||
"%s" % self.volume_id)
|
||||
raise
|
||||
|
||||
try:
|
||||
volume = self.volume_client.volumes.get(self.volume_id)
|
||||
utils.poll_until(
|
||||
lambda: self.volume_client.volumes.get(self.volume_id),
|
||||
lambda volume: volume.status == 'in-use',
|
||||
lambda volume: volume.size == int(new_size),
|
||||
sleep_time=2,
|
||||
time_out=CONF.volume_time_out)
|
||||
volume = self.volume_client.volumes.get(self.volume_id)
|
||||
self.update_db(volume_size=volume.size)
|
||||
self.nova_client.volumes.rescan_server_volume(self.server,
|
||||
self.volume_id)
|
||||
self.send_usage_event('modify_volume',
|
||||
old_volume_size=old_volume_size,
|
||||
launched_at=timeutils.isotime(),
|
||||
modify_at=timeutils.isotime(),
|
||||
volume_size=new_size)
|
||||
self.update_db(volume_size=new_size)
|
||||
except PollTimeOut as pto:
|
||||
LOG.error("Timeout trying to rescan or resize the attached volume "
|
||||
"filesystem for volume: %s" % self.volume_id)
|
||||
@ -497,6 +511,23 @@ class BuiltInstanceTasks(BuiltInstance, NotifyMixin, ConfigurationMixin):
|
||||
finally:
|
||||
self.update_db(task_status=inst_models.InstanceTasks.NONE)
|
||||
|
||||
def resize_volume(self, new_size):
|
||||
old_volume_size = self.volume_size
|
||||
new_size = int(new_size)
|
||||
LOG.debug("%s: Resizing volume for instance: %s from %s to %r GB"
|
||||
% (greenthread.getcurrent(), self.server.id,
|
||||
old_volume_size, new_size))
|
||||
|
||||
if self.server.status == 'active':
|
||||
self._resize_active_volume(new_size)
|
||||
else:
|
||||
self._do_resize(new_size)
|
||||
|
||||
self.send_usage_event('modify_volume', old_volume_size=old_volume_size,
|
||||
launched_at=timeutils.isotime(),
|
||||
modify_at=timeutils.isotime(),
|
||||
volume_size=new_size)
|
||||
|
||||
def resize_flavor(self, old_flavor, new_flavor):
|
||||
action = ResizeAction(self, old_flavor, new_flavor)
|
||||
action.execute()
|
||||
|
@ -501,11 +501,23 @@ class FakeVolumes(object):
|
||||
LOG.debug("Resize volume id (%s) to size (%s)" % (volume_id, new_size))
|
||||
volume = self.get(volume_id)
|
||||
|
||||
if volume._current_status != 'available':
|
||||
raise Exception("Invalid volume status")
|
||||
|
||||
def finish_resize():
|
||||
volume._current_status = "in-use"
|
||||
volume.size = new_size
|
||||
self.event_spawn(1.0, finish_resize)
|
||||
|
||||
def detach(self, volume_id):
|
||||
volume = self.get(volume_id)
|
||||
|
||||
if volume._current_status != 'in-use':
|
||||
raise Exception("Invalid volume status")
|
||||
|
||||
def finish_detach():
|
||||
volume._current_status = "available"
|
||||
self.event_spawn(1.0, finish_detach)
|
||||
|
||||
|
||||
class FakeAccount(object):
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user