Skip to content
This repository has been archived by the owner on Nov 9, 2020. It is now read-only.

Fix KV files on clone. #2077

Merged
merged 5 commits into from
Mar 27, 2018
Merged
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
101 changes: 72 additions & 29 deletions esx_service/utils/kvESX.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@

from ctypes import \
CDLL, POINTER, byref, Structure,\
c_char_p, c_int32, c_bool, c_uint32, c_uint64
c_char_p, c_int32, c_bool, c_uint32, c_uint64,\
create_string_buffer, addressof
import json
import logging
import sys
Expand Down Expand Up @@ -49,6 +50,9 @@
# Volume KV prop
KV_VOL_DESC_PROP = "sidecars".encode()

# KV file type
KV_FILE_TYPE='sidecars'

# VSphere lib to access ESX proprietary APIs.
DISK_LIB64 = "/lib64/libvmsnapshot.so"
DISK_LIB = "/lib/libvmsnapshot.so"
Expand Down Expand Up @@ -185,6 +189,30 @@ def kv_esx_init():
disk_lib_init()


def get_vol_type(volpath):
vol_type = c_uint32(0)
res = lib.ObjLib_PathToType(volpath.encode(), byref(vol_type))
if res != 0:
logging.warning("Could not determine type of volume %s, error - %x", volpath, res)
return None
return vol_type.value

def get_kv_filename(volpath):
kv_type = KV_FILE_TYPE
try:
with open(volpath) as f:
for line in f:
if KV_FILE_TYPE in line:
s=line.split(',')[1]
kv_file = s.split('"')[0]
return "{0}/{1}".format(os.path.dirname(volpath),
kv_file)
except IOError as open_error:
logging.exception("Failed to open %s", volpath)
return None
return None


@diskLibLock
def vol_open_path(volpath, open_flags=VMDK_OPEN_DEFAULT):
"""
Expand All @@ -210,15 +238,12 @@ def create(volpath, kv_dict):
"""
obj_handle = get_uint(0)

# If the volume is a virtual type then
# create the KV as a flat file.
vol_type = c_uint32(0)
res = lib.ObjLib_PathToType(volpath.encode(), byref(vol_type))
if res != 0:
logging.warning("Could not determine type of volume %s, error - %x", volpath, res)
# If the volume is a virtual type then the KV as a flat file.
vol_type = get_vol_type(volpath)
if not vol_type:
logging.warning("Could not determine type of volume %s", volpath)
return False

if vol_type.value == c_uint32(KV_VOL_VIRTUAL).value:
if vol_type == c_uint32(KV_VOL_VIRTUAL).value:
return save(volpath, kv_dict)

dhandle = vol_open_path(volpath)
Expand Down Expand Up @@ -248,12 +273,11 @@ def delete(volpath):
"""
Delete the side car for the given volume.
"""
vol_type = c_uint32(0)
res = lib.ObjLib_PathToType(volpath.encode(), byref(vol_type))
if res != 0:
logging.warning("KV delete - could not determine type of volume %s, error - %x", volpath, res)
vol_type = get_vol_type(volpath)
if not vol_type:
logging.warning("KV delete - could not determine type of volume %s", volpath)
return False
if vol_type.value == c_uint32(KV_VOL_VIRTUAL).value:
if vol_type == c_uint32(KV_VOL_VIRTUAL).value:
meta_file = lib.DiskLib_SidecarMakeFileName(volpath.encode(), DVOL_KEY.encode())
if os.path.exists(meta_file):
os.unlink(meta_file)
Expand Down Expand Up @@ -288,8 +312,17 @@ def load(volpath):
"""
Load and return dictionary from the sidecar
"""
meta_file = lib.DiskLib_SidecarMakeFileName(volpath.encode(),
DVOL_KEY.encode())
vol_type = get_vol_type(volpath)
if not vol_type:
logging.warning("KV delete - could not determine type of volume %s", volpath)
return None
if vol_type == c_uint32(KV_VOL_VIRTUAL).value:
meta_file = lib.DiskLib_SidecarMakeFileName(volpath.encode(),
DVOL_KEY.encode())
else:
meta_file = get_kv_filename(volpath)
if not meta_file:
return None
retry_count = 0
vol_name = vmdk_utils.get_volname_from_vmdk_path(volpath)
while True:
Expand Down Expand Up @@ -320,8 +353,18 @@ def save(volpath, kv_dict, key=None, value=None):
"""
Save the dictionary to side car.
"""
meta_file = lib.DiskLib_SidecarMakeFileName(volpath.encode(),
DVOL_KEY.encode())
vol_type = get_vol_type(volpath)
if not vol_type:
logging.warning("KV delete - could not determine type of volume %s", volpath)
return False
if vol_type == c_uint32(KV_VOL_VIRTUAL).value:
meta_file = lib.DiskLib_SidecarMakeFileName(volpath.encode(),
DVOL_KEY.encode())
else:
meta_file = get_kv_filename(volpath)
if not meta_file:
return False

kv_str = json.dumps(kv_dict)

retry_count = 0
Expand Down Expand Up @@ -361,23 +404,23 @@ def fixup_kv(src_volpath, dst_volpath):
Fix up the sidecars for the destination volume which ever is a
volume of type - virtual.
"""
src_vol_type = c_uint32(0)
res = lib.ObjLib_PathToType(src_volpath.encode(), byref(src_vol_type))
if res != 0:
logging.warning("Could not determine type of volume %s, error - %x", src_volpath, res)
src_vol_type = get_vol_type(src_volpath)
logging.warning("Source vvol type %x", src_vol_type)
if not src_vol_type:
logging.warning("KV delete - could not determine type of volume %s", src_volpath)
return False

dst_vol_type = c_uint32(0)
res = lib.ObjLib_PathToType(dst_volpath.encode(), byref(dst_vol_type))
if res != 0:
logging.warning("Could not determine type of volume %s, error - %x", dst_volpath, res)
dst_vol_type = get_vol_type(dst_volpath)
logging.warning("Dest vvol type %x", src_vol_type)
if not dst_vol_type:
logging.warning("KV delete - could not determine type of volume %s", dst_volpath)
return False

if src_vol_type.value != c_uint32(KV_VOL_VIRTUAL).value:
if src_vol_type != c_uint32(KV_VOL_VIRTUAL).value:
# If the destination is a virtual type volume,
# the source will create a native sidecar that must be deleted
# and a new flat file version is created.
if dst_vol_type.value == c_uint32(KV_VOL_VIRTUAL).value:
if dst_vol_type == c_uint32(KV_VOL_VIRTUAL).value:
dhandle = vol_open_path(dst_volpath)
if not disk_is_valid(dhandle):
return False
Expand All @@ -386,7 +429,7 @@ def fixup_kv(src_volpath, dst_volpath):
logging.warning("Side car delete for %s failed - %x", dst_volpath, res)
lib.DiskLib_Close(dhandle)
return False

lib.DiskLib_Close(dhandle)
src_dict = load(src_volpath)
return create(dst_volpath, src_dict)
Expand Down
5 changes: 4 additions & 1 deletion esx_service/vmdk_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,10 @@ def cloneVMDK(vm_name, vmdk_path, opts={}, vm_uuid=None, datastore_url=None, vm_

vol_name = vmdk_utils.strip_vmdk_extension(src_vmdk_path.split("/")[-1])

# Fix up the KV for the destination
# Clone creates side cars with a random key and hence filename
# which need more work to figure out and use each time a volume
# op is performed. Remove the side car that the clone created
# and create a new one. Fix up the KV for the destination
if not kv.fixup_kv(src_vmdk_path, vmdk_path):
msg = ("Failed to create volume KV for %s" % vol_name)
logging.warning(msg)
Expand Down