分享:VMware vSphere API玩法

简介: 分享:VMware vSphere API玩法

写在前面

接上篇,上篇分享了openstack的api使用套路,本篇分享vmware的api使用套路,希望可以帮助到有需要的盆友。

在观看本文之前,也是最重要的一点,就是请确保你已经搭建好了用于测试的vsphere环境(esxi和vcenter)。

我的测试环境:

API文档阅读套路&实战

首次阅读vsphere api文档的话,可能会有点懵,下面我把最需要关注的点,以及阅读套路给说清楚,搞明白之后,其实也都够用了。

官方API文档: https://developer.vmware.com/apis

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 main
import (
 "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 poweredOn
photon3-hdcs poweredOn

使用Python编码,获取虚拟机属性:

import ssl
import atexit
from pyVim.connect import SmartConnect, Disconnect
from pyVmomi import vim
def 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.104
photon3-hdcs

4. 方法

继续拿VirtualMachine对象来看看它都有哪些方法,通过文档可看到虚拟机对象支持很多方法,创建、克隆、开机、关机、添加磁盘、添加网卡等等。每一个方法都详细描述了所需要的参数。在每个具体的对象类型中,都描述了所支持的方法,这些方法也可以在“All Methods”里查到。

下面使用Python编码,从模板克隆虚拟,代码如下:

import atexit
from pyVmomi import vim
from pyVim.connect import SmartConnectNoSSL, Disconnect
vcenterhost = '192.168.11.104'
vcenteruser = 'administrator@vsphere.local'
vcenterpassword = '1qaz#EDC'
vcenterport = 443
templatename = 'centos7_ttr_temp'
vmname = 'DEMO-13'
parserCpu = 1
parserMem = 128
parserIpaddress = "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 = None
parserDatastore_name = 'datastore1'
parserCluster_name = 'DEMO环境'
parserResource_pool = None
parserPower_on = True
parserDatastorecluster_name = None
def 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))
                break
def 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 obj
def 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()

写在最后

本次分享就到这里,希望本文可以帮助到有需要的盆友,关于代码,下面分享一下官方的参考资料。

相关文章
|
4月前
|
存储 监控 固态存储
【vSAN分布式存储服务器数据恢复】VMware vSphere vSAN 分布式存储虚拟化平台VMDK文件1KB问题数据恢复案例
在一例vSAN分布式存储故障中,因替换故障闪存盘后磁盘组失效,一台采用RAID0策略且未使用置备的虚拟机VMDK文件受损,仅余1KB大小。经分析发现,该VMDK文件与内部虚拟对象关联失效导致。恢复方案包括定位虚拟对象及组件的具体物理位置,解析分配空间,并手动重组RAID0结构以恢复数据。此案例强调了深入理解vSAN分布式存储机制的重要性,以及定制化数据恢复方案的有效性。
110 5
|
4月前
|
存储 固态存储 虚拟化
【vSAN分布式存储服务器数据恢复】VMware vSphere vSAN ESXi超融合HCI分布式存储数据恢复案例
近期,我司处理了一个由10台华为OceanStor存储组成的vSAN超融合架构,其中一台存储闪存盘出现故障,用户取下后用新的闪存盘代替,然后对该闪存盘所在的磁盘组进行重建,导致集群中一台使用0置备策略的虚拟机数据丢失。
100 6
|
7月前
|
JSON 监控 数据库
使用Telegraf+Influxdb+Grafana配置VMware vSphere监控大屏
使用Telegraf+Influxdb+Grafana配置VMware vSphere监控大屏
254 0
|
虚拟化
VMware vSphere Client中虚拟机“Disc Found”解决方法
VMware vSphere Client中虚拟机“Disc Found”解决方法
110 0
|
监控 负载均衡 安全
VMware vSphere 5.5 高可用性 2
VMware vSphere 5.5 高可用性
236 0
|
存储 资源调度 监控
VMware vSphere 5.5 高可用性 1
VMware vSphere 5.5 高可用性
122 0
|
存储 运维 程序员
[运维]VMware vSphere介绍
[运维]VMware vSphere介绍
198 1
|
存储 文件存储 开发工具
【VMware vSphere 7】虚拟化概述(一)
【VMware vSphere 7】虚拟化概述(一)
233 0
|
存储 Linux 虚拟化
VMware vSphere 入门学习笔记
ESXi是在物理服务器安装的服务端,所有虚拟机是安装再ESXi里面的,是服务端。 Vcenter是管理端 是安装在ESXi内的一台虚拟机,提供集中管理功能的,比如管理多台ESXi集群,还可以对虚拟机进行复制 克隆 制作模版等各种一系列管理功能操作。 Linux内核的Vcenter名字叫VCSA,Windows版本的Vcenter名字叫Vcenter。
334 0
VMware vSphere 入门学习笔记