通过vnc或spice方式访问虚拟主机上的KVM虚拟机,可以直接通过图形化界面virt-manager来设置,但此处通过xml配置文件修改。
#vi /etc/libvirt/qemu.conf vnc_listen = "0.0.0.0"vnclisten默认绑定127.0.0.1,在配置文件里指定VNC绑定0.0.0.0,就不用在安装kvm虚拟机时指定vnclisten参数了。当在虚拟主机上有很多个虚拟机的时候,若指定每个虚拟机的端口,将会很乱,所以采用0.0.0.0自动分配端口。
<graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'> <listen type='address' address='0.0.0.0'/> </graphics>#virsh start smb3.1
也可以通过virsh命令动态查看虚拟机的xml配置文件#virsh dumpxml smb3.1
(4)vnc登录
windows下可以通过vnc viewer或TightVNC或RealVNC等工具登录。
linux下可以安装tigervnc,然后通过#vncviewer 127.0.0.1:5901登录。
linux下也可以通过#virt-viewer --connect qemu:///system smb3.1访问,非本机的linux通过#virt-viewer qemu+ssh://[email protected]/system smb3.1访问。
(5)vnc源码登录
kde桌面的源码包kdenetwork中可以找到krdc/vnc中关于vnc的源码,提取vncview.cpp、vncclientthread.cpp和remoteview.cpp即可运行vnc。
#include "widget.h" #include "vncview.h" Widget::Widget(QWidget *parent) : QWidget(parent, Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint) { resize(900+20, 900+20); VncView *vncView = new VncView(this, QUrl("vnc://:@192.168.40.125:5901")); vncView->enableScaling(true); vncView->scaleResize(900, 900); vncView->show(); vncView->start(); } Widget::~Widget() { }
<graphics type='spice' autoport='yes' listen='0.0.0.0'> <listen type='address' address='0.0.0.0'/> </graphics>#virsh start smb3.0
或通过virsh命令动态查看虚拟机的xml配置文件#virsh dumpxml smb3.0
(3)spice登录
linux下通过#virt-viewer --connect qemu:///system smb3.0登录到图形化界面。
也可以通过命令#spicy -h 127.0.0.1 -p 5900(需安装spice-gtk-tools软件包)。
(4)spice源码登录
spice-gtk提供了完整的gtk界面。
#include <stdio.h> #include <stdlib.h> #include <getopt.h> #include <gtk/gtk.h> #include <spice-channel.h> #include <spice-session.h> #include <spice-widget.h> static GtkWidget *main_window; static SpiceSession *spice_session; static SpiceDisplay *spice_display; static char *host; static char *port; static void channel_new(SpiceSession *s, SpiceChannel *c, gpointer *data) { int id = 0; g_object_get(c, "channel-id", &id, NULL); if (SPICE_IS_MAIN_CHANNEL(c)) { fprintf(stdout, "new main channel\n"); return; } if (SPICE_IS_DISPLAY_CHANNEL(c)) { fprintf(stdout, "new display channel (#%d), creating window\n", id); spice_display = spice_display_new(s, id); gtk_container_add(GTK_CONTAINER(main_window), GTK_WIDGET(spice_display)); gtk_widget_show_all(main_window); return; } } static void usage() { fprintf(stdout, "spice-client: A spice client\n" "Usage: spice-client [options]...\n" " -h, --host\n" " Set address of spice server\n" " -p, --port\n" " Set port of spice server\n" " -e, --help\n" " Print help and exit\n" ); } static void parse_cmd(int argc, char *argv[]) { int c, e = 0; if (argc == 1) { usage(); exit(1); } const struct option long_options[] = { { "help", 0, 0, 'e' }, { "host", 0, 0, 'h' }, { "port", 0, 0, 'p' }, { 0, 0, 0, 0 }, }; while ((c = getopt_long(argc, argv, "eh:p:", long_options, NULL)) != EOF) { switch (c) { case 'e': goto failed; case 'h': host = optarg; break; case 'p': port = optarg; break; default: e++; break; } } if (e || argc > optind) { goto failed; } if (host == NULL || port == NULL) { fprintf(stderr, "No host or port found\n"); goto failed; } return ; failed: usage(); exit(1); } int main(int argc, char *argv[]) { parse_cmd(argc, argv); gtk_init(&argc, &argv); main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); spice_session = spice_session_new(); g_object_set(spice_session, "host", host, NULL); g_object_set(spice_session, "port", port, NULL); g_signal_connect(spice_session, "channel-new", G_CALLBACK(channel_new), NULL); if (!spice_session_connect(spice_session)) { fprintf(stderr, "spice_session_connect failed\n"); exit(1); } gtk_main(); return 0; }
gcc -o spice-client client.c `pkg-config --cflags --libs spice-client-gtk-2.0` ./spice-client -h 127.0.0.1 -p 5900