Skip to content

Commit

Permalink
COSI initial pre-alpha driver (libopenstorage#1997)
Browse files Browse the repository at this point in the history
* COSI initial commit

Signed-off-by: Grant Griffiths <[email protected]>

* Add x509ignoreCN flag

With go 1.15+, our test certs are no longer valid.
Adding this flag for now

Signed-off-by: Grant Griffiths <[email protected]>
  • Loading branch information
ggriffiths authored Feb 24, 2022
1 parent ffee2ef commit 3621ce7
Show file tree
Hide file tree
Showing 332 changed files with 92,498 additions and 1,318 deletions.
2 changes: 1 addition & 1 deletion Dockerfile.osd-dev
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM quay.io/openstorage/osd-dev-base:1.14
FROM docker.io/openstorage/osd-dev-base:1.16
MAINTAINER [email protected]

EXPOSE 9005
Expand Down
3 changes: 1 addition & 2 deletions Dockerfile.osd-dev-base
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
FROM golang:1.14
FROM golang:1.16
MAINTAINER [email protected]

EXPOSE 9005
RUN \
apt-get update -yq && \
apt-get install -yq --no-install-recommends \
btrfs-tools \
ca-certificates && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,9 @@ test-sdk: install-sdk-test launch-sdk
timeout 30 sh -c 'until curl --silent -X GET -d {} http://localhost:9110/v1/clusters/inspectcurrent | grep STATUS_OK; do sleep 1; done'
sdk-test -ginkgo.noColor -ginkgo.noisySkippings=false -sdk.endpoint=localhost:9100 -sdk.cpg=$(GOPATH)/src/github.com/libopenstorage/sdk-test/cmd/sdk-test/cb.yaml

# TODO: Remove GODEBUG and fix test certs
test: packr
go test -tags "$(TAGS)" $(TESTFLAGS) $(PKGS)
GODEBUG=x509ignoreCN=0 go test -tags "$(TAGS)" $(TESTFLAGS) $(PKGS)

docs:
go generate ./cmd/osd/main.go
Expand Down
16 changes: 16 additions & 0 deletions bucket/bucket.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package bucket

// BucketDriver represents an method for interacting with various object storage backends
type BucketDriver interface {
// String returns a name for the driver implementation
String() string

// Start starts the bucket driver for usage
Start() error

// CreateBucket provisions a new bucket
CreateBucket(name string) (string, error)

// DeleteBucket deprovisions a bucket
DeleteBucket(id string) error
}
56 changes: 56 additions & 0 deletions bucket/drivers/fake/fake.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package fake

import (
"net/http"

"github.com/johannesboyne/gofakes3"
"github.com/johannesboyne/gofakes3/backend/s3mem"
"github.com/libopenstorage/openstorage/bucket"
"github.com/sirupsen/logrus"
)

var _ bucket.BucketDriver = &Fake{}

type Fake struct {
backend *s3mem.Backend
httpServer *http.Server
}

func New() *Fake {
backend := s3mem.New()
return &Fake{
backend: backend,
httpServer: &http.Server{
Addr: ":8085",
Handler: gofakes3.New(backend).Server(),
},
}
}

// String name representation of driver
func (f *Fake) String() string {
return "fake"
}

// Start starts a new fake object storage server
func (f *Fake) Start() error {
logrus.Infof("Starting fake object storage driver on %s", f.httpServer.Addr)
return f.httpServer.ListenAndServe()
}

// Stop closes the http server for the fake driver
func (f *Fake) Stop() error {
return f.httpServer.Close()
}

// CreateBucket provisions a new in-memory bucket
func (f *Fake) CreateBucket(name string) (string, error) {
logrus.Info("bucket_driver.Fake create bucket received")
return name, f.backend.CreateBucket(name)
}

// DeleteBucket deprovisions an in-memory bucket
func (f *Fake) DeleteBucket(name string) error {
logrus.Info("bucket_driver.Fake delete bucket received")
return f.backend.DeleteBucket(name)
}
34 changes: 34 additions & 0 deletions cmd/osd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ package main
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"path/filepath"
Expand All @@ -38,10 +39,12 @@ import (
"github.com/libopenstorage/openstorage/api"
"github.com/libopenstorage/openstorage/api/server"
"github.com/libopenstorage/openstorage/api/server/sdk"
"github.com/libopenstorage/openstorage/bucket/drivers/fake"
osdcli "github.com/libopenstorage/openstorage/cli"
"github.com/libopenstorage/openstorage/cluster"
clustermanager "github.com/libopenstorage/openstorage/cluster/manager"
"github.com/libopenstorage/openstorage/config"
"github.com/libopenstorage/openstorage/cosi"
"github.com/libopenstorage/openstorage/csi"
graphdrivers "github.com/libopenstorage/openstorage/graph/drivers"
"github.com/libopenstorage/openstorage/objectstore"
Expand Down Expand Up @@ -496,6 +499,37 @@ func start(c *cli.Context) error {
return fmt.Errorf("Failed to start CSI server for driver %s: %v", d, err)
}

// Start fake bucket driver
fakeDriver := fake.New()
go func() {
if err := fakeDriver.Start(); err != http.ErrServerClosed {
logrus.Errorf("failed to start fake driver: %v", err)
}
}()

// Start COSI server
cosisock := os.Getenv("COSI_ENDPOINT")
if len(cosisock) == 0 {
cosisock = fmt.Sprintf("/var/lib/osd/driver/%s-cosi.sock", d)
}
os.Remove(cosisock)
if err := os.MkdirAll(filepath.Dir(cosisock), 0750); err != nil {
logrus.Errorf("failed to create COSI sock")
}
cosiServer, err := cosi.NewServer(&cosi.Config{
Driver: fakeDriver,
Net: "unix",
Address: cosisock,
})
if err != nil {
return fmt.Errorf("failed to create COSI server for driver %s: %v", fakeDriver, err)
}

err = cosiServer.Start()
if err != nil {
return fmt.Errorf("failed to start COSI server for driver %s: %v", fakeDriver, err)
}

// Create a role manager
rm, err := role.NewSdkRoleManager(kv)
if err != nil {
Expand Down
52 changes: 52 additions & 0 deletions cosi/cosi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package cosi

import (
"fmt"

"github.com/libopenstorage/openstorage/bucket"
"github.com/libopenstorage/openstorage/pkg/grpcserver"
"google.golang.org/grpc"
cosi "sigs.k8s.io/container-object-storage-interface-spec"
)

// Server represents a COSI server
type Server struct {
cosi.IdentityServer
cosi.ProvisionerServer
*grpcserver.GrpcServer

driver bucket.BucketDriver
}

// Config for setting up a COSI server
type Config struct {
Driver bucket.BucketDriver
Net string
Address string
}

// NewServer creates a new COSI gRPC server
func NewServer(cfg *Config) (grpcserver.Server, error) {
// Create server
gServer, err := grpcserver.New(&grpcserver.GrpcServerConfig{
Name: "COSI Alpha Server",
Net: cfg.Net,
Address: cfg.Address,
})
if err != nil {
return nil, fmt.Errorf("failed to create CSI server: %v", err)
}

return &Server{
GrpcServer: gServer,
driver: cfg.Driver,
}, nil
}

// Start registers COSI services and starts the gRPC server
func (s *Server) Start() error {
return s.GrpcServer.Start(func(grpcServer *grpc.Server) {
cosi.RegisterIdentityServer(grpcServer, s)
cosi.RegisterProvisionerServer(grpcServer, s)
})
}
70 changes: 70 additions & 0 deletions cosi/cosi_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package cosi

import (
"net/http"
"os"
"path/filepath"
"testing"

"github.com/libopenstorage/openstorage/bucket/drivers/fake"
"github.com/libopenstorage/openstorage/pkg/grpcserver"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"google.golang.org/grpc"
)

type testServer struct {
conn *grpc.ClientConn
server grpcserver.Server
driver *fake.Fake
}

func newCOSITestServer(t *testing.T) *testServer {
// Start fake driver
fakeDriver := fake.New()
go func() {
if err := fakeDriver.Start(); err != http.ErrServerClosed {
logrus.Errorf("failed to start fake driver: %v", err)
}
}()

// Start COSI server
tempDir := os.TempDir()
cosisock := tempDir + "/cosi.sock"
os.Remove(cosisock)
if err := os.MkdirAll(filepath.Dir(cosisock), 0750); err != nil {
logrus.Errorf("failed to create COSI sock")
}
s, err := NewServer(&Config{
Driver: fakeDriver,
Net: "tcp",
Address: "127.0.0.1:0",
})
assert.NoError(t, err)

err = s.Start()
assert.NoError(t, err)

// Setup a connection to the driver
conn, err := grpc.Dial(s.Address(), grpc.WithInsecure())
assert.NoError(t, err)

// Return test server
return &testServer{
conn: conn,
server: s,
driver: fakeDriver,
}
}

// Stop stops a given test server
func (ts *testServer) Stop() {
if err := ts.conn.Close(); err != nil {
logrus.Errorf("failed to close test server conn: %v", err)
}
ts.server.Stop()

if err := ts.driver.Stop(); err != nil {
logrus.Errorf("failed to stop driver: %v", err)
}
}
21 changes: 21 additions & 0 deletions cosi/identify_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package cosi

import (
"context"
"testing"

"github.com/stretchr/testify/assert"
cosi "sigs.k8s.io/container-object-storage-interface-spec"
)

func TestProvisionerGetInfo(t *testing.T) {
// Create test server
testServer := newCOSITestServer(t)
defer testServer.Stop()

// Test provisioner get info
cosiClient := cosi.NewIdentityClient(testServer.conn)
resp, err := cosiClient.ProvisionerGetInfo(context.TODO(), &cosi.ProvisionerGetInfoRequest{})
assert.NoError(t, err)
assert.Equal(t, "osd.openstorage.org", resp.GetName())
}
14 changes: 14 additions & 0 deletions cosi/identity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package cosi

import (
"context"

cosi "sigs.k8s.io/container-object-storage-interface-spec"
)

// ProvisionerGetInfo returns any required provisioner info
func (s *Server) ProvisionerGetInfo(ctx context.Context, req *cosi.ProvisionerGetInfoRequest) (*cosi.ProvisionerGetInfoResponse, error) {
return &cosi.ProvisionerGetInfoResponse{
Name: "osd.openstorage.org",
}, nil
}
51 changes: 51 additions & 0 deletions cosi/provisioner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package cosi

import (
"context"
"fmt"

"github.com/sirupsen/logrus"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
cosi "sigs.k8s.io/container-object-storage-interface-spec"
)

// ProvisionerCreateBucket is made to create the bucket in the backend.
// This call is idempotent
// 1. If a bucket that matches both name and parameters already exists, then OK (success) must be returned.
// 2. If a bucket by same name, but different parameters is provided, then the appropriate error code ALREADY_EXISTS must be returned.
func (s *Server) ProvisionerCreateBucket(ctx context.Context, req *cosi.ProvisionerCreateBucketRequest) (*cosi.ProvisionerCreateBucketResponse, error) {
logrus.Info("cosi.ProvisionerCreateBucket received")
id, err := s.driver.CreateBucket(req.GetName())
if err != nil {
return &cosi.ProvisionerCreateBucketResponse{}, status.Error(codes.Internal, fmt.Sprintf("failed to create bucket: %s", err))
}

return &cosi.ProvisionerCreateBucketResponse{
BucketId: id,
}, nil
}

// ProvisionerDeleteBucket is made to delete the bucket in the backend.
// If the bucket has already been deleted, then no error should be returned.
func (s *Server) ProvisionerDeleteBucket(ctx context.Context, req *cosi.ProvisionerDeleteBucketRequest) (*cosi.ProvisionerDeleteBucketResponse, error) {
logrus.Info("cosi.ProvisionerDeleteBucket received")
if err := s.driver.DeleteBucket(req.GetBucketId()); err != nil {
return &cosi.ProvisionerDeleteBucketResponse{}, status.Error(codes.Internal, fmt.Sprintf("failed to delete bucket: %s", err))
}

return &cosi.ProvisionerDeleteBucketResponse{}, nil
}

// ProvisionerGrantBucketAccess grants access to an account. The account_name in the request shall be used as a unique identifier to create credentials.
// The account_id returned in the response will be used as the unique identifier for deleting this access when calling ProvisionerRevokeBucketAccess.
func (s *Server) ProvisionerGrantBucketAccess(context.Context, *cosi.ProvisionerGrantBucketAccessRequest) (*cosi.ProvisionerGrantBucketAccessResponse, error) {
logrus.Info("cosi.ProvisionerGrantBucketAccessResponse received")
return &cosi.ProvisionerGrantBucketAccessResponse{}, nil
}

// ProvisionerRevokeBucketAccess revokes all access to a particular bucket from a principal.
func (s *Server) ProvisionerRevokeBucketAccess(context.Context, *cosi.ProvisionerRevokeBucketAccessRequest) (*cosi.ProvisionerRevokeBucketAccessResponse, error) {
logrus.Info("cosi.ProvisionerRevokeBucketAccessResponse received")
return &cosi.ProvisionerRevokeBucketAccessResponse{}, nil
}
Loading

0 comments on commit 3621ce7

Please sign in to comment.