Skip to content

Commit

Permalink
Azure driver renaming and enhancements
Browse files Browse the repository at this point in the history
This patchset renames the driver to `azureud`, to signify Azure
Unmanaged Disk driver. This set of enhancements builds off of previous
work, and completes the driver for inclusion into libStorage.

Use metadata server to detect azure instance

Don't return '.vhd' as part of volume name

Don't return OS disks

Proper attachment logic, remove instance filtering

improve login/init logic

Combine toTypeVolume and toTypesVolume

No need for separate functions here. This is in preparation for a call
to get VM details when getting attached device info. When we receive a
list of several volumes, and attachments.Devices() is true, we don't
want to have to query the VM status for every volume. By combining these
functions we can ensure that we only make one additional API call,
instead of making 1 call for every volume.

make executor localDevices return LUN number

The only way we have to match up an attached disk on a VM is via its LUN
number. When we query a disk, we get the name of the VM its attached to,
and that's it. When we query the VM, we get a list of data disks
attached to it, but not it's device path, only its LUN. Therefore, in
order to match up a volume with a device, we have to match on the LUN.

The easiest way to get the LUN is with the `lsscsi` utility. This
introduces a new, external dependency. It's technically possible to
parse through /sys/bus/scsi/devices/*/block/sd* to get this without an
external utility, but that is more effor than I am willing to put in at
this point.

This is the last hurdle needed to match up a volume with a device when
attachments.Devices() is requested.

Return attachment device info when requested

Remove IID restriction from VolumeCreate

VolumeCreate was requiring an IID, which is not necessary.
  • Loading branch information
codenrhoden committed Feb 21, 2017
1 parent 3a24099 commit a337287
Show file tree
Hide file tree
Showing 18 changed files with 496 additions and 462 deletions.
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -1099,6 +1099,13 @@ test-digitalocean:
test-digitalocean-clean:
DRIVERS=digitalocean $(MAKE) clean

test-azureud:
DRIVERS=azureud $(MAKE) deps
DRIVERS=azureud $(MAKE) ./drivers/storage/azureud/tests/azureud.test

test-azureud-clean:
DRIVERS=azureud $(MAKE) clean

clean: $(GO_CLEAN)

clobber: clean $(GO_CLOBBER)
Expand Down
17 changes: 0 additions & 17 deletions drivers/storage/azure/tests/README.md

This file was deleted.

81 changes: 0 additions & 81 deletions drivers/storage/azure/utils/utils.go

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// +build !libstorage_storage_driver libstorage_storage_driver_azure
// +build !libstorage_storage_driver libstorage_storage_driver_azureud

package azure
package azureud

import (
gofigCore "github.com/akutz/gofig"
Expand All @@ -9,7 +9,7 @@ import (

const (
// Name is the provider's name.
Name = "azure"
Name = "azureud"

// TagDelimiter separates tags from volume or snapshot names
TagDelimiter = "/"
Expand All @@ -18,31 +18,40 @@ const (
// or not for Azure URI's
DefaultUseHTTPS = true

// TenantIDKey is a Directory ID from Azure
// TenantIDKey is an Active Directory ID from Azure
TenantIDKey = "tenantID"

// ClientIDKey is an Application ID from Azure
ClientIDKey = "clientID"

// ClientSecretKey is a secret of the application
ClientSecretKey = "clientSecret"

// CertPathKey is a path to application certificate in case of
// authorization via certificate
CertPathKey = "certPath"

// StorageAccountKey is a name of storage account
StorageAccountKey = "storageAccount"

// StorageAccessKey is an access key of storage account
StorageAccessKey = "storageAccessKey"

// TODO: add option to pass StorageURI

// SubscriptionIDKey is an ID of subscription
SubscriptionIDKey = "subscriptionID"

// ResourceGroupKey is a name of resource group
ResourceGroupKey = "resourceGroup"

// ContainerKey is a name of container in the storage account
// ('vhds' by default)
ContainerKey = "container"

// UseHTTPSKey is a flag about use https or not for making Azure URI's
UseHTTPSKey = "useHTTPS"

// TagKey is a tag key
TagKey = "tag"
)
Expand All @@ -63,8 +72,8 @@ const (
// ConfigAzureStorageAccountKey is a config key
ConfigAzureStorageAccountKey = ConfigAzure + "." + StorageAccountKey

// ConfigAzureStorageAccessKeyKey is a config key
ConfigAzureStorageAccessKeyKey = ConfigAzure + "." + StorageAccessKey
// ConfigAzureStorageAccessKey is a config key
ConfigAzureStorageAccessKey = ConfigAzure + "." + StorageAccessKey

// ConfigAzureContainerKey is a config key
ConfigAzureContainerKey = ConfigAzure + "." + ContainerKey
Expand All @@ -86,12 +95,13 @@ const (
)

func init() {
r := gofigCore.NewRegistration("Azure")
r := gofigCore.NewRegistration("AzureUnmanagedDisk")
r.Key(gofig.String, "", "", "", ConfigAzureSubscriptionIDKey)
r.Key(gofig.String, "", "", "", ConfigAzureResourceGroupKey)
r.Key(gofig.String, "", "", "", ConfigAzureTenantIDKey)
r.Key(gofig.String, "", "", "", ConfigAzureStorageAccountKey)
r.Key(gofig.String, "", "", "", ConfigAzureContainerKey)
r.Key(gofig.String, "", "", "", ConfigAzureStorageAccessKey)
r.Key(gofig.String, "", "vhds", "", ConfigAzureContainerKey)
r.Key(gofig.String, "", "", "", ConfigAzureClientIDKey)
r.Key(gofig.String, "", "", "", ConfigAzureClientSecretKey)
r.Key(gofig.String, "", "", "", ConfigAzureCertPathKey)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,45 +1,48 @@
// +build !libstorage_storage_executor libstorage_storage_executor_azure
// +build !libstorage_storage_executor libstorage_storage_executor_azureud

package executor

import (
"bufio"
"bytes"
"fmt"
"os"
"path"
"os/exec"
"regexp"
"strings"

log "github.com/Sirupsen/logrus"

gofig "github.com/akutz/gofig/types"
"github.com/akutz/goof"
"github.com/akutz/gotil"

"github.com/codedellemc/libstorage/api/registry"
"github.com/codedellemc/libstorage/api/types"
"github.com/codedellemc/libstorage/drivers/storage/azure"
"github.com/codedellemc/libstorage/drivers/storage/azure/utils"
"github.com/codedellemc/libstorage/drivers/storage/azureud"
"github.com/codedellemc/libstorage/drivers/storage/azureud/utils"
)

// driver is the storage executor for the azure storage driver.
// driver is the storage executor for the azureud storage driver.
type driver struct {
config gofig.Config
}

func init() {
registry.RegisterStorageExecutor(azure.Name, newDriver)
registry.RegisterStorageExecutor(azureud.Name, newDriver)
}

func newDriver() types.StorageExecutor {
return &driver{}
}

func (d *driver) Init(ctx types.Context, config gofig.Config) error {
ctx.Info("azure_executor: Init")
ctx.Info("azureud_executor: Init")
d.config = config
return nil
}

func (d *driver) Name() string {
return azure.Name
return azureud.Name
}

// Supported returns a flag indicating whether or not the platform
Expand All @@ -48,6 +51,12 @@ func (d *driver) Name() string {
func (d *driver) Supported(
ctx types.Context,
opts types.Store) (bool, error) {

if !gotil.FileExistsInPath("lsscsi") {
ctx.Error("lsscsi executable not found in PATH")
return false, nil
}

return utils.IsAzureInstance(ctx)
}

Expand All @@ -63,7 +72,7 @@ var nextDevRe = regexp.MustCompile("^/dev/" +
utils.NextDeviceInfo.Prefix +
"(" + utils.NextDeviceInfo.Pattern + ")")
var availLetters = []string{
"c", "d", "f", "g", "h", "i", "j", "k", "l", "m", "n",
"c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
"o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}

// NextDevice returns the next available device.
Expand Down Expand Up @@ -100,36 +109,39 @@ func (d *driver) NextDevice(
return "", errNoAvaiDevice
}

const procPartitions = "/proc/partitions"

var devRX = regexp.MustCompile(`^sd[a-z]$`)
var (
devRX = regexp.MustCompile(`^/dev/sd[c-z]$`)
scsiRx = regexp.MustCompile(`^\[\d+:\d+:\d+:(\d+)\]$`)
)

// Retrieve device paths currently attached and/or mounted
func (d *driver) LocalDevices(
ctx types.Context,
opts *types.LocalDevicesOpts) (*types.LocalDevices, error) {

f, err := os.Open(procPartitions)
// Read all of the attached devices
scsiDevs, err := getSCSIDevs()
if err != nil {
return nil, goof.WithError(
"error reading "+procPartitions, err)
return nil, err
}
defer f.Close()

devMap := map[string]string{}

scanner := bufio.NewScanner(f)
scanner := bufio.NewScanner(bytes.NewReader(scsiDevs))
for scanner.Scan() {
fields := strings.Fields(scanner.Text())
if len(fields) != 4 {
device := fields[len(fields)-1]
if !devRX.MatchString(device) {
continue
}
devName := fields[3]
if !devRX.MatchString(devName) {

matches := scsiRx.FindStringSubmatch(fields[0])
if matches == nil {
continue
}
devPath := path.Join("/dev/", devName)
devMap[devPath] = devPath

lun := matches[1]
devMap[device] = lun
}

ld := &types.LocalDevices{Driver: d.Name()}
Expand All @@ -141,3 +153,20 @@ func (d *driver) LocalDevices(

return ld, nil
}

func getSCSIDevs() ([]byte, error) {

out, err := exec.Command("lsscsi").Output()
if err != nil {
if exiterr, ok := err.(*exec.ExitError); ok {
stderr := string(exiterr.Stderr)
log.Errorf("Unable to get scsi devices: %s", stderr)
return nil,
goof.Newf("Unable to get scsi devices: %s",
stderr)
}
return nil, goof.WithError("Unable to get scsci devices", err)
}

return out, nil
}
Loading

0 comments on commit a337287

Please sign in to comment.