kvm生成一台新机器后,并不能自动分配新的ip。本文介绍了基于php语言,结合libvirt一系列的工具,实现通过命令行对虚拟机进行克隆和自动ip分配的方案。

前置条件

克隆来源的domain里边的文件已经被删除:/etc/udev/rules.d/70-persistent-net.rules。

实现流程

process.png

实现代码

<?php
$opts = getopt('d:', [
    'ip:',
    'old:',
    'new:',
]);
if (empty($opts)) {
    help();
}
define('IMG_DIR', '/data/vm-images/');
function help()
{
    echo <<<HELP
Usage: php clone.php --ip [ip] --old [domain] --new [domain]
  ip 创建的domain的ip,选填
  old 从哪个domain复制,默认为standard
  new 新domain的名称,必填
HELP;
    exit(1);
}
$ip = '';
if (isset($opts['ip'])) {
    $ip = $opts['ip'];
}
$old = 'standard';
if (isset($opts['old'])) {
    $old = $opts['old'];
}
if (!isset($opts['new'])) {
    help();
}
$new = $opts['new'];
$file = IMG_DIR.$new.'.img';
echo '克隆镜像'.PHP_EOL;
$cmd = sprintf('virt-clone -o %s -n %s -f %s', $old, $new, $file);
echo $cmd.PHP_EOL;
system($cmd, $status);
if ($status === 0) {
    echo '镜像克隆成功'.PHP_EOL;
}
if (!$ip) {
    exit;
}
$cmd = sprintf('cat /etc/libvirt/qemu/%s.xml |grep -E "(uuid|<mac address)"', $new);
exec($cmd, $lines, $status);
if ($status !== 0) {
    die('获取配置失败');
}
$uuid = '';
$mac = '';
foreach($lines as $line) {
    if (preg_match('#uuid>([^<]+)<#', $line, $ms)) {
        $uuid = $ms[1];
    } elseif (preg_match('#address\=\'([^\']+)\'#', $line, $ms)) {
        $mac = $ms[1];
    }
}
var_dump($uuid, $mac);
unset($lines);
echo "获取网卡配置".PHP_EOL;
$domFile = '/etc/sysconfig/network-scripts/ifcfg-eth0';
$cmd = sprintf('virt-cat -d %s %s', $new, $domFile);
echo $cmd.PHP_EOL;
exec($cmd, $lines, $status);
if ($status !== 0) {
    die('获取网卡配置失败');
}
foreach($lines as &$line) {
    list($key, $value) = explode('=', $line);
    switch($key) {
        case 'HWADDR':
            $line = $key.'='.$mac;
            break;
        case 'IPADDR':
            $line = $key.'='.$ip;
            break;
        case 'UUID':
            $line = $key.'='.$uuid;
            break;
    }
}
$ethFile = __DIR__.'/tmp/'.$new.'/ifcfg-eth0';
if (!is_dir(dirname($ethFile))) {
    mkdir(dirname($ethFile), 0755, true);
}
file_put_contents($ethFile, implode("\n", $lines));
unset($lines);
echo "替换网卡文件".PHP_EOL;
$cmd = sprintf('virt-copy-in -d %s %s %s', $new, $ethFile, dirname($domFile));
echo $cmd.PHP_EOL;
system($cmd, $status);
if ($status !==0) {
    die("写入网卡文件失败");
}
echo "写入网卡文件成功".PHP_EOL;
echo "克隆成功!".PHP_EOL;

标签: php, kvm

添加新评论