pyvmomiでVMのクローンを以前はやってみましたが、今回はLinux Prepを加えたクローンするスクリプトを作ってみました。
実行環境
項目 | バージョン |
---|---|
vCenter | 6.5.0 ビルド 4602587 |
pyvmomi | 6.5.0.2017.5.post1 |
python | 3.4.5 |
検証方針
-
centos
という仮想マシンを元にTEST
という仮想マシンを作成する。 - クローン先は
esxi-03.local
というホストを指定します。 - クローンタスク完了後に
TEST
の状態を確認して設定した内容に間違いが無いか調べます。
Linux Prepについて
VMwareのLinux Prepを使うことで、クローン時にホスト名やネットワーク設定を同時に行うことが可能です。
ソース
ここでは Network settings.
にネットワーク設定をしています。
以下は、クローンでLinux Prepを実行するスクリプト例です。
#!/usr/bin/env python3
from pyVim.connect import SmartConnect, Disconnect
from pyVmomi import vim, vmodl
from getpass import getpass
import ssl
import atexit
import argparse
import time
# Network settings.
ipaddr = '10.1.0.1'
netmask = '255.255.255.0'
gateway = '10.1.0.254'
dns = ['8.8.8.8','10.1.0.1']
def options():
"""
コマンドラインオプション設定
:rtype: class
:return: argparse.Namespace
"""
parser = argparse.ArgumentParser(prog='example_clone_script',
add_help=True,
description='VMクローンでLinux Prepを使うスクリプト例')
parser.add_argument('--host', '-vc',
type=str, required=True,
help='vCenterのIP又はホスト名')
parser.add_argument('--username', '-u',
type=str, default='administrator@vsphere.local',
help='vCenterのログインユーザー名(default:administrator@vsphere.local)')
parser.add_argument('--password', '-p',
type=str,
help='vCenterのログインユーザーパスワード')
parser.add_argument('--targetvm', '-tvm',
type=str, required=True,
help='クローン元の仮想マシン名を指定')
parser.add_argument('--targethost', '-th',
type=str, required=True,
help='仮想マシンのクローン先ホスト名を指定')
parser.add_argument('--vmname', '-vn',
type=str, required=True,
help='作成する仮想マシンのホスト名を指定')
args = parser.parse_args()
if(not(args.password)):
args.password = getpass()
return args
def get_mob_info(content, mob, target=''):
"""
Management Objectを取得する。
targetが指定されていない場合はContainerView(https://goo.gl/WXMfJK)で返す。
:type content: vim.ServiceInstanceContent
:param content: ServiceContent(https://goo.gl/oMtVFh)
:type mob: Management Object
:param mob: 取得する対象のManagement Objectを指定
:type target: str
:param target: 返すmobの名前を指定
:rtype: Management Object
:return: 指定したManagement Object又はContainerViewを返す
"""
r = content.viewManager.CreateContainerView(content.rootFolder,
[mob],
True)
# 返すmobを名前で指定する場合
if(target):
for i in r.view:
if(i.name == target):
r = i
return r
def login(args):
"""
ServiceContentオブジェクトを返す。
:rtype: class
:return: pyVmomi.VmomiSupport.vim.ServiceInstanceContent
"""
# SSL証明書対策
context = None
if hasattr(ssl, '_create_unverified_context'):
context = ssl._create_unverified_context()
# 接続
si = SmartConnect(host = args.host,
user = args.username,
pwd = args.password,
sslContext = context)
# 処理完了時にvCenterから切断
atexit.register(Disconnect, si)
# ServiceContent(Data Object)を取得
content = si.content
return content
def task_check(content, task):
"""
実行したタスクのステータスを確認してタスク終了時に実行結果を返す。
ステータス参考
runnin: タスク実行中
success: タスクが成功
error: タスクが失敗
:rtype: str
:return: タスク実行結果
"""
while True :
r = content.taskManager.recentTask
if(task in r):
task_r = [ x for x in r if task == x ]
if(task_r[0].info.state == vim.TaskInfo.State.success):
return task_r[0].info.state
break
elif(task_r[0].info.state == vim.TaskInfo.State.error):
return task_r[0].info.state
break
else:
return "Not found task: " + task
time.sleep(5)
def main(args):
# ServiceContent.
content = login(args)
# Create Linux Prep.
customization_linux_prep = vim.vm.customization.LinuxPrep()
linux_host_name = vim.vm.customization.FixedName()
linux_host_name.name = args.vmname
customization_linux_prep.hostName = linux_host_name
customization_linux_prep.hwClockUTC = True
customization_linux_prep.timeZone = 'Asia/Tokyo'
# Create customizationIPSettings.
nic = vim.vm.customization.AdapterMapping()
nic.adapter = vim.vm.customization.IPSettings()
nic.adapter.dnsDomain = ''
nic.adapter.gateway = gateway
nic.adapter.ip = vim.vm.customization.FixedIp()
nic.adapter.ip.ipAddress = ipaddr
nic.adapter.subnetMask = netmask
# Create CustomizationSpec.
customization_spec = vim.vm.customization.Specification()
customization_spec.globalIPSettings = vim.vm.customization.GlobalIPSettings()
customization_spec.globalIPSettings.dnsServerList = dns
customization_spec.nicSettingMap = [nic]
customization_spec.identity = customization_linux_prep
# Create RelocateSpec.
relocate_spec = vim.vm.RelocateSpec()
relocate_spec.host = get_mob_info(content, vim.HostSystem, args.targethost)
# Create CloneSpec.
clone_spec = vim.vm.CloneSpec()
clone_spec.customization = customization_spec
clone_spec.location = relocate_spec
clone_spec.powerOn = True
clone_spec.template = False
# Execute clone task.
v = get_mob_info(content, vim.VirtualMachine, args.targetvm)
task = v.CloneVM_Task(folder = v.parent, name = args.vmname, spec = clone_spec)
# Task check.
r = task_check(content, task)
print("Task結果: " + r)
if __name__ == '__main__':
args = options()
main(args)
処理の流れは以下のようになっています。
スクリプトで一時的にカスタマイズ仕様を作ってクローンメソッドに食わせています。
-
LinuxPrepを作成
- ホスト名やたいむゾーンを設定するオブジェクト
-
customizationIPSettingsを作成
- ネットワークを設定するオブジェクト
-
RelocateSpecを作成
- 仮想マシンの移動先を設定するオブジェクト
-
CloneSpecを作成
- 仮想マシンのクローン仕様を設定するオブジェクト
- クローン処理実行
- 実行したクローン処理のタスクを確認
- クローン処理の結果を出力
実行
(1) スクリプトを実行してみます。
$ ./example_clone_script.py -vc vcenter01.local -tvm centos -vn TEST -th esxi-03.local
Password:
Task結果: success
問題なく終了したら success
が表示されます。
(2) クローンした仮想マシンにログインしてホスト名やネットワーク設定が出来ていることを確認します。
[root@TEST ~]# hostnamectl
Static hostname: TEST
(snip)
[root@TEST ~]# ip a s ens192 | grep inet
inet 10.1.0.1/24 brd 10.1.0.255 scope global ens192
[root@TEST ~]# cat /etc/resolv.conf
(snip)
nameserver 8.8.8.8
nameserver 10.1.0.1
問題なく設定されていました :-)
vNICが複数ある場合は設定を customization_spec.nicSettingMap
の配列に数分入れる必要があります。