付録C 完全なディスクイメージ

メインのオーバークラウドイメージは、フラットパーティションイメージです。これは、パーティション情報またはブートローダーがイメージ自体に含まれていないことを意味します。director は、起動時に別のカーネルと ramdisk を使用し、オーバークラウドイメージをディスクに書き込む際には基本的なパーティションレイアウトを作成しますが、パーティションレイアウトとブートローダーが含まれる完全なディスクイメージを作成することが可能です。

C.1. 完全なディスクイメージの作成

overcloud-full.qcow2 フラットパーティションから完全なディスクイメージを作成するには、以下のステップを実行します。

  1. overcloud-full フラットパーティションを完全なディスクイメージのベースとして開きます。
  2. 希望のサイズで完全なディスクイメージを新規作成します。以下の例では、10 GB のイメージを使用します。
  3. 完全なディスクイメージにパーティションとボリュームを作成します。このイメージには、パーティションおよびボリュームを必要な数だけ作成します。以下の例では、boot には分離されたパーティションを作成し、ファイルシステム内の他のコンテンツには論理ボリュームを作成します。
  4. パーティションとボリュームに初期ファイルシステムを作成します。
  5. フラットパーティションのファイルシステムをマウントして、完全なディスクイメージの適切なパーティションにコンテンツをコピーします。
  6. fstab の内容を生成して、完全なディスクイメージの /etc/fstab に保存します。
  7. 全ファイルシステムをアンマウントします。
  8. 完全なディスクイメージのパーティションのみをマウントします。/ にマウントされた root パーティションから開始して、適切なディレクトリーに他のパーティションをマウントします。
  9. shell コマンドを使用してブートローダーをインストールし、完全なディスクイメージに grub2-installgrub2-mkconfig を実行します。これにより、完全なディスクイメージに grub2 ブートローダーがインストールされます。
  10. dracut を更新して、論理ボリューム管理のサポートを追加します。
  11. 全ファイルシステムをアンマウントして、イメージを終了します。

完全なディスクイメージの手動作成

イメージ作成の推奨ツールは 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 に変更しておく必要があります。


このページには機械翻訳が使用されている場合があります (詳細はこちら)。