def testPolicy(self): # info for testPolicy testInfo = [ # size policy expected success? ["2000kb", "good", True, "zeroedthick"], ["14000pb", "good", False, "zeroedthick"], ["bad size", "good", False, "eagerzeroedthick"], ["100mb", "impossible", True, "eagerzeroedthick"], ["100mb", "good", True, "thin"], ] path = vsan_info.get_vsan_dockvols_path() i = 0 for unit in testInfo: vol_name = '{0}{1}'.format(self.volName, i) vmdk_path = vmdk_utils.get_vmdk_path(path,vol_name) i = i+1 # create a volume with requests size/policy and check vs expected result err = vmdk_ops.createVMDK(vm_name=self.vm_name, vmdk_path=vmdk_path, vol_name=vol_name, opts={volume_kv.VSAN_POLICY_NAME: unit[1], volume_kv.SIZE: unit[0], volume_kv.DISK_ALLOCATION_FORMAT: unit[3]}) self.assertEqual(err == None, unit[2], err) # clean up should fail if the created should have failed. err = vmdk_ops.removeVMDK(vmdk_path) self.assertEqual(err == None, unit[2], err)
def executeRequest(vm_uuid, vm_name, config_path, cmd, full_vol_name, opts): """ Executes a <cmd> request issused from a VM. The request is about volume <full_volume_name> in format volume@datastore. If @datastore is omitted, the one where the VM resides is used. For VM, the function gets vm_uuid, vm_name and config_path <opts> is a json options string blindly passed to a specific operation Returns None (if all OK) or error string """ vm_datastore = get_datastore_name(config_path) error_info, tenant_uuid, tenant_name = auth.authorize(vm_uuid, vm_datastore, cmd, opts) if error_info: return err(error_info) if cmd == "list": return listVMDK(vm_datastore, tenant_name) try: vol_name, datastore = parse_vol_name(full_vol_name) except ValidationError as ex: return err(str(ex)) if not datastore: datastore = vm_datastore elif datastore not in known_datastores(): return err("Invalid datastore '%s'.\n" \ "Known datastores: %s.\n" \ "Default datastore: %s" \ % (datastore, ", ".join(known_datastores()), vm_datastore)) # get /vmfs/volumes/<volid>/dockvols path on ESX: path = get_vol_path(datastore, tenant_name) logging.debug("executeRequest %s %s", tenant_name, path) if path is None: return err("Failed to initialize volume path {0}".format(path)) vmdk_path = vmdk_utils.get_vmdk_path(path, vol_name) if cmd == "get": response = getVMDK(vmdk_path, vol_name, datastore) elif cmd == "create": response = createVMDK(vmdk_path, vm_name, vol_name, opts) # create succeed, insert infomation of this volume to volumes table if not response: if tenant_uuid: vol_size_in_MB = convert.convert_to_MB(auth.get_vol_size(opts)) auth.add_volume_to_volumes_table(tenant_uuid, datastore, vol_name, vol_size_in_MB) else: logging.warning(" VM %s does not belong to any tenant", vm_name) elif cmd == "remove": response = removeVMDK(vmdk_path) elif cmd == "attach": response = attachVMDK(vmdk_path, vm_uuid) elif cmd == "detach": response = detachVMDK(vmdk_path, vm_uuid) else: return err("Unknown command:" + cmd) return response
def testPolicy(self): # info for testPolicy testInfo = [ # size policy expected success? ["2000kb", "good", True, "zeroedthick"], ["14000pb", "good", False, "zeroedthick"], ["bad size", "good", False, "eagerzeroedthick"], ["100mb", "impossible", True, "eagerzeroedthick"], ["100mb", "good", True, "thin"], ] path = vsan_info.get_vsan_dockvols_path() i = 0 for unit in testInfo: vol_name = '{0}{1}'.format(self.volName, i) vmdk_path = vmdk_utils.get_vmdk_path(path, vol_name) i = i + 1 # create a volume with requests size/policy and check vs expected result err = vmdk_ops.createVMDK(vm_name=self.vm_name, vmdk_path=vmdk_path, vol_name=vol_name, opts={ volume_kv.VSAN_POLICY_NAME: unit[1], volume_kv.SIZE: unit[0], volume_kv.DISK_ALLOCATION_FORMAT: unit[3] }) self.assertEqual(err == None, unit[2], err) # clean up should fail if the created should have failed. err = vmdk_ops.removeVMDK(vmdk_path) self.assertEqual(err == None, unit[2], err)
def setUp(self): self.name = vmdk_utils.get_vmdk_path(path, self.volName) self.policy_names = ['good', 'impossible'] self.orig_policy_content = ('(("proportionalCapacity" i0) ' '("hostFailuresToTolerate" i0))') self.new_policy_content = '(("hostFailuresToTolerate" i0))' for n in self.policy_names: vsan_policy.create(n, self.orig_policy_content)
def executeRequest(vm_uuid, vm_name, config_path, cmd, full_vol_name, opts): """ Executes a <cmd> request issused from a VM. The request is about volume <full_volume_name> in format volume@datastore. If @datastore is omitted, the one where the VM resides is used. For VM, the function gets vm_uuid, vm_name and config_path <opts> is a json options string blindly passed to a specific operation Returns None (if all OK) or error string """ vm_datastore = get_datastore_name(config_path) if cmd == "list": return listVMDK(vm_datastore) try: vol_name, datastore = parse_vol_name(full_vol_name) except ValidationError as ex: return err(str(ex)) if not datastore: datastore = vm_datastore elif datastore not in known_datastores(): return err("Invalid datastore '%s'.\n" \ "Known datastores: %s.\n" \ "Default datastore: %s" \ % (datastore, ", ".join(known_datastores()), vm_datastore)) # get /vmfs/volumes/<volid>/dockvols path on ESX: path = get_vol_path(datastore) if path is None: return err("Failed to initialize volume path {0}".format(path)) vmdk_path = vmdk_utils.get_vmdk_path(path, vol_name) if cmd == "get": response = getVMDK(vmdk_path, vol_name, datastore) elif cmd == "create": response = createVMDK(vmdk_path, vm_name, vol_name, opts) elif cmd == "remove": response = removeVMDK(vmdk_path) elif cmd == "attach": response = attachVMDK(vmdk_path, vm_uuid) elif cmd == "detach": response = detachVMDK(vmdk_path, vm_uuid) else: return err("Unknown command:" + cmd) return response
def testPolicyUpdate(self): path = vsan_info.get_vsan_dockvols_path() vmdk_path = vmdk_utils.get_vmdk_path(path, self.volName) err = vmdk_ops.createVMDK(vm_name=self.vm_name, vmdk_path=vmdk_path, vol_name=self.volName, opts={'vsan-policy-name': 'good'}) self.assertEqual(err, None, err) self.assertEqual(None, vsan_policy.update('good', self.new_policy_content)) # Setting an identical policy returns an error msg self.assertNotEqual( None, vsan_policy.update('good', self.new_policy_content)) backup_policy_file = vsan_policy.backup_policy_filename(self.name) #Ensure there is no backup policy file self.assertFalse(os.path.isfile(backup_policy_file)) # Fail to update because of a bad policy, and ensure there is no backup self.assertNotEqual(None, vsan_policy.update('good', 'blah')) self.assertFalse(os.path.isfile(backup_policy_file))
def testPolicyUpdate(self): path = vsan_info.get_vsan_dockvols_path() vmdk_path = vmdk_utils.get_vmdk_path(path, self.volName) err = vmdk_ops.createVMDK(vm_name=self.vm_name, vmdk_path=vmdk_path, vol_name=self.volName, opts={'vsan-policy-name': 'good'}) self.assertEqual(err, None, err) self.assertEqual(None, vsan_policy.update('good', self.new_policy_content)) # Setting an identical policy returns an error msg self.assertNotEqual(None, vsan_policy.update('good', self.new_policy_content)) backup_policy_file = vsan_policy.backup_policy_filename(self.name) #Ensure there is no backup policy file self.assertFalse(os.path.isfile(backup_policy_file)) # Fail to update because of a bad policy, and ensure there is no backup self.assertNotEqual(None, vsan_policy.update('good', 'blah')) self.assertFalse(os.path.isfile(backup_policy_file))
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