Remove Azure location requirement

Instead of requiring the Ark admin to specify a "location" in the azure
persistentVolumeProvider config (meaning only a single location is
supported), get info about the disk (for its location) when creating a
snapshot, and get info about the snapshot (for its location) when
creating a disk from a snapshot.

Signed-off-by: Andy Goldstein <andy.goldstein@gmail.com>
pull/344/head
Andy Goldstein 2018-03-01 12:00:30 -05:00
parent 7c7bfb06b4
commit 331e0c28cc
4 changed files with 18 additions and 51 deletions

View File

@ -87,7 +87,7 @@ To integrate Ark with Azure, you must create an Ark-specific [service principal]
az group list --query '[].{ ResourceGroup: name, Location:location }'
```
Get your cluster's Resource Group name from the `ResourceGroup` value in the response, and use it to set `$AZURE_RESOURCE_GROUP`. (Also note the `Location` value in the response -- this is later used in the Azure-specific portion of the Ark Config).
Get your cluster's Resource Group name from the `ResourceGroup` value in the response, and use it to set `$AZURE_RESOURCE_GROUP`.
1. Create a service principal with `Contributor` role. This will have subscription-wide access, so protect this credential. You can specify a password or let the `az ad sp create-for-rbac` command create one for you.
@ -129,7 +129,7 @@ Now that you have your Azure credentials stored in a Secret, you need to replace
* In file `examples/azure/10-ark-config.yaml`:
* Replace `<YOUR_BUCKET>`, `<YOUR_LOCATION>`, and `<YOUR_TIMEOUT>`. See the [Config definition][8] for details.
* Replace `<YOUR_BUCKET>` and `<YOUR_TIMEOUT>`. See the [Config definition][8] for details.
Here is an example of a completed file.
@ -142,7 +142,6 @@ metadata:
persistentVolumeProvider:
name: azure
config:
location: "West US"
apiTimeout: 15m
backupStorageProvider:
name: azure
@ -153,12 +152,6 @@ scheduleSyncPeriod: 1m
restoreOnlyMode: false
```
You can get a complete list of Azure locations with the following command:
```bash
az account list-locations --query "sort([].displayName)" -o tsv
```
## Start the server
In the root of your Ark directory, run:

View File

@ -98,17 +98,14 @@ No parameters required.
| Key | Type | Default | Meaning |
| --- | --- | --- | --- |
| `location` | string | Required Field | *Example*: "Canada East"<br><br>See [the list of available locations][5] (note that this particular page refers to them as "Regions"). |
| `apiTimeout` | metav1.Duration | 2m0s | How long to wait for an Azure API request to complete before timeout. |
[0]: #aws
[1]: #gcp
[2]: #azure
[3]: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions
[5]: https://azure.microsoft.com/en-us/regions/
[6]: #parameter-reference
[7]: #main-config-parameters
[8]: #overview
[9]: #example
[10]: http://docs.aws.amazon.com/kms/latest/developerguide/overview.html

View File

@ -21,7 +21,6 @@ metadata:
persistentVolumeProvider:
name: azure
config:
location: <YOUR_LOCATION>
apiTimeout: <YOUR_TIMEOUT>
backupStorageProvider:
name: azure

View File

@ -25,7 +25,6 @@ import (
"github.com/Azure/azure-sdk-for-go/arm/disk"
"github.com/Azure/azure-sdk-for-go/arm/examples/helpers"
"github.com/Azure/azure-sdk-for-go/arm/resources/subscriptions"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/pkg/errors"
@ -45,7 +44,6 @@ const (
azureStorageKeyKey string = "AZURE_STORAGE_KEY"
azureResourceGroupKey string = "AZURE_RESOURCE_GROUP"
locationKey = "location"
apiTimeoutKey = "apiTimeout"
)
@ -54,7 +52,6 @@ type blockStore struct {
snaps *disk.SnapshotsClient
subscription string
resourceGroup string
location string
apiTimeout time.Duration
}
@ -82,16 +79,11 @@ func NewBlockStore() cloudprovider.BlockStore {
func (b *blockStore) Init(config map[string]string) error {
var (
location = config[locationKey]
apiTimeoutVal = config[apiTimeoutKey]
apiTimeout time.Duration
err error
)
if location == "" {
return errors.Errorf("missing %s in azure configuration", locationKey)
}
if apiTimeout, err = time.ParseDuration(apiTimeoutVal); err != nil {
return errors.Wrapf(err, "could not parse %s (expected time.Duration)", apiTimeoutKey)
}
@ -114,48 +106,28 @@ func (b *blockStore) Init(config map[string]string) error {
disksClient.Authorizer = authorizer
snapsClient.Authorizer = authorizer
// validate the location
groupClient := subscriptions.NewGroupClient()
groupClient.Authorizer = authorizer
locs, err := groupClient.ListLocations(cfg[azureSubscriptionIDKey])
if err != nil {
return errors.WithStack(err)
}
if locs.Value == nil {
return errors.New("no locations returned from Azure API")
}
locationExists := false
for _, loc := range *locs.Value {
if (loc.Name != nil && *loc.Name == location) || (loc.DisplayName != nil && *loc.DisplayName == location) {
locationExists = true
break
}
}
if !locationExists {
return errors.Errorf("location %q not found", location)
}
b.disks = &disksClient
b.snaps = &snapsClient
b.subscription = cfg[azureSubscriptionIDKey]
b.resourceGroup = cfg[azureResourceGroupKey]
b.location = location
b.apiTimeout = apiTimeout
return nil
}
func (b *blockStore) CreateVolumeFromSnapshot(snapshotID, volumeType, volumeAZ string, iops *int64) (string, error) {
// Lookup snapshot info for its Location
snapshotInfo, err := b.snaps.Get(b.resourceGroup, snapshotID)
if err != nil {
return "", errors.WithStack(err)
}
fullSnapshotName := getFullSnapshotName(b.subscription, b.resourceGroup, snapshotID)
diskName := "restore-" + uuid.NewV4().String()
disk := disk.Model{
Name: &diskName,
Location: &b.location,
Location: snapshotInfo.Location,
Properties: &disk.Properties{
CreationData: &disk.CreationData{
CreateOption: disk.Copy,
@ -170,7 +142,7 @@ func (b *blockStore) CreateVolumeFromSnapshot(snapshotID, volumeType, volumeAZ s
_, errChan := b.disks.CreateOrUpdate(b.resourceGroup, *disk.Name, disk, ctx.Done())
err := <-errChan
err = <-errChan
if err != nil {
return "", errors.WithStack(err)
@ -201,6 +173,12 @@ func (b *blockStore) IsVolumeReady(volumeID, volumeAZ string) (ready bool, err e
}
func (b *blockStore) CreateSnapshot(volumeID, volumeAZ string, tags map[string]string) (string, error) {
// Lookup disk info for its Location
diskInfo, err := b.disks.Get(b.resourceGroup, volumeID)
if err != nil {
return "", errors.WithStack(err)
}
fullDiskName := getFullDiskName(b.subscription, b.resourceGroup, volumeID)
// snapshot names must be <= 80 characters long
var snapshotName string
@ -221,7 +199,7 @@ func (b *blockStore) CreateSnapshot(volumeID, volumeAZ string, tags map[string]s
},
},
Tags: &map[string]*string{},
Location: &b.location,
Location: diskInfo.Location,
}
for k, v := range tags {
@ -234,7 +212,7 @@ func (b *blockStore) CreateSnapshot(volumeID, volumeAZ string, tags map[string]s
_, errChan := b.snaps.CreateOrUpdate(b.resourceGroup, *snap.Name, snap, ctx.Done())
err := <-errChan
err = <-errChan
if err != nil {
return "", errors.WithStack(err)