股票代码: 836286    股票简称: 易云股份
官方微信

扫一扫关注易云捷讯官方微信

备案 |       管理控制台

从 backport ovirt 的主机设备穿透代码学习 ovirt (前端部分)

一直基于开源的虚拟化项目 ovirt 做产品,也渐渐对这个以 java 为核心的管理系统有所熟悉。前一段时间,公司有需求要实现宿主机的显卡和网卡设备的穿透功能,而当前公司的产品基于的是 ovirt 3.5,碰巧ovirt 3.6 也实现好了宿主机的设备穿透功能, 拿 3.6 的跑了一遍没有问题,并且 3.5 和 3.6 之间的代码区别还没有大到水火不相容的程度,于是萌生了 backport 的想法,正好从界面到后端纵向的过一遍。

所谓 backport 就是将同一个项目的新版本实现好的代码转移到旧版本中,在一个项目中,对新功能的开发往往都是在该项目的最新版本上进行,而老版本则主要进入维护阶段。

主机设备穿透功能想法很简单,就是将把运行了虚拟机的宿主机上的硬件设备(可为 PCI 设备,usb 设备)穿透给虚拟机使用。 穿透给了虚拟机使用的设备主机不能再使用,并且虚拟机没有经过虚拟化层,而是直接从硬件层面上与宿主机的设备进行通信,在性能、延迟方面自然有先天优势,但是其劣势也是很显然的,它就像反虚拟化,把虚拟化的种种优势给抛开了。例如,一台虚拟机如果穿透了宿主机上的设备,它就只能在这台宿主机上面运行,失去了虚拟机可以在集群中随处运行的灵活性,并且虚拟机是独占式的使用该设备,导致资源的利用率可能不高。不过对于某些场景,该功能还是很实用且必不可少的。

ovirt engine 前端

MVP

对于宿主机设备穿透功能,界面上要体现的元素有:

●  主机下的子选项卡应该多出一个选项卡,用于列出主机的所有设备


1.jpg


●  虚拟机的子选项卡下面应该多出一个选项卡,用于列出虚拟机已经使用(穿透)的主机设备


2.jpg


●  设置按钮用于编辑用于穿透的主机设备,点击设置按钮后还需要有对应的弹出窗口


3.jpg

 

首先, ovirt 前端采用 gwt,它是一个用 Java 编码,编译成 Javascript 在浏览器上运行的一个前端框架。

ovirt engine 前端采用了 gwtp 结构,即 gwt 的 MVP 实现,即 Model,View,Presenter。这种模式在当下的很多前端业务逻辑框架中都有采用。

●  Model:主要负责逻辑,比如界面元素的内容写入,向后台发送数据请求

●  View:顾名思义,即界面元素的样式以及界面结构定义

●  Presenter:控制单元,负责控制 View 在什么时候展现,比如用户点击某个按钮弹出窗口,窗口的弹出就是按钮事件所触发的回调函数调用了由该窗口所对应的 Presenter 来弹出的

接下来需要找到管理员门户的前端的 M、V、P 所对应的代码:

●  M:在 ovirt 中,Model 的定义都在 uicommonweb 这个 maven 工程里,根据包名很快就能对号入座

●  V:对于管理员门户,View 放在了 webadmin 这个 maven 工程里

●  P:因为在 ovirt 中,一般一个 View 就对应了一个 Presenter,所以它也放在了 webadmin 中,根据包名很容易区分它们

根据以上,于是从 ovirt 3.6 的代码中找到了以下文件:

●  虚拟机设置主机设备的弹出窗口所对应的 MVP

  frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/hostdev/AddVmHostDevicesModel.java

  frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/vm/AddVmHostDevicePopupView.java

  frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/popup/hostdev/AddVmHostDevicePopupPresenterWidget.java

●  虚拟机已使用的主机设备列表的子选项卡所对应的 MVP

  frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/hostdev/VmHostDeviceListModel.java

  frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/virtualMachine/SubTabVirtualMachineHostDeviceView.java

  frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/tab/virtualMachine/SubTabVirtualMachineHostDevicePresenter.java

●  主机的设备列表的子选项卡所对应的 MVP

  frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/hostdev/HostDeviceListModel.java

  frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/host/SubTabHostDeviceView.java

  frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/tab/host/SubTabHostDevicePresenter.java

对于 ovirt 里 MVP 的一般位置,有如下规律:

●  Model 在 org.ovirt.engine.ui.uicommonweb.models 包里,一般可以根据具体的 Model 的类名称判断其作用,如:*ListModel 是对应列表界面的 Model

●  View 在 org.ovirt.engine.ui.webadmin.section.main.view 包里。选项卡对应的 View 可在 tab 目录下找到,并且根据所在的主选项卡名称来分类;弹出窗口的 View 可在 popup 目录下找到,并且根据所在的主选项卡名称来分类

●  Presenter 在 org.ovirt.engine.ui.webadmin.section.main.presenter 里,一般与每一个 View 都有对应的 Presenter,相对位置一致

GIN

ovirt 前端还采用了 GIN 注入框架,即 google inject,这很像 java 里著名的 shh 框架里的 Spring,用于将面向对象的 Java 语言的对象的创建集中起来,以便于管理,比如某类的对象是单例还是多例。

GIN 的作用为,当你将一个函数标注了 @Provides (com.google.inject.Provides)时,该函数的返回值类型将会被 GIN 记录;

通过 bind(A.class)to(B.class) 的方式可将 A 类的实例绑定给 B 类,即 GIN 会将所有关于 A 类的实例化请求通过 B 类的实例来实现。

当在一个构造方法或者一个类的属性上标注了 @Inject (com.google.inject.Inject)时,GIN 会从 GIN 的类型记录中与构造方法或类属性的类型进行匹配,然后 GIN 将创建好的实例赋予构造方法或实例。这也是为什么 ovirt 前端代码中很少出现 new 关键字。

例如管理门户中左侧的书签弹出窗口的 View 的构造函数为:


4.png


这时,GIN 会在整个项目范围的代码内搜寻 EventBus、ApplicationResources、ApplicationConstants 这三个类的实例化声明,于是找到了如下:


5.png


对于 GWTP 框架来说,使用了 GIN 作为注入的方式,实例化的声明有很多,但就目前我们要新添加的弹出窗口和选项卡,有下面两个地方:

●  MVP 之间的关系的绑定:告诉 GWTP,当某一个 Presenter 被调用时,应该使用哪一个 View 和 Model,此关系定义在下面这个文件中:

●  frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/PresenterModule.java

所以在该文件中,需要通过 bindPresenter() 函数来绑定上面三个 MVP。

此时,对于主机和虚拟机的子选项卡的 backport 工作已经完成,但对于虚拟机设置主机设备的弹出窗口,还需要额外工作。在继续修改代码前,需要先了解 ovirt 处理弹出窗口的逻辑。

●  ModelPorvider 的定义:用于定义 UICommand 和 Presenter 之间的对应关系,例如在某一个 View 中触发了一个按钮操作,按钮操作会触发一个 UICommand 事件,该 UICommand 会传给指定的 ModelProvider,然后 ModelPorvider 会执行自己的逻辑返回对应的 Presenter,从而将弹出窗口界面显示出来。对于虚拟机的弹出窗口,需要定义 ModelPorvider 的地方为:

  frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/VirtualMachineModule.java

在里面增加 getVmHostDeviceListProvider() 函数,如下(省略了部分):


6.png


至此,ovirt 前端部分基本完成。

 

 

二维码.gif

关注易云微信号,浏览更多技术文档


© 2011-2017 易云捷讯科技(北京)股份有限公司, 版权所有 | © 2011-2017 Eayun,Inc. All rights reserved.

京公网安备 11010802022475号 | 京ICP备 11028869号

业务咨询:400-606-6396