存档

2013年9月 的存档

Get the guest IP address of Virtual Machine

2013年9月23日 没有评论

These days, I am developing a small project. One of the convenient functions it provides is that user can access QEMU virtual machine directly via ssh as long as user knows the name of VM.

There are two methods to archive this if user knows the guest’s MAC address:

Using ARP

ARP is a protocol which is used to convert an IP address to MAC Address.

With the ARP, we can get the MAC Address of a machine by its IP address, but what we have known is guest’s MAC address and what we want to know is IP address.

A hack method is to query all IP<->MAC address, then filter them by guest’s MAC.

#!/usr/bin/python
 
import commands
import sys
 
def find_ipaddr(mac):
    outtext = commands.getoutput('arp -n')
    for l in outtext.split('\n'):
        if l.split()[2] == mac:
            return l.split()[0]
    return None
 
if __name__ == '__main__':
    if len(sys.argv) != 2:
        print 'please input MAC Address'
        exit(1)
    ip = find_ipaddr(sys.argv[1])
    if ip:
        print '%s <-> %s' % (sys.argv[1], ip)
    else:
        print '%s <-> None' % (sys.argv[1])

Using GuestAgent

GuestAgent is a tool provided by QEMU official which aims to provide access to a system-level agent via standard QMP commands.

There are many commands available, one of them named “guest-network-get-interfaces”, outputs guest network information we need.

This way is more useful and graceful than using ARP, we can also get the guest’s IP address even if guest is on another subnet.

The following code shows how it works:

Start guest, append following arguments:

-chardev socket,id=qga0,path=/tmp/qga.sock,server,nowait \
-device virtio-serial -device virtserialport,chardev=qga0,name=org.mathslinux.qemu

Or if you want to use libvirt to start guest, append following xml under <device> tag

    <channel type='unix'>
      <source mode='bind' path='/tmp/qga.sock'/>
      <target type='virtio' name='org.mathslinux.qemu'/>
    </channel>

Then in the guest, run qemu-ga

./qemu-ga -p /dev/virtio-ports/org.mathslinux.qemu

After guest starts, we can fetch its IP address by connecting and sending “guest-network-get-interface” command to unix socket defined above.

#!/usr/bin/python
 
import socket
import sys
 
path = '/tmp/qga.sock'
 
def find_ipaddr(mac):
    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    sock.connect(path)
 
    sock.send('{"execute": "guest-network-get-interfaces"}')
    data = sock.recv(4096)
    for l in eval(data)['return']:
        if l['hardware-address'] == mac:
            ip_list = l['ip-addresses']
            for ip in ip_list:
                if ip['ip-address-type'] == 'ipv4':
                    return ip['ip-address']
 
    return None
 
if __name__ == '__main__':
    if len(sys.argv) != 2:
        print 'please input MAC Address'
        exit(1)
    ip = find_ipaddr(sys.argv[1])
    if ip:
        print '%s <-> %s' % (sys.argv[1], ip)
    else:
        print '%s <-> None' % (sys.argv[1])

分类: QEMU 标签:

Remove Gnome From Gentoo Completely

2013年9月3日 2 条评论

It has been a year since I didn’t use gnome! The new Gnome3 disappointed me too much. So I use LXDE as my desktop, which is more simple, more confortable to me. But for some reasons, Gnome still get inside in my system.

Today, When I attempt to upgrade all my installed packages to latest, the package “systemd” drives me crazy. It conflicts with udev, which is a very basic packages in gentoo. Since I have not been ready to use systemd, all packages will be broken without udev installed correctlly. I have used many ways to solve the issue, e.g. mask udev and systemd temporarily, however, all methods I have tried failed.

As above metioned, I don’t need systemd at all actually, so why I need to install it when upgrade my system. After some research, I find it is the gnome’s upgrade which requires systemd.

BS, now I find the reason, the fix is very easy.

// Add USE="-gnome" in /etc/make.conf file 
// Set system profile through "eselect profile set", i.e. dont select gnome profile
emerge -C $(grep gnome /var/lib/portage/world) # Delete all packages belong to gnome
emerge -DuNav world # Rebuild the system
emerge -Da --depclean # Clean up system
revdep-rebuild -i # Check whether something is missing

That’s all!

分类: Gentoo 标签:

开始半深入研究存储体系

2013年9月2日 没有评论

我目前存储的知识仅仅来停留在大学时候阅读的 ext2 的源代码, 和刚来北京时候(没记错的话) 读的 深入 Linux 内核架构 里面的 VFS 上. 近来由于工作的原因, 研究 QEMU 的 相对多一些, 对 QEMU 内部的存储体系算是比较了解. 但是在实际业务中, 考虑的不仅仅是 底层 hypervise 的能力, 上层存储架构也很重要.

而我对上层存储的实践能力, 还仅仅在 LVM, NFS 这些比较普通的技术里, 对于时下热门的 Ceph, GlusterFS, GFS2 等, 只是 “精通这些存储技术的拼写”.

就此机会, 半深入的对这些技术进行一下研究, 相信以我已有的对于文件系统, I/O 等的基础, 实践这些技术并不难.

分类: Storage 标签:

利用 API 获取 CPU 和内存信息

2013年9月1日 没有评论

今天在研究 CPU 的热插拔时,看到了获取系统 CPU 和内存信息的 API, 才发现以前在实现 这些功能的时候去 /proc 获取数据是多么的 ugly.

这些 API 主要是利用了 sysconf 这个 POSIX 的接口, 这个接口可以获取系统运行 时信息, 包括 CPU 信息, 内存信息, 进程可以打开的最大文件句柄数等. 它的声明如下:

long sysconf(int name);

  • _SC_NPROCESSORS_CONF: 获取系统中总的 CPU 数量, 注意这里获取的是所有的 CPU 线程的数量
  • _SC_NPROCESSORS_ONLN: 获取系统中可用的 CPU 数量, 没有被激活的 CPU 则不统计 在内, 例如热添加后还没有激活的.
  • _SC_PHYS_PAGES: 总的物理内存页大小.
  • _SC_AVPHYS_PAGES: 可用的物理内存页大小.

下面是我写的一些 demo 代码(在下面的代码里把 windows 获取这新信息的方法也写出来做参考):

#include<stdio.h>
 
#if defined(_WIN32)
#define _WIN32_WINNT 0x0500
#include <windows.h>
void sysinfo_print()
{
    int cpu_num;
    SYSTEM_INFO si;
    MEMORYSTATUSEX memory;
 
    // 大部分 Windows 系统不支持热添加功能, 所以 online number 没有什么意义.
    GetSystemInfo(&si);
    cpu_num = si.dwNumberOfProcessors;
    printf("The number of processors: %d\n", cpu_num);
 
    memory.dwLength = sizeof(memory);
    GlobalMemoryStatusEx(&memory);
    printf("The memory size: %I64uK\n", memory.ullTotalPhys/1024);
    printf("The free memory size: %I64uK\n", memory.ullAvailPhys/1024);
}
#else
#include<unistd.h>  
#include<errno.h>
#include <string.h>
void sysinfo_print()
{
    int cpu_num, cpu_online_num;
    int mem_size, mem_free_size;
 
    cpu_num = sysconf(_SC_NPROCESSORS_CONF);
    if (cpu_num != -1) {
        printf("The number of processors: %d\n", cpu_num);
    } else {
        printf("Failed to get number of processors: %s\n", strerror(errno));
    }
 
    cpu_online_num = sysconf(_SC_NPROCESSORS_ONLN);
    if (cpu_online_num) {
        printf("The number of online processors: %d\n", cpu_num);
    } else {
        printf("Failed to get number of online processors: %s\n",
               strerror(errno));
    }
 
    // 注意: OSX 不支持下面两个宏.
    mem_size = sysconf(_SC_PHYS_PAGES);
    if (mem_size) {
        printf("The memory size: %dK\n", mem_size * 4);
    } else {
        printf("Failed to get memory size: %s\n", strerror(errno));
    }
 
    mem_free_size = sysconf(_SC_AVPHYS_PAGES);
    if (mem_free_size) {
        printf("The free memory size: %dK\n", mem_free_size * 4);
    } else {
        printf("Failed to get free memory size: %s\n", strerror(errno));
    }
 
}
#endif
 
int main(int argc, char *argv[])
{
    sysinfo_print();
 
    return 0;
}

分类: linux, programming 标签: ,