2017年1月9日

KVMゲストをシリアルコンソールとUSBメモリでインストール

 何でも「仮想マシン」と呼んでしまう癖が抜けないのですけど、 CPUなどのエミュレータがQEMUでリソース管理を行うハイパーバイザーがKVM、 そしてXenなど他のハイパーバイザーと共通化を図ったlibvirtライブラリがあり、 CUIならvirshコマンド、GUIならvirt-managerで操作します。

自分が仮想マシンと呼んでいるものはlibvirtの「ドメイン」にあたり、 これだけでも覚えておかないとヘルプを読んだときに「ドメインの再起動???」となってしまうのです。

ドメインの定義

 ディスプレイ無しでシリアルコンソールを使うシンプルなXMLファイルが書けました。 このXMLで仮想マシン毎に変更が必要なのはnameとdiskのsourceだけです。 あとはホスト側に用意した仮想ネットワークに合わせてinterfaceが変わります。

ドメインXMLのフォーマットについてはここを参照
<domain type='kvm'>
  <name>centos-73min</name>
  <memory unit='GiB'>1</memory>
  <vcpu>1</vcpu>
  <os>
    <type arch='x86_64' machine='pc-i440fx-rhel7.0.0'>hvm</type>
    <bootmenu enable='yes' timeout='3000'/>
    <bios useserial='yes' rebootTimeout='0'/>
  </os>
  <features>
    <acpi/>
    <apic/>
  </features>
  <devices>
    <emulator>/usr/libexec/qemu-kvm</emulator>
    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/var/lib/libvirt/images/centos-73min.qcow2'/>
      <target dev='vda' bus='virtio'/>
    </disk>
    <controller type='usb' index='0' model='nec-xhci'/>
    <interface type='bridge'>
      <source bridge='br0'/>
      <model type='virtio'/>
    </interface>
    <console type='pty'>
      <target type='serial' port='0'/>
    </console>
  </devices>
</domain>

 次にdiskのsourceで指定した位置に好きな容量でディスクイメージを用意して、XMLファイルから仮想マシンを作成します。 virsh defineした段階でuuid、macアドレス、pciスロット番号などが適切に補われるため上記のXMLファイルでは指定していません。 さらにvirsh startした段階でホスト側のブリッジと繋がるTAPインタフェースの名前(vnet?)やシリアルコンソールが繋がる擬似端末(/dev/pts/?)の番号が決まります。
[root@localhost 170107_vm]# qemu-img create -f qcow2 /var/lib/libvirt/images/centos-73min.qcow2 10G
Formatting '/var/lib/libvirt/images/centos-73min.qcow2', fmt=qcow2 size=10737418240 encryption=off cluster_size=65536 lazy_refcounts=off

[root@localhost ~]# virsh define centos-73min.xml
ドメイン centos-73min が centos-73min.xml から定義されました

[root@localhost 170107_vm]# virsh list --all
 Id    名前                         状態
----------------------------------------------------
 -     centos-73min                   シャットオフ


USBインストールメディアの作成

 CentOSのISOイメージをddコマンドでUSBメモリに書き込むだけでそのままブート可能なメディアになります。
[root@localhost ~]# dd if=CentOS-7-x86_64-Minimal-1611.iso of=/dev/sdc bs=512k
1360+0 レコード入力
1360+0 レコード出力
713031680 バイト (713 MB) コピーされました、 46.8097 秒、 15.2 MB/秒
そのUSBメモリを仮想マシンに接続するためのXMLファイルも用意しておきましょう。
[root@localhost ~]# lsusb
Bus 001 Device 002: ID 8087:0a2b Intel Corp.
Bus 002 Device 009: ID 0411:021a BUFFALO INC. (formerly MelCo., Inc.)
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub

[root@localhost ~]# cat usb.xml
<hostdev mode='subsystem' type='usb'>
  <source>
    <vendor  id='0x0411'/>
    <product id='0x021a'/>
  </source>
</hostdev>


テキストモードでのインストール

 仮想マシンを起動してUSBメモリを接続したらシリアルコンソールにアクセスします。 このとき仮想マシンはブートメディアが無くてリブートを繰り返している状態です。
[root@localhost ~]# virsh start centos-73min
ドメイン centos-73min が起動されました

[root@localhost ~]# virsh attach-device centos-73min usb.xml --live
デバイスが正常に接続されました

[root@localhost ~]# virsh console centos-73min


 ESCキーを押してブートメニューを開き、認識されたUSBメモリを選択します。 ドメインの定義でbootmenuとuseserialを有効にしておかないとこの辺の作業はできません。



 CentOSをDVDでインストールするときと同じ画面が出るので Tabキーを押して起動オプションに「inst.keymap=jp inst.text console=ttyS0」を書き足します。 一気にコピペすると失敗するため1文字ずつ入力しましょう。



 テキストモードのインストールプログラムが表示され、 Installation sourceが検出できていれば成功したも同然です。 最小構成以外の場合は素直にVNC経由でグラフィカルモードを使いましょう。




 CentOSのインストールが完了すると1つのCPUと1GBのメモリ、XMLファイルで定義したPCIデバイスが仮想マシンに実装されたことを確認できます。
[root@localhost ~]# cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 13
model name      : QEMU Virtual CPU version 1.5.3
stepping        : 3
microcode       : 0x1
cpu MHz         : 4008.000
cache size      : 4096 KB
physical id     : 0
siblings        : 1
core id         : 0
cpu cores       : 1
apicid          : 0
initial apicid  : 0
fpu             : yes
fpu_exception   : yes
cpuid level     : 4
wp              : yes
flags           : fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pse36 clflush mmx fxsr sse sse2 syscall nx lm rep_good nopl pni cx16 hypervisor lahf_lm abm
bogomips        : 8016.00
clflush size    : 64
cache_alignment : 64
address sizes   : 39 bits physical, 48 bits virtual
power management:

[root@localhost ~]# free
              total        used        free      shared  buff/cache   available
Mem:        1016532       83880      664024        6640      268628      765616
Swap:       1048572           0     1048572

[root@localhost ~]# lspci
00:00.0 Host bridge: Intel Corporation 440FX - 82441FX PMC [Natoma] (rev 02)
00:01.0 ISA bridge: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II]
00:01.1 IDE interface: Intel Corporation 82371SB PIIX3 IDE [Natoma/Triton II]
00:01.3 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 03)
00:03.0 Ethernet controller: Red Hat, Inc Virtio network device
00:04.0 USB controller: NEC Corporation uPD720200 USB 3.0 Host Controller (rev 03)
00:05.0 SCSI storage controller: Red Hat, Inc Virtio block device
00:06.0 Unclassified device [00ff]: Red Hat, Inc Virtio memory balloon

 ここから先はACPIが有効になるため、virsh destroyでなくvirsh shutdownで仮想マシンを停止させるようにしましょう。 最後にUSBメモリが仮想マシンに挿さったままになっているためホスト側に戻って抜いておきます。
[root@localhost ~]# virsh detach-device centos-73min usb.xml --live
デバイスが正常に切断されました

2017年1月2日

DVDからISOイメージを作成

 仮想マシンを作成する際に必要になるでしょうから CentOS7のインストールに使用したDVD-RからISOイメージを吸い出しておきます。 DVD-Rを焼く際に使用したISOイメージをそのまま転送すれば済む話なのですけどメモ的に。

 まずCentOS7のインストールメディアはUSB接続したBD-Rドライブに挿入されている状態です。 そしてそのBD-Rドライブが/dev/配下のどれに対応するのかわからない「Linuxあるある」ですけど、 一般的にはdmesgコマンドの出力からUSBデバイスを接続した瞬間のイベントを探して解決します。 しかしlsblkコマンドの方が直感的にわかり易いので覚えておきたい。
[root@localhost ~]# lsusb
Bus 001 Device 003: ID 8087:0a2b Intel Corp.
Bus 002 Device 003: ID 08e4:017b Pioneer Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub

[root@localhost ~]# lsblk
NAME                MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINT
sda                   8:0    0  2.7T  0 disk
└─md126             9:126  0  2.7T  0 raid1
  ├─md126p1       259:0    0  200M  0 md    /boot/efi
  ├─md126p2       259:1    0  500M  0 md    /boot
  └─md126p3       259:2    0  2.7T  0 md
    ├─centos-root 253:0    0   50G  0 lvm   /
    ├─centos-swap 253:1    0 15.7G  0 lvm   [SWAP]
    └─centos-home 253:2    0  2.7T  0 lvm   /home
sdb                   8:16   0  2.7T  0 disk
└─md126             9:126  0  2.7T  0 raid1
  ├─md126p1       259:0    0  200M  0 md    /boot/efi
  ├─md126p2       259:1    0  500M  0 md    /boot
  └─md126p3       259:2    0  2.7T  0 md
    ├─centos-root 253:0    0   50G  0 lvm   /
    ├─centos-swap 253:1    0 15.7G  0 lvm   [SWAP]
    └─centos-home 253:2    0  2.7T  0 lvm   /home
sr0                  11:0    1 1024M  0 rom


 BD-Rドライブが/dev/sr0と判明したのでddコマンドを使って ブロックデバイスの中身を単純にダンプしてしまいます。 するとそれがそのままISOイメージとなります。
[root@localhost ~]# dd if=/dev/sr0 of=CentOS-7-x86_64-DVD-1511.iso
8456192+0 レコード入力
8456192+0 レコード出力
4329570304 バイト (4.3 GB) コピーされました、 548.663 秒、 7.9 MB/秒

[root@localhost ~]# file CentOS-7-x86_64-DVD-1511.iso
CentOS-7-x86_64-DVD-1511.iso: # ISO 9660 CD-ROM filesystem data 'CentOS 7 x86_64' (bootable)

 作成したISOイメージとインストールメディアをそれぞれマウントして、 同じファイルが入っていることを確認できました。 ISOイメージをマウントする際は-o loopオプションが必要です。
[root@localhost ~]# mkdir -p /mnt/{dvd,iso}

[root@localhost ~]# mount -t iso9660 /dev/sr0 /mnt/dvd
mount: /dev/sr0 is write-protected, mounting read-only

[root@localhost ~]# mount -o loop -t iso9660 CentOS-7-x86_64-DVD-1511.iso /mnt/iso
mount: /dev/loop0 is write-protected, mounting read-only

[root@localhost ~]# ls /mnt/dvd
CentOS_BuildTag  EULA  LiveOS    RPM-GPG-KEY-CentOS-7          TRANS.TBL  isolinux
EFI              GPL   Packages  RPM-GPG-KEY-CentOS-Testing-7  images     repodata
[root@localhost ~]# ls /mnt/iso
CentOS_BuildTag  EULA  LiveOS    RPM-GPG-KEY-CentOS-7          TRANS.TBL  isolinux
EFI              GPL   Packages  RPM-GPG-KEY-CentOS-Testing-7  images     repodata

[root@localhost ~]# umount /mnt/dvd
[root@localhost ~]# umount /mnt/iso
[root@localhost ~]# eject /dev/sr0
ejectコマンドをTABキーで補完すると/dev/sr0が出るのは裏技かもしれません。

2017年1月1日

nmcliコマンドでブリッジ作成

 NetworkManagerというとIPアドレスを設定するGUIという認識で、 とりあえず無効化してしまうLinux機能の1つだったのですけど、 CUI環境でもnmcliコマンドで設定するのがRHEL7からのスタイルらしいです。

NICの命名規則

 手始めにnmcliコマンドで状態を表示させてみます。 NetworkManagerではdeviceが仮想も含めたネットワークインタフェースそのものを指し、 connectionが/etc/sysconfig/network-scripts/配下の設定ファイルを指しているようです。

なおCentOS7を仮想マシンホスト構成でインストールしたので最初からvirbr0が作られていました。
[root@localhost ~]# nmcli device
DEVICE      TYPE      STATE        CONNECTION
virbr0      bridge    connected     virbr0
virbr0-nic  tap       connected     virbr0-nic
enp0s31f6   ethernet  disconnected  --
enp3s0      ethernet  unavailable   --
lo          loopback  unmanaged     --
wlp4s0      wifi      unmanaged     --

[root@localhost ~]# nmcli connection
NAME        UUID                                  TYPE            DEVICE
virbr0      b93007c6-e0e6-4916-b186-050966e59bb2  bridge          virbr0
enp0s31f6   714634a0-f8b2-40d1-a169-1cddc501e836  802-3-ethernet  --
enp3s0      20ba6fa2-4a25-4747-b3e8-fb37459caa7e  802-3-ethernet  --
virbr0-nic  1e0e6f66-4257-47a6-b48a-f4b6c57f49e7  generic         virbr0-nic


 ところでこのPCのマザーボード(GA-Z170N-WIFI)には有線LANが2つと無線LANが搭載されています。 どれにどんな名前が付いているのか「予想可能なネットワークインターフェイスデバイスの命名」に従って予想してみました。

デバイスタイプPci busSlotFunctionチップ
enp3s0EtherNet0x030x00-Intel I211
enp0s31f6EtherNet0x000x1f (31)6Intel I219-V
wlp4s0WirelessLan0x040x00-Intel 8260


予想結果がlspciコマンドで確認できるPCIバスの番号と一致しました。 ちなみにバックパネルの有線LANポートのうち無線LAN寄りにあるものがenp3s0のようですが、これはLANケーブルを挿してリンクアップしてみれば当然わかります。
[root@localhost ~]# lspci
00:00.0 Host bridge: Intel Corporation Sky Lake Host Bridge/DRAM Registers (rev 07)
00:02.0 VGA compatible controller: Intel Corporation Sky Lake Integrated Graphics (rev 06)
00:14.0 USB controller: Intel Corporation Sunrise Point-H USB 3.0 xHCI Controller (rev 31)
00:14.2 Signal processing controller: Intel Corporation Sunrise Point-H Thermal subsystem (rev 31)
00:16.0 Communication controller: Intel Corporation Sunrise Point-H CSME HECI #1 (rev 31)
00:17.0 RAID bus controller: Intel Corporation SATA Controller [RAID mode] (rev 31)
00:1b.0 PCI bridge: Intel Corporation Sunrise Point-H PCI Root Port #17 (rev f1)
00:1c.0 PCI bridge: Intel Corporation Sunrise Point-H PCI Express Root Port #1 (rev f1)
00:1c.4 PCI bridge: Intel Corporation Sunrise Point-H PCI Express Root Port #5 (rev f1)
00:1c.5 PCI bridge: Intel Corporation Sunrise Point-H PCI Express Root Port #6 (rev f1)
00:1d.0 PCI bridge: Intel Corporation Sunrise Point-H PCI Express Root Port #9 (rev f1)
00:1d.4 PCI bridge: Intel Corporation Sunrise Point-H PCI Express Root Port #13 (rev f1)
00:1f.0 ISA bridge: Intel Corporation Sunrise Point-H LPC Controller (rev 31)
00:1f.2 Memory controller: Intel Corporation Sunrise Point-H PMC (rev 31)
00:1f.3 Audio device: Intel Corporation Sunrise Point-H HD Audio (rev 31)
00:1f.4 SMBus: Intel Corporation Sunrise Point-H SMBus (rev 31)
00:1f.6 Ethernet controller: Intel Corporation Ethernet Connection (2) I219-V (rev 31)
03:00.0 Ethernet controller: Intel Corporation I211 Gigabit Network Connection (rev 03)
04:00.0 Network controller: Intel Corporation Wireless 8260 (rev 3a)


ブリッジの作成

 名前がハッキリしたところでenp0s31f6の方を使って 仮想マシンが家庭内LANに直接繋がるためのブリッジを作成し、 ホストマシンにアクセスするためのIPアドレスも設定します。
[root@localhost ~]# nmcli connection add type bridge ifname br0 stp no
接続 'bridge-br0' (19b14072-cf3f-491b-8f86-bca39d822977) が正常に追加されました。
[root@localhost ~]# nmcli connection modify bridge-br0 ipv4.method manual ipv4.addresses 192.168.3.91/24
[root@localhost ~]# nmcli connection modify bridge-br0 ipv4.gateway 192.168.3.1 ipv4.dns 192.168.3.1

[root@localhost ~]# nmcli connection add type bridge-slave ifname enp0s31f6 master br0
接続 'bridge-slave-enp0s31f6' (6e0bb72c-7c61-4e16-8ef5-61d08908c124) が正常に追加されました。
[root@localhost ~]# nmcli connection delete enp0s31f6
Connection 'enp0s31f6' (714634a0-f8b2-40d1-a169-1cddc501e836) successfully deleted.

[root@localhost ~]# reboot
再起動したらbr0にDHCPでIPアドレスが設定されてしまったので調べたところ、 /etc/sysconfig/network-scripts/ifcfg-bridge-br0の他にifcfg-br0が作成されていました。 なのでこの設定ファイルを削除したら解決しました。
[root@localhost ~]# nmcli connection delete br0
Connection 'br0' (d4043198-f545-447b-bb95-7efa8fcda68a) successfully deleted.
 connectionをdeleteして消えるのはあくまで設定ファイルです。 再起動の前にenp0s31f6もdeleteしていますけど、それはdeviceとしてのenp3s0の管理を ifcfg-enp0s31f6からifcfg-bridge-slave-enp0s31f6へ移す目的で行っています。

[root@localhost ~]# nmcli device
DEVICE      TYPE      STATE        CONNECTION
br0         bridge    connected    bridge-br0
virbr0      bridge    connected    virbr0
enp0s31f6   ethernet  connected    bridge-slave-enp0s31f6
virbr0-nic  tap       connected    virbr0-nic
enp3s0      ethernet  unavailable  --
lo          loopback  unmanaged    --
wlp4s0      wifi      unmanaged    --

[root@localhost ~]# nmcli connection
NAME                    UUID                                  TYPE            DEVICE
bridge-br0              19b14072-cf3f-491b-8f86-bca39d822977  bridge          br0
enp3s0                  20ba6fa2-4a25-4747-b3e8-fb37459caa7e  802-3-ethernet  --
bridge-slave-enp0s31f6  6e0bb72c-7c61-4e16-8ef5-61d08908c124  802-3-ethernet  enp0s31f6
virbr0-nic              9f76e889-2b08-4c22-b645-7a4545e25207  generic         virbr0-nic
virbr0                  8756b226-eb23-4ca9-a31b-3741a4910e0e  bridge          virbr0

[root@localhost ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.408d5c52d894       no              enp0s31f6
virbr0          8000.525400a1a3d6       yes             virbr0-nic
CentOS7のnmcliはコマンドラインをTABキーで補完できるので設定ファイルを直書きするより楽でした。