[ARVADOS] created: 8626abb0a44cfc303bef3552a7bc57163c79231a
git at public.curoverse.com
git at public.curoverse.com
Tue Sep 22 19:55:02 EDT 2015
at 8626abb0a44cfc303bef3552a7bc57163c79231a (commit)
commit 8626abb0a44cfc303bef3552a7bc57163c79231a
Author: Tom Clegg <tom at curoverse.com>
Date: Tue Sep 22 19:54:12 2015 -0400
7241: Add AzureBlobVolume
diff --git a/services/keepstore/azure_blob_volume.go b/services/keepstore/azure_blob_volume.go
new file mode 100644
index 0000000..b1d528d
--- /dev/null
+++ b/services/keepstore/azure_blob_volume.go
@@ -0,0 +1,83 @@
+package main
+
+import (
+ "fmt"
+ "io"
+ "time"
+
+ "github.com/Azure/azure-sdk-for-go/storage"
+)
+
+// An AzureBlobVolume stores and retrieves blocks in an Azure Blob
+// container.
+type AzureBlobVolume struct {
+ azClient storage.Client
+ bsClient storage.BlobStorageClient
+ containerName string
+ readonly bool
+}
+
+func NewAzureBlobVolume(client storage.Client, containerName string, readonly bool) *AzureBlobVolume {
+ return &AzureBlobVolume{
+ azClient: client,
+ bsClient: client.GetBlobService(),
+ containerName: containerName,
+ readonly: readonly,
+ }
+}
+
+func (v *AzureBlobVolume) Get(loc string) ([]byte, error) {
+ rdr, err := v.bsClient.GetBlob(v.containerName, loc)
+ if err != nil {
+ return nil, err
+ }
+ buf := bufs.Get(BlockSize)
+ n, err := io.ReadFull(rdr, buf)
+ switch err {
+ case io.EOF, io.ErrUnexpectedEOF:
+ return buf[:n], nil
+ default:
+ bufs.Put(buf)
+ return nil, err
+ }
+}
+
+func (v *AzureBlobVolume) Compare(loc string, data []byte) error {
+ return NotFoundError
+}
+
+func (v *AzureBlobVolume) Put(loc string, block []byte) error {
+ return NotFoundError
+}
+
+func (v *AzureBlobVolume) Touch(loc string) error {
+ return NotFoundError
+}
+
+func (v *AzureBlobVolume) Mtime(loc string) (time.Time, error) {
+ return time.Time{}, NotFoundError
+}
+
+func (v *AzureBlobVolume) IndexTo(prefix string, writer io.Writer) error {
+ return nil
+}
+
+func (v *AzureBlobVolume) Delete(loc string) error {
+ return NotFoundError
+}
+
+func (v *AzureBlobVolume) Status() *VolumeStatus {
+ return &VolumeStatus{
+ DeviceNum: 1,
+ BytesFree: BlockSize * 1000,
+ BytesUsed: 1,
+ }
+}
+
+func (v *AzureBlobVolume) String() string {
+ return fmt.Sprintf("%+v", v.azClient)
+}
+
+func (v *AzureBlobVolume) Writable() bool {
+ return !v.readonly
+}
diff --git a/services/keepstore/azure_blob_volume_test.go b/services/keepstore/azure_blob_volume_test.go
new file mode 100644
index 0000000..59021c0
--- /dev/null
+++ b/services/keepstore/azure_blob_volume_test.go
@@ -0,0 +1,100 @@
+package main
+
+import (
+ "log"
+ "net"
+ "net/http"
+ "net/http/httptest"
+ "regexp"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/Azure/azure-sdk-for-go/storage"
+)
+
+const (
+ // The same fake credentials used by Microsoft's Azure emulator
+ emulatorAccountName = "devstoreaccount1"
+ emulatorAccountKey = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="
+)
+
+type azStubHandler struct {}
+
+func (azStubHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
+}
+
+// azStubDialer is a net.Dialer that notices when the Azure driver
+// tries to connect to "devstoreaccount1.blob.127.0.0.1:46067", and
+// in such cases transparently dials "127.0.0.1:46067" instead.
+type azStubDialer struct {
+ net.Dialer
+}
+
+var localHostPortRe = regexp.MustCompile(`(127\.0\.0\.1|localhost|\[::1\]):\d+`)
+func (d *azStubDialer) Dial(network, address string) (net.Conn, error) {
+ if hp := localHostPortRe.FindString(address); hp != "" {
+ log.Println("custom dialer: dial", hp, "instead of", address)
+ address = hp
+ }
+ return d.Dialer.Dial(network, address)
+}
+
+type TestableAzureBlobVolume struct {
+ *AzureBlobVolume
+ azStub *httptest.Server
+ t *testing.T
+}
+
+func NewTestableAzureBlobVolume(t *testing.T, readonly bool) *TestableAzureBlobVolume {
+ azStub := httptest.NewServer(azStubHandler{})
+
+ stubURLBase := strings.Split(azStub.URL, "://")[1]
+ azClient, err := storage.NewClient(emulatorAccountName, emulatorAccountKey, stubURLBase, storage.DefaultAPIVersion, false)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ v := NewAzureBlobVolume(azClient, "fakecontainername", readonly)
+
+ return &TestableAzureBlobVolume{
+ AzureBlobVolume: v,
+ azStub: azStub,
+ t: t,
+ }
+}
+
+func TestAzureBlobVolumeWithGeneric(t *testing.T) {
+ defer func(t http.RoundTripper) {
+ http.DefaultTransport = t
+ }(http.DefaultTransport)
+ http.DefaultTransport = &http.Transport{
+ Dial: (&azStubDialer{}).Dial,
+ }
+ DoGenericVolumeTests(t, func(t *testing.T) TestableVolume {
+ return NewTestableAzureBlobVolume(t, false)
+ })
+}
+
+func TestReadonlyAzureBlobVolumeWithGeneric(t *testing.T) {
+ defer func(t http.RoundTripper) {
+ http.DefaultTransport = t
+ }(http.DefaultTransport)
+ http.DefaultTransport = &http.Transport{
+ Dial: (&azStubDialer{}).Dial,
+ }
+ DoGenericVolumeTests(t, func(t *testing.T) TestableVolume {
+ return NewTestableAzureBlobVolume(t, true)
+ })
+}
+
+func (v *TestableAzureBlobVolume) PutRaw(locator string, data []byte) {
+ v.Put(locator, data)
+}
+
+func (v *TestableAzureBlobVolume) TouchWithDate(locator string, lastPut time.Time) {
+}
+
+func (v *TestableAzureBlobVolume) Teardown() {
+ v.azStub.Close()
+}
diff --git a/services/keepstore/volume_generic_test.go b/services/keepstore/volume_generic_test.go
index 193d9d2..b64f345 100644
--- a/services/keepstore/volume_generic_test.go
+++ b/services/keepstore/volume_generic_test.go
@@ -61,7 +61,7 @@ func testGet(t *testing.T, factory TestableVolumeFactory) {
buf, err := v.Get(TestHash)
if err != nil {
- t.Error(err)
+ t.Fatal(err)
}
bufs.Put(buf)
@@ -397,7 +397,7 @@ func testDeleteOldBlock(t *testing.T, factory TestableVolumeFactory) {
t.Error(err)
}
if _, err := v.Get(TestHash); err == nil || !os.IsNotExist(err) {
- t.Errorf("os.IsNotExist(%v) should have been true", err.Error())
+ t.Errorf("os.IsNotExist(%v) should have been true", err)
}
}
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list