rexray是EMC推出的一个为docker容器分配persistent volume的一款开源插件,最近在做这方面的二次开发项目,所以对这个插件总结一下:
在rexray的rexray/drivers/文件夹下,有三个目录,分别代表rexray目前所支持的几种driver:比如
os中:
const providerName = "linux" type driver struct{ r *core.RexRay }
storage中有以下几种产品的driver:
亚马逊的EWS:
const providerName = "ec2" type driver struct{ instanceDocument *instanceIdentityDocument ec2Instance *ec2.EC2 r *core.RexRay }
谷歌的GCE:
const providerName = "gce" type driver struct { currentInstanceID string client *compute.Service r *core.RexRay zone string project string }
EMC的isilon:
const providerName = "Isilon" type driver struct { client *isi.Client r *core.RexRay }
openstack:
const providerName = "Openstack" type driver struct { provider *gophercloud.ProviderClient client *gophercloud.ServiceClient clientBlockStorage *gophercloud.ServiceClient clientBlockStoragev2 *gophercloud.ServiceClient region string availabilityZone string instanceID string r *core.RexRay }
rackspace:
const providerName = "Rackspace" type driver struct { provider *gophercloud.ProviderClient client *gophercloud.ServiceClient clientBlockStorage *gophercloud.ServiceClient region string instanceID string r *core.RexRay
EMC的scaleio:
const providerName = "ScaleIO" type driver struct { client *goscaleio.Client system *goscaleio.System protectionDomain *goscaleio.ProtectionDomain storagePool *goscaleio.StoragePool sdc *goscaleio.Sdc r *core.RexRay }
virtualbox:
const providerName = "virtualbox" type driver struct { virtualbox *vbox.VirtualBox machine *vbox.Machine r *core.RexRay m sync.Mutex }
EMC的vmax:
const providerName = "VMAX" type driver struct { client *govmax.SMIS arrayID string volPrefix string instanceID string vmh *govmax.VMHost r *core.RexRay }
EMC的xtremio:
const providerName = "XtremIO" type driver struct { client *xtio.Client initiator xtio.Initiator volumesSig string lunMapsSig string initiatorsSig string volumesByNaa map[string]xtio.Volume initiatorsByName map[string]xtio.Initiator r *core.RexRay }
Volume中:
const providerName = "docker" type driver struct { r *core.RexRay }
以上,所有类型的driver都实现了下面这个接口:
type Driver interface { Name() string Init(rexray *RexRay) error }
在引入所有driver所在的包时,都会在init函数中执行下面这个步骤:
core.RegisterDriver(providerName, newDriver)
在package core中,RegisterDriver函数如下所示:
func RegisterDriver(driverName string, ctor NewDriver) { driverCtors[driverName] = ctor }
其中,driverCtors的类型为:
driverCtors map[string]NewDriver
这样,以上所有driver实例都会被存放在driverCtors中。
下面首先看一下os。
对于os,定义了两个接口,如下所示:
type OSDriver interface { Driver GetMounts(string, string) (MountInfoArray, error) Mounted(string) (bool, error) Unmount(string) error Mount(string, string, string, string) error Format(string, string, bool) error }
type OSDriverManager interface { OSDriver Drivers() <-chan OSDriver }
os的driver实例(Linux)实现了上面的OSDriver这个接口。
下面是针对os driver的manager。
type odm struct { rexray *RexRay drivers map[string]OSDriver }
其中,odm实现了OSDriverManager、OSDriver、Driver这几个接口。
对于,storage:
type StorageDriver interface { Driver GetVolumeMapping() ([]*BlockDevice, error) GetInstance() (*Instance, error) GetVolume(volumeID, volumeName string) ([]*Volume, error) GetVolumeAttach(volumeID, instanceID string) ([]*VolumeAttachment, error) CreateSnapshot(。。。 GetSnapshot(volumeID, snapshotID, snapshotName string) ([]*Snapshot, error) RemoveSnapshot(snapshotID string) error CreateVolume( RemoveVolume(volumeID string) error GetDeviceNextAvailable() (string, error) AttachVolume(。。。 DetachVolume(runAsync bool, volumeID string, instanceID string, force bool) error CopySnapshot(。。。
虽然没有仔细看每一个srotage driver的代码,但是我相信每一个storage driver的实例都应该实现了StorageDriver接口。
type StorageDriverManager interface { StorageDriver Drivers() <-chan StorageDriver GetInstances() ([]*Instance, error) }
下面是针对storage driver的manager
type sdm struct { rexray *RexRay drivers map[string]StorageDriver }
其中,sdm实现了Driver、StorageDriver、StorageDriverManager这几个接口。
对于volume:
type VolumeDriver interface { Driver Mount(。。。 Unmount(volumeName, volumeID string) error Path(volumeName, volumeID string) (string, error) Create(volumeName string, opts VolumeOpts) error Remove(volumeName string) error Get(volumeName string) (VolumeMap, error) List() ([]VolumeMap, error) Attach(volumeName, instanceID string, force bool) (string, error) Detach(volumeName, instanceID string, force bool) error NetworkName(volumeName, instanceID string) (string, error) }
volume实例(provider=docker)实现了VolumeDriver这个接口。
type VolumeDriverManager interface { VolumeDriver Drivers() <-chan VolumeDriver UnmountAll() error RemoveAll() error DetachAll(instanceID string) error }
type vdm struct { rexray *RexRay drivers map[string]VolumeDriver m sync.Mutex mapUsedCount map[string]*int }
vdm实现了上面的Driver、VolumeDriver、VolumeDriverManager这三个接口。
Rexray是统一的存储管理平台,其具体结构如下所示:
type RexRay struct { Config gofig.Config OS OSDriverManager Volume VolumeDriverManager Storage StorageDriverManager Context string drivers map[string]Driver }
下面的步骤将会把所有的driver实例添加到RexRay实例的drivers属性中:
for name, ctor := range driverCtors { r.drivers[name] = ctor() log.WithField("driverName", name).Debug("constructed driver") }
下面的步骤则是将RexRay实例中的每一个driver实例进行初始化:
od := map[string]OSDriver{} vd := map[string]VolumeDriver{} sd := map[string]StorageDriver{} for n, d := range r.drivers { switch td := d.(type) { case OSDriver: if gotil.StringInSlice(n, osDrivers) { if err := d.Init(r); err != nil { log.WithFields(log.Fields{ "driverName": n, "error": err}).Debug("error initializing driver") } od[n] = td } case VolumeDriver: if gotil.StringInSlice(n, volDrivers) { if err := d.Init(r); err != nil { 。。。 vd[n] = td } case StorageDriver: if gotil.StringInSlice(n, storDrivers) { if err := d.Init(r); err != nil { 。。。 sd[n] = td } r.OS = &odm{ rexray: r, drivers: od, } r.Volume = &vdm{ rexray: r, drivers: vd, } r.Storage = &sdm{ rexray: r, drivers: sd, }
完成以上的初始化步骤后,假设rexray开始工作则对应的流程以getVolume为例:
1、allVolumes, err := c.r.Storage.GetVolume(c.volumeID, c.volumeName)
2、c.r.Storage为sdm的实例,即执行func (r *sdm) GetVolume(volumeID, volumeName string) ([]*Volume, error)
3、for _, d := range r.drivers {
return d.GetVolume(volumeID, volumeName)
即执行具体的storage的GetVolume方法
4、以ECS为例,即
resp, err := d.ec2Instance.Volumes(volumeList, filter)