xm info命令用来查看物理结构信息,其中对于NUMA信息的查询到底深入到哪一层次,如何进行的,进行简单的分析。
首先,根据xm info命令查找xm命令
/xen-4.0.0/tools/python/xen/main.py
函数入口如下所示:
def main(argv=sys.argv):
if len(argv)< 2:
usage()
# intercept--help(-h) and output our own help
for help in['--help', '-h']:
if help in argv[1:]:
if help == argv[1]:
longHelp()
sys.exit(0)
else:
usage(argv[1])
cmd_name =argv[1]
cmd =xm_lookup_cmd(cmd_name)
//查找参数列表找到info命令对应的函数xm_info
ifcmd:
# strip off prog name and subcmd
args = argv[2:]
_,rc = _run_cmd(cmd, cmd_name,args)
//对指定的命令以及函数进行执行
sys.exit(rc)
else:
err('Subcommand %s not found!' % cmd_name)
usage()
----------------------------------------------------------------
转入到_run_cmd()函数进行执行;
def _run_cmd(cmd, cmd_name,args):
globalserver
try:
if server is None:
if serverType == SERVER_XEN_API:
server = XenAPI.Session(serverURI)
username, password = parseAuthentication()
server.login_with_password(username, password)
def logout():
try:
server.xenapi.session.logout()
except:
pass
atexit.register(logout)
else:
server =ServerProxy(serverURI)
//在后面的操作过程中要用到服务代理;
returnTrue,cmd(args)
//其中返回的第二个参数是一个函数xm_info(args),转到到相应的操作;
-----------------------------------------------------------------------------------
该过程为执行 xm_info的具体操作,其中主要查找过程;
defxm_info(args):
arg_check(args, "info", 0, 1)
try:
(options, params) = getopt.gnu_getopt(args, 'c', ['config'])
exceptgetopt.GetoptError, opterr:
err(opterr)
usage('info')
show_xend_config = 0
for (k, v)in options:
if k in ['-c', '--config']:
show_xend_config = 1
ifshow_xend_config:
for name, obj in inspect.getmembers(xoptions):
if not inspect.ismethod(obj):
if name == "config":
for x in obj[1:]:
if len(x) < 2:
print "%-38s: (none)" % x[0]
else:
print "%-38s:" % x[0], x[1]
else:
print "%-38s:" % name, obj
return
ifserverType == SERVER_XEN_API:
# Need to fake out old style xm info as people rely on parsingit
//从下面黑体显示的内容可
以看出,其中所有的内容都是在host_record结构体中获得的,而该数据结构都是在这个函数中得到;以及其他有的数据也是在host_cpu_records和host_metrics_record中获得;
host_record =server.xenapi.host.get_record(
server.xenapi.session.get_this_host(server.getSession()))
host_cpu_records = map(server.xenapi.host_cpu.get_record,host_record["host_CPUs"])
host_metrics_record =server.xenapi.host_metrics.get_record(host_record["metrics"])
def getVal(keys, default=""):
data = host_record
for key in keys:
if key in data:
data = data[key]
else:
return default
return data
def getCpuMhz():
cpu_speeds = [int(host_cpu_record["speed"])
for host_cpu_record in host_cpu_records
if "speed" in host_cpu_record]
if len(cpu_speeds) > 0:
return sum(cpu_speeds) / len(cpu_speeds)
else:
return 0
getCpuMhz()
def getCpuFeatures():
if len(host_cpu_records) > 0:
return host_cpu_records[0].get("features", "")
else:
return ""
info ={
"host": getVal(["name_label"]),
"release": getVal(["software_version", "release"]),
"version": getVal(["software_version", "version"]),
"machine": getVal(["software_version", "machine"]),
"nr_cpus": getVal(["cpu_configuration", "nr_cpus"]),
"nr_nodes": getVal(["cpu_configuration", "nr_nodes"]),
"cores_per_socket": getVal(["cpu_configuration","cores_per_socket"]),
"threads_per_core": getVal(["cpu_configuration","threads_per_core"]),
"cpu_mhz": getCpuMhz(),
"hw_caps": getCpuFeatures(),
"total_memory": int(host_metrics_record["memory_total"])/1024/1024,
"free_memory": int(host_metrics_record["memory_free"])/1024/1024,
"xen_major": getVal(["software_version", "xen_major"]),
"xen_minor": getVal(["software_version", "xen_minor"]),
"xen_extra": getVal(["software_version", "xen_extra"]),
"xen_caps": " ".join(getVal(["capabilities"], [])),
"xen_scheduler": getVal(["sched_policy"]),
"xen_pagesize": getVal(["other_config", "xen_pagesize"]),
"platform_params": getVal(["other_config", "platform_params"]),
"xen_commandline": getVal(["other_config", "xen_commandline"]),
"xen_changeset": getVal(["software_version", "xen_changeset"]),
"cc_compiler": getVal(["software_version", "cc_compiler"]),
"cc_compile_by": getVal(["software_version", "cc_compile_by"]),
"cc_compile_domain": getVal(["software_version","cc_compile_domain"]),
"cc_compile_date": getVal(["software_version", "cc_compile_date"]),
"xend_config_format":getVal(["software_version","xend_config_format"])
}
sorted = info.items()
sorted.sort(lambda (x1,y1), (x2,y2): -cmp(x1,x2))
for (k, v) in sorted:
print "%-23s:" % k, v
else:
info = server.xend.node.info()
for x in info[1:]:
if len(x) < 2:
print "%-23s: (none)" % x[0]
else:
print "%-23s:" % x[0], x[1]
------------------------------------------------------------------------------------------------
在 /xen-4.0.0/tools/python/xen/xenapi.py中可以找到getSession()函数;
def __init__(self, uri, transport=None, encoding=None,verbose=0,
allow_none=1):
xmlrpcclient.ServerProxy.__init__(self, uri, transport,encoding,
verbose, allow_none)
self._session = None
self.last_login_method = None
self.last_login_params = None
//该部分的xenapi主要完成与xend的通信过程,初始化过程可以看出没有具体赋值,其中返回了回话;
def getSession(self):
return self._session
------------------------------------------------------------------------------------------------------
在 /xen-4.0.0/tools/python/xend/xendapi.py中可以找到外面一层server.xenapi.session.get_this_host()对应的具体函数;
defsession_get_this_host(self, session, self_session):
if self_session != session:
return xen_api_error(['PERMISSION_DENIED'])
return xen_api_success(XendNode.instance().uuid)
defxen_api_success(value):
"""Wraps areturn value in XenAPI format."""
if value isNone:
s = ''
else:
s = stringify(value)
return{"Status": "Success", "Value": s}
在 /xen-4.0.0/tools/python/xend/xendapi.py中可以找到最外层对应的server.xenapi.host.get_record()对应的函数原型
def host_get_record(self,session, host_ref):
node = XendNode.instance()
dom = XendDomain.instance()
record = {'uuid': node.uuid,
'name_label': node.name,
'name_description': '',
'API_version_major': XEN_API_VERSION_MAJOR,
'API_version_minor': XEN_API_VERSION_MINOR,
'API_version_vendor': XEN_API_VERSION_VENDOR,
'API_version_vendor_implementation':
XEN_API_VERSION_VENDOR_IMPLEMENTATION,
'software_version': node.xen_version(),
'enabled': XendDomain.instance().allow_new_domains(),
'other_config': node.other_config,
'resident_VMs': dom.get_domain_refs(),
'host_CPUs': node.get_host_cpu_refs(),
'cpu_configuration': node.get_cpu_configuration(),
'metrics': node.host_metrics_uuid,
'capabilities': node.get_capabilities(),
'supported_bootloaders': ['pygrub'],
'sched_policy': node.get_vcpus_policy(),
'logging': {},
'PIFs': XendPIF.get_all(),
'PBDs': XendPBD.get_all(),
'PPCIs': XendPPCI.get_all(),
'PSCSIs': XendPSCSI.get_all(),
'PSCSI_HBAs': XendPSCSI_HBA.get_all()}
return xen_api_success(record)
整个host_record的获取过程如上所示;因为我只想获得NUMA结构的信息,所以我只关注nr_cpus,nr_node数据的来源,因此根据
node = XendNode.instance()函数获得
-------------------------------------------------------------------------------------------------------
找到 /xen4.0.0/tools/python/xen/xend/XendNode.py文件,并在该文件中找到具体的活动过程,经过传递过
程,最后来源为:
defphysinfo(self):
info=self.xc.physinfo()
//最终通过xc底层库获得,终于找到最底层获得过程。
info['cpu_mhz'] = info['cpu_khz'] / 1000
# physinfo is in KiB, need it in MiB
info['total_memory'] = info['total_memory'] / 1024
info['free_memory']
= info['free_memory'] /1024
info['node_to_cpu']
=self.format_node_to_cpu(info)
info['node_to_memory'] = \
self.format_node_to_memory(info, 'node_to_memory')
info['node_to_dma32_mem'] = \
self.format_node_to_memory(info, 'node_to_dma32_mem')
ITEM_ORDER = ['nr_cpus',
'nr_nodes',
'cores_per_socket',
'threads_per_core',
'cpu_mhz',
'hw_caps',
'virt_caps',
'total_memory',
'free_memory',
'node_to_cpu',
'node_to_memory',
'node_to_dma32_mem',
'max_node_id'
]
return [[k, info[k]] for k in ITEM_ORDER]
--------------------------------------------------------------------------------------
值得注意的一点就是在查找对应的xc中相应的函数时,可能会找不到制定的函数,原来在XendNode.py文件中有这么一条语句:
self.xc= xen.lowlevel.xc.xc();
解释了xc的具体位置;
然后再注意两点,就是在lowlevel的xc.c文件中,两个预定义
#definePKG "xen.lowlevel.xc"
#defineCLS "xc"
首先,根据xm info命令查找xm命令
/xen-4.0.0/tools/python/xen/main.py
函数入口如下所示:
def main(argv=sys.argv):
----------------------------------------------------------------
转入到_run_cmd()函数进行执行;
def _run_cmd(cmd, cmd_name,args):
-----------------------------------------------------------------------------------
该过程为执行 xm_info的具体操作,其中主要查找过程;
defxm_info(args):
------------------------------------------------------------------------------------------------
在 /xen-4.0.0/tools/python/xen/xenapi.py中可以找到getSession()函数;
//该部分的xenapi主要完成与xend的通信过程,初始化过程可以看出没有具体赋值,其中返回了回话;
------------------------------------------------------------------------------------------------------
在 /xen-4.0.0/tools/python/xend/xendapi.py中可以找到外面一层server.xenapi.session.get_this_host()对应的具体函数;
defsession_get_this_host(self, session, self_session):
defxen_api_success(value):
在 /xen-4.0.0/tools/python/xend/xendapi.py中可以找到最外层对应的server.xenapi.host.get_record()对应的函数原型
def host_get_record(self,session, host_ref):
整个host_record的获取过程如上所示;因为我只想获得NUMA结构的信息,所以我只关注nr_cpus,nr_node数据的来源,因此根据
-------------------------------------------------------------------------------------------------------
找到 /xen4.0.0/tools/python/xen/xend/XendNode.py文件,并在该文件中找到具体的活动过程,经过传递过
程,最后来源为:
defphysinfo(self):
--------------------------------------------------------------------------------------
值得注意的一点就是在查找对应的xc中相应的函数时,可能会找不到制定的函数,原来在XendNode.py文件中有这么一条语句:
self.xc= xen.lowlevel.xc.xc();
解释了xc的具体位置;
然后再注意两点,就是在lowlevel的xc.c文件中,两个预定义
#definePKG "xen.lowlevel.xc"
#defineCLS "xc"