2018-05-09 00:49:54 +01:00
|
|
|
// Copyright (C) 2018 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package storj
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"io"
|
2018-07-16 20:22:34 +01:00
|
|
|
"log"
|
2018-05-09 00:49:54 +01:00
|
|
|
"time"
|
|
|
|
|
2018-07-12 18:29:02 +01:00
|
|
|
"github.com/gogo/protobuf/proto"
|
2018-05-09 00:49:54 +01:00
|
|
|
"github.com/minio/cli"
|
2018-06-01 13:51:13 +01:00
|
|
|
minio "github.com/minio/minio/cmd"
|
2018-05-09 00:49:54 +01:00
|
|
|
"github.com/minio/minio/pkg/auth"
|
|
|
|
"github.com/minio/minio/pkg/hash"
|
2018-07-12 18:29:02 +01:00
|
|
|
"github.com/zeebo/errs"
|
|
|
|
monkit "gopkg.in/spacemonkeygo/monkit.v2"
|
2018-06-01 13:51:13 +01:00
|
|
|
|
2018-07-12 18:29:02 +01:00
|
|
|
"storj.io/storj/pkg/objects"
|
|
|
|
"storj.io/storj/pkg/paths"
|
|
|
|
mpb "storj.io/storj/protos/objects"
|
2018-06-01 13:51:13 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2018-07-12 18:29:02 +01:00
|
|
|
mon = monkit.Package()
|
|
|
|
//Error is the errs class of standard End User Client errors
|
|
|
|
Error = errs.Class("Storj Gateway error")
|
2018-05-09 00:49:54 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
2018-07-16 20:22:34 +01:00
|
|
|
if err := minio.RegisterGatewayCommand(cli.Command{
|
2018-05-09 00:49:54 +01:00
|
|
|
Name: "storj",
|
|
|
|
Usage: "Storj",
|
|
|
|
Action: storjGatewayMain,
|
|
|
|
HideHelpCommand: true,
|
2018-07-16 20:22:34 +01:00
|
|
|
}); err != nil {
|
|
|
|
log.Fatal("Failed to register command storj")
|
|
|
|
}
|
2018-05-09 00:49:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func storjGatewayMain(ctx *cli.Context) {
|
2018-07-12 18:29:02 +01:00
|
|
|
s := &Storj{os: mockObjectStore()}
|
2018-06-01 13:51:13 +01:00
|
|
|
minio.StartGateway(ctx, s)
|
|
|
|
}
|
|
|
|
|
2018-07-12 18:29:02 +01:00
|
|
|
func mockObjectStore() objects.ObjectStore {
|
|
|
|
return &objects.Objects{}
|
2018-05-09 00:49:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Storj is the implementation of a minio cmd.Gateway
|
2018-06-01 13:51:13 +01:00
|
|
|
type Storj struct {
|
2018-07-12 18:29:02 +01:00
|
|
|
os objects.ObjectStore
|
2018-06-01 13:51:13 +01:00
|
|
|
}
|
2018-05-09 00:49:54 +01:00
|
|
|
|
|
|
|
// Name implements cmd.Gateway
|
|
|
|
func (s *Storj) Name() string {
|
|
|
|
return "storj"
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewGatewayLayer implements cmd.Gateway
|
|
|
|
func (s *Storj) NewGatewayLayer(creds auth.Credentials) (
|
2018-06-01 13:51:13 +01:00
|
|
|
minio.ObjectLayer, error) {
|
|
|
|
return &storjObjects{storj: s}, nil
|
2018-05-09 00:49:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Production implements cmd.Gateway
|
|
|
|
func (s *Storj) Production() bool {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
type storjObjects struct {
|
2018-06-01 13:51:13 +01:00
|
|
|
minio.GatewayUnsupported
|
2018-07-12 18:29:02 +01:00
|
|
|
storj *Storj
|
2018-05-09 00:49:54 +01:00
|
|
|
}
|
|
|
|
|
2018-07-12 18:29:02 +01:00
|
|
|
func (s *storjObjects) DeleteBucket(ctx context.Context, bucket string) (err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
2018-05-09 00:49:54 +01:00
|
|
|
panic("TODO")
|
|
|
|
}
|
|
|
|
|
2018-07-12 18:29:02 +01:00
|
|
|
func (s *storjObjects) DeleteObject(ctx context.Context, bucket, object string) (err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
objpath := paths.New(bucket, object)
|
|
|
|
return s.storj.os.DeleteObject(ctx, objpath)
|
2018-05-09 00:49:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *storjObjects) GetBucketInfo(ctx context.Context, bucket string) (
|
2018-06-01 13:51:13 +01:00
|
|
|
bucketInfo minio.BucketInfo, err error) {
|
2018-07-12 18:29:02 +01:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
2018-05-09 00:49:54 +01:00
|
|
|
panic("TODO")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *storjObjects) GetObject(ctx context.Context, bucket, object string,
|
|
|
|
startOffset int64, length int64, writer io.Writer, etag string) (err error) {
|
2018-07-12 18:29:02 +01:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
objpath := paths.New(bucket, object)
|
|
|
|
rr, _, err := s.storj.os.GetObject(ctx, objpath)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-07-16 20:22:34 +01:00
|
|
|
defer func() {
|
|
|
|
if err := rr.Close(); err != nil {
|
|
|
|
// ignore for now
|
|
|
|
}
|
|
|
|
}()
|
2018-07-12 18:29:02 +01:00
|
|
|
r, err := rr.Range(ctx, startOffset, length)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-07-16 20:22:34 +01:00
|
|
|
|
|
|
|
defer func() {
|
|
|
|
if err := r.Close(); err != nil {
|
|
|
|
// ignore for now
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2018-07-12 18:29:02 +01:00
|
|
|
_, err = io.Copy(writer, r)
|
|
|
|
return err
|
2018-05-09 00:49:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *storjObjects) GetObjectInfo(ctx context.Context, bucket,
|
2018-06-01 13:51:13 +01:00
|
|
|
object string) (objInfo minio.ObjectInfo, err error) {
|
2018-07-12 18:29:02 +01:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
objPath := paths.New(bucket, object)
|
|
|
|
rr, m, err := s.storj.os.GetObject(ctx, objPath)
|
|
|
|
if err != nil {
|
|
|
|
return objInfo, err
|
|
|
|
}
|
2018-07-16 20:22:34 +01:00
|
|
|
|
|
|
|
defer func() {
|
|
|
|
if err := rr.Close(); err != nil {
|
|
|
|
// ignore for now
|
|
|
|
}
|
|
|
|
}()
|
2018-07-12 18:29:02 +01:00
|
|
|
newmetainfo := &mpb.StorjMetaInfo{}
|
|
|
|
err = proto.Unmarshal(m.Data, newmetainfo)
|
|
|
|
if err != nil {
|
|
|
|
return objInfo, err
|
|
|
|
}
|
|
|
|
return minio.ObjectInfo{
|
|
|
|
Name: newmetainfo.GetName(),
|
|
|
|
Bucket: newmetainfo.GetBucket(),
|
|
|
|
ModTime: m.Modified,
|
|
|
|
Size: newmetainfo.GetSize(),
|
|
|
|
ETag: newmetainfo.GetETag(),
|
|
|
|
}, err
|
2018-05-09 00:49:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *storjObjects) ListBuckets(ctx context.Context) (
|
2018-06-01 13:51:13 +01:00
|
|
|
buckets []minio.BucketInfo, err error) {
|
2018-07-12 18:29:02 +01:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
buckets = nil
|
|
|
|
err = nil
|
|
|
|
return buckets, err
|
2018-05-09 00:49:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *storjObjects) ListObjects(ctx context.Context, bucket, prefix, marker,
|
2018-06-01 13:51:13 +01:00
|
|
|
delimiter string, maxKeys int) (result minio.ListObjectsInfo, err error) {
|
2018-07-12 18:29:02 +01:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
result = minio.ListObjectsInfo{}
|
|
|
|
err = nil
|
|
|
|
return result, err
|
2018-05-09 00:49:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *storjObjects) MakeBucketWithLocation(ctx context.Context,
|
2018-07-12 18:29:02 +01:00
|
|
|
bucket string, location string) (err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
2018-06-01 13:51:13 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-05-09 00:49:54 +01:00
|
|
|
func (s *storjObjects) PutObject(ctx context.Context, bucket, object string,
|
2018-06-01 13:51:13 +01:00
|
|
|
data *hash.Reader, metadata map[string]string) (objInfo minio.ObjectInfo,
|
2018-05-09 00:49:54 +01:00
|
|
|
err error) {
|
2018-07-12 18:29:02 +01:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
//metadata serialized
|
|
|
|
serMetaInfo := &mpb.StorjMetaInfo{
|
|
|
|
ContentType: metadata["content-type"],
|
|
|
|
Bucket: bucket,
|
|
|
|
Name: object,
|
|
|
|
}
|
|
|
|
metainfo, err := proto.Marshal(serMetaInfo)
|
2018-06-01 13:51:13 +01:00
|
|
|
if err != nil {
|
|
|
|
return objInfo, err
|
|
|
|
}
|
2018-07-12 18:29:02 +01:00
|
|
|
objPath := paths.New(bucket, object)
|
|
|
|
// setting zero value means the object never expires
|
|
|
|
expTime := time.Time{}
|
|
|
|
err = s.storj.os.PutObject(ctx, objPath, data, metainfo, expTime)
|
2018-06-01 13:51:13 +01:00
|
|
|
return minio.ObjectInfo{
|
2018-07-12 18:29:02 +01:00
|
|
|
Name: object,
|
|
|
|
Bucket: bucket,
|
|
|
|
// TODO create a followup ticket in JIRA to fix ModTime
|
2018-06-01 13:51:13 +01:00
|
|
|
ModTime: time.Now(),
|
2018-07-12 18:29:02 +01:00
|
|
|
Size: data.Size(),
|
2018-06-01 13:51:13 +01:00
|
|
|
ETag: minio.GenETag(),
|
|
|
|
}, err
|
2018-05-09 00:49:54 +01:00
|
|
|
}
|
|
|
|
|
2018-07-12 18:29:02 +01:00
|
|
|
func (s *storjObjects) Shutdown(ctx context.Context) (err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
2018-05-09 00:49:54 +01:00
|
|
|
panic("TODO")
|
|
|
|
}
|
|
|
|
|
2018-06-01 13:51:13 +01:00
|
|
|
func (s *storjObjects) StorageInfo(context.Context) minio.StorageInfo {
|
|
|
|
return minio.StorageInfo{}
|
2018-05-09 00:49:54 +01:00
|
|
|
}
|