EMC开源产品rexray

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)

你可能感兴趣的:(EMC开源产品rexray)