Openstack Horizon二次開發


 系統整體頁面:

1.png (54.53 KB, 下載次數: 2)

下載附件  保存到相冊

2014-11-1 17:08 上傳




代碼結構:


horizon采用django框架編寫(django是一個強大的mvc 框架。具體參考djangobook中文版  http://djangobook.py3k.cn/2.0/。)


左側面板布局:


代碼:
  1. vim /usr/share/openstack-dashboard/openstack_dashboard/dashboards/admin/dashboard.py
復制代碼



實例列表布局:


  1. vim /usr/share/openstack-dashboard/openstack_dashboard/dashboards/project/instances/tables.py
復制代碼



上述三個按鈕在table_actions中定義。



上述按鈕在row_actions中定義。

第一部分:openstack_dashboard調用流程
接下來以resize instance 為例:



重點關注下圖url鏈接:



1、urls.py層代碼分析:

所有頁面的url鏈接都由urls.py處理:
  1. vim /usr/share/openstack-dashboard/openstack_dashboard/dashboards/project/instances/urls.py
復制代碼



找到risize對應的url行。調用views.ResizeView.as_view().


2、views.py層代碼分析詳解--跟進到views層的ResizeView:
  1. #說明resize功能使用workflow工作,下一步詳解,請參考:workflow-1.1
  2. workflow_class = project_workflows.ResizeInstance
  3. #執行成功跳轉到horizon:project:instances:index鏈接文件:下一步詳解,請參考:模板頁面-1.1
  4. success_url = reverse_lazy("horizon:project:instances:index")
復制代碼
  1. #這個函數返回的值給context這個字典,這個字典里的值可以在html中取到
  2.     @memoized.memoized_method
  3.     def get_object(self, *args, **kwargs):
  4.         instance_id = self.kwargs['instance_id']
  5.         try:#根據實例id獲取實例,下一步詳解,下一步api調用流程請參考:“horizon中實例resize的API調用步驟詳解“(與之類似)。
  6.             instance = api.nova.server_get(self.request, instance_id)
  7.             flavor_id = instance.flavor['id']
  8.             flavors = self.get_flavors()
  9.             if flavor_id in flavors:
  10.                 instance.flavor_name = flavors[flavor_id].name
  11.             else:
  12.                 flavor = api.nova.flavor_get(self.request, flavor_id)
  13.                 instance.flavor_name = flavor.name
  14.         except Exception:
  15.             redirect = reverse("horizon:project:instances:index")
  16.             msg = _('Unable to retrieve instance details.')
  17.             exceptions.handle(self.request, msg, redirect=redirect)
  18.         return instance
復制代碼
  1. #這個函數主要用來填充context字典,該字典可以和對應的html模板傳參
  2.     def get_context_data(self, **kwargs):
  3.         context = super(ResizeView, self).get_context_data(**kwargs)
  4.         context["instance_id"] = self.kwargs['instance_id']
  5.         return context
復制代碼
  1. #獲取flavors list
  2.     @memoized.memoized_method
  3.     def get_flavors(self, *args, **kwargs):
  4.         try:
  5.              #獲取數據庫中已存在的flavors,下一步api調用流程請參考:“horizon中實例resize的API調用步驟詳解“(與之類似)。
  6.             flavors = api.nova.flavor_list(self.request)
  7.             return SortedDict((str(flavor.id), flavor) for flavor in flavors)
  8.         except Exception:
  9.             redirect = reverse("horizon:project:instances:index")
  10.             exceptions.handle(self.request,
  11.                 _('Unable to retrieve flavors.'), redirect=redirect)
復制代碼
  1. #獲取初始化數據,為對應的表單forms.py提供數據。(譬如下拉框數據如下圖1。)
  2.     def get_initial(self):
  3.         initial = super(ResizeView, self).get_initial()
  4.         _object = self.get_object()
  5.         if _object:
  6.             initial.update({'instance_id': self.kwargs['instance_id'],
  7.                 'name': getattr(_object, 'name', None),
  8.                 'old_flavor_id': _object.flavor['id'],
  9.                 'old_flavor_name': getattr(_object, 'flavor_name', ''),
  10.                 'flavors': self.get_flavors()}) #此處調用上處get_flavors函數
  11.         return initial
復制代碼

圖1:



1、詳解resize功能的workflow機制:
  1. class ResizeView類中:workflow_class = project_workflows.ResizeInstance
  2. vim /usr/share/openstack-dashboard/openstack_dashboard/dashboards/project/instances/workflows/resize_instance.py
復制代碼

  1. #成功與失敗的彈出消息及成功之后的跳轉url地址。
  2. success_message = _('Scheduled resize of instance "%s".')
  3. failure_message = _('Unable to resize instance "%s".')
  4. success_url = "horizon:project:instances:index"
  5. #完成resize工作流兩個步驟:(如下圖2)
  6. default_steps = (SetFlavorChoice, create_instance.SetAdvanced)
  7. #格式化狀態消息輸出
  8.     def format_status_message(self, message):
  9.         return message % self.context.get('name', 'unknown instance')
  10. #完成resize工作流兩個步驟:(如下圖2)
  11.     @sensitive_variables('context')
  12.     def handle(self, request, context):
  13. #從views.py層中的context字典獲取數據
  14.         instance_id = context.get('instance_id', None)
  15.         flavor = context.get('flavor', None)
  16.         disk_config = context.get('disk_config', None)
  17.         try: #頁面點擊確認resize按鈕,調用api resize 實例。本步驟將重點分析。下一步詳情,請參考horizon中實例resize的API調用步驟詳解:
  18.             api.nova.server_resize(request, instance_id, flavor, disk_config)
  19.             return True
  20.         except Exception:
  21.             exceptions.handle(request)
  22.             return False
復制代碼

圖2:



模板頁面-1.1:
模板頁面文件位置:
  1. vim /usr/share/openstack-dashboard/openstack_dashboard/dashboards/project/instances/templates/instances/index.html
復制代碼


其中%%代表要替換掉的變量(若有疑問自行參考djangobook文檔)。
table.render:表示將model層的數據渲染到頁面。

horizon中實例resize的API調用步驟詳解:
接着上述workflow中resize
  1. api.nova.server_resize(request, instance_id, flavor, disk_config)
復制代碼

根據import原則找到api文件:
  1. vim /usr/share/openstack-dashboard/openstack_dashboard/api/__init__.py
復制代碼



此處將base、ceilometer、keystone等 都導入進來了。
跟蹤到nova.api代碼中:找到server_resize方法:
  1. def server_resize(request, instance_id, flavor, disk_config=None, **kwargs):
  2.     novaclient(request).servers.resize(instance_id, flavor,
  3.                                        disk_config, **kwargs)
復制代碼
  1. #拼裝client,組裝url參數(包括keystone的token,以及調用v1_1、還是v3版本的novaclient參數等等)
  2. def novaclient(request):
  3.     insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
  4.     cacert = getattr(settings, 'OPENSTACK_SSL_CACERT', None)
  5.     LOG.debug('novaclient connection created using token "%s" and url "%s"' %
  6.               (request.user.token.id, base.url_for(request, 'compute')))
  7. #根據返回的c知道接下來調用的是novaclient代碼:因此上述方法server_resize調用novaclient中server.py中的resize方法
復制代碼


下述流程則參考以下的novaclientAPI調用流程。
  1.     c = nova_client.Client(request.user.username,
  2.                            request.user.token.id,
  3.                            project_id=request.user.tenant_id,
  4.                            auth_url=base.url_for(request, 'compute'),
  5.                            insecure=insecure,
  6.                            cacert=cacert,
  7.                            http_log_debug=settings.DEBUG)
  8.     c.client.auth_token = request.user.token.id
  9.     c.client.management_url = base.url_for(request, 'compute')
  10.     return c
復制代碼


第二部分:novaclientAPI調用流程
從dashboard代碼入口開始:
  1. def server_resize(request, instance_id, flavor, disk_config=None, **kwargs):
  2.     novaclient(request).servers.resize(instance_id, flavor,
  3.                                        disk_config, **kwargs)
復制代碼


下圖為novaclient的代碼結構:
接着調用novaclient模塊中v1_1里面的services.py文件resize方法。


manage里面的resize方法:




調用action方法:



#下面兩句代碼拼接一個url地址
  1. url = '/servers/%s/action' % base.getid(server)
  2.         return self.api.client.post(url, body=body)
  3. #發送url,通過wsgi調用nova代碼。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM