写在后面接上篇,上篇分享了openstack的api应用套路,本篇分享vmware的api应用套路,心愿能够帮忙到有须要的盆友。在观看本文之前,也是最重要的一点,就是请确保你曾经搭建好了用于测试的vsphere环境(esxi和vcenter)。
我的测试环境:
API文档浏览套路&实战首次浏览vsphere api文档的话,可能会有点懵,上面我把最须要关注的点,以及浏览套路给说分明,搞明确之后,其实也都够用了。官网API文档: https://developer.vmware.com/...
1. 对于vsphere的能力,咱们更关注的是vSphere Web Services API
2. 依据vsphere版本抉择绝对应的API版本
3. 对象类型
如上图,All Types蕴含了上面几种类型,只是做了分类而已:
Managed Object TypesData Object TypesEnumerated TypesFault TypesManaged Object Types是最罕用的,有虚拟机(VirtualMachine)、存储(Datastore)、宿主机(HostSystem)、网络(Network)等等,那平时怎么应用它呢?假如,当失去一个虚拟机实例对象时,想晓得它都能获取到什么属性,那么就能够在Property进行查阅。![图片]()
还有一个特地留神的中央,就是vim.VirtualMachine,它其实是某种对象类型的示意办法或者说是标识。比方,应用python的pyvmomi库,就须要指定查找的对象类型。如果是应用go,则是指定"VirtualMachine"应用Go编码,获取虚拟机属性:
package mainimport ( "context" "flag" "fmt" "log" "net/url" "os" "strings" "github.com/vmware/govmomi/session/cache" "github.com/vmware/govmomi/simulator" "github.com/vmware/govmomi/view" "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/soap")func getEnvString(v string, def string) string { r := os.Getenv(v) if r == "" { return def } return r}func getEnvBool(v string, def bool) bool { r := os.Getenv(v) if r == "" { return def } switch strings.ToLower(r[0:1]) { case "t", "y", "1": return true } return false}const ( envURL = "GOVMOMI_URL" envUserName = "GOVMOMI_USERNAME" envPassword = "GOVMOMI_PASSWORD" envInsecure = "GOVMOMI_INSECURE")var urlDescription = fmt.Sprintf("ESX or vCenter URL [%s]", envURL)var urlFlag = flag.String("url", getEnvString(envURL, ""), urlDescription)var insecureDescription = fmt.Sprintf("Don't verify the server's certificate chain [%s]", envInsecure)var insecureFlag = flag.Bool("insecure", getEnvBool(envInsecure, false), insecureDescription)func processOverride(u *url.URL) { envUsername := os.Getenv(envUserName) envPassword := os.Getenv(envPassword) if envUsername != "" { var password string var ok bool if u.User != nil { password, ok = u.User.Password() } if ok { u.User = url.UserPassword(envUsername, password) } else { u.User = url.User(envUsername) } } if envPassword != "" { var username string if u.User != nil { username = u.User.Username() } u.User = url.UserPassword(username, envPassword) }}func NewClient(ctx context.Context) (*vim25.Client, error) { u, err := soap.ParseURL(*urlFlag) if err != nil { return nil, err } processOverride(u) s := &cache.Session{ URL: u, Insecure: *insecureFlag, } c := new(vim25.Client) err = s.Login(ctx, c, nil) if err != nil { return nil, err } return c, nil}func Run(f func(context.Context, *vim25.Client) error) { flag.Parse() var err error var c *vim25.Client if *urlFlag == "" { err = simulator.VPX().Run(f) } else { ctx := context.Background() c, err = NewClient(ctx) if err == nil { err = f(ctx, c) } } if err != nil { log.Fatal(err) }}const ( vimVirtualMachine = "VirtualMachine")func a(ctx context.Context, c *vim25.Client) error { m := view.NewManager(c) v, err := m.CreateContainerView(ctx, c.ServiceContent.RootFolder, []string{vimVirtualMachine}, true) if err != nil { return err } defer v.Destroy(ctx) var vms []mo.VirtualMachine err = v.Retrieve(ctx, []string{vimVirtualMachine}, []string{"summary"}, &vms) if err != nil { return err } for _, vm := range vms { fmt.Println(vm.Summary.Guest.HostName, vm.Summary.Runtime.PowerState) } return nil}func main() { Run(a)}设置好环境变量:
export GOVMOMI_URL="192.168.11.104"export GOVMOMI_USERNAME="administrator@vsphere.local"export GOVMOMI_PASSWORD="1qaz#EDC"export GOVMOMI_INSECURE="y"测试运行并输入后果:
[root@devhost vmware]# go run coll-vsphere.go 192.168.11.104 poweredOnphoton3-hdcs poweredOn应用Python编码,获取虚拟机属性:
import sslimport atexitfrom pyVim.connect import SmartConnect, Disconnectfrom pyVmomi import vimdef main(): si = None ssl_context = ssl.create_default_context(purpose=ssl.Purpose.CLIENT_AUTH) ssl_context.verify_mode = ssl.CERT_NONE si = SmartConnect( host="192.168.11.104", user="administrator@vsphere.local", pwd="1qaz#EDC", port=int(443), sslContext=ssl_context ) atexit.register(Disconnect, si) content = si.RetrieveContent() container = content.rootFolder viewType = [vim.VirtualMachine] recursive = True containerView = content.viewManager.CreateContainerView( container, viewType, recursive) children = containerView.view for child in children: # print(child.summary.config.name) print(child.guest.hostName)if __name__ == "__main__": main()运行并输入后果:
[root@devhost cloud-collect]# /usr/local/python2.7.13/bin/python vmcollect.py 192.168.11.104photon3-hdcs4. 办法持续拿VirtualMachine对象来看看它都有哪些办法,通过文档可看到虚拟机对象反对很多办法,创立、克隆、开机、关机、增加磁盘、增加网卡等等。每一个办法都详细描述了所须要的参数。在每个具体的对象类型中,都形容了所反对的办法,这些办法也能够在“All Methods”里查到。
上面应用Python编码,从模板克隆虚构,代码如下:
import atexitfrom pyVmomi import vimfrom pyVim.connect import SmartConnectNoSSL, Disconnectvcenterhost = '192.168.11.104'vcenteruser = 'administrator@vsphere.local'vcenterpassword = '1qaz#EDC'vcenterport = 443templatename = 'centos7_ttr_temp'vmname = 'DEMO-13'parserCpu = 1parserMem = 128parserIpaddress = "192.168.11.90"parserNetmask = "255.255.255.0"parserGateway = "192.168.11.2"parserDnsServer = ["8.8.8.8"]parserDnsdomain = "local.com"parserPortgroup = "VM Network"parserDatacenter_name = 'Datacenter'parserVm_folder = NoneparserDatastore_name = 'datastore1'parserCluster_name = 'DEMO环境'parserResource_pool = NoneparserPower_on = TrueparserDatastorecluster_name = Nonedef wait_for_task(task): print('工作创立工夫 {}, 工作ID: {}'.format(task.info.queueTime, task.info.key)) while True: if task.info.state == 'error': print('创立过程中产生了谬误或正告,音讯: {}'.format(task.info.error)) print('创立进度 {}%'.format(task.info.progress)) # 如果工作状态为“正在运行”,则此属性蕴含进度度量,示意为从0到100的实现百分比。如果未设置此属性,则该命令不会报告进度。 if task.info.completeTime: # 判断进度条是否存在 print('创立工作进度终止,谬误音讯: {}'.format(task.info.error)) break else: if task.info.state == 'success': print('虚拟机创立胜利,VM对象: {}'.format(task.info.result)) breakdef get_obj(content, vimtype, name): """ Return an object by name, if name is None the first found object is returned """ obj = None container = content.viewManager.CreateContainerView(content.rootFolder, vimtype, True) for c in container.view: if name: if c.name == name: obj = c break else: obj = c break return objdef clone_vm(content, template, vm_name, si, datacenter_name, vm_folder, datastore_name, cluster_name, resource_pool, power_on, datastorecluster_name, is_cards): """ Clone a VM from a template/VM, datacenter_name, vm_folder, datastore_name cluster_name, resource_pool, and power_on are all optional. """ # if none git the first one datacenter = get_obj(content, [vim.Datacenter], datacenter_name) if vm_folder: destfolder = get_obj(content, [vim.Folder], vm_folder) else: destfolder = datacenter.vmFolder if datastore_name: datastore = get_obj(content, [vim.Datastore], datastore_name) else: datastore = get_obj( content, [vim.Datastore], template.datastore[0].info.name) # if None, get the first one cluster = get_obj(content, [vim.ClusterComputeResource], cluster_name) if resource_pool: resource_pool = get_obj(content, [vim.ResourcePool], resource_pool) else: resource_pool = cluster.resourcePool vmconf = vim.vm.ConfigSpec() if datastorecluster_name: podsel = vim.storageDrs.PodSelectionSpec() pod = get_obj(content, [vim.StoragePod], datastorecluster_name) podsel.storagePod = pod storagespec = vim.storageDrs.StoragePlacementSpec() storagespec.podSelectionSpec = podsel storagespec.type = 'create' storagespec.folder = destfolder storagespec.resourcePool = resource_pool storagespec.configSpec = vmconf try: rec = content.storageResourceManager.RecommendDatastores( storageSpec=storagespec) rec_action = rec.recommendations[0].action[0] real_datastore_name = rec_action.destination.name except: real_datastore_name = template.datastore[0].info.name datastore = get_obj(content, [vim.Datastore], real_datastore_name) # set relospec relospec = vim.vm.RelocateSpec() relospec.datastore = datastore relospec.pool = resource_pool nic_changes = [] if is_cards: # 编辑现有网卡连贯指定的端口组 nic_prefix_label = 'Network adapter' # nic_label = nic_prefix_label + str(1) nic_label = 'Network adapter 1' virtual_nic_device = None for dev in template.config.hardware.device: if isinstance(dev, vim.vm.device.VirtualEthernetCard) \ and dev.deviceInfo.label == nic_label: virtual_nic_device = dev virtual_nic_spec = vim.vm.device.VirtualDeviceSpec() virtual_nic_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit virtual_nic_spec.device = virtual_nic_device content = si.RetrieveContent() network = get_obj(content, [vim.Network], parserPortgroup) virtual_nic_spec.device.backing = vim.vm.device.VirtualEthernetCard.NetworkBackingInfo() virtual_nic_spec.device.backing.deviceName = parserPortgroup virtual_nic_spec.device.backing.network = network virtual_nic_spec.device.connectable = vim.vm.device.VirtualDevice.ConnectInfo() virtual_nic_spec.device.connectable.startConnected = True virtual_nic_spec.device.connectable.allowGuestControl = True virtual_nic_spec.device.connectable.connected = True virtual_nic_spec.device.connectable.status = 'untried' nic_changes.append(virtual_nic_spec) else: # 增加网卡并设置连贯端口组 nic_spec = vim.vm.device.VirtualDeviceSpec() nic_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add nic_spec.device = vim.vm.device.VirtualVmxnet3() nic_spec.device.deviceInfo = vim.Description() nic_spec.device.deviceInfo.summary = 'vCenter API test' content = si.RetrieveContent() network = get_obj(content, [vim.Network], parserPortgroup) nic_spec.device.backing = vim.vm.device.VirtualEthernetCard.NetworkBackingInfo() nic_spec.device.backing.deviceName = parserPortgroup nic_spec.device.backing.network = network nic_spec.device.connectable = vim.vm.device.VirtualDevice.ConnectInfo() nic_spec.device.connectable.startConnected = True nic_spec.device.connectable.allowGuestControl = True nic_spec.device.connectable.connected = True nic_spec.device.connectable.status = 'untried' nic_spec.device.wakeOnLanEnabled = True nic_spec.device.addressType = 'assigned' nic_changes.append(nic_spec) # set vmconf = vim.vm.ConfigSpec(numCPUs=parserCpu, memoryMB=parserMem, deviceChange=nic_changes) # Network adapter settings adaptermap = vim.vm.customization.AdapterMapping() globalip = vim.vm.customization.GlobalIPSettings() adaptermap.adapter = vim.vm.customization.IPSettings() adaptermap.adapter.ip = vim.vm.customization.FixedIp() adaptermap.adapter.ip.ipAddress = parserIpaddress adaptermap.adapter.subnetMask = parserNetmask adaptermap.adapter.gateway = parserGateway adaptermap.adapter.dnsDomain = parserDnsdomain adaptermap.adapter.dnsServerList = parserDnsServer # 主机名设置 ident = vim.vm.customization.LinuxPrep(domain=parserDnsdomain, hostName=vim.vm.customization.FixedName(name=vmname)) # 将所有这些部件放在一起以自定义规格 customspec = vim.vm.customization.Specification(nicSettingMap=[adaptermap], globalIPSettings=globalip,identity=ident) clonespec = vim.vm.CloneSpec(customization=customspec, config=vmconf) clonespec.location = relospec clonespec.powerOn = power_on task = template.Clone(folder=destfolder, name=vm_name, spec=clonespec) wait_for_task(task)def main(): si = SmartConnectNoSSL(host=vcenterhost, user=vcenteruser, pwd=vcenterpassword, port=vcenterport) atexit.register(Disconnect, si) content = si.RetrieveContent() template = get_obj(content, [vim.VirtualMachine], templatename) if template: num_cards = template.summary.config.numEthernetCards # 获取网卡数量 if num_cards: print('模板有网卡') clone_vm( content, template, vmname, si, parserDatacenter_name, parserVm_folder, parserDatastore_name, parserCluster_name, parserResource_pool, parserPower_on, parserDatastorecluster_name, is_cards=True) else: print('模板无网卡') clone_vm( content, template, vmname, si, parserDatacenter_name, parserVm_folder, parserDatastore_name, parserCluster_name, parserResource_pool, parserPower_on, parserDatastorecluster_name, is_cards=False) else: print("模板没有找到")if __name__ == "__main__": main()写在最初本次分享就到这里,心愿本文能够帮忙到有须要的盆友,对于代码,上面分享一下官网的参考资料。Golang:
https://pkg.go.dev/github.com...https://github.com/vmware/gov...Python:
https://pypi.org/project/pyvm...https://github.com/vmware/vsp...https://github.com/vmware/pyv...本文转载于(喜爱的盆友关注咱们):https://mp.weixin.qq.com/s/yb...