写在后面

接上篇,上篇分享了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 Types
  • Data Object Types
  • Enumerated Types
  • Fault Types
Managed 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-hdcs

4. 办法

持续拿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...