3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

pyvmomiでVMクローンをする際にLinux Prepを実行してみる

Posted at

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 の配列に数分入れる必要があります。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?