后端服务框架
介绍云平台后端服务所用的框架和相关库的使用方法,建议先阅读 开发手册/服务组件介绍 了解各个服务大概的功能。
后端服务框架
keystone, region, glance 等后端服务,都是用的同一套后端服务框架,这个框架是我们自己定义实现的,核心模块如下:
-
REST API: 负责解析客户端发送的 CRUD http 请求,将不同的请求对应到 Model Dispatcher 模块。
-
Model Dispatcher: 将客户端的请求分发到对应资源的业务操作。
-
Model: 定义云平台各种资源,会进行数据库读写相关操作,如果具体业务需要进行耗时操作,会通过 Task 机制来执行耗时任务。
-
Task: 后台处理异步耗时任务的模块,会通过更新 Model 的状态来更新任务的执行结果。
Cloudpods 代码结构
- build: 打包rpm脚本
- cmd: 可执行binary入口程序
- pkg: 库
- appsrv: 通用http服务框架
- cloudcommon: 云平台服务框架,基于appsrv扩展
- cloudcommon/options: 通用options
- cloudcommon/app: 通用服务初始化代码
- cloudcommon/db: Model dispatcher和Models的基础实现
- cloudcommon/db/lockman: 锁实现
- cloudcommon/db/taskman: 异步任务框架
认证部分
- 客户端向服务发起请求前,需要从keystone获得token
- 客户端通过携带用户名密码调用keystone的/v3/auth/tokens接口获得token
- 客户端向服务发起的每次API请求都会在HTTP头携带该token,比如: X-Auth-Token: {token}
- 后端服务向keystone验证该token,获得用户的身份信息,执行后续API的流程
- 每个服务都有一个keystone注册的服务用户账号(user/password),并且以admin角色加入system项目
- 服务启动后,会向keystone发起认证,获得admin token
- 用户通过API访问服务时,将在header携带token
- 使用这个admin token访问keystone的token验证接口,验证这个token,获得用户的身份信息
Model Dispatcher
把 REST API 和 Manager/Model 的方法进行一一映射
REST API 请求 | API 功能 | 对应对象 | 框架方法 | 说明 |
---|---|---|---|---|
GET /$resources | 列表 | Manager | ListItemFilter | 过滤 |
- | Manager | FetchCustomizeColumns | 获得扩展字段的信息 | |
GET /<resources>/<property> | 获得该类资源特定属性 | Manager | GetProperty<Property> | 获得该类资源的特定属性 |
GET /<resources>/<res_id> | 获得某个资源详情 | Model | FetchCustomizeColumns | 获取扩展字段的信息 |
GET /<resources>/<res_id>/<spec> | 获得某个资源特定属性 | Model | GetDetails<Spec> | 获取某个资源的特定属性 |
POST /<resources> | 新建资源 | Manager | ValidateCreateData | 校验和处理创建的数据 |
- | Model | CustomizeCreate | 自定义的创建操作 | |
- | Model | PostCreate | 创建后的hook | |
- | Manager | OnCreateComplete | 创建完成的hook | |
POST /<resources>/<action> | 对该类资源执行操作 | Manager | Perform<Action> | 对该类资源执行特定操作 |
POST /<resources>/<res_id>/<action> | 对某个资源执行操作 | Model | Perform<Action> | 对某个资源执行特定操作 |
PUT /<resources>/<res_id> | 更新某个资源的属性 | Model | ValidateUpdateData | 校验和处理更新操作的数据 |
- | Model | PreUpdate | 自定义的创建操作 | |
- | Model | PostUpdate | 创建后的hook | |
DELETE /<resources>/<res_id> | 删除某个资源 | Model | CustomizeDelete | 自定义的删除操作 |
- | Model | PreDelete | 删除前的hook | |
- | Model | Delete | 执行删除操作 | |
- | Model | PostDelete | 删除后的hook |
具体 restful 请求的绑定函数在: pkg/appsrv/dispatcher/dispatcher.go 文件中的 AddModelDispatcher 函数。
数据库 ORM 模型
代码位于 cloudcommon/db
- 接口
- IModelManager: 对应资源在数据库里面的表
- IModel: 对应资源在数据库里面的单条数据
- 数据结构
- SResourceBase: 基础资源
- SStandaloneResourceBase: 基础设施的物理资源,没有具体ownerId的资源,如zone, host
- SVirtualResourceBase: 虚拟资源,如虚拟机(guest)
- SSharableVirtualResourceBase: 虚拟的可以共享的虚拟资源,如disk, network
- SAdminSharableVirtualInfoBase: 管理配置用的可共享虚拟资源,如security group
- SSharableVirtualResourceBase: 虚拟的可以共享的虚拟资源,如disk, network
- SVirtualResourceBase: 虚拟资源,如虚拟机(guest)
- SJointResourceBase: 联合数据类型,如虚拟网卡是虚拟机和网络的联合,虚拟磁盘挂在:虚拟机和虚拟磁盘的联合
- SStandaloneResourceBase: 基础设施的物理资源,没有具体ownerId的资源,如zone, host
- SResourceBase: 基础资源
举例
用虚拟机的 model 来举例,代码在: pkg/compute/models/guests.go。
GuestManager 对应数据库里面的 guests_tbl,该对象嵌套 db.SVirtualResourceBaseManager 表示是虚拟资源的 Manager,这样会默认实现 db.IModelManager 接口,然后根据业务需要重写一些方法会比较方便。
SGuest 对应 guests_tbl 数据库里面的每一行数据,由 GuestManager 管理,嵌套 db.SVirtualResourceBase 结构,默认就会有虚拟资源所需要的表结构,然后再定义一些虚拟机独有的属性比如 VcpuCount 表示 cpu 核数,VmemSize 表示内存大小。 在代码抽象后表示虚拟机实例,该对象会绑定对虚拟机具体的业务操作实现函数。
import "yunion.io/x/cloudpods/pkg/cloudcommon/db"
......
type SGuestManager struct {
db.SVirtualResourceBaseManager
}
var GuestManager *SGuestManager
func init() {
GuestManager = &SGuestManager{
SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager(
SGuest{},
"guests_tbl",
"server",
"servers",
),
}
GuestManager.SetVirtualObject(GuestManager)
GuestManager.SetAlias("guest", "guests")
}
type SGuest struct {
db.SVirtualResourceBase
db.SExternalizedResourceBase
SBillingResourceBase
VcpuCount int `nullable:"false" default:"1" list:"user" create:"optional"` // Column(TINYINT, nullable=False, default=1)
VmemSize int `nullable:"false" list:"user" create:"required"` // Column(Integer, nullable=False)
BootOrder string `width:"8" charset:"ascii" nullable:"true" default:"cdn" list:"user" update:"user" create:"optional"` // Column(VARCHAR(8, charset='ascii'), nullable=True, default='cdn')
DisableDelete tristate.TriState `nullable:"false" default:"true" list:"user" update:"user" create:"optional"` // Column(Boolean, nullable=False, default=True)
ShutdownBehavior string `width:"16" charset:"ascii" default:"stop" list:"user" update:"user" create:"optional"` // Column(VARCHAR(16, charset='ascii'), default=SHUTDOWN_STOP)
KeypairId string `width:"36" charset:"ascii" nullable:"true" list:"user" create:"optional"` // Column(VARCHAR(36, charset='ascii'), nullable=True)
HostId string `width:"36" charset:"ascii" nullable:"true" list:"admin" get:"admin" index:"true"` // Column(VARCHAR(36, charset='ascii'), nullable=True)
BackupHostId string `width:"36" charset:"ascii" nullable:"true" list:"user" get:"user"`
Vga string `width:"36" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"` // Column(VARCHAR(36, charset='ascii'), nullable=True)
Vdi string `width:"36" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"` // Column(VARCHAR(36, charset='ascii'), nullable=True)
Machine string `width:"36" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"` // Column(VARCHAR(36, charset='ascii'), nullable=True)
Bios string `width:"36" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"` // Column(VARCHAR(36, charset='ascii'), nullable=True)
OsType string `width:"36" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"` // Column(VARCHAR(36, charset='ascii'), nullable=True)
FlavorId string `width:"36" charset:"ascii" nullable:"true" list:"user" create:"optional"` // Column(VARCHAR(36, charset='ascii'), nullable=True)
SecgrpId string `width:"36" charset:"ascii" nullable:"true" get:"user" create:"optional"` // Column(VARCHAR(36, charset='ascii'), nullable=True)
AdminSecgrpId string `width:"36" charset:"ascii" nullable:"true" get:"admin"` // Column(VARCHAR(36, charset='ascii'), nullable=True)
Hypervisor string `width:"16" charset:"ascii" nullable:"false" default:"kvm" list:"user" create:"required"` // Column(VARCHAR(16, charset='ascii'), nullable=False, default=HYPERVISOR_DEFAULT)
InstanceType string `width:"64" charset:"ascii" nullable:"true" list:"user" create:"optional"`
}
......