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
parent
7c7bfb06b4
commit
331e0c28cc
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ metadata:
|
|||
persistentVolumeProvider:
|
||||
name: azure
|
||||
config:
|
||||
location: <YOUR_LOCATION>
|
||||
apiTimeout: <YOUR_TIMEOUT>
|
||||
backupStorageProvider:
|
||||
name: azure
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue