VMWARE SDK 调用demo

•王越:VMware存储API整理,比如核心的存储池与卷两者的CURD。
可以参考:VMware in OpenStack、华为对接VMware这两个平台,两个平台地址或源码长生有。
华为的纳管说明书:
http://support.huawei.com/enterprise/docinforeader!loadDocument1.action?contentId=DOC1000117733&partNo=10012#_ZH-CN_TOPIC_0025959320
两种:

  • 纳管,元数据导出来,目标是导入Cinder
  • 使用,

图 1.Vcenter managed objects结构图

一、连接vmware服务器
Vmware Api调用,需要获取与vmware服务器连接的session:

from oslo_vmware import api
session = api.VMwareAPISession('172.24.26.20', 'administrator@ruijie.local', 'RuiJie@123', 1, 0.1)

二、集群
Cinder对接vmware,cinder-volume.conf配置后端需要设置参数vmware_cluster_name = cluster,这个vmware_cluster_name就是对应vmware平台的集群(Managed Object - ClusterComputeResource)。所以vmware的一个集群,对于cinder来说其实就是一个存储池。

平台操作:

1.创建集群
Folder.CreateCluster接口说明
参数:
NAME TYPE DESCRIPTION
_this ManagedObjectReference A reference to the Folder used to make the method call.
name xsd:string Name for the new cluster.
spec ClusterConfigSpec Specification for the cluster.
返回值:
TYPE DESCRIPTION
ManagedObjectReference
to a ClusterComputeResource A new ClusterComputeResource instance.

接口调用:
def get_host_folder():
"""
从datacenter获取集群文件夹列表,我们这里就取出第一个来用
:return:
"""
datacenter = session.invoke_api(vim_util, 'get_objects',
session.vim,
'Datacenter',
max_objects).objects[0].obj

hostFolder = session.invoke_api(vim_util,
                                'get_object_property',
                                session.vim,
                                datacenter,
                                'hostFolder')
return hostFolder

def create_cluster(cluster_name):
"""
创建集群
:param cluster_name:
:return:
"""
hostfolder = get_host_folder()
cluster_spec = session.vim.client.factory.create('ns0:ClusterConfigSpec')
# EVC模式设置为禁用
cluster_spec.drsConfig.enableVmBehaviorOverrides = False

task = session.invoke_api(session.vim,
                          "CreateCluster",
                          hostfolder,
                          name=cluster_name,
                          spec=cluster_spec)
return task

2.删除集群
def remove_cluster(cluster_name):
"""
删除集群
:param cluster_name:
:return:
"""
retrieve_result = session.invoke_api(vim_util, 'get_objects',
session.vim,
'ClusterComputeResource',
max_objects)
for c in retrieve_result.objects:
if c.propSet[0].val == cluster_name:
cluster = c.obj
task = session.invoke_api(session.vim,
"Destroy_Task",
cluster)

三、存储池Datastore
Properties
NAME TYPE DESCRIPTION
browser ManagedObjectReference
to aHostDatastoreBrowser DatastoreBrowser used to browse this datastore.
capability DatastoreCapability Capabilities of this datastore.
host* DatastoreHostMount[] Hosts attached to this datastore.
info DatastoreInfo Specific information about the datastore.
iormConfiguration* StorageIORMInfo Configuration of storage I/O resource management for the datastore. Currently we only support storage I/O resource management on VMFS volumes of a datastore.
This configuration may not be available if the datastore is not accessible from any host, or if the datastore does not have VMFS volume. The configuration can be modified using the method ConfigureDatastoreIORM_Task
summary DatastoreSummary Global properties of the datastore.
vm* ManagedObjectReference[]
to a VirtualMachine[] Virtual machines stored on this datastore.

1.查询存储池
# 查询Datastore列表,返回host、summary、vm属性
# host:存储挂载设备的信息
# summary:存储的基本信息,可以看到容量、存储类型等
# vm:挂载这个存储的虚机列表
retrieve_result = session.invoke_api(vim_util, 'get_objects',
session.vim,
'Datastore',
max_objects,
properties_to_collect=['host', 'summary', 'vm'])

返回值:
(ObjectContent){
obj =
(obj){
value = "datastore-954"
_type = "Datastore"
}
propSet[] =
(DynamicProperty){
name = "host"
val =
(ArrayOfDatastoreHostMount){
DatastoreHostMount[] =
(DatastoreHostMount){
key =
(key){
value = "host-195"
_type = "HostSystem"
}
mountInfo =
(HostMountInfo){
path = "/vmfs/volumes/02950f8a-1ba54877-0000-000000000000"
accessMode = "readWrite"
mounted = True
accessible = True
}
},
}
},
(DynamicProperty){
name = "summary"
val =
(DatastoreSummary){
datastore =
(datastore){
value = "datastore-954"
_type = "Datastore"
}
name = "Datastore_NFS"
url = "ds:///vmfs/volumes/02950f8a-1ba54877-0000-000000000000/"
capacity = 204010946560
freeSpace = 202497806336
uncommitted = 70654537728
accessible = True
multipleHostAccess = False
type = "NFS41"
maintenanceMode = "normal"
}
},
(DynamicProperty){
name = "vm"
val =
(ArrayOfManagedObjectReference){
ManagedObjectReference[] =
(ManagedObjectReference){
value = "vm-961"
_type = "VirtualMachine"
},
(ManagedObjectReference){
value = "vm-958"
_type = "VirtualMachine"
},
}
},
}

也可以调用HostDatastoreBrowser.SearchDatastore_Task根据datastore路径查找
Parameters
NAME TYPE DESCRIPTION
_this ManagedObjectReference A reference to the HostDatastoreBrowser used to make the method call.
datastorePath xsd:string
searchSpec* HostDatastoreBrowserSearchSpec
*Need not be set
Return Value
TYPE DESCRIPTION
ManagedObjectReference
to a Task This method returns a Task object with which to monitor the operation. The info.result property in the Task contains the HostDatastoreBrowserSearchResults upon success.

设置datastore的地址,格式是’[path]’

datastore_path = "[datastore1]"

设置查询用的spec

search_spec = session.vim.client.factory.create('ns0:HostDatastoreBrowserSearchSpec')
search_spec.matchPattern = match_pttern

启动搜索任务

task = session.invoke_api(session.vim,
"SearchDatastore_Task",
browser,
datastorePath=datastore_path,
searchSpec=search_spec)
session.wait_for_task(task)

search_result = session.invoke_api(vim_util,
'get_object_property',
session.vim,
task,
'info').result
print search_result

返回值
(HostDatastoreBrowserSearchResults){
datastore =
(datastore){
value = "datastore-199"
_type = "Datastore"
}
folderPath = "[datastore1]"
}

2.添加存储池
创建存储池有四种方法:

方法 说明
CreateLocalDatastore 创建本地存储池
CreateNasDatastore 在nfs共享中创建nas存储池
CreateVmfsDatastore 在磁盘、lan上创建vmfs存储池
CreateVvolDatastore

以HostDatastoreSystem.CreateNasDatastore为例,该方法需要传两个参数:
Parameters
NAME TYPE DESCRIPTION
_this ManagedObjectReference A reference to the HostDatastoreSystem used to make the method call.
spec HostNasVolumeSpec The specification for creating a network-attached storage volume.

_this
_this是HostDatastoreSystem对象。如果想通过get_objects查询ManagedObjectReference是获取不到的,检查文档可知HostDatastoreSystem是HostConfigManager的属性datastoreSystem;HostConfigManager通过get_objects也是拿不到的,而HostConfigManager又是HostSystem的属性configManager,HostSystem通过get_objects可以拿到,我们再从属性查。

代码:
def get_datastoreSystem():
# 获取 HostSystem 资源清单
retrieve_result = session.invoke_api(
vim_util,
'get_objects',
session.vim,
'HostSystem',
max_objects)

datastore_system = None

# 获取HostSystem的属性configManager.datastoreSystem
if retrieve_result.objects:
    hostsystem = retrieve_result.objects[0].obj
    datastore_system = session.invoke_api(vim_util,
                                          'get_object_property',
                                          session.vim,
                                          hostsystem,
                                          'configManager.datastoreSystem')

return datastore_system

spec
Spec是HostNasVolumeSpec,封装了创建存储池的基本参数,可通过session.vim.client.factory.create('ns0:HostNasVolumeSpec')创建的。
HostNasVolumeSpec Properties List
NAME TYPE DESCRIPTION
accessMode xsd:string Access mode for the mount point.
Mounting in read-write mode would be successful irregardless on how the mount point is exported or access permissions. For example, mounting a volume that is exported as read-only as readWrite will succeed. Hence, that a readWrite mount succeeds should not be taken as an indication that all files on a mount is writable.
If a file system is mounted readOnly, the system cannot create or modify any files on the file system. This is mostly useful for storing ISO images and templates, since a virtual machine cannot be powered on from a readOnly volume.
The access mode of a mounted NFS volume can be obtained at accessMode.

See HostMountMode
localPath xsd:string The localPath refers to the name of the NAS datastore to be created using this specification.
In the case of ESX Server, the datastore name is a component in the file system path at which the NAS volume can be found. For example, if localPath is set to "nas_volume" the created NAS datastore will be named "nas_volume" and it can be accessed via the file system path "/vmfs/volumes/nas_volume".
In the case of VMware Server, the localPath will also be used as the datastore name, but the datastore name may not necessarily be reflected in the file system path where the NAS volume may be accessed.
password* xsd:string If type is CIFS, the password to use when connecting to the CIFS server. If type is NFS, this field will be ignored.
Since VI API 2.5
remoteHost xsd:string The host that runs the NFS v3 or CIFS server. For NFS v4.1 and beyond use remoteHostNames defined later. The field remotehost may be deprecated in future for NFS, so clients should plan to use the property remoteHostNames to send in the host name(s) for both NFS v3 and v4.1
remoteHostNames* xsd:string[] Hostnames or IP addresses of remote NFS server. In case of NFS v4.1 this may have multiple entries. For NFS v3 the input should be same in both remoteHost and remoteHostNames.
Since vSphere API 6.0
remotePath xsd:string The remote path of the NFS mount point.
securityType* xsd:string Provided during mount indicating what security type, if any, to use See HostNasVolumeSecurityType
Since vSphere API 6.0
type* xsd:string Specifies the type of the the NAS volume. Supported types are CIFS, NFS, NFS41 If not specified, defaults to NFS
Since VI API 2.5
userName* xsd:string If type is CIFS, the user name to use when connecting to the CIFS server. If type is NFS, this field will be ignored.
Since VI API 2.5

创建NFS存储我们需要设置以下几个参数:
def host_nas_volume_spec(client_factory, name, remote_host_name=None,
remote_path=None, nas_type=None, access_mode=None):
rel_spec = client_factory.create('ns0:HostNasVolumeSpec')
# 远端服务器地址
rel_spec.remoteHost = remote_host_name
# 远端服务器地址数组,nfs4.1要求
rel_spec.remoteHostNames = [remote_host_name]
# 远端nfs路径
rel_spec.remotePath = remote_path
# nfs类型,可选值CIFS/NFS/NFS41
rel_spec.type = nas_type
# 本地存储路径名,也作为本地存储池的名字
rel_spec.localPath = name
# 存储访问模式,可选值readOnly和readWrite
if not access_mode:
rel_spec.accessMode = 'readWrite'
return rel_spec

有了这两个参数,我们就可执行创建了:
def create_nas_datastore():
client_factory = session.vim.client.factory
datastoresystem = get_datastoreSystem()
spec = host_nas_volume_spec(
client_factory,
'storage_nfs2',
'172.24.3.172',
'/wangyue_test_nfs2',
'NFS41')

task = session.invoke_api(
    session.vim,
    "CreateNasDatastore",
    datastoresystem,
    spec=spec)

3.删除存储池
可调用方法HostDatastoreSystem.RemoveDatastore。参数如下:
Parameters
NAME TYPE DESCRIPTION
_this ManagedObjectReference A reference to the HostDatastoreSystem used to make the method call.
datastore ManagedObjectReference
to a Datastore The datastore to be removed.

def get_special_datastore(datastore_name):
"""
根据存储池名字获取存储池对象
:param datastore_name:
:return:
"""
retrieve_result = session.invoke_api(vim_util, 'get_objects',
session.vim,
'Datastore',
max_objects)

if retrieve_result.objects:
    for obj_content in retrieve_result.objects:
        props = _get_object_properties(obj_content)
        if 'name' in props and props['name'] == datastore_name:
            return obj_content.obj

def remove_nas_datastore():
"""
删除nas数据库
:return:
"""
datastoresystem = get_datastoreSystem()

datastore = get_special_datastore('storage_nfs2')

task = session.invoke_api(
    session.vim,
    "RemoveDatastore",
    datastoresystem,
    datastore=datastore)

4.修改存储池
Datastore.RenameDatastore可修改存储池名称
Parameters
NAME TYPE DESCRIPTION
_this ManagedObjectReference A reference to the Datastore used to make the method call.
newName xsd:string The new name to assign to the datastore.

def rename_datastore(oldname, newname):
"""
修改存储池名称
:param oldname:
:param newname:
:return:
"""
datastore = get_special_datastore(oldname)
task = session.invoke_api(
session.vim,
"RenameDatastore",
datastore,
newName=newname)
5.判断cluster是否连接datastore
ClusterComputeResource 和 datastore 都有host属性,表示所连接的host。只要判断两者的host是否一样即可。
代码:
def check_cluster_access_datastore(cluster_name, datastore_name):
"""
判断cluster连接着datastore
:param cluster_name:
:param datastore_name:
:return:
"""
# 1. 根据名字查找cluster
cluster_result = session.invoke_api(
vim_util,
'get_objects',
session.vim,
'ClusterComputeResource',
max_objects
)
cluster = None
if cluster_result.objects:
for obj_content in cluster_result.objects:
props = _get_object_properties(obj_content)
if props['name'] == cluster_name:
cluster = obj_content.obj
if not cluster:
print('ERROR~there is no cluster %s ~' % cluster_name)
return False
# 2. 获取cluster的host属性
cluster_hosts = session.invoke_api(vim_util,
'get_object_property',
session.vim,
cluster,
'host')
# 转成数组
cluster_valid_hosts = [host_ref.value for host_ref in cluster_hosts.ManagedObjectReference]

# 3. 根据名字查找datastore
datastore = get_special_datastore(datastore_name)
# 4. 获取datastore的host
if datastore:
    datastore_hosts = session.invoke_api(vim_util,
                                         'get_object_property',
                                         session.vim,
                                         datastore,
                                         'host')
    # 5. 判断datastore的host有没有在cluster的host列表里
    for dh in datastore_hosts.DatastoreHostMount:
        if dh.key.value in cluster_valid_hosts:
            return True
print('ERROR~the datastore %s is not belongs cluster %s' % (datastore_name, cluster_name))
return False

6.获取存储池信息
Cinder对接vmware,cinder配置后端存储的时候只需要配置vmware的集群名字,一个vmware集群可以拥有多个datastore。Cinder上不配置指定vmware的datastore,创建、挂载卷的时候,vmware driver会从集群里找一个能用的datastore来存放vmdk文件。
Cinder getpools --detail 获取的vmware存储池信息是由vmware driver方法cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver#get_volume_stats 拿到的。但是目前这个方法,total_capacity_gb和free_capacity_gb写死unknown。

驱动这样做的原因,可能是因为一个cluster可以有多个datastore,容量不好获取,如果是用全部datastore的容量总和作为容量返回,可能10个datastore每个只剩下1G容量,返回总容量有10G,但是想要创建2G的vmdk文件是创建不了的。

四、硬盘/卷信息
1.查看虚机的硬盘信息
VirtualMachine.config.hardware包含以下属性,可以查看虚机配置的内存、cpu、存储等。

NAME TYPE DESCRIPTION
device* VirtualDevice[] The set of virtual devices belonging to the virtual machine. This list is unordered.
memoryMB xsd:int Memory size, in MB.
numCoresPerSocket* xsd:int Number of cores used to distribute virtual CPUs among sockets in this virtual machine. If the value is unset it implies to numCoresPerSocket = 1.
Since vSphere API 5.0
numCPU xsd:int Number of virtual CPUs present in this virtual machine.
virtualICH7MPresent* xsd:boolean Does this virtual machine have Virtual Intel I/O Controller Hub 7
Since vSphere API 5.0
virtualSMCPresent* xsd:boolean Does this virtual machine have System Management Controller
Since vSphere API 5.0

代码:
def get_storage(vm_name):
# 获取虚机列表
retrieve_result = session.invoke_api(vim_util,
'get_objects',
session.vim,
'VirtualMachine',
max_objects)
# 遍历虚机列表,根据名称找到虚机对象,作为backing
vms = retrieve_result.objects
backing = None
for vm in vms:
if vm.propSet[0].val == vm_name:
backing = vm.obj

# 获取backing的属性config.hardware.device
hardware_devices = session.invoke_api(vim_util,
                                      'get_object_property',
                                      session.vim,
                                      backing,
                                      'config.hardware.device')

hardware_devices = hardware_devices.VirtualDevice
devices = []
for device in hardware_devices:
    # 返回所有VirtualDisk对象
    if device.__class__.__name__ == "VirtualDisk":
        devices.append(device)
return devices

返回:
[(VirtualDisk){
key = 2000
deviceInfo =
(Description){
label = "Hard disk 1"
summary = "10,485,760 KB"
}
backing =
(VirtualDiskFlatVer2BackingInfo){
fileName = "[storage_nfs3] wangyue_vm/wangyue_vm.vmdk"
datastore =
(datastore){
value = "datastore-1001"
_type = "Datastore"
}
backingObjectId = None
diskMode = "persistent"
split = False
writeThrough = False
thinProvisioned = True
uuid = "6000C29f-9286-0b6b-21c5-4154503fb734"
contentId = "be21a9c0aa3ffdf2413ea572fffffffe"
digestEnabled = False
sharing = "sharingNone"
}
controllerKey = 1000
unitNumber = 0
capacityInKB = 10485760
capacityInBytes = 10737418240
shares =
(SharesInfo){
shares = 1000
level = "normal"
}
storageIOAllocation =
(StorageIOAllocationInfo){
limit = -1
shares =
(SharesInfo){
shares = 1000
level = "normal"
}
reservation = 0
}
diskObjectId = "708-2000"
}]
2.增加硬盘
调用VirtualDiskManager.CreateVirtualDisk_Task往datastore指定路径里添加vmdk文件
NAME TYPE DESCRIPTION
_this ManagedObjectReference A reference to the VirtualDiskManager used to make the method call.
name xsd:string The name of the disk, either a datastore path or a URL referring to the virtual disk to be created.
datacenter* ManagedObjectReference
to a Datacenter If name is a datastore path, the datacenter for that datastore path. Not needed when invoked directly on ESX. If not specified on a call to VirtualCenter, name must be a URL.
spec VirtualDiskSpec The specification of the virtual disk to be created.

VirtualDiskSpec属性:
NAME TYPE DESCRIPTION
adapterType xsd:string The type of the virtual disk adapter for the new virtual disk.
See VirtualDiskAdapterType
diskType xsd:string The type of the new virtual disk.
See VirtualDiskType

adapterType Enum Constants:
NAME DESCRIPTION
busLogic Use BusLogic emulation for the virtual disk
ide Use IDE emulation for the virtual disk
lsiLogic Use LSILogic emulation for the virtual disk

diskType Enum Constants:
NAME DESCRIPTION
delta A redo log disk. This format is only applicable as a destination format in a clone operation, and not usable for disk creation.
Since vSphere API 5.5
eagerZeroedThick An eager zeroed thick disk has all space allocated and wiped clean of any previous contents on the physical media at creation time. Such disks may take longer time during creation compared to other disk formats.
flatMonolithic A preallocated monolithic disk. Disks in this format can be used with other VMware products. This format is only applicable as a destination format in a clone operation, and not usable for disk creation.
Since vSphere API 4.0
preallocated A preallocated disk has all space allocated at creation time and the space is zeroed on demand as the space is used.
raw Raw device.
rdm Virtual compatibility mode raw disk mapping. An rdm virtual disk grants access to the entire raw disk and the virtual disk can participate in snapshots.
rdmp Physical compatibility mode (pass-through) raw disk mapping. An rdmp virtual disk passes SCSI commands directly to the hardware, but the virtual disk cannot participate in snapshots.
seSparse A sparse (allocate on demand) format with additional space optimizations.
Since vSphere API 5.1
sparse2Gb A sparse disk with 2GB maximum extent size. Disks in this format can be used with other VMware products. The 2GB extent size makes these disks easier to burn to dvd or use on filesystems that don't support large files. This format is only applicable as a destination format in a clone operation, and not usable for disk creation.
sparseMonolithic A sparse monolithic disk. Disks in this format can be used with other VMware products. This format is only applicable as a destination format in a clone operation, and not usable for disk creation.
Since vSphere API 4.0
thick A thick disk has all space allocated at creation time. This space may contain stale data on the physical media. Thick disks are primarily used for virtual machine clustering, but they are generally insecure and should not be used. Due to better performance and security properties, the use of the 'preallocated' format is preferred over this format.
thick2Gb A thick disk with 2GB maximum extent size. Disks in this format can be used with other VMware products. The 2GB extent size makes these disks easier to burn to dvd or use on filesystems that don't support large files. This format is only applicable as a destination format in a clone operation, and not usable for disk creation.
thin Space required for thin-provisioned virtual disk is allocated and zeroed on demand as the space is used.

def create_diskdevice(vm_name, disk_name):
# 获取datastore的datacenter,从Vcenter managed objects结构图看出datacenter是datastore的上级
retrieve_result = session.invoke_api(vim_util, 'get_objects',
session.vim,
'Datastore',
max_objects)

if retrieve_result.objects:
    for obj_content in retrieve_result.objects:
        props = _get_object_properties(obj_content)
        if 'name' in props and props['name'] == 'storage_nfs3':
            backing = obj_content.obj

datacenter = _get_parent(backing, 'Datacenter')

virtual_disk_manager = session.vim.service_content.virtualDiskManager

# 生成VirtualDiskSpec
cf = session.vim.client.factory
spec = cf.create('ns0:FileBackedVirtualDiskSpec')
spec.capacityKb = 1024 * 1024 * 8
spec.adapterType = 'busLogic'
spec.diskType = 'preallocated'

disk_name = '[%s] %s' % ('storage_nfs3',
                         "%s/%s%s.vmdk" % (vm_name, vm_name, disk_name))
# 向datastore里添加vmdk文件,路径datastore/{vm_name}/{vm_name}{disk_name}.vmdk
task = session.invoke_api(session.vim,
                          "CreateVirtualDisk_Task",
                          virtual_disk_manager,
                          name=disk_name,
                          datacenter=datacenter,
                          spec=spec)

3.删除硬盘
调用VirtualDiskManager.DeleteVirtualDisk_Task删除datastore的vmdk文件
Parameters
NAME TYPE DESCRIPTION
_this ManagedObjectReference A reference to the VirtualDiskManager used to make the method call.
name xsd:string The name of the disk, either a datastore path or a URL referring to the virtual disk to be deleted.
datacenter* ManagedObjectReference
to a Datacenter If name is a datastore path, the datacenter for that datastore path. Not needed when invoked directly on ESX. If not specified on a call to VirtualCenter, name must be a URL.

def delete_diskdevice(ds_name, disk_folder, disk_name):
# 查询datastore的datacenter
backing = None
retrieve_result = session.invoke_api(vim_util, 'get_objects',
session.vim,
'Datastore',
max_objects)
if retrieve_result.objects:
for obj_content in retrieve_result.objects:
props = _get_object_properties(obj_content)
if 'name' in props and props['name'] == ds_name:
backing = obj_content.obj
data_center = _get_parent(backing, 'Datacenter')

virtual_disk_manager = session.vim.service_content.virtualDiskManager

disk_name = '[%s] %s' % (ds_name,
                         "%s/%s%s.vmdk" % (disk_folder, disk_folder, disk_name))
# 向datastore里删除vmdk文件,路径{ds_name}/{disk_folder}/{disk_folder}{disk_name}.vmdk
task = session.invoke_api(session.vim,
                          "DeleteVirtualDisk_Task",
                          virtual_disk_manager,
                          name=disk_name,
                          datacenter=data_center)
print task

4.Datastore之间迁移磁盘
调用VirtualDiskManager.MoveVirtualDisk_Task迁移datastore的vmdk文件到另一个datastore
Parameters
NAME TYPE DESCRIPTION
_this ManagedObjectReference A reference to the VirtualDiskManager used to make the method call.
sourceName xsd:string The name of the source, either a datastore path or a URL referring to the virtual disk to be moved.
sourceDatacenter* ManagedObjectReference
to a Datacenter If sourceName is a datastore path, the datacenter for that datastore path. Not needed when invoked directly on ESX. If not specified on a call to VirtualCenter, sourceName must be a URL.
destName xsd:string The name of the destination, either a datastore path or a URL referring to the destination virtual disk.
destDatacenter* ManagedObjectReference
to a Datacenter If destName is a datastore path, the datacenter for that datastore path. Not needed when invoked directly on ESX. If not specified on a call to VirtualCenter, it is assumed that the destination path belongs to the source datacenter.
force* xsd:boolean If true, overwrite any indentically named disk at the destination. If not specified, it is assumed to be false
profile* VirtualMachineProfileSpec[] User can specify new set of profile when moving virtual disk.
Since vSphere API 5.5

def move_vmdk_file(src_dc_name, dest_dc_name, disk_folder, disk_name):
# 获取原datastore
src_dc = get_special_datastore(src_dc_name)
# 获取目标datastore
dest_dc = get_special_datastore(dest_dc_name)
# 获取原datastore的datacenter
src_data_center = _get_parent(src_dc, 'Datacenter')
# 获取目标datastore的datacenter
des_data_center = _get_parent(dest_dc, 'Datacenter')

diskMgr = session.vim.service_content.virtualDiskManager
# 设置源、目标的文件地址
src_vmdk_file_path = '[%s] %s' % (src_dc_name,
                                  "%s/%s%s.vmdk" % (disk_folder, disk_folder, disk_name))
dest_vmdk_file_path = '[%s] %s' % (dest_dc_name,
                                   "%s/%s%s.vmdk" % ('wangyuetest', disk_folder, disk_name))
task = session.invoke_api(session.vim,
                          'MoveVirtualDisk_Task',
                          diskMgr,
                          sourceName=src_vmdk_file_path,
                          sourceDatacenter=src_data_center,
                          destName=dest_vmdk_file_path,
                          destDatacenter=des_data_center,
                          force=True)
print task

5.Datastore之间复制磁盘
调用VirtualDiskManager.CopyVirtualDisk_Task迁移datastore的vmdk文件到另一个datastore。
参数和调用方式都跟VirtualDiskManager.MoveVirtualDisk_Task一样,方法名字改下而已。
task = session.invoke_api(session.vim,
'CopyVirtualDisk_Task',
diskMgr,
sourceName=src_vmdk_file_path,
sourceDatacenter=src_data_center,
destName=dest_vmdk_file_path,
destDatacenter=des_data_center,
force=True)
6.查询datastore下面vmdk文件
Datastore有属性browser,类型是HostDatastoreBrowser。
NAME TYPE DESCRIPTION
browser ManagedObjectReference
to aHostDatastoreBrowser DatastoreBrowser used to browse this datastore.

HostDatastoreBrowser对象包含方法SearchDatastoreSubFolders_Task,就是用于查询datastore下的文件和文件夹,返回列表。该方法的官方说明是:
Returns the information for the files that match the given search criteria as a SearchResults[] object. Searches the folder specified by the datastore path and all subfolders. The Datastore.Browse privilege must be held on the datastore identified by the datastore path.

调用该方法,需要传递参数:
NAME TYPE DESCRIPTION
_this ManagedObjectReference A reference to the HostDatastoreBrowser used to make the method call.
datastorePath xsd:string
searchSpec* HostDatastoreBrowserSearchSpec

返回值是一个task
TYPE DESCRIPTION
ManagedObjectReference
to a Task This method returns a Task object with which to monitor the operation. The info.result property in the Task contains the HostDatastoreBrowserSearchResults upon success.

这个task不会很快结束得到查询结果,我们需要通过while一直检查task.info.state是否从running变为success,然后才能拿到task.info.result。Result是FileInfo类型的数组,我们从FileInfo对象拿到文件大小、路径等属性。
NAME TYPE DESCRIPTION
fileSize* xsd:long The size of the file in bytes.
modification* xsd:dateTime The last date and time the file was modified.
owner* xsd:string The user name of the owner of the file.
Since vSphere API 4.0
path xsd:string The path relative to the folder path in the search results.

代码:
def get_allfile_in_datastore(ds_name):
"""
查询datastore下的所有文件列表
:param ds_name:
:return:
"""
retrieve_result = session.invoke_api(vim_util, 'get_objects',
session.vim,
'Datastore',
max_objects)
if retrieve_result.objects:
for obj_content in retrieve_result.objects:
props = _get_object_properties(obj_content)
# 查询datastore对象
if 'name' in props and props['name'] == ds_name:
browser = session.invoke_api(vim_util,
'get_object_property',
session.vim,
obj_content.obj,
'browser')
summary = session.invoke_api(vim_util,
'get_object_property',
session.vim,
obj_content.obj,
'summary')
# 设置datastore的地址,格式是[summary.name]
datastore_path = "[" + summary.name + "]"
# 设置查询用的spec
search_spec = session.vim.client.factory.create('ns0:HostDatastoreBrowserSearchSpec')
search_spec.matchPattern = '*'
# 启动搜索任务
task = session.invoke_api(session.vim,
"SearchDatastoreSubFolders_Task",
browser,
datastorePath=datastore_path,
searchSpec=search_spec)
# 一直循环查询任务的状态info.state是否从running变成success
search_result = session.invoke_api(vim_util,
'get_object_property',
session.vim,
task,
'info')
while search_result.state == 'running':
search_result = session.invoke_api(vim_util,
'get_object_property',
session.vim,
task,
'info')
print search_result.result

查询结果:
(ArrayOfHostDatastoreBrowserSearchResults){
HostDatastoreBrowserSearchResults[] =
(HostDatastoreBrowserSearchResults){
datastore =
(datastore){
value = "datastore-1001"
_type = "Datastore"
}
folderPath = "[storage_nfs3] wangyue_vm/"
file[] =
(FileInfo){
path = "wangyue_vm-flat.vmdk"
},
(FileInfo){
path = "wangyue_vmdisk1-flat.vmdk"
},
(FileInfo){
path = "wangyue_vm-511c0281.hlog"
},
(FileInfo){
path = "wangyue_vm.vmdk"
},
(FileInfo){
path = "volume-377cb9aa-ad18-44c3-9524-924570a1f949"
},
(FileInfo){
path = "wangyue_vm.vmx"
},
(FileInfo){
path = "wangyue_vmdisk1.vmdk"
},
(FileInfo){
path = "wangyue_vm.vmsd"
},
},
(HostDatastoreBrowserSearchResults){
datastore =
(datastore){
value = "datastore-1001"
_type = "Datastore"
}
folderPath = "[storage_nfs3]"
file[] =
(FileInfo){
path = "volume-d5c58e06-d231-4f65-9c82-aafa970045fe"
},
(FileInfo){
path = "volume-377cb9aa-ad18-44c3-9524-924570a1f949"
},
(FileInfo){
path = "wangyue_vm"
},
},
}

7.给硬盘扩展空间
调用VirtualDiskManager.ExtendVirtualDisk_Task

Parameters
NAME TYPE DESCRIPTION
_this ManagedObjectReference A reference to the VirtualDiskManager used to make the method call.
name xsd:string The name of the disk, either a datastore path or a URL referring to the virtual disk whose capacity should be expanded.
datacenter* ManagedObjectReference
to a Datacenter If name is a datastore path, the datacenter for that datastore path. Not needed when invoked directly on ESX. If not specified on a call to VirtualCenter, name must be a URL.
newCapacityKb xsd:long The new capacty of the virtual disk in Kb.
eagerZero* xsd:boolean If true, the extended part of the disk will be explicitly filled with zeroes.
Since vSphere API 4.0

代码:
def extend_disk():
data_store = get_special_datastore('storage_nfs3')
data_center = _get_parent(data_store, 'Datacenter')
virtual_disk_manager = session.vim.service_content.virtualDiskManager
vmdk_file_path = '[storage_nfs3] wangyue_vm/wangyue_vmdisk1.vmdk'
capacityKb = 1024 ** 3 * 2
task = session.invoke_api(session.vim,
"ExtendVirtualDisk_Task",
virtual_disk_manager,
datacenter=data_center,
name=vmdk_file_path,
newCapacityKb=capacityKb,
eagerZero=True)
session.wait_for_task(task)
result = session.invoke_api(vim_util,
'get_object_property',
session.vim,
task,
'info')
print result

8.虚机上挂载、卸载卷
这些工作主要有nova那边负责。我从nova vmware driver代码了解了实现原理:
本质都是调用VirtualMachine.ReconfigVM_Task重配置虚机。
Parameters
NAME TYPE DESCRIPTION
_this ManagedObjectReference A reference to the VirtualMachine used to make the method call.
spec VirtualMachineConfigSpec The new configuration values.

VirtualMachineConfigSpec对象有个deviceChange属性,保存用户对虚机磁盘设备修改操作。
deviceChange* VirtualDeviceConfigSpec[] Set of virtual devices being modified by the configuration operation.
VirtualDeviceConfigSpec:
Properties
NAME TYPE DESCRIPTION
device VirtualDevice Device specification, with all necessary properties set.
fileOperation* VirtualDeviceConfigSpecFileOperation Type of operation being performed on the backing of the specified virtual device. If no file operation is specified in the VirtualDeviceSpec, then any backing filenames in theVirtualDevice must refer to files that already exist. The "replace" and "delete" values for this property are only applicable to virtual disk backing files.
operation* VirtualDeviceConfigSpecOperation Type of operation being performed on the specified virtual device. If no operation is specified, the spec. is ignored.
profile* VirtualMachineProfileSpec[] Virtual Device Profile requirement. Profiles are solution specifics. Storage Profile Based Management(SPBM) is a vSphere server extension. The API users who want to provision VMs using Storage Profiles, need to interact with SPBM service. This is an optional parameter and if user doesn't specify profile, the default behavior will apply.
Since vSphere API 5.5
上面有个operation属性,用于设置你这个磁盘要做什么操作,比如添加或者移除,有三种可选项:
VirtualDeviceConfigSpecOperation Enum Constants:
NAME DESCRIPTION
add Specifies the addition of a virtual device to the configuration.
edit Specifies changes to the virtual device specification.
remove Specifies the removal of a virtual device.

对虚机挂载、卸载磁盘设备,就是往VirtualMachineConfigSpec.deviceChange这个数组里添加VirtualDeviceConfigSpec对象,然后对象设置operation为add或者remove,invoke_api后就能实现。主要是nova的逻辑,在此就不用demo实现了。
五、快照
Cinder以vmware集群为后端创建的卷,在vmware这边其实是一个虚机,不过这个虚机只有一个没有操作系统的盘。Cinder给vmware卷创建快照,调用的是vmware虚机快照的方法。最后真正开始做卷快照实际上是在将卷挂载到影子虚拟机上,对影子虚拟机做虚拟机快照。
1.创建快照

VirtualMachineSnapshot.CreateSnapshot_Task
Parameters
NAME TYPE DESCRIPTION
_this ManagedObjectReference A reference to the VirtualMachine used to make the method call.
name xsd:string The name for this snapshot. The name need not be unique for this virtual machine.
description* xsd:string A description for this snapshot. If omitted, a default description may be provided.
memory xsd:boolean If TRUE, a dump of the internal state of the virtual machine (basically a memory dump) is included in the snapshot. Memory snapshots consume time and resources, and thus take longer to create. When set to FALSE, the power state of the snapshot is set to powered off.
capabilities indicates whether or not this virtual machine supports this operation.
quiesce xsd:boolean If TRUE and the virtual machine is powered on when the snapshot is taken, VMware Tools is used to quiesce the file system in the virtual machine. This assures that a disk snapshot represents a consistent state of the guest file systems. If the virtual machine is powered off or VMware Tools are not available, the quiesce flag is ignored.
Return Value
TYPE DESCRIPTION
ManagedObjectReference
to a Task This method returns a Task object with which to monitor the operation. The info.result property in the Task contains the newly created VirtualMachineSnapshot upon success.

代码:
def create_snapshot(volume_name, snapshot_name, description):
# cinder的卷在vmware对应一个虚机,先查出这个虚机
snapshot = None
retrieve_result = session.invoke_api(vim_util, 'get_objects',
session.vim,
'VirtualMachine',
max_objects)
for vm in retrieve_result.objects:
if vm.propSet[0].val == volume_name:
# We got the result, so cancel further retrieval.
backing = vm.obj
# 对虚机做快照
task = session.invoke_api(session.vim,
'CreateSnapshot_Task',
backing, name=snapshot_name,
description=description,
memory=False, quiesce=False)

        task_info = session.wait_for_task(task)
        snapshot = task_info.result

return snapshot

2.查询快照树
Vmware的快照是一棵树,每一次快照都是上一次的子快照。
快照VirtualMachineSnapshotInfo属于虚机VirtualMachine的snapshot属性。
Properties
NAME TYPE DESCRIPTION
currentSnapshot* ManagedObjectReference
to a VirtualMachineSnapshot Current snapshot of the virtual machine
This property is set by calling Snapshot.revert or VirtualMachine.createSnapshot. This property will be empty when the working snapshot is at the root of the snapshot tree.
rootSnapshotList VirtualMachineSnapshotTree[] Data for the entire set of snapshots for one virtual machine.

代码:
snapshot = session.invoke_api(vim_util, 'get_object_property',
session.vim, backing,
'snapshot')

输出:

3.修改快照名
VirtualMachineSnapshot.RenameSnapshot 可用于修改快照名和解释
Parameters
NAME TYPE DESCRIPTION
_this ManagedObjectReference A reference to the VirtualMachineSnapshot used to make the method call.
name* xsd:string New name for the snapshot.
description* xsd:string New description for the snapshot.

session.invoke_api(session.vim,
                   'RenameSnapshot',
                   snapshot,
                   name=newname,
                   description=newdes
                   )

4.删除快照
VirtualMachineSnapshot.RemoveSnapshot_Task
Parameters
NAME TYPE DESCRIPTION
_this ManagedObjectReference A reference to the VirtualMachineSnapshot used to make the method call.
removeChildren xsd:boolean Flag to specify removal of the entire snapshot subtree.
consolidate* xsd:boolean (optional) If set to true, the virtual disk associated with this snapshot will be merged with other disk if possible. Defaults to true.
Since vSphere API 5.0

task = session.invoke_api(session.vim,
                        'RemoveSnapshot_Task',
                        snapshot, removeChildren=False)

5.导出快照
VirtualMachineSnapshot.ExportSnapshot,可用于导出快照,返回值是一个HttpNfcLease。
Parameters
NAME TYPE DESCRIPTION
_this ManagedObjectReference A reference to the VirtualMachineSnapshot used to make the method call.
Return Value
TYPE DESCRIPTION
ManagedObjectReference
to a HttpNfcLease The export lease on this VirtualMachineSnapshot. The export task continues running until the lease is completed by the caller.

6.从快照创建卷
这个功能cinder vmware driver原生支持,入口在cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver#create_volume_from_snapshot。 流程:
① 检查目标卷是否存在
② 检查vmware快照的backing是否存在
③ 拿到vmware快照
④ 获得目标卷的clone_type
⑤ 根据快照克隆到目标卷

Cinder定义了两种clone_type,用户可以设置在volume-type的extra_spec,没设置默认选用FULL_CLONE_TYPE。
LINKED_CLONE_TYPE = 'linked'
FULL_CLONE_TYPE = 'full'

这两种clone_type分别对应了vmware上的两种diskMoveType:"createNewChildDiskBacking"和"moveAllDiskBackingsAndDisallowSharing"。"moveAllDiskBackingsAndDisallowSharing"就是把快照原卷的backing全量拷到目标datastore里,"createNewChildDiskBacking"则是目标卷和快照卷共享backing。
Enum - VirtualMachineRelocateDiskMoveOptions详细说明:
NAME DESCRIPTION
createNewChildDiskBacking Create a new child disk backing on the destination datastore. None of the virtual disk's existing files should be moved from their current locations.
Note that in the case of a clone operation, this means that the original virtual machine's disks are now all being shared. This is only safe if the clone was taken from a snapshot point, because snapshot points are always read-only. Thus for a clone this option is only valid when cloning from a snapshot. Note that in the case of a RelocateVM_Task operation, child disks are created for the virtual disks in the current virtual machine configuration only.
moveAllDiskBackingsAndDisallowSharing All of the virtual disk's backings should be moved to the new datastore. It is not acceptable to attach to a disk backing with the same content ID on the destination datastore. During a clone operation any delta disk backings will be consolidated.

最后实际调用的是VirtualMachine.CloneVM_Task
Parameters
NAME TYPE DESCRIPTION
_this ManagedObjectReference A reference to the VirtualMachine used to make the method call.
folder P ManagedObjectReference
to a Folder The location of the new virtual machine.
name xsd:string The name of the new virtual machine.
spec VirtualMachineCloneSpec Specifies how to clone the virtual machine. The folder specified in the spec takes precedence over the folder parameter.

VirtualMachineCloneSpec
Properties
NAME TYPE DESCRIPTION
config* VirtualMachineConfigSpec Deprecated. as of vSphere API 6.0. Use deviceChange in location instead for specifying any virtual device changes for disks and networks. All other VM configuration changes should useReconfigVM_Task API after the clone operation finishes.
An optional specification of changes to the virtual hardware. For example, this can be used to, (but not limited to) reconfigure the networks the virtual switches are hooked up to in the cloned virtual machine.
customization* CustomizationSpec An optional guest operating system customization specification. This value is ignored if a template is being created.
location VirtualMachineRelocateSpec A type of RelocateSpec that specifies the location of resources the newly cloned virtual machine will use. The location specifies:
oA datastore where the virtual machine will be located on physical storage. This is always provided because it indicates where the newly created clone will be copied.
oa resource pool and optionally a host. The resource pool determines what compute resources will be available to the clone and the host indicates which machine will host the clone.

memory* xsd:boolean Flag indicating whether to retain a copy of the source virtual machine's memory state in the clone. Retaining the memory state during clone results in a clone in suspended state with all network adapters removed to avoid network conflicts, except those with a VirtualEthernetCard.addressType of "manual". Users of this flag should take special care so that, when adding a network adapter back to the clone, the VM is not resumed on the same VM network as the source VM, or else MAC address conflicts could occur. When cloning between two hosts with different CPUs outside an EVC cluster, users of this flag should be aware that vCenter does not verify CPU compatibility between the clone's memory state and the target host prior to the clone operation, so the clone may fail to resume until it is migrated to a host with a compatible CPU.
This flag is ignored if the snapshot parameter is unset. This flag only applies for a snapshot taken on a running or suspended virtual machine with the 'memory' parameter set to true, because otherwise the snapshot has no memory state. This flag defaults to false.
Since vSphere API 5.5
powerOn xsd:boolean Specifies whether or not the new VirtualMachine should be powered on after creation. As part of a customization, this flag is normally set to true, since the first power-on operation completes the customization process. This flag is ignored if a template is being created.
snapshot* ManagedObjectReference
to aVirtualMachineSnapshot Snapshot reference from which to base the clone.
If this parameter is set, the clone is based off of the snapshot point. This means that the newly created virtual machine will have the same configuration as the virtual machine at the time the snapshot was taken.
If this property is not set then the clone is based off of the virtual machine's current configuration.
Setting this is only supported if the host this virtual machine is currently residing on supports cloning from a snapshot point. Such support does not need to exist on the destination host for the clone.
Setting this is only supported if the virtual machine supports reporting snapshot configuration information. See snapshotConfigSupported. Such support does not need to exist on the destination host for the clone.
Since vSphere API 4.0
template xsd:boolean Specifies whether or not the new virtual machine should be marked as a template.

VirtualMachineConfigSpec和VirtualMachineRelocateSpec参数太多,就不贴出来了。

代码调用:
def _get_relocate_spec(self, datastore, resource_pool, host,
disk_move_type, disk_type=None, disk_device=None):
"""Return spec for relocating volume backing.

:param datastore: Reference to the datastore
:param resource_pool: Reference to the resource pool
:param host: Reference to the host
:param disk_move_type: Disk move type option
:param disk_type: Destination disk type
:param disk_device: Virtual device corresponding to the disk
:return: Spec for relocation
"""
cf = self._session.vim.client.factory
relocate_spec = cf.create('ns0:VirtualMachineRelocateSpec')
relocate_spec.datastore = datastore
relocate_spec.pool = resource_pool
relocate_spec.host = host
relocate_spec.diskMoveType = disk_move_type

if disk_type is not None and disk_device is not None:
    disk_locator = self._create_relocate_spec_disk_locator(datastore,
                                                           disk_type,
                                                           disk_device)
    relocate_spec.disk = [disk_locator]

LOG.debug("Spec for relocating the backing: %s.", relocate_spec)
return relocate_spec

def _get_clone_spec(self, datastore, disk_move_type, snapshot, backing,
disk_type, host=None, resource_pool=None,
extra_config=None):
"""Get the clone spec.

:param datastore: Reference to datastore
:param disk_move_type: Disk move type
:param snapshot: Reference to snapshot
:param backing: Source backing VM
:param disk_type: Disk type of clone
:param host: Target host
:param resource_pool: Target resource pool
:param extra_config: Key-value pairs to be written to backing's
                     extra-config
:return: Clone spec
"""
if disk_type is not None:
    disk_device = self._get_disk_device(backing)
else:
    disk_device = None

relocate_spec = self._get_relocate_spec(datastore, resource_pool, host,
                                        disk_move_type, disk_type,
                                        disk_device)
cf = self._session.vim.client.factory
clone_spec = cf.create('ns0:VirtualMachineCloneSpec')
clone_spec.location = relocate_spec
clone_spec.powerOn = False
clone_spec.template = False
clone_spec.snapshot = snapshot

if extra_config:
    config_spec = cf.create('ns0:VirtualMachineConfigSpec')
    if BACKING_UUID_KEY in extra_config:
        config_spec.instanceUuid = extra_config.pop(BACKING_UUID_KEY)
    config_spec.extraConfig = self._get_extra_config_option_values(
        extra_config)
    clone_spec.config = config_spec

LOG.debug("Spec for cloning the backing: %s.", clone_spec)
return clone_spec

clone_spec = self._get_clone_spec(
datastore, disk_move_type, snapshot, backing, disk_type, host=host,
resource_pool=resource_pool, extra_config=extra_config)
task = self._session.invoke_api(self._session.vim, 'CloneVM_Task',
backing, folder=folder, name=name,
spec=clone_spec)

六、QOS控制
VMware vSphere Storage/ Network IO Control可设定存储和网络服务质量优先级,确保关键业务对资源的访问。

StorageIORMInfo 对象用于管理datastore存储IO。
Properties
NAME TYPE DESCRIPTION
congestionThreshold xsd:int The latency beyond which the storage array is considered congested.
If storage I/O resource management is enabled on a datastore, the algorithm tries to maintain the latency to be below or close to this value. The unit is millisecond. The range of this value is between 5 to 100 milliseconds.
congestionThresholdMode xsd:string Mode of congestion threshold specification For more information, see StorageIORMThresholdMode
Since vSphere API 5.1
enabled xsd:boolean Flag indicating whether or not the service is enabled.
percentOfPeakThroughput* xsd:int The percentage of peak throughput to be used for setting congestion threshold of a datastore. Valid values are between 50 to 100. Default value is 90%
For more information, see congestionThreshold
Since vSphere API 5.1
reservableIopsThreshold* xsd:int Storage DRS makes storage migration recommendations if total IOPs reservation for all VMs running on the datastore is higher than specified threshold value. This value (if present) overrides
Since vSphere API 6.0
reservationEnabled xsd:boolean Flag indicating whether IO reservations support is enabled.
Since vSphere API 6.0
statsAggregationDisabled* xsd:boolean Flag indicating whether stats aggregation is disabled.
Since vSphere API 5.0
statsCollectionEnabled xsd:boolean Flag indicating whether service is running in stats collection mode.
Since vSphere API 5.0
1.查看storage io control
Datastore对象有StorageIORMInfo类型的属性iormConfiguration,保存了当前datastore的io控制配置。

代码调用:
def query_storage_io(datastore):
io_conf = session.invoke_api(vim_util,
'get_object_property',
session.vim,
datastore,
'iormConfiguration')
print io_conf

返回值:
(StorageIORMInfo){
enabled = True
congestionThresholdMode = "automatic"
congestionThreshold = 30
percentOfPeakThroughput = 88
statsCollectionEnabled = False
reservationEnabled = False
statsAggregationDisabled = False
}

2.设置storage io control
可通过方法StorageResourceManager.ConfigureDatastoreIORM_Task配置。
Parameters
NAME TYPE DESCRIPTION
_this ManagedObjectReference A reference to the StorageResourceManager used to make the method call.
datastore P ManagedObjectReference
to a Datastore The datastore to be configured.
spec StorageIORMConfigSpec The configuration spec.

代码调用:
def configure_storage_io(ds):
ioconfig_spec = session.vim.client.factory.create('ns0:StorageIORMConfigSpec')

# 启用storage io 控制,设置手动模式的拥堵阈值
# ioconfig_spec.enabled = True
# ioconfig_spec.congestionThresholdMode = 'manual'
# ioconfig_spec.congestionThreshold = 70
# --------------

# 启用storage io 控制,设置88% 的吞吐量峰值
# ioconfig_spec.enabled = True
# ioconfig_spec.congestionThresholdMode = 'automatic'
# ioconfig_spec.percentOfPeakThroughput = 88
# --------------

# 禁用storage io 控制。存储I/O控制默认就是关闭的。
ioconfig_spec.enabled = False
ioconfig_spec.reservationEnabled = False
ioconfig_spec.statsAggregationDisabled = False

ioconfig_spec.statsCollectionEnabled = False

--------------

storage_resource_manager = session.vim.service_content.storageResourceManager

task = session.invoke_api(session.vim,
                          "ConfigureDatastoreIORM_Task",
                          storage_resource_manager,
                          datastore=ds,
                          spec=ioconfig_spec)
print session.wait_for_task(task)

七、配额控制
Vmware好像没有配额功能。目前没看到。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容