标签:
基于openstack kilo版本中的Nova代码,新增根据特定项目中的特定用户对外提供计算资源:vcpu ,ram统计的接口。
原始openstack中的计算资源统计颗粒度只到达项目这个层面。所以需要新增针对单个用户的统计接口。思路是通过nova内部接口遍历出当前用户所在的项目中的所有虚机条目,然后根据用户ID进行匹配,获取匹配虚机的flavor,然后从flavor中取得ram,vcpu的值进行累加。最后返回单个用户的统计值。
除了要考虑涉及api外,还需要考虑命令行的实现。此文先记录nova的api扩展,命令行的实现在下一文记录。
nova中的扩展api作为一种扩展资源存在于nova的代码框架中。所以在下述目录中添加新的资源:
为此功能新建文件:
此文件中定义了资源类和操作资源的控制类;
对于资源类,是按照扩展资源框架,继承
extensions.ExtensionDescriptor
nova-api服务初始化加载extension资源时会遍历contrib目录,根据目录下的文件名,映射到文件中和文件同名的类,注册资源。所以,此文件中定义的资源类就是:
class Server_use_statistics(extensions.ExtensionDescriptor): """Server use statitistics support. currently only consider cpu ram sum by a user in a project """
在此类中定义get_resource方法:
def get_resources(self): resources = [] res = extensions.ResourceExtension(‘os-server-statistics‘, ServersStatisticsController(self.ext_mgr), member_actions={‘defaults‘: ‘GET‘}) resources.append(res) return resources
调用extensions中的方法注册了访问此资源的url,和对应处理的controller对象,其对应的就是
ServersStatisticsController 类。
使用extensions扩展的资源访问的url是:http://controller:8774/v2/{tenant-id}/os-server-statistics/{user-id}
接下来就是具体的处理类:
ServersStatisticsController
这个类继承wsgi.controller
class ServersStatisticsController(wsgi.Controller):
由于需要调用内部函数获取instance list。nova的设计中,计算资源的实现在如下目录中:
处理compute相关的内部操作。所有关于计算资源的操作都通过API类进行了归集管理。所以要使用compute相关的接口,需要有一个方法的动态加载:
class ServersStatisticsController(wsgi.Controller): def __init__(self,ext_mgr=None): self.compute_api = compute.API() self.ext_mgr = ext_mgr
每一个ServersStatisticsController对象都会挂载compute的处理接口供其使用。
接下来,实现show函数,用以获取资源统计:
def show(self, req, id): ‘‘‘ :request url: /v2/{tenant_id}/os-server-statistics/{user_id} :param req: user_id:the user to caculate :param id: input the tenant_id which the user belong to :return: ‘‘‘ ‘‘‘ :param req: :param id: :return: ‘‘‘ context = req.environ[‘nova.context‘] user_id = id search_opts = { ‘deleted‘:False, ‘project_id‘:context.project_id, } limit = 1000 marker = None sort_keys = [‘created_at‘] sort_dirs = [‘desc‘] used_ram = 0 used_vcpu = 0 try: instance_list = self.compute_api.get_all(context, search_opts=search_opts, limit=limit, marker=None, want_objects=True, sort_keys=sort_keys, sort_dirs=sort_dirs) except exception.MarkerNotFound: msg = _(‘marker [%s] not found‘) % marker raise exc.HTTPBadRequest(explanation=msg) except exception.FlavorNotFound: LOG.debug("Flavor ‘%s‘ could not be found", search_opts[‘flavor‘]) instance_list = objects.InstanceList() if instance_list: for instance in instance_list: if instance.get(‘user_id‘) == user_id: used_ram += instance.get(‘flavor‘).get(‘memory_mb‘) used_vcpu += instance.get(‘flavor‘).get(‘vcpus‘) result = { ‘user_usage‘:{ ‘used_vcpus‘ : used_vcpu, ‘used_rams‘ : used_ram } } return result前半部分都是为调用真正的处理函数做参数准备。最后调用get_all函数获取当前用户所在的项目下的所有instance.其实,nova list的命令最后调用的处理函数也是get_all。get_all函数返回的是包含完整instance信息的list.
这其中也包括此instance所使用的flavor的展开信息。也就是说,只要从此函数取得了instance信息,就可以直接从此数据中取得flavor中的ram和cpu信息。然而,nova list中是没有这些展开信息的。原因是因为,nova 的api层处理函数:
def _get_servers(self, req, is_detail): """Returns a list of servers, based on any search options specified."""
对get_all取得的instance_list最后是做了信息的过滤:
if is_detail: instance_list.fill_faults() response = self._view_builder.detail(req, instance_list) else: response = self._view_builder.index(req, instance_list)
滤掉了一些数据。这也导致了外界通过现有的获取instance的api是无法一次性得到flavor的数据的原因。其实在内部接口中,get_all返回的数据是十分详尽的。
然后就是过滤信息,统计使用的资源,最后按JSON格式返回数据。
eg:
GET:http://controller:8774/v2/61d86e0499e94217819d87006a20de88/os-server-statistics/50519e0465b44cf2ac01fa07590211f3
结果:
- {
- "user_usage":
- {
- "used_vcpus": 3,
- "used_rams": 1536
- }
- }
标签:
原文地址:http://blog.csdn.net/klyhuntermax/article/details/51312244