Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 30 additions & 22 deletions drivers/LinstorSR.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

from sm_typing import Optional, override
from sm_typing import Optional, override, Tuple

from constants import CBTLOG_TAG

Expand Down Expand Up @@ -1907,7 +1907,30 @@ def detach(self, sr_uuid, vdi_uuid) -> None:
vdi_uuid = parent_vdi_uuid

@override
def resize(self, sr_uuid, vdi_uuid, size) -> str:
def resize(self, sr_uuid: str, vdi_uuid: str, size: int) -> str:
def compute_vdi_sizes(vdi: LinstorVDI) -> Tuple[int, int]:
if vdi.vdi_type == vhdutil.VDI_TYPE_RAW:
return vdi.size, LinstorVolumeManager.round_up_volume_size(size)

old_volume_size = vdi.utilisation
if vdi.sr._provisioning == 'thin':
# VDI is currently deflated, so keep it deflated.
return old_volume_size, old_volume_size

return old_volume_size, LinstorVhdUtil.compute_volume_size(size, vdi.vdi_type)

def resize_vdi(vdi: LinstorVDI, old_volume_size: int, new_volume_size) -> None:
if vdi.vdi_type == vhdutil.VDI_TYPE_RAW:
vdi._linstor.resize_volume(vdi.uuid, new_volume_size)
return

if new_volume_size != old_volume_size:
vdi.sr._vhdutil.inflate(
vdi.sr._journaler, vdi.uuid, vdi.path,
new_volume_size, old_volume_size
)
vdi.sr._vhdutil.set_size_virt_fast(vdi.path, size)

util.SMlog('LinstorVDI.resize for {}'.format(self.uuid))
if not self.sr.is_master():
raise xs_errors.XenError(
Expand All @@ -1934,37 +1957,22 @@ def resize(self, sr_uuid, vdi_uuid, size) -> str:
raise xs_errors.XenError('VDISize', opterr='shrinking not allowed')

if size == self.size:
return VDI.VDI.get_params(self)
return VDI.VDI.get_params(self) # No change needed

if self.vdi_type == vhdutil.VDI_TYPE_RAW:
old_volume_size = self.size
new_volume_size = LinstorVolumeManager.round_up_volume_size(size)
else:
old_volume_size = self.utilisation
if self.sr._provisioning == 'thin':
# VDI is currently deflated, so keep it deflated.
new_volume_size = old_volume_size
else:
new_volume_size = LinstorVhdUtil.compute_volume_size(size, self.vdi_type)
old_volume_size, new_volume_size = compute_vdi_sizes(self)
assert new_volume_size >= old_volume_size

space_needed = new_volume_size - old_volume_size
self.sr._ensure_space_available(space_needed)

old_size = self.size
if self.vdi_type == vhdutil.VDI_TYPE_RAW:
self._linstor.resize(self.uuid, new_volume_size)
else:
if new_volume_size != old_volume_size:
self.sr._vhdutil.inflate(
self.sr._journaler, self.uuid, self.path,
new_volume_size, old_volume_size
)
self.sr._vhdutil.set_size_virt_fast(self.path, size)

resize_vdi(self, old_volume_size, new_volume_size)

# Reload size attributes.
self._load_this()

# Update metadata
vdi_ref = self.sr.srcmd.params['vdi_ref']
self.session.xenapi.VDI.set_virtual_size(vdi_ref, str(self.size))
self.session.xenapi.VDI.set_physical_utilisation(
Expand Down
44 changes: 22 additions & 22 deletions drivers/linstorvolumemanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -841,31 +841,31 @@ def resize_volume(self, volume_uuid, new_size):
self.ensure_volume_is_not_locked(volume_uuid)
new_size = self.round_up_volume_size(new_size) // 1024

retry_count = 30
while True:
result = self._linstor.volume_dfn_modify(
rsc_name=volume_name,
volume_nr=0,
size=new_size
)

self._mark_resource_cache_as_dirty()

error_str = self._get_error_str(result)
if not error_str:
break
# We can't resize anything until DRBD is up to date
# We wait here for 5min max and raise an easy to understand error for the user
# This is mostly an issue for thick provisioning, thin isn't affected
start_time = time.monotonic()
try:
self._linstor.resource_dfn_wait_synced(volume_name, wait_interval=1.0, timeout=60*5)
except linstor.LinstorTimeoutError:
raise linstor.LinstorTimeoutError(
f"Volume `{volume_uuid}` from SR `{self._group_name}` is busy and can't be resized right now. " +
"Please retry later."
)
util.SMlog(f"DRBD is up to date, syncing took {time.monotonic() - start_time}s")

result = self._linstor.volume_dfn_modify(
rsc_name=volume_name,
volume_nr=0,
size=new_size
)

# After volume creation, DRBD volume can be unusable during many seconds.
# So we must retry the definition change if the device is not up to date.
# Often the case for thick provisioning.
if retry_count and error_str.find('non-UpToDate DRBD device') >= 0:
time.sleep(2)
retry_count -= 1
continue
self._mark_resource_cache_as_dirty()

error_str = self._get_error_str(result)
if error_str:
raise LinstorVolumeManagerError(
'Could not resize volume `{}` from SR `{}`: {}'
.format(volume_uuid, self._group_name, error_str)
f"Could not resize volume `{volume_uuid}` from SR `{self._group_name}`: {error_str}"
)

def get_volume_name(self, volume_uuid):
Expand Down