本文共 5682 字,大约阅读时间需要 18 分钟。
感谢朋友支持本博客,欢迎共同探讨交流,由于能力和时间有限,错误之处在所难免,欢迎指正!
如有转载,请保留源作者博客信息。
: 系统整体页面:
horizon采用django框架编写(django是一个强大的mvc 框架。具体参考djangobook中文版 。)
代码:vim /usr/share/openstack-dashboard/openstack_dashboard/dashboards/admin/dashboard.py
vim /usr/share/openstack-dashboard/openstack_dashboard/dashboards/project/instances/tables.py
第一部分: openstack_dashboard调 用流程 vim /usr/share/openstack-dashboard/openstack_dashboard/dashboards/project/instances/urls.py
找到risize对应的url行。调用views.ResizeView.as_view().
2、views.py层代码分析详解--跟进到views层的ResizeView: #说明resize功能使用workflow工作,下一步详解,请参考:workflow-1.1 workflow_class = project_workflows.ResizeInstance #执行成功跳转到horizon:project:instances:index链接文件: 下一步详解,请参考:模板页面-1.1 success_url = reverse_lazy("horizon:project:instances:index") #这个函数返回的值给context这个字典,这个字典里的值可以在html中取到 @memoized.memoized_method def get_object(self, *args, **kwargs): instance_id = self.kwargs['instance_id'] try: #根据实例id获取实例, 下一步详解, 下一步api调用流程 请参考:“
horizon中实例resize的API调用步骤详解“(
与之类似)。
instance = api.nova.server_get(self.request, instance_id) flavor_id = instance.flavor['id'] flavors = self.get_flavors() instance.flavor_name = flavors[flavor_id].name flavor = api.nova.flavor_get(self.request, flavor_id) instance.flavor_name = flavor.name redirect = reverse("horizon:project:instances:index") msg = _('Unable to retrieve instance details.') exceptions.handle(self.request, msg, redirect=redirect) #这个函数主要用来填充context字典,该字典可以和对应的html模板传参 def get_context_data(self, **kwargs): context = super(ResizeView, self).get_context_data(**kwargs) context["instance_id"] = self.kwargs['instance_id'] @memoized.memoized_method def get_flavors(self, *args, **kwargs): #获取数据库中已存在的flavors,下一步api调用流程 请参考:“
horizon中实例resize的API调用步骤详解“(
与之类似)。
flavors = api.nova.flavor_list(self.request) return SortedDict((str(flavor.id), flavor) for flavor in flavors) redirect = reverse("horizon:project:instances:index") exceptions.handle(self.request, _('Unable to retrieve flavors.'), redirect=redirect) #获取初始化数据,为对应的表单forms.py提供数据。(譬如下拉框数据如下图1。) initial = super(ResizeView, self).get_initial() _object = self.get_object() initial.update({'instance_id': self.kwargs['instance_id'], 'name': getattr(_object, 'name', None), 'old_flavor_id': _object.flavor['id'], 'old_flavor_name': getattr(_object, 'flavor_name', ''), 'flavors': self.get_flavors()}) #此处调用上处get_flavors函数 1、详解 resize功能的workflow机制: class ResizeView类中:workflow_class = project_workflows.ResizeInstance vim /usr/share/openstack-dashboard/openstack_dashboard/dashboards/project/instances/workflows/resize_instance.py
#成功与失败的弹出消息及成功之后的跳转url地址。 success_message = _('Scheduled resize of instance "%s".') failure_message = _('Unable to resize instance "%s".') success_url = "horizon:project:instances:index" default_steps = (SetFlavorChoice, create_instance.SetAdvanced) def format_status_message(self, message): return message % self.context.get('name', 'unknown instance') @sensitive_variables('context') def handle(self, request, context): #从views.py层中的context字典获取数据 instance_id = context.get('instance_id', None) flavor = context.get('flavor', None) disk_config = context.get('disk_config', None) try: #页面点击确认resize按钮,调用api resize 实例。本步骤将重点分析。下一步详情,请参考horizon中实例 resize的 API调用步骤详解: api.nova.server_resize(request, instance_id, flavor, disk_config) exceptions.handle(request) return False vim /us r/share/openstack-dashboard/openstack_dashboard/dashboards/project/instances/templates/instances/index.html 其中%%代表要替换掉的变量(若有疑问自行参考djangobook文档)。 table.render:表示将model层的数据渲染到页面。 horizon中实例resize的API调用步骤详解: api.nova.server_resize(request, instance_id, flavor, disk_config) vim /usr/share/openstack-dashboard/openstack_dashboard/api/__init__.py 此处将base、ceilometer、keystone等 都导入进来了。 跟踪到nova.api代码中:找到server_resize方法: def server_resize(request, instance_id, flavor, disk_config=None, **kwargs): novaclient(request).servers.resize(instance_id, flavor, #拼装client,组装url参数(包括keystone的token,以及调用v1_1、还是v3版本的novaclient参数等等) insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False) cacert = getattr(settings, 'OPENSTACK_SSL_CACERT', None) LOG.debug('novaclient connection created using token "%s" and url "%s"' % (request.user.token.id, base.url_for(request, 'compute'))) #根据返回的c知道接下来调用的是novaclient代码:因此上述方 法server_resize调用novaclient中server.py中的resize方法 下述流程则参考以下的novaclientAPI调用流程。 c = nova_client.Client(request.user.username, project_id=request.user.tenant_id, auth_url=base.url_for(request, 'compute'), http_log_debug=settings.DEBUG) c.client.auth_token = request.user.token.id c.client.management_url = base.url_for(request, 'compute') def server_resize(request, instance_id, flavor, disk_config=None, **kwargs): novaclient(request).servers.resize(instance_id, flavor, 接着调用novaclient模块中v1_1里面的services.py文件resize方法。 url = '/servers/%s/action' % base.getid(server) return self.api.client.post(url, body=body) #发送url,通过wsgi调用nova代码。(关于novaclient代码如何调用nova代码的WSGI介绍,请参考openstack的novaclient与nova WSGI调用 文章)