def set_vol_opts(vmdk_path, options): # Create a dict of the options, the options are provided as # "access=read-only" and we get a dict like {'access': 'read-only'} opts_list = "".join(options.replace("=", ":").split()) opts = dict(i.split(":") for i in opts_list.split(",")) # For now only allow resetting the access mode. valid_opts = [kv.ACCESS] invalid = frozenset(opts.keys()).difference(valid_opts) if len(invalid) != 0: msg = 'Invalid options: {0} \n'.format(list(invalid)) \ + 'Options that can be edited: ' \ + '{0}'.format(list(valid_opts)) raise ValidationError(msg) if not opts[kv.ACCESS] in kv.ACCESS_TYPES: msg = 'Invalid option value {0}.\n'.format(opts[kv.ACCESS]) +\ 'Supported values are {0}.\n'.format(kv.ACCESS_TYPES) logging.warning(msg) return False vol_meta = kv.getAll(vmdk_path) if vol_meta: vol_meta[kv.VOL_OPTS][kv.ACCESS] = opts[kv.ACCESS] return kv.setAll(vmdk_path, vol_meta) return False
def getVMDK(vmdk_path, vol_name, datastore): """Checks if the volume exists, and returns error if it does not""" # Note: will return more Volume info here, when Docker API actually accepts it if not os.path.isfile(vmdk_path): return err("Volume {0} not found (file: {1})".format(vol_name, vmdk_path)) # Return volume info - volume policy, size, allocated capacity, allocation # type, creat-by, create time. return vol_info(kv.getAll(vmdk_path), kv.get_vol_info(vmdk_path), datastore)
def kv_get_vsan_policy_name(path): """ Take a path for a vmdk and return a policy name if it exists or None if it doesn't """ try: return kv.getAll(path)[kv.VOL_OPTS][kv.VSAN_POLICY_NAME] except: return None
def setStatusAttached(vmdk_path, vm): '''Sets metadata for vmdk_path to (attached, attachedToVM=uuid''' logging.debug("Set status=attached disk=%s VM name=%s uuid=%s", vmdk_path, vm.config.name, vm.config.uuid) vol_meta = kv.getAll(vmdk_path) if not vol_meta: vol_meta = {} vol_meta[kv.STATUS] = kv.ATTACHED vol_meta[kv.ATTACHED_VM_UUID] = vm.config.uuid vol_meta[kv.ATTACHED_VM_NAME] = vm.config.name if not kv.setAll(vmdk_path, vol_meta): logging.warning("Attach: Failed to save Disk metadata for %s", vmdk_path)
def getStatusAttached(vmdk_path): '''Returns (attached, uuid) tuple. For 'detached' status uuid is None''' vol_meta = kv.getAll(vmdk_path) if not vol_meta or kv.STATUS not in vol_meta: return False, None attached = (vol_meta[kv.STATUS] == kv.ATTACHED) try: uuid = vol_meta[kv.ATTACHED_VM_UUID] except: uuid = None return attached, uuid
def setStatusDetached(vmdk_path): '''Sets metadata for vmdk_path to "detached"''' logging.debug("Set status=detached disk=%s", vmdk_path) vol_meta = kv.getAll(vmdk_path) if not vol_meta: vol_meta = {} vol_meta[kv.STATUS] = kv.DETACHED # If attachedVMName is present, so is attachedVMUuid try: del vol_meta[kv.ATTACHED_VM_UUID] del vol_meta[kv.ATTACHED_VM_NAME] except: pass if not kv.setAll(vmdk_path, vol_meta): logging.warning("Detach: Failed to save Disk metadata for %s", vmdk_path)
def doDetach(volDir, vmName): print "Detaching volumes" for vol in vols: volPath = os.path.join(volDir, "%s.vmdk" % vol) vmci.detachVMDK(volPath, vmName) print "Verifying volume metadata" for vol in vols: volPath = os.path.join(volDir, "%s.vmdk" % vol) volDict = kv.getAll(volPath) if volDict[kv.STATUS] != kv.DETACHED: print 'Found volume %s with status %s, expected %s' % ( vol, volDict[kv.STATUS], kv.DETACHED) return
def getStatusAttached(vmdk_path): '''Returns (attached, uuid, attach_as) tuple. For 'detached' status uuid is None''' vol_meta = kv.getAll(vmdk_path) try: attach_as = vol_meta[kv.VOL_OPTS][kv.ATTACH_AS] except: attach_as = kv.DEFAULT_ATTACH_AS if not vol_meta or kv.STATUS not in vol_meta: return False, None, attach_as attached = (vol_meta[kv.STATUS] == kv.ATTACHED) try: uuid = vol_meta[kv.ATTACHED_VM_UUID] except: uuid = None return attached, uuid, attach_as
def reset_vol_meta(vmdk_path): '''Clears metadata for vmdk_path''' vol_meta = kv.getAll(vmdk_path) if not vol_meta: vol_meta = {} logging.debug("Reseting meta-data for disk=%s", vmdk_path) if set(vol_meta.keys()) & {kv.STATUS, kv.ATTACHED_VM_UUID, kv.ATTACHED_VM_NAME}: logging.debug("Old meta-data for %s was (status=%s VM name=%s uuid=%s)", vmdk_path, vol_meta[kv.STATUS], vol_meta[kv.ATTACHED_VM_NAME], vol_meta[kv.ATTACHED_VM_UUID]) vol_meta[kv.STATUS] = kv.DETACHED vol_meta[kv.ATTACHED_VM_UUID] = None vol_meta[kv.ATTACHED_VM_NAME] = None if not kv.setAll(vmdk_path, vol_meta): msg = "Failed to save volume metadata for {0}.".format(vmdk_path) logging.warning("reset_vol_meta: " + msg) return err(msg)
def doCreate(volDir): print "Creating volumes" for vol in vols: volPath = os.path.join(volDir, "%s.vmdk" % vol) vmci.createVMDK(volPath, vol, None) print "Verifying volume metadata" for vol in vols: volPath = os.path.join(volDir, "%s.vmdk" % vol) volDict = kv.getAll(volPath) if not volDict: print "Failed to fetch volume meta-data for ", volPath continue print "Vol metadata 'status' - %s, 'volOpts' - %s" % ( volDict[kv.STATUS], volDict[kv.VOL_OPTS]) if volDict[kv.STATUS] != kv.DETACHED: print 'Found volume %s with status %s, expected %s' % ( vol, volDict[kv.STATUS], kv.DETACHED) return
def get_metadata(volPath): """ Take the absolute path to volume vmdk and return its metadata as a dict """ return kv.getAll(volPath)
def set_vol_opts(name, options): # Create a dict of the options, the options are provided as # "access=read-only" and we get a dict like {'access': 'read-only'} opts_list = "".join(options.replace("=", ":").split()) opts = dict(i.split(":") for i in opts_list.split(",")) # create volume path try: vol_name, datastore = parse_vol_name(name) except ValidationError as ex: logging.exception(ex) return False if not datastore: msg = "Invalid datastore '{0}'.\n".format(datastore) logging.warning(msg) return False # get /vmfs/volumes/<datastore>/dockvols path on ESX: path = get_vol_path(datastore) if path is None: msg = "Failed to get datastore path {0}".format(path) logging.warning(msg) return False vmdk_path = vmdk_utils.get_vmdk_path(path, vol_name) if not os.path.isfile(vmdk_path): msg = 'Volume {0} not found.'.format(vol_name) logging.warning(msg) return False # For now only allow resetting the access and attach-as options. valid_opts = { kv.ACCESS : kv.ACCESS_TYPES, kv.ATTACH_AS : kv.ATTACH_AS_TYPES } invalid = frozenset(opts.keys()).difference(valid_opts.keys()) if len(invalid) != 0: msg = 'Invalid options: {0} \n'.format(list(invalid)) \ + 'Options that can be edited: ' \ + '{0}'.format(list(valid_opts)) raise ValidationError(msg) has_invalid_opt_value = False for key in opts.keys(): if key in valid_opts: if not opts[key] in valid_opts[key]: msg = 'Invalid option value {0}.\n'.format(opts[key]) +\ 'Supported values are {0}.\n'.format(valid_opts[key]) logging.warning(msg) has_invalid_opt_value = True if has_invalid_opt_value: return False vol_meta = kv.getAll(vmdk_path) if vol_meta: if not vol_meta[kv.VOL_OPTS]: vol_meta[kv.VOL_OPTS] = {} for key in opts.keys(): vol_meta[kv.VOL_OPTS][key] = opts[key] return kv.setAll(vmdk_path, vol_meta) return False