付録C 完全なディスクイメージ
メインのオーバークラウドイメージは、フラットパーティションイメージです。これは、パーティション情報またはブートローダーがイメージ自体に含まれていないことを意味します。director は、起動時に別のカーネルと ramdisk を使用し、オーバークラウドイメージをディスクに書き込む際には基本的なパーティションレイアウトを作成しますが、パーティションレイアウトとブートローダーが含まれる完全なディスクイメージを作成することが可能です。
C.1. 完全なディスクイメージの作成
overcloud-full.qcow2 フラットパーティションから完全なディスクイメージを作成するには、以下のステップを実行します。
-
overcloud-fullフラットパーティションを完全なディスクイメージのベースとして開きます。 - 希望のサイズで完全なディスクイメージを新規作成します。以下の例では、10 GB のイメージを使用します。
-
完全なディスクイメージにパーティションとボリュームを作成します。このイメージには、パーティションおよびボリュームを必要な数だけ作成します。以下の例では、
bootには分離されたパーティションを作成し、ファイルシステム内の他のコンテンツには論理ボリュームを作成します。 - パーティションとボリュームに初期ファイルシステムを作成します。
- フラットパーティションのファイルシステムをマウントして、完全なディスクイメージの適切なパーティションにコンテンツをコピーします。
-
fstabの内容を生成して、完全なディスクイメージの/etc/fstabに保存します。 - 全ファイルシステムをアンマウントします。
-
完全なディスクイメージのパーティションのみをマウントします。
/にマウントされた root パーティションから開始して、適切なディレクトリーに他のパーティションをマウントします。 -
shell コマンドを使用してブートローダーをインストールし、完全なディスクイメージに
grub2-installとgrub2-mkconfigを実行します。これにより、完全なディスクイメージにgrub2ブートローダーがインストールされます。 -
dracutを更新して、論理ボリューム管理のサポートを追加します。 - 全ファイルシステムをアンマウントして、イメージを終了します。
完全なディスクイメージの手動作成
イメージ作成の推奨ツールは guestfish で、以下のコマンドを使用してインストールします。
$ sudo yum install -y guestfish
インストールしたら guestfish の対話シェルを実行します。
$ guestfish
Welcome to guestfish, the guest filesystem shell for
editing virtual machine filesystems and disk images.
Type: 'help' for help on commands
'man' to read the manual
'quit' to quit the shell
><fs>
guestfish の使用に関する詳しい情報は、Red Hat Enterprise Linux 7 『仮想化導入および管理ガイド』の「Guestfish シェル」を参照してください。
C.2. 完全なディスクイメージの自動作成
以下の Python スクリプトは guestfish ライブラリーを使用して、完全なディスクイメージを自動的に生成します。
#!/usr/bin/env python
import guestfs
import os
# remove old generated drive
try:
os.unlink("/home/stack/images/overcloud-full-partitioned.qcow2")
except:
pass
g = guestfs.GuestFS(python_return_dict=True)
# import old and new images
print("Creating new repartitioned image")
g.add_drive_opts("/home/stack/images/overcloud-full.qcow2", format="qcow2", readonly=1)
g.disk_create("/home/stack/images/overcloud-full-partitioned.qcow2", "qcow2", 10.2 * 1024 * 1024 * 1024) #10.2G
g.add_drive_opts("/home/stack/images/overcloud-full-partitioned.qcow2", format="qcow2", readonly=0)
g.launch()
# create the partitions for new image
print("Creating the initial partitions")
g.part_init("/dev/sdb", "mbr")
g.part_add("/dev/sdb", "primary", 2048, 616448)
g.part_add("/dev/sdb", "primary", 616449, -1)
g.pvcreate("/dev/sdb2")
g.vgcreate("vg", ['/dev/sdb2', ])
g.lvcreate("var", "vg", 5 * 1024)
g.lvcreate("tmp", "vg", 500)
g.lvcreate("swap", "vg", 250)
g.lvcreate("home", "vg", 100)
g.lvcreate("root", "vg", 4 * 1024)
g.part_set_bootable("/dev/sdb", 1, True)
# add filesystems to volumes
print("Adding filesystems")
ids = {}
keys = [ 'var', 'tmp', 'swap', 'home', 'root' ]
volumes = ['/dev/vg/var', '/dev/vg/tmp', '/dev/vg/swap', '/dev/vg/home', '/dev/vg/root']
swap_volume = volumes[2]
count = 0
for volume in volumes:
if count!=2:
g.mkfs('ext4', volume)
ids[keys[count]] = g.vfs_uuid(volume)
count +=1
# create filesystem on boot and swap
g.mkfs('ext4', '/dev/sdb1')
g.mkswap_opts(volumes[2])
ids['swap'] = g.vfs_uuid(volumes[2])
# mount drives and copy content
print("Start copying content")
g.mkmountpoint('/old')
g.mkmountpoint('/root')
g.mkmountpoint('/boot')
g.mkmountpoint('/home')
g.mkmountpoint('/var')
g.mount('/dev/sda', '/old')
g.mount('/dev/sdb1', '/boot')
g.mount(volumes[4], '/root')
g.mount(volumes[3], '/home')
g.mount(volumes[0], '/var')
# copy content to root
results = g.ls('/old/')
for result in results:
if result not in ('boot', 'home', 'tmp', 'var'):
print("Copying %s to root" % result)
g.cp_a('/old/%s' % result, '/root/')
# copy extra content
folders_to_copy = ['boot', 'home', 'var']
for folder in folders_to_copy:
results = g.ls('/old/%s/' % folder)
for result in results:
print("Copying %s to %s" % (result, folder))
g.cp_a('/old/%s/%s' % (folder, result),
'/%s/' % folder)
# create /etc/fstab file
print("Generating fstab content")
fstab_content = """
UUID={boot_id} /boot ext4 defaults 0 2
UUID={root_id} / ext4 defaults 0 1
UUID={swap_id} none swap sw 0 0
UUID={tmp_id} /tmp ext4 defaults 0 2
UUID={home_id} /home ext4 defaults 0 2
UUID={var_id} /var ext4 defaults 0 2
""".format(
boot_id=g.vfs_uuid('/dev/sdb1'),
root_id=ids['root'],
swap_id=ids['swap'],
tmp_id=ids['tmp'],
home_id=ids['home'],
var_id=ids['var'])
g.write('/root/etc/fstab', fstab_content)
# unmount filesystems
g.umount('/root')
g.umount('/boot')
g.umount('/old')
g.umount('/var')
# mount in the right directories to install bootloader
print("Installing bootloader")
g.mount(volumes[4], '/')
g.mkdir('/boot')
g.mkdir('/var')
g.mount('/dev/sdb1', '/boot')
g.mount(volumes[0], '/var')
# do a selinux relabel
g.selinux_relabel('/etc/selinux/targeted/contexts/files/file_contexts', '/', force=True)
g.selinux_relabel('/etc/selinux/targeted/contexts/files/file_contexts', '/var', force=True)
g.sh('grub2-install --target=i386-pc /dev/sdb')
g.sh('grub2-mkconfig -o /boot/grub2/grub.cfg')
# create dracut.conf file
dracut_content = """
add_dracutmodules+="lvm crypt"
"""
g.write('/etc/dracut.conf', dracut_content)
# update initramfs to include lvm and crypt
kernels = g.ls('/lib/modules')
for kernel in kernels:
print("Updating dracut to include modules in kernel %s" % kernel)
g.sh('dracut -f /boot/initramfs-%s.img %s --force' % (kernel, kernel))
g.umount('/boot')
g.umount('/var')
g.umount('/')
# close images
print("Finishing image")
g.shutdown()
g.close()
アンダークラウドで実行可能ファイルとしてこのスクリプトを保存して、stack ユーザーとして実行します。
$ ./whole-disk-image.py
これにより、フラットなパーティションイメージから完全なディスクイメージが自動的に作成されます。完全なディスクイメージの作成が完了したら、以前の overcloud-full.qcow2 イメージを置き換えます。
$ mv ~/images/overcloud-full.qcow2 ~/images/overcloud-full-old.qcow2 $ cp ~/images/overcloud-full-partitioned.qcow2 ~/images/overcloud-full.qcow2
これで、完全なディスクイメージを他のイメージとともにアップロードできるようになりました。
C.3. ディスクイメージ全体にわたるボリュームの暗号化
また、guestfish を使用して、完全なディスクイメージ上のボリュームを暗号化することもできます。これには、現在のボリュームを消去して暗号化されたボリュームを作成する luks-format のサブコマンドを使用する必要があります。
以下の Python スクリプトは、以前に作成した overcloud-full-partitioned.qcow2 イメージを開き、現在の 空の home ボリュームを削除して、暗号化された home ボリュームに置き換えます。
#!/usr/bin/env python
import binascii
import guestfs
g = guestfs.GuestFS(python_return_dict=True)
g.add_drive_opts("/home/stack/images/overcloud-full-partitioned.qcow2", format="qcow2", readonly=0)
g.launch()
random_content = binascii.b2a_hex(os.urandom(1024))
g.luks_format('/dev/vg/home', random_content, 0)
g.luks_open('/dev/vg/home', random_content, 'cryptedhome')
g.vgscan()
g.vg_activate_all(True)
g.mkfs('ext4', '/dev/mapper/cryptedhome')
g.mount('/dev/vg/root','/')
volumes = lvs()
volumes.remove('/dev/vg/home')
volumes.remove('/dev/vg/root')
volumes.remove('/dev/vg/swap')
fstab_content = []
fstab_content.append('UUID=%s /boot ext4 defaults 0 2' % g.vfs_uuid('/dev/sda1'))
fstab_content.append('UUID=%s / ext4 defaults 0 1' % g.vfs_uuid('/dev/vg/root'))
fstab_content.append('UUID=%s none swap sw 0 0' % g.vfs_uuid('/dev/vg/swap'))
fstab_content.append('/dev/mapper/cryptedhome /home ext4 defaults 0 1')
for volume in volumes:
volume_name = volume.replace('/dev/vg/', '')
fstab_content.append('UUID=%s /%s ext4 defaults 0 2' % (g.vfs_uuid(volume), volume_name))
g.write('/etc/fstab', '\n'.join(fstab_content))
print '\n'.join(fstab_content)
g.write('/root/home_keyfile', random_content)
g.chmod(0400, '/root/home_keyfile')
mapper = """
home UUID={home_id} /root/home_keyfile
""".format(home_id=g.vfs_uuid('/dev/mapper/cryptedhome'))
g.write('/etc/crypttab', mapper)
g.luks_close('/dev/mapper/cryptedhome')
g.selinux_relabel('/etc/selinux/targeted/contexts/files/file_contexts', '/', force=True)
g.shutdown()
g.close()このスクリプトは以下の操作も実行します。
-
キーを作成します (
random_content)。 -
新しい暗号化されたボリュームで
/etc/fstabファイルを再生成します。 -
/root/home_keyfileへ暗号化キーを保存します。 -
/root/home_keyfileを使用してボリュームの復号化を自動的に行うcrypttabファイルにデータを投入します。
例としてこのスクリプトを使用して、ディスクイメージ全体の作成プロセスの一部として暗号化されたボリュームを作成します。
C.4. 完全なディスクイメージのアップロード
完全なディスクイメージをアップロードするには、イメージのアップロードコマンドで --whole-disk-image オプションを使用します。以下に例を示します。
$ openstack overcloud image upload --whole-disk --image-path /home/stack/images
このコマンドは /home/stack/images からイメージをアップロードしますが、overcloud-full.qcow2 ファイルを完全なディスクイメージとして扱います。このため、イメージのアップロードコマンドを実行する前に、アップロードする必要のある完全なディスクイメージの名前を overcloud-full.qcow2 に変更しておく必要があります。

Where did the comment section go?
Red Hat's documentation publication system recently went through an upgrade to enable speedier, more mobile-friendly content. We decided to re-evaluate our commenting platform to ensure that it meets your expectations and serves as an optimal feedback mechanism. During this redesign, we invite your input on providing feedback on Red Hat documentation via the discussion platform.