Skip to content

Commit

Permalink
Merge pull request #567 from opensds/development
Browse files Browse the repository at this point in the history
Merge from Development to Master branch to prepare for Bali RC2 release
  • Loading branch information
xing-yang committed Dec 7, 2018
2 parents a7e9da1 + 0b5e8bf commit f52f384
Show file tree
Hide file tree
Showing 30 changed files with 244 additions and 4,734 deletions.
3 changes: 1 addition & 2 deletions .travis.yml
@@ -1,6 +1,5 @@
dist: trusty
dist: xenial
sudo: required
group: deprecated-2017Q4

language: go
go_import_path: github.com/opensds/opensds
Expand Down
96 changes: 78 additions & 18 deletions contrib/backup/multicloud/client.go
Expand Up @@ -17,6 +17,7 @@ package multicloud
import (
"encoding/xml"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"path"
Expand All @@ -25,7 +26,9 @@ import (

"github.com/astaxie/beego/httplib"
log "github.com/golang/glog"
"io/ioutil"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack"
"github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
)

const (
Expand All @@ -35,49 +38,106 @@ const (
ApiVersion = "v1"
)

type AuthOptions struct {
Endpoint string
UserName string
Password string
TenantId string
}

type Client struct {
endpoint string
userName string
password string
tenantId string
version string
baseURL string
auth *AuthOptions
token *tokens.Token
timeout time.Duration
uploadTimeout time.Duration
}

func NewClient(opt *AuthOptions, uploadTimeout int64) (*Client, error) {
u, err := url.Parse(opt.Endpoint)
func NewClient(endpooint string, opt *AuthOptions, uploadTimeout int64) (*Client, error) {
u, err := url.Parse(endpooint)
if err != nil {
return nil, err
}
u.Path = path.Join(u.Path, ApiVersion)
baseURL := u.String() + "/"

return &Client{
endpoint: opt.Endpoint,
userName: opt.UserName,
password: opt.Password,
tenantId: opt.TenantId,
client := &Client{
endpoint: endpooint,
tenantId: DefaultTenantId,
version: ApiVersion,
baseURL: baseURL,
timeout: time.Duration(DefaultTimeout) * time.Minute,
uploadTimeout: time.Duration(uploadTimeout) * time.Minute,
}, nil
auth: opt,
}

if opt.Strategy == "keystone" {
if err := client.UpdateToken(); err != nil {
return nil, err
}
}
return client, nil
}

type ReqSettingCB func(req *httplib.BeegoHTTPRequest) error

func (c *Client) getToken(opt *AuthOptions) (*tokens.CreateResult, error) {
auth := gophercloud.AuthOptions{
IdentityEndpoint: opt.AuthUrl,
DomainName: opt.DomainName,
Username: opt.UserName,
Password: opt.Password,
TenantName: opt.TenantName,
}

provider, err := openstack.AuthenticatedClient(auth)
if err != nil {
log.Error("When get auth client:", err)
return nil, err
}

// Only support keystone v3
identity, err := openstack.NewIdentityV3(provider, gophercloud.EndpointOpts{})
if err != nil {
log.Error("When get identity session:", err)
return nil, err
}
r := tokens.Create(identity, &auth)
return &r, nil
}

func (c *Client) UpdateToken() error {
t, err := c.getToken(c.auth)
if err != nil {
log.Errorf("Get token failed, %v", err)
return err
}
project, err := t.ExtractProject()
if err != nil {
log.Errorf("extract project failed, %v", err)
return err
}
c.tenantId = project.ID
token, err := t.ExtractToken()
if err != nil {
log.Errorf("extract token failed, %v", err)
return err
}
c.token = token
log.V(5).Infof("TokenId:%s, ExpiresAt:%v", token.ID, token.ExpiresAt)
return nil
}

func (c *Client) doRequest(method, u string, in interface{}, cb ReqSettingCB) ([]byte, http.Header, error) {
req := httplib.NewBeegoRequest(u, method)
req.Header("Content-Type", "application/xml")
if c.auth.Strategy == "keystone" {
beforeExpires := c.token.ExpiresAt.Add(time.Minute)
if time.Now().After(beforeExpires) {
log.Warning("token is about to expire, update it")
if err := c.UpdateToken(); err != nil {
return nil, nil, err
}
}
req.Header("X-Auth-Token", c.token.ID)
}

req.SetTimeout(c.timeout, c.timeout)
if cb != nil {
if err := cb(req); err != nil {
Expand Down
34 changes: 25 additions & 9 deletions contrib/backup/multicloud/driver.go
Expand Up @@ -22,6 +22,7 @@ import (

"github.com/golang/glog"
"github.com/opensds/opensds/contrib/backup"
"github.com/opensds/opensds/pkg/utils"
"gopkg.in/yaml.v2"
)

Expand All @@ -38,11 +39,21 @@ func NewMultiCloud() (backup.BackupDriver, error) {
return &MultiCloud{}, nil
}

type AuthOptions struct {
Strategy string `yaml:"Strategy"`
AuthUrl string `yaml:"AuthUrl,omitempty"`
DomainName string `yaml:"DomainName,omitempty"`
UserName string `yaml:"UserName,omitempty"`
Password string `yaml:"Password,omitempty"`
TenantName string `yaml:"TenantName,omitempty"`
}

type MultiCloudConf struct {
Endpoint string `yaml:"Endpoint,omitempty"`
TenantId string `yaml:"TenantId,omitempty"`
UploadTimeout int64 `yaml:"UploadTimeout,omitempty"`
AuthOptions `yaml:"AuthOptions,omitempty"`
}

type MultiCloud struct {
client *Client
conf *MultiCloudConf
Expand All @@ -51,7 +62,6 @@ type MultiCloud struct {
func (m *MultiCloud) loadConf(p string) (*MultiCloudConf, error) {
conf := &MultiCloudConf{
Endpoint: "http://127.0.0.1:8088",
TenantId: DefaultTenantId,
UploadTimeout: DefaultUploadTimeout,
}
confYaml, err := ioutil.ReadFile(p)
Expand All @@ -73,11 +83,7 @@ func (m *MultiCloud) SetUp() error {
return err
}

opt := &AuthOptions{
Endpoint: m.conf.Endpoint,
TenantId: m.conf.TenantId,
}
if m.client, err = NewClient(opt, m.conf.UploadTimeout); err != nil {
if m.client, err = NewClient(m.conf.Endpoint, &m.conf.AuthOptions, m.conf.UploadTimeout); err != nil {
return err
}

Expand Down Expand Up @@ -118,7 +124,12 @@ func (m *MultiCloud) Backup(backup *backup.BackupSpec, volFile *os.File) error {
if size == 0 {
break
}
uploadResp, err := m.client.UploadPart(bucket, key, partNum, initResp.UploadId, buf[:size], int64(size))
var uploadResp *UploadPartResult
err = utils.Retry(3, "upload part", false, func(retryIdx int, lastErr error) error {
var inErr error
uploadResp, inErr = m.client.UploadPart(bucket, key, partNum, initResp.UploadId, buf[:size], int64(size))
return inErr
})
if err != nil {
glog.Errorf("upload part failed, err:%v", err)
return err
Expand All @@ -145,7 +156,12 @@ func (m *MultiCloud) Restore(backup *backup.BackupSpec, backupId string, volFile
// if the size of data of smaller than require download size
// downloading is completed.
for offset := int64(0); downloadSize == ChunkSize; offset += ChunkSize {
data, err := m.client.DownloadPart(bucket, backupId, offset, ChunkSize)
var data []byte
err := utils.Retry(3, "download part", false, func(retryIdx int, lastErr error) error {
var inErr error
data, inErr = m.client.DownloadPart(bucket, backupId, offset, ChunkSize)
return inErr
})
if err != nil {
glog.Errorf("download part failed: %v", err)
return err
Expand Down
11 changes: 9 additions & 2 deletions contrib/backup/multicloud/driver_test.go
Expand Up @@ -32,10 +32,17 @@ func TestLoadConf(t *testing.T) {
}
expect := &MultiCloudConf{
Endpoint: "http://127.0.0.1:8088",
TenantId: "FakeTenantId",
UploadTimeout: DefaultUploadTimeout,
AuthOptions: AuthOptions{
Strategy: "keystone",
AuthUrl: "http://127.0.0.1/identity",
DomainName: "Default",
UserName: "admin",
Password: "opensds@123",
TenantName: "admin",
},
}
fmt.Println(conf)
fmt.Printf("%+v", conf)
if !reflect.DeepEqual(expect, conf) {
t.Errorf("load conf file error")
}
Expand Down
10 changes: 8 additions & 2 deletions contrib/backup/multicloud/testdata/multi-cloud.yaml
@@ -1,4 +1,10 @@
"Endpoint": "http://127.0.0.1:8088"
"TenantId": "FakeTenantId"
# upload object timeout in seconds
"UploadTimeout": 30
"UploadTimeout": 30
AuthOptions:
Strategy: "keystone"
AuthUrl: "http://127.0.0.1/identity"
DomainName: "Default"
UserName: "admin"
Password: "opensds@123"
TenantName: "admin"
2 changes: 0 additions & 2 deletions contrib/cindercompatibleapi/README.md

This file was deleted.

63 changes: 0 additions & 63 deletions contrib/cindercompatibleapi/api/apiversion.go

This file was deleted.

0 comments on commit f52f384

Please sign in to comment.