출처 : http://kldp.org/node/119629

가상머신 상에서 사운드, 프린터, usb 등을 사용하는 방법을 몰랐을 때는 많이 불편했습니다. 특히 파일을 이동할 때는 많이 불편하더군요. 저는 물리 파티션(sdb1)을 이용하고 있어서 처음에는 ntfs를 마운트하는 방법을 이용했습니다. 물리 파티션이 아니더라도 마운트해서 사용할 수 있을 거라고 생각합니다만… 문제는 kvm에서 사용 중인 장치 파일이나 가상머신 이미지를 write permission을 줘서 오픈할 수 없다는 것입니다. sdb1을 이용해서 가상머신을 띄우는 경우에 kvm/qemu에서 그걸 인지하지 못하더군요. 하지만 호스트에서 해당 파티션에 쓰거나 가상머신에서 해당 파티션에 쓰는 경우 그 결과가 다른 쪽에 바로 반영되지 않을 뿐더러 문제가 발생합니다. 가상머신을 종료하고 파티션을 호스트에 마운트해서 파일을 이동하곤 했는데 매우 불편하더군요.


차라리 usb 형태의 이동식 디스크를 사용하는 것이 편할 수도 있겠습니다. kvm/qemu option에 -usbdevice host:[장치번호]를 주면 해당 usbdevice를 가상머신에서 사용할 수 있게됩니다. 하지만 이것도 가상머신을 다시 시작해야 하니 불편하기 그지 없지요.


쓰려고 했던 내용은 아니지만… 사운드의 경우엔 ALSA니 OSS니 하는 문제 때문에 복잡하던데요. 내용은 대충 잊어버렸고… aoss 프로그램을 이용하거나 kvm/qemu 시작시 OSS 드라이버를 지정해줘서 사용하고 있습니다. 많은 층의 소프트웨어를 통과해서 실제 디바이스에 도달하는 거라 그런지 음질은 최악입니다. 가상 머신 상에서 음악을 들으면 끔찍하죠. 온라인 상에서 음악을 구입하려고 하면 윈도우즈를 써야 하는데 미리 들어보려고 미리듣기 신청하면 끔찍합니다.


결국엔 파일이동/프린팅을 위해서 네트워크를 이용한 방법이 제일 심플할 텐데요. 가상머신이 윈도우즈인 경우에 호스트에서 삼바를 구동하고 윈도우즈에서 삼바를 통해 접근하면 편하겠죠. 그래서 둘 사이 네트워크 통신을 위해 시스템을 세팅해야 합니다.


kvm/qemu에서 내부적으로 NAT를 지원합니다. -net user 옵션을 주거나 해당 옵션을 주지 않으면 디폴트로 NAT 방식을 지원합니다. KVM 홈페이지의 Networking 부분(http://www.linux-kvm.org/page/Networking)에서는 "User Networking"으로 소개하고 있습니다. 이 방식을 사용하면 host에서 네트워크를 통해 게스트 컴퓨터를 엑세스할 수 없습니다. 사용하려는 목적에 맞지 않죠.


해당 페이지 용어로 얘기하면 "Private Virtual Bridge"와 "Public Bridge" 두 종류가 남았는데요. "Private Virtual Bridge" 또한 호스트에서 게스트를 엑세스할 수가 없으므로 남는 것은 "Public Bridge" 밖에 없습니다.


젠투(Gentoo) KVM 페이지(http://en.gentoo-wiki.com/wiki/KVM)에서 발췌한 그림인데요. KVM Networking 페이지에서 설명하는 내용과 맞춰보면 첫번째 것이 "Public Bridge"에 해당하고 두번째가 "Privage Virtual Bridge"에 해당합니다. ASCII art로 그린 그림이라 그림이 깨져보이는데요. 노트패드나 편집기로 옮긴 다음 픽스드 사이즈 폰트(예를 들면 Courier)로 변경해서 보시면 잘 보이실 겁니다.


Direct bridging (so guests use an IP address on the same subnet as the host):


              HOST
+—————+
| | KVM GUEST1
| | +————–+
| +——+ | | |
LAN —+— eth0 | +–+—+—- nic0 | KVM GUEST2
| | tap0—-+ | |192.168.1.13 | +————–+
| | tap1—-+ | +————–+ | |
| +——+ | | | |
| br0 +–+———————-+—- nic0 |
|192.168.1.12 | |192.168.1.14 |
+—————+ +————–+

When use NAT/Masquerading (to hide the guests behind the host):


              HOST
+—————+
| 192.168.1.12 | KVM GUEST1
LAN —+—- eth0 | +————–+
| ^ | | |
| | | | |
| +——+ +–+—+—- nic0 | KVM GUEST2
| | tap0—-+ | |192.168.100.1 | +————–+
| | tap1—-+ | +————–+ | |
| +——+ | | | |
| br0 +–+———————-+—- nic0 |
|192.168.100.254| |192.168.100.2 |
+—————+ +————–+

KVM 홒페이지에 따르면 Redhat, Debian, Suse의 경우에는 시스템 차원에서 설정만으로 Public Bridge를 구성할 수가 있습니다. 젠투에서도 되더군요. 하지만 제가 사용하는 Slackware는 그렇지 않으니 수동으로(manually) 해줘야만 합니다. 이 글을 쓰는 목적도 자동 구성을 지원하지 않는 시스템을 사용하는 사람들을 돕기 위한 것입니다.


다음 내용을 /etc/rc.d 시작 스크립트 중 하나에 넣어서 시스템 기동시 호출되도록 하면 됩니다. 이런 스크립트에 익숙하지 않아 에러 처리는 전혀하지 않았습니다. ^^; 그리고 기존 코드를 수정하기 싫어서 eth1이 이미 설정된 다음에 브릿지 세팅을 하게됩니다. 제 시스템에서는 eth1이 첫번째 네트워크 디바이스네요. 반드시 rc 스크립트에 넣어줘야만 되는 것은 아닙니다. KVM 시작 전에 kvm_net_start()의 내용을 roo user로 실행을 해줘도 됩니다. 그 상태에서도 컴퓨터를 잘 사용하실 수 있을 거구요. 그 후에 kvm_net_stop()의 내용을 반드시 실행해 줘야 하는 것은 아닙니다.


kvm_net_start() {
# eth1의 net addr lease 중단
dhcpcd -k eth1
# eth1 디바이스 내림
ifconfig eth1 down
# 해당 디바이스의 이름을 br0로 바꿈
nameif br0 6c:f0:49:76:e0:39
# br0 인터페이스 올림
ifconfig br0 up
# 브릿지 인터페이스 추가
brctl addbr eth1
# eth1 브릿지 인터페이스에 br0 추가
brctl addif eth1 br0
#brctl showmacs eth1
# eth1 인터페이스 올림
ifconfig eth1 up
# eth1 net addr 받기
dhcpcd eth1
}

kvm_net_stop() {
# 브릿지에서 br0 디바이스 제거
brctl delif eth1 br0

# eth1 주소 반납
dhcpcd -k eth1
# eth1 인터페이스내림
ifconfig eth1 down
# 브릿지 제거
brctl delbr eth1

# br0 인터페이스 다운
ifconfig br0 down
# br0 인터페이스 이름을 eth1으로 변경
nameif eth1 6c:f0:49:76:e0:39

# eth1 인터페이스 올리기
ifconfig eth1 up
# eth1 net addr lease 시작
dhcpcd eth1
}


첫번째 그림에서 tab device만 제외하고 동일한 구성이 만들어졌습니다.


kvm/qemu 시작/종료시 호출되는 스크립트(/etc/qemu-ifup, /etc/qemu-ifdown)가 있는데 거기에서 tap device를 설정하면 됩니다.


/etc/qemu-ifup


#!/bin/sh
set -x

switch=eth1

if [ -n "$1" ];then
/usr/bin/sudo /usr/sbin/tunctl -u `whoami` -t $1
/usr/bin/sudo /usr/sbin/brctl addif $switch $1
/usr/bin/sudo /sbin/ifconfig qtap0 up
exit 0
else
echo "Error: no interface specified"
exit 1
fi


/etc/qemu-ifdown


#!/bin/sh
set -x

switch=eth1

if [ -n "$1" ];then
/usr/bin/sudo /usr/sbin/brctl delif $switch $1
/usr/bin/sudo /sbin/ifconfig qtap0 down
/usr/bin/sudo /usr/sbin/tunctl -d $1
exit 0
else
echo "Error: no interface specified"
exit 1
fi


실제 윈도우즈가 구동될 때 네트워크 인터페이스 상황입니다. eth1과 br0의 HWaddr이 동일한 것을 볼 수 있습니다. qtap0의 HWaddr은 랜덤하게 생성되는 것 같습니다.


#ifconfig
br0 Link encap:Ethernet HWaddr 6c:f0:49:76:e0:39
inet6 addr: fe80::6ef0:49ff:fe76:e039/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:56865 errors:0 dropped:0 overruns:0 frame:0
TX packets:57281 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:52943645 (50.4 MiB) TX bytes:12826391 (12.2 MiB)
Interrupt:27 Base address:0xa000

eth1 Link encap:Ethernet HWaddr 6c:f0:49:76:e0:39
inet addr:192.168.1.3 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::6ef0:49ff:fe76:e039/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:52108 errors:0 dropped:0 overruns:0 frame:0
TX packets:47875 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:43368392 (41.3 MiB) TX bytes:11620863 (11.0 MiB)

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:74 errors:0 dropped:0 overruns:0 frame:0
TX packets:74 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:16667 (16.2 KiB) TX bytes:16667 (16.2 KiB)

qtap0 Link encap:Ethernet HWaddr 2a:01:bd:d8:43:57
inet6 addr: fe80::2801:bdff:fed8:4357/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:707 errors:0 dropped:0 overruns:0 frame:0
TX packets:64 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:137042 (133.8 KiB) TX bytes:11422 (11.1 KiB)


디폴트 게이트웨이가 브릿지 eth1으로 설정된 것을 볼 수 있습니다.


# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.123.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo
0.0.0.0 192.168.123.254 0.0.0.0 UG 0 0 0 eth1

# brctl showmacs eth1
port no mac addr is local? ageing timer
1 6c:f0:49:76:e0:39 yes 0.00
2 2a:01:bd:d8:43:57 yes 0.00

# brctl show eth1
bridge name bridge id STP enabled interfaces
eth1 8000.6cf04976e039 no br0
qtap0


다음은 sdb에 설치된 윈도우7을 가상머신을 실행하기 위한 명령입니다. 여기서 net옵션 중에서 script를 지정해주지 않았기 때문에 시작시 자동으로 /etc/qemu-if이 실행됩니다. net 옵션에 tap을 지정했기 때문에 kvm/qemu 내부 NAT를 사용하지 않습니다. net option에 지정해주는 macaddr은 가상 머신의 HWaddr로 br0나 qtap0와 다르게 지정해주셔야 합니다(대충 충돌 안될만한 주소를 써주시면 됩니다.).


$ sudo aoss /usr/local/kvm/bin/qemu-system-x86_64 \
-net nic,macaddr=52:54:12:34:56:78 \
-net tap,ifname=qtap0 \
-hda /dev/sdb \
-soundhw ac97 \
-m 1536 &

가상 머신 상에서 파일이동/프린팅, USB 디바이스 사용, 사운드 등이 해결되니 쓸만하네요. ^^

호스트와 KVM/QEMU 가상머신 사이의 네트워크 통신

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다