Mikor virtuális gépekkel dolgozunk, lépten-nyomon beleakadunk abba a problémába, hogy a különféle virtualizációs megoldásoknak más és igényei vannak a virtuális lemez image-ek szerkezetére vonatkozóan. Egyesek az image-eket mint teljes merevlemezt (partíciós táblával, partíciókkal együtt) kezelik (pl.: qemu), míg mások egy partíciónak tekintik azt. Ebben az írásban összefoglaljuk, hogyan készíthetünk és kezelhetünk különféle elvárásoknak megfelelő virtuális lemez image-eket Linux alatt.
Virtuális lemez partíciók
A legegyszerűbb esetben a virtualizációs megoldás úgy tekint a virtális lemez image-re, mint egy partícióra. Ekkor az image tartalma semmi más nem kell, hogy legyen csak a nyers adat, például az állományrendszer.
A dd paranccsal könnyen és gyorsan létrehozhatunk tetszőleges nagyságú üres virtuális lemez image-et, az alábbi módon:
dd if=/dev/zero of=disk1.img bs=1M count=1 seek=512
A fenti parancs hatására egy 512M nagyságú állomány keletkezik disk1.img néven a parancs kiadásának helyén. Az állomány még nem foglalja el a teljes 512M-t a fizikai lemezen, mivel ez egy úgynevezett ritka (sparse) állomány. Amint elkezdjük használni, a felhasználás mértékével arányosan, maximum 512M méretig folyamatosan foglalja majd a helyet az operációs rendszer a fizikai lemezen.
A Linux loop modulja teszi lehetővé, hogy tetszőleges állományokat, mint blokk eszközöket kezelhessünk. Ehhez először az állományt csatolni kell egy blokk eszköz meghajtóhoz. Ezt az összerendelést az alábbi parancs segítségével végezhetjük el:
losetup -f disk1.img
Ez a legkisebb szabad /dev/loopX (ahol X=0,1,2…) blokk eszköz állományon keresztül elérhetővé teszi a megadott állományt. Sajnos a parancs nem mondja meg, ki lett a kiválasztott blokk eszköz állomány, ezért érdemes a fenti parancs előtt a
losetup -f
parancsot kiadni, ami megmondja, hogy mi a neve a következő szabad /dev/loopX állománynak, vagy a parancs kiadása után a
cat /proc/partitions
megmutatja a partíciókat, köztük a loopokat is. Ha nem egyértelmű a helyzet, akkor a
# losetup /dev/loop0 /dev/loop0: [0303]:5560165 (/home/tudor/work/uml/raid1.bin)
parancs tisztázhatja, hogy melyik blokkeszközhöz melyik fájl tartozik.
A létrejött blokkeszközzel most már pontosan úgy járhatunk el, mintha valódi fizikai partíció lenne. Például az alábbi utasítással készíthetünk állomány rendszert rá:
mkfs.ext3 /dev/loop0
Valójában attól lesz egy tetszőleges image állomány virtuális lemez image, hogy állományrendszert tettünk rá.
A keletkezett új állományrendszerre például Debian linux rendszeren az alábbi parancsokkal telepíthetünk egy Etch változatú alaprendszert:
mount /dev/loop0 /mnt debootstrap --arch i386 etch /mnt http://ftp.debian.org/debian umount /mnt
Ha nem alkarjuk tovább használni a image állományt blokk eszközként, akkor szüntessük meg az összerendelést az alábbi paranccsal:
losetup -d /dev/loop0
Figyelmeztetés: mielőtt egy adott virtualizációs megoldással használatba vennénk a virtuális lemez image-et, mindenképpen csatoljuk le (umount) és szüntessük meg az összerendelést a blokk eszköz állománnyal. Ellenkező esetben adatvesztéssel járó hibát is elkövethetünk véletlen írással.
Teljes virtuális lemezek
Amikor az image állománnyal, mint teljes lemezzel dolgozunk, ugyanúgy kell a méreteket meghatározni, mint a fizikai lemezek esetén. Azaz a CHS (cylinder, head, sector) rendszerben kell gondolkoznunk.
Történelmileg úgy alakult, hogy a korai PC-k BIOS-ai maximum 63 szektort kezeltek, az IDE interfész esetén pedig maximum 16 fejet lehetett használni. Mára ezeknek az adatok elvesztették tényleges jelentésüket. Ennek ellenére kompatibilitási okokból elterjedt megoldás e két limitet felhasználva a virtuális lemezek geometriáját így kialakítani. A leírás további részében mi is ezt követjük, azaz továbbiakban mindig: head=16, sector=63.
Ahhoz, hogy jól kezelhető virtuális lemez image-ket kapjunk, célszerű cilinderre pontos méretű image állományt készíteni. Rövid számolás után megkapjuk, hogy 512 byte méretű blokkok esetén egy cilinder 512*16*63=516096 byte méretű. Egy 512 MB méretű merevlemez hozzávetőlegesen 1040 cilindert tartalmaz. Ennek megfelelően az eredeti dd parancsunkat az alábbiak szerint módosíthatjuk:
dd if=/dev/zero of=disk1.img bs=516096c count=1 seek=1040
Ezen a lemezen az alábbi módszerrel tudunk érvényes partíciós táblát kialakítani (egy partíciót fogunk készíteni, de a módszer kellő körültekintéssel általánosítható több partícióra is):
# losetup -f /dev/loop0 # losetup -f disk1.img # fdisk -u -C1040 -H16 -S63 /dev/loop0 o n p 1 <enter> <enter> a 1 w
A partíciónálás jobban automatizálható az sfdisk parancs segítségével. A fenti fdisk parancs megfelelője az alábbi:
sfdisk -D -C1040 -H16 -S63 /dev/loop0 <<EOF ,,,* EOF
A művelet elvégzése után az eredményt az alábbi utasítással tekinthetjük meg:
# fdisk -ul /dev/loop0 Disk /dev/loop0: 537 MB, 537255936 bytes 16 heads, 63 sectors/track, 1041 cylinders, total 1049328 sectors Units = sectors of 1 * 512 = 512 bytes Device Boot Start End Blocks Id System /dev/loop0p1 * 63 1048319 524128+ 83 Linux
Jól látható, hogy a partíció nem az első szektortól indul, így erre az image-re a korábban bemutatott módszerrel nem tudunk állományrendszert készíteni és aztán csatolni (mount) azt, egy kis trükkhöz kell folyamodni.
Az állományban az első partíció a 63*512=32256 bytenál kezdődik. Ezért a losetup parancsot az alábbiak szerint kell módosítani:
losetup -f -o32256 disk1.img
Ezek után az így kapott /dev/loopX-el úgy tudunk dolgozni, ahogy eddig.
A teljes virtuális lemezek esetén haszons lehet, ha tudjuk, hogyan kell egy boot loadert telepíteni azokra. Példának okáert most a grub telepítését mutatjuk be röviden.
Első szüntessük meg az összerendelést az állomány és a loopback eszköz között.
losetup -d /dev/loop0
Ezt követően indítsunk grub shellt:
grub --no-floppy
majd a grub shellben adjuk ki az alábbi parancsokat:
grub> device (hd0) disk1.img grub> geometry (hd0) 1040 16 63 grub> root (hd0,0) grub> setup (hd0)
Itt feltételeztük, hogy a disk1.img lesz az eszköz, amiről a rendszer bootolni fog és ez az eszköz lesz az első a biosban (hd0). A geometry paranccsnál a korábban kiszámolt cilinder, fej és szektor méreteket használtuk.
Forrás: Avaxio