pythonでvSphere操作　その6　VM作成

#本題

とりあえず本体。
目的は検証用VMを複数作成したり、基本構成のサーバ作成自動化用。

```python:py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pyVim.connect import SmartConnectNoSSL, Disconnect
from pyVmomi import vim, vmodl
import atexit, argparse, sys
from datetime import datetime
from pyVim.task import WaitForTask

#time
def time():
    d = datetime.today().strftime("%Y-%m-%d %H:%M:%S") + " "
    return d

#set arguments
def set_args():
    parser = argparse.ArgumentParser(
             description='required arguments for retreiving infos from vcenter.')

    parser.add_argument('-s', '--host',
                        required=True,
                        action='store',
                        help='specify vCenter IP')

    parser.add_argument('-o', '--port',
                        type=int,
                        default=443,
                        action='store',
                        help='specify port')

    parser.add_argument('-u', '--user',
                        required=True,
                        action='store',
                        help='specify login User')

    parser.add_argument('-p', '--password',
                        required=True,
                        action='store',
                        help='specify Password')

    parser.add_argument('-q', '--queryname',
                        required=True,
                        action='store',
                        help='specify VM name to make')

    parser.add_argument('-d', '--datastore',
                        required=True,
                        action='store',
                        help='specify datastore to store vmx')

    parser.add_argument('-g', '--portgroup',
                        required=True,
                        action='store',
                        help='specify portgroup to attach')

    parser.add_argument('-e', '--esxhost',
                        required=True,
                        action='store',
                        help='specify esxhost IP')


    args = parser.parse_args()
    return args

def searcher(vm,queryname):
    vname = vm.summary.config.name
    if vname == queryname:
        print time() + queryname + " already exists."
        sys.exit(1)
    else:
        pass

def main():
    #make connection
    args = set_args()
    si = SmartConnectNoSSL(host=args.host,
                           user=args.user,
                           pwd=args.password,
                           port=args.port)

    #set action at the end
    atexit.register(Disconnect, si)

    #create container
    content = si.RetrieveContent()
    datacenter = content.rootFolder.childEntity[0]
    vmnames = [vim.VirtualMachine]
    vmfolder = datacenter.vmFolder
    hosts = datacenter.hostFolder.childEntity
    esx = content.searchIndex.FindByIp(None,
                                       args.esxhost,
                                       vmSearch=False)
    resource_pool = hosts[0].resourcePool
    recursive = True
    vmcontainer = content.viewManager.CreateContainerView(
                    datacenter, vmnames, recursive)
    nwcontainer = content.viewManager.CreateContainerView(
                    datacenter, [vim.Network], recursive)

    #search
    children = vmcontainer.view
    for child in children:
        searcher(child, args.queryname)

    print time() + "begin creating " + args.queryname + " as a new VM."

    #set vm-spec
    spec_vmname = args.queryname
    spec_mem = 2048
    spec_guestId = 'rhel7_64Guest' #rhel7Guestとするとエラーするから注意
    spec_version = 'vmx-13'
    spec_cpu = 1

    #set vmxfile
    datastore_path = '[' + args.datastore + ']' + spec_vmname
    spec_vmx = vim.vm.FileInfo(logDirectory=None,
                               snapshotDirectory=None,
                               suspendDirectory=None,
                               vmPathName=datastore_path)

    #start setting devices
    spec_device = []

    #fetch portgroup object
    spec_pgrp = args.portgroup
    for c in nwcontainer.view:
        if c.name == spec_pgrp:
             pgr_obj = c

    #network
    nic_spec = vim.vm.device.VirtualDeviceSpec()
    nic_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add
    nic_spec.device = vim.vm.device.VirtualVmxnet3() #DO
    nic_spec.device.backing = vim.vm.device.VirtualEthernetCard.NetworkBackingInfo() #DO
    nic_spec.device.backing.network = pgr_obj #Prop
    nic_spec.device.backing.deviceName = spec_pgrp #Prop.o.VDDB
    nic_spec.device.connectable = vim.vm.device.VirtualDevice.ConnectInfo() #DO
    nic_spec.device.connectable.startConnected = False #Prop
    nic_spec.device.connectable.allowGuestControl = True #Prop
    spec_device.append(nic_spec)

    #scsicontroller
    scsi_spec = vim.vm.device.VirtualDeviceSpec()
    scsi_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add
    scsi_spec.device = vim.vm.device.ParaVirtualSCSIController()  #DO
    scsi_spec.device.sharedBus = vim.vm.device.VirtualSCSIController.Sharing.noSharing #DO.Prop.enum
    spec_device.append(scsi_spec)

    #set vdisk
    spec_disksize = 16 * 1024 * 1024
    disk_spec = vim.vm.device.VirtualDeviceSpec() #DO
    disk_spec.fileOperation = "create" #Prop.o.VDS(Enum)
    disk_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add #DO.Prop.Enum
    disk_spec.device = vim.vm.device.VirtualDisk() #DO
    disk_spec.device.backing = vim.vm.device.VirtualDisk.FlatVer2BackingInfo() #DO
    disk_spec.device.backing.thinProvisioned = True #Prop.o.FV2BI
    disk_spec.device.backing.diskMode = 'persistent' #Prop.o.FV2BI
    disk_spec.device.capacityInKB = spec_disksize #Prop.o.VD
    disk_spec.device.unitNumber = 0  #Prop.o.VDdev
    disk_spec.device.controllerKey = 0  #Prop.o.VDdev
    spec_device.append(disk_spec)

    #create standard VM
    #machine spec
    config = vim.vm.ConfigSpec(name = spec_vmname,
                               memoryMB = spec_mem,
                               files = spec_vmx,
                               guestId = spec_guestId,
                               version = spec_version,
                               numCPUs =  spec_cpu,
                               deviceChange = spec_device)

    #create machine
    task = vmfolder.CreateVM_Task(config=config,
                                  pool=resource_pool,
                                  host=esx)

    if WaitForTask(task):
        print time() +"creating vm done."

if __name__ == "__main__":
    main()
```

あとは処理を待たないので待つ処理(たぶん、WaitForTaskメソッド)と、ESXが指定できるようにするところ。

2018/4/5
→WaitForTaskは解決。"CreateVM_Task"をインスタンス化してWaitForTaskメソッドで囲んだだけ。
→ESX指定も解決。SearchIndex(MO)でESXをIPで調べて変数として"CreateVM_Task"に渡しただけ。

#組み方
目的のコマンドからすべきことを割り出す。
CreateVM_Task(config, pool, host)
以下から。
https://code.vmware.com/apis/197/vsphere#/doc/vim.Folder.html#createVm

vmのコンフィグ、プール、ホストを指定する。
じゃあコンフィグの指定は？
https://code.vmware.com/apis/197/vsphere#/doc/vim.vm.ConfigSpec.html

プールは？
四苦八苦したが、リソースプールが解ればいいっぽいので、vcenterからのhostからのpoolを順番に検索してく。

ホストは？
hostsystemのプロパティ情報を渡す必要があるみたいなので、いろんなやり方はあると思うが、ここでは”searchIndex”を使う。

ここから、vmの詳細などを決めていく。
vsphereからの返答は辞書型。

以上。