XenでDom0からDomUのCPU使用率を得る方法

仮想マシンモニタXenがインストールされた環境上でDomain0のホストからDomainUのホストのCPU使用率を取得する方法を調べた。
Domain0のホストにおいてRootユーザは「xm」コマンドを用いてDomainUのホストの管理・監視ができる。xmコマンドには「list」というサブコマンドがあり、これを用いることによりドメインの表示ができる。さらにlistサブコマンドに「--long(-l)」オプションを与えることによりドメインの詳細表示、ドメインIDを与えることにより、そのドメインについての表示・詳細表示ができる。

# xm list -l mydebian
(domain
    (domid 5)
    (uuid f2c86828-5627-68e3-1a2d-0f3e118e3c12)
    (ssidref 0)
    (vcpus 1)
    (cpu_weight 1.0)
    (memory 64)
    (maxmem 64)
    (name mydebian)
    (on_poweroff destroy)
    (on_reboot restart)
    (on_crash restart)
    (image
        (linux
            (kernel /boot/vmlinuz-2.6.16-xenU)
            (root '/dev/sda1 ro')
            (args 4)
        )
    )
    (device
        (vif
            (backend 0)
            (script vif-bridge)
            (bridge xenbr0)
            (mac 00:16:11:00:00:11)
        )
    )
    (device
        (vbd
            (backend 0)
            (dev sda1)
            (uname file:/home/stakizawa/xen/debian_image)
            (mode w)
        )
    )
    (state -b----)
    (shutdown_reason poweroff)
    (cpu_time 5.756133222)
    (online_vcpus 1)
    (up_time 69.1984128952)
    (start_time 1169713353.14)
    (store_mfn 107771)
    (console_mfn 107770)
)

ここでCPU使用率に関連する項目は下のほうにある「cpu_time」。これはドメインが起動してから、CPUが使われた時間を表している(と考えている。間違えていたら指摘してください)。なので、「xm list」コマンドを時間を置いて2回実行し、その実行時刻の差分でcpu_timeの差分を割ればCPU使用率が求まる。式で表すと以下のようになる。
\frac{cputime2 - cputime1}{time2 - time1}
そこで、「xm list」を実行し、指定したドメインのCPU使用率を取得する簡単なプログラムをRubyで書いた。以下にそのソースを載せます。

class XenCPUUsage
  def initialize(vm_name)
    @vm_name = vm_name
    @old_cpu_time = get_xen_cpu_time
    @old_time = Time.now.to_f
  end

  def get_usage
    cpu_time = get_xen_cpu_time
    time = Time.now.to_f
    xen_usage = (cpu_time - @old_cpu_time) / (time - @old_time)
    xen_usage = (xen_usage * 100).round / 100.0
    @old_cpu_time = cpu_time
    @old_time = time
    return xen_usage
  end

  private
  def get_xen_cpu_time
    cpu_time = 0.0
    output = `xm list -l #{@vm_name}`
    output.each { |line|
      if /\(cpu_time\s+(.+)\)/ =~ line
        cpu_time = $1.to_f
        break;
      end
    }
    return cpu_time
  end
end

xu = XenCPUUsage.new "mydebian"
50.times {
  sleep 1
  puts xu.get_usage
}

Domain0のホスト上でRootになれば実行できる。ただし、下のほう、"mydebian"を実行中のOSのホスト名(or ID)に変える必要がある。