减少API调用次数

This commit is contained in:
屈轩
2018-10-25 20:35:18 +08:00
parent 9971d6cf88
commit f63ee0b716
28 changed files with 971 additions and 613 deletions
+13 -7
View File
@@ -651,7 +651,7 @@ func (manager *SDiskManager) getDisksByStorage(storage *SStorage) ([]SDisk, erro
return disks, nil
}
func (manager *SDiskManager) syncCloudDisk(ctx context.Context, userCred mcclient.TokenCredential, vdisk cloudprovider.ICloudDisk) (*SDisk, error) {
func (manager *SDiskManager) syncCloudDisk(ctx context.Context, userCred mcclient.TokenCredential, vdisk cloudprovider.ICloudDisk, index int) (*SDisk, error) {
diskObj, err := manager.FetchByExternalId(vdisk.GetGlobalId())
if err != nil {
if err == sql.ErrNoRows {
@@ -662,13 +662,13 @@ func (manager *SDiskManager) syncCloudDisk(ctx context.Context, userCred mcclien
return nil, err
}
storage := storageObj.(*SStorage)
return manager.newFromCloudDisk(ctx, userCred, vdisk, storage)
return manager.newFromCloudDisk(ctx, userCred, vdisk, storage, index)
} else {
return nil, err
}
} else {
disk := diskObj.(*SDisk)
err = disk.syncWithCloudDisk(ctx, userCred, vdisk)
err = disk.syncWithCloudDisk(ctx, userCred, vdisk, index)
if err != nil {
return nil, err
}
@@ -708,7 +708,7 @@ func (manager *SDiskManager) SyncDisks(ctx context.Context, userCred mcclient.To
}
for i := 0; i < len(commondb); i += 1 {
err = commondb[i].syncWithCloudDisk(ctx, userCred, commonext[i])
err = commondb[i].syncWithCloudDisk(ctx, userCred, commonext[i], -1)
if err != nil {
syncResult.UpdateError(err)
} else {
@@ -719,7 +719,7 @@ func (manager *SDiskManager) SyncDisks(ctx context.Context, userCred mcclient.To
}
for i := 0; i < len(added); i += 1 {
new, err := manager.newFromCloudDisk(ctx, userCred, added[i], storage)
new, err := manager.newFromCloudDisk(ctx, userCred, added[i], storage, -1)
if err != nil {
syncResult.AddError(err)
} else {
@@ -732,7 +732,7 @@ func (manager *SDiskManager) SyncDisks(ctx context.Context, userCred mcclient.To
return localDisks, remoteDisks, syncResult
}
func (self *SDisk) syncWithCloudDisk(ctx context.Context, userCred mcclient.TokenCredential, extDisk cloudprovider.ICloudDisk) error {
func (self *SDisk) syncWithCloudDisk(ctx context.Context, userCred mcclient.TokenCredential, extDisk cloudprovider.ICloudDisk, index int) error {
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
extDisk.Refresh()
self.Name = extDisk.GetName()
@@ -742,6 +742,9 @@ func (self *SDisk) syncWithCloudDisk(ctx context.Context, userCred mcclient.Toke
self.AutoDelete = extDisk.GetIsAutoDelete()
// self.TemplateId = extDisk.GetTemplateId() no sync template ID
self.DiskType = extDisk.GetDiskType()
if index == 0 {
self.DiskType = DISK_TYPE_SYS
}
// self.FsFormat = extDisk.GetFsFormat()
self.Nonpersistent = extDisk.GetIsNonPersistent()
@@ -775,7 +778,7 @@ func (self *SDisk) syncWithCloudDisk(ctx context.Context, userCred mcclient.Toke
return nil
}
func (manager *SDiskManager) newFromCloudDisk(ctx context.Context, userCred mcclient.TokenCredential, extDisk cloudprovider.ICloudDisk, storage *SStorage) (*SDisk, error) {
func (manager *SDiskManager) newFromCloudDisk(ctx context.Context, userCred mcclient.TokenCredential, extDisk cloudprovider.ICloudDisk, storage *SStorage, index int) (*SDisk, error) {
disk := SDisk{}
disk.SetModelManager(manager)
@@ -789,6 +792,9 @@ func (manager *SDiskManager) newFromCloudDisk(ctx context.Context, userCred mccl
disk.DiskSize = extDisk.GetDiskSizeMB()
disk.AutoDelete = extDisk.GetIsAutoDelete()
disk.DiskType = extDisk.GetDiskType()
if index == 0 {
disk.DiskType = DISK_TYPE_SYS
}
disk.Nonpersistent = extDisk.GetIsNonPersistent()
disk.IsEmulated = extDisk.IsEmulated()
+5 -1
View File
@@ -1883,8 +1883,9 @@ func (self *SGuest) SyncVMDisks(ctx context.Context, userCred mcclient.TokenCred
if len(vdisks[i].GetGlobalId()) == 0 {
continue
}
disk, err := DiskManager.syncCloudDisk(ctx, userCred, vdisks[i])
disk, err := DiskManager.syncCloudDisk(ctx, userCred, vdisks[i], i)
if err != nil {
log.Errorf("syncCloudDisk error: %v", err)
result.Error(err)
return result
}
@@ -1934,6 +1935,7 @@ func (self *SGuest) SyncVMDisks(ctx context.Context, userCred mcclient.TokenCred
vdisk := needAdds[i].vdisk
err := self.attach2Disk(needAdds[i].disk, userCred, vdisk.GetDriver(), vdisk.GetCacheMode(), vdisk.GetMountpoint())
if err != nil {
log.Errorf("attach2Disk error: %v", err)
result.AddError(err)
} else {
result.Add()
@@ -4257,10 +4259,12 @@ func (self *SGuest) SyncVMEip(ctx context.Context, userCred mcclient.TokenCreden
// add
neip, err := ElasticipManager.getEipByExtEip(userCred, extEip, self.getRegion())
if err != nil {
log.Errorf("getEipByExtEip error %v", err)
result.AddError(err)
} else {
err = neip.AssociateVM(userCred, self)
if err != nil {
log.Errorf("AssociateVM error %v", err)
result.AddError(err)
} else {
result.Add()
+2 -2
View File
@@ -233,7 +233,7 @@ func (manager *SWireManager) newFromCloudWire(extWire cloudprovider.ICloudWire,
wire.VpcId = vpc.Id
zoneObj, err := ZoneManager.FetchByExternalId(extWire.GetIZone().GetGlobalId())
if err != nil {
log.Errorf("cannot find zone for wire %s", err)
log.Errorf("cannot find zone %s for wire %s", extWire.GetIZone().GetGlobalId(), err)
return nil, err
}
wire.ZoneId = zoneObj.(*SZone).Id
@@ -605,4 +605,4 @@ func (self *SWire) getMoreDetails(extra *jsonutils.JSONDict) *jsonutils.JSONDict
}
}
return extra
}
}
+148 -138
View File
@@ -29,24 +29,28 @@ const (
)
type SAzureClient struct {
client autorest.Client
providerId string
providerName string
subscriptionId string
tenantId string
clientId string
clientScret string
domain string
baseUrl string
secret string
envName string
subscriptionName string
env azureenv.Environment
authorizer autorest.Authorizer
iregions []cloudprovider.ICloudRegion
client autorest.Client
providerId string
providerName string
subscriptionId string
tenantId string
clientId string
clientScret string
domain string
baseUrl string
secret string
envName string
ressourceGroups []SResourceGroup
fetchResourceGroups bool
subscriptionName string
env azureenv.Environment
authorizer autorest.Authorizer
iregions []cloudprovider.ICloudRegion
}
var DEFAULT_API_VERSION = map[string]string{
"vmSizes": "2018-06-01", //2015-05-01-preview,2015-06-15,2016-03-30,2016-04-30-preview,2016-08-30,2017-03-30,2017-12-01,2018-04-01,2018-06-01,2018-10-01
"Microsoft.Compute/virtualMachineScaleSets": "2017-12-01",
"Microsoft.Compute/virtualMachines": "2018-04-01",
"Microsoft.ClassicCompute/virtualMachines": "2017-04-01",
"Microsoft.Compute/operations": "2018-10-01",
@@ -111,13 +115,7 @@ func (self *SAzureClient) jsonRequest(method, url string, body string) (jsonutil
if err != nil {
return nil, err
}
version := AZURE_API_VERSION
for resourceType, _version := range DEFAULT_API_VERSION {
if strings.Index(strings.ToLower(url), strings.ToLower(resourceType)) > 0 {
version = _version
}
}
return jsonRequest(cli, method, version, self.domain, url, body)
return jsonRequest(cli, method, self.domain, url, body)
}
func (self *SAzureClient) Get(resourceId string, retVal interface{}) error {
@@ -125,13 +123,7 @@ func (self *SAzureClient) Get(resourceId string, retVal interface{}) error {
if err != nil {
return err
}
version := AZURE_API_VERSION
for resourceType, _version := range DEFAULT_API_VERSION {
if strings.Index(strings.ToLower(resourceId), strings.ToLower(resourceType)) > 0 {
version = _version
}
}
body, err := jsonRequest(cli, "GET", version, self.domain, resourceId, "")
body, err := jsonRequest(cli, "GET", self.domain, resourceId, "")
if err != nil {
return err
}
@@ -151,7 +143,7 @@ func (self *SAzureClient) ListVmSizes(location string) (jsonutils.JSONObject, er
return nil, fmt.Errorf("need subscription id")
}
url := fmt.Sprintf("/subscriptions/%s/providers/Microsoft.Compute/locations/%s/vmSizes", self.subscriptionId, location)
return jsonRequest(cli, "GET", "2018-06-01", self.domain, url, "")
return jsonRequest(cli, "GET", self.domain, url, "")
}
func (self *SAzureClient) ListClassicDisks() (jsonutils.JSONObject, error) {
@@ -163,7 +155,7 @@ func (self *SAzureClient) ListClassicDisks() (jsonutils.JSONObject, error) {
return nil, fmt.Errorf("need subscription id")
}
url := fmt.Sprintf("/subscriptions/%s/services/disks", self.subscriptionId)
return jsonRequest(cli, "GET", "2018-06-01", self.domain, url, "")
return jsonRequest(cli, "GET", self.domain, url, "")
}
func (self *SAzureClient) ListAll(resourceType string, retVal interface{}) error {
@@ -175,18 +167,17 @@ func (self *SAzureClient) ListAll(resourceType string, retVal interface{}) error
if len(self.subscriptionId) > 0 {
url += fmt.Sprintf("/%s", self.subscriptionId)
}
version := AZURE_API_VERSION
if len(resourceType) > 0 {
url += fmt.Sprintf("/providers/%s", resourceType)
if _version, ok := DEFAULT_API_VERSION[resourceType]; ok {
version = _version
}
}
body, err := jsonRequest(cli, "GET", version, self.domain, url, "")
body, err := jsonRequest(cli, "GET", self.domain, url, "")
if err != nil {
return err
}
return body.Unmarshal(retVal, "value")
if retVal != nil {
body.Unmarshal(retVal, "value")
}
return nil
}
func (self *SAzureClient) ListSubscriptions() (jsonutils.JSONObject, error) {
@@ -194,7 +185,7 @@ func (self *SAzureClient) ListSubscriptions() (jsonutils.JSONObject, error) {
if err != nil {
return nil, err
}
return jsonRequest(cli, "GET", AZURE_API_VERSION, self.domain, "/subscriptions", "")
return jsonRequest(cli, "GET", self.domain, "/subscriptions", "")
}
func (self *SAzureClient) List(golbalResource string, retVal interface{}) error {
@@ -209,14 +200,14 @@ func (self *SAzureClient) List(golbalResource string, retVal interface{}) error
if len(self.subscriptionId) > 0 && len(golbalResource) > 0 {
url += fmt.Sprintf("/%s", golbalResource)
}
body, err := jsonRequest(cli, "GET", AZURE_API_VERSION, self.domain, url, "")
body, err := jsonRequest(cli, "GET", self.domain, url, "")
if err != nil {
return err
}
return body.Unmarshal(retVal, "value")
}
func (self *SAzureClient) ListByType(Type string, retVal interface{}) error {
func (self *SAzureClient) ListByTypeWithResourceGroup(resourceGroupName string, Type string, retVal interface{}) error {
cli, err := self.getDefaultClient()
if err != nil {
return err
@@ -224,17 +215,8 @@ func (self *SAzureClient) ListByType(Type string, retVal interface{}) error {
if len(self.subscriptionId) == 0 {
return fmt.Errorf("Missing subscription Info")
}
resourceGroupName, ok := defaultResourceGroups[Type]
if !ok {
return fmt.Errorf("Not find default resourceGroup for %s", Type)
}
version := AZURE_API_VERSION
if _version, ok := DEFAULT_API_VERSION[Type]; ok {
version = _version
}
url := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/%s", self.subscriptionId, resourceGroupName, Type)
body, err := jsonRequest(cli, "GET", version, self.domain, url, "")
body, err := jsonRequest(cli, "GET", self.domain, url, "")
if err != nil {
return err
}
@@ -246,13 +228,7 @@ func (self *SAzureClient) Delete(resourceId string) error {
if err != nil {
return err
}
version := AZURE_API_VERSION
for resourceType, _version := range DEFAULT_API_VERSION {
if strings.Index(resourceId, resourceType) > 0 {
version = _version
}
}
_, err = jsonRequest(cli, "DELETE", version, self.domain, resourceId, "")
_, err = jsonRequest(cli, "DELETE", self.domain, resourceId, "")
return err
}
@@ -261,14 +237,41 @@ func (self *SAzureClient) PerformAction(resourceId string, action string) (jsonu
if err != nil {
return nil, err
}
version := AZURE_API_VERSION
for resourceType, _version := range DEFAULT_API_VERSION {
if strings.Index(resourceId, resourceType) > 0 {
version = _version
}
}
url := fmt.Sprintf("%s/%s", resourceId, action)
return jsonRequest(cli, "POST", version, self.domain, url, "")
return jsonRequest(cli, "POST", self.domain, url, "")
}
func (self *SAzureClient) fetchResourceGroup(cli *autorest.Client, location string) error {
if !self.fetchResourceGroups {
err := self.List("resourcegroups", &self.ressourceGroups)
if err != nil {
log.Errorf("failed to list resourceGroups: %v", err)
return err
}
self.fetchResourceGroups = true
}
if len(self.ressourceGroups) == 0 {
//Create Default resourceGroup
_url := fmt.Sprintf("/subscriptions/%s/resourcegroups/Default", self.subscriptionId)
body, err := jsonRequest(cli, "PUT", self.domain, _url, fmt.Sprintf(`{"name": "Default", "location": "%s"}`, location))
if err != nil {
return err
}
return body.Unmarshal(&self.ressourceGroups, "value")
}
return nil
}
func (self *SAzureClient) checkParams(body jsonutils.JSONObject, params []string) (map[string]string, error) {
result := map[string]string{}
for i := 0; i < len(params); i++ {
data, err := body.GetString(params[i])
if err != nil {
return nil, fmt.Errorf("Missing %s params")
}
result[params[i]] = data
}
return result, nil
}
func (self *SAzureClient) Create(body jsonutils.JSONObject, retVal interface{}) error {
@@ -276,34 +279,22 @@ func (self *SAzureClient) Create(body jsonutils.JSONObject, retVal interface{})
if err != nil {
return err
}
url := "/subscriptions"
if len(self.subscriptionId) == 0 {
return fmt.Errorf("Missing subscription info")
}
url += fmt.Sprintf("/%s", self.subscriptionId)
Type, err := body.GetString("type")
params, err := self.checkParams(body, []string{"type", "name", "location"})
if err != nil {
return fmt.Errorf("Azure create resource failed: %s", err.Error())
}
err = self.fetchResourceGroup(cli, params["location"])
if err != nil {
return err
}
if resourceGroupName, ok := defaultResourceGroups[Type]; ok {
url += fmt.Sprintf("/resourceGroups/%s/providers/%s", resourceGroupName, Type)
} else {
msg := fmt.Sprintf("Create %s Missing resourceGroupName", Type)
return fmt.Errorf(msg)
if len(self.ressourceGroups) == 0 {
return fmt.Errorf("Create Default resourceGroup error?")
}
version := AZURE_API_VERSION
if _version, ok := DEFAULT_API_VERSION[Type]; ok {
version = _version
}
name, err := body.GetString("name")
if err != nil {
log.Errorf("Create %s error: Missing name params", Type)
return err
}
url += fmt.Sprintf("/%s", name)
result, err := jsonRequest(cli, "PUT", version, self.domain, url, body.String())
url := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/%s/%s", self.subscriptionId, self.ressourceGroups[0].Name, params["type"], params["name"])
result, err := jsonRequest(cli, "PUT", self.domain, url, body.String())
if err != nil {
return err
}
@@ -319,66 +310,30 @@ func (self *SAzureClient) CheckNameAvailability(Type string, body string) (jsonu
return nil, fmt.Errorf("Missing subscription ID")
}
url := fmt.Sprintf("/subscriptions/%s/providers/%s/checkNameAvailability", self.subscriptionId, Type)
version := AZURE_API_VERSION
for resourceType, _version := range DEFAULT_API_VERSION {
if strings.Index(url, resourceType) > 0 {
version = _version
}
}
return jsonRequest(cli, "POST", version, self.domain, url, body)
return jsonRequest(cli, "POST", self.domain, url, body)
}
func (self *SAzureClient) Update(body jsonutils.JSONObject) (jsonutils.JSONObject, error) {
func (self *SAzureClient) Update(body jsonutils.JSONObject, retVal interface{}) error {
cli, err := self.getDefaultClient()
if err != nil {
return nil, err
return err
}
url, err := body.GetString("id")
version := AZURE_API_VERSION
for resourceType, _version := range DEFAULT_API_VERSION {
if strings.Index(url, resourceType) > 0 {
version = _version
}
}
return jsonRequest(cli, "PUT", version, self.domain, url, body.String())
}
func jsonRequest(client *autorest.Client, method, version, domain, baseUrl string, body string) (jsonutils.JSONObject, error) {
return _jsonRequest(client, method, version, domain, baseUrl, body)
}
func _jsonRequest(client *autorest.Client, method, version, domain, baseUrl string, body string) (result jsonutils.JSONObject, err error) {
url := fmt.Sprintf("%s%s?api-version=%s", domain, baseUrl, version)
if strings.Index(baseUrl, "?") > 0 {
url = fmt.Sprintf("%s%s&api-version=%s", domain, baseUrl, version)
}
req := &http.Request{}
if len(body) != 0 {
req, err = http.NewRequest(method, url, strings.NewReader(body))
if err != nil {
return nil, err
}
} else {
req, err = http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
}
req.Header.Add("Content-Type", "application/json; charset=utf-8")
resp, err := client.Do(req)
result, err := jsonRequest(cli, "PUT", self.domain, url, body.String())
if err != nil {
return nil, err
return err
}
if resp.StatusCode == 404 {
data := []byte{}
if resp.ContentLength != 0 {
data, _ = ioutil.ReadAll(resp.Body)
}
log.Errorf("failed find %s error: %s", url, string(data))
return nil, cloudprovider.ErrNotFound
if retVal != nil {
return result.Unmarshal(retVal)
}
return nil
}
func jsonRequest(client *autorest.Client, method, domain, baseUrl string, body string) (jsonutils.JSONObject, error) {
return _jsonRequest(client, method, domain, baseUrl, body)
}
func waitForComplatetion(client *autorest.Client, req *http.Request, resp *http.Response) (jsonutils.JSONObject, error) {
location := resp.Header.Get("Location")
asyncoperation := resp.Header.Get("Azure-Asyncoperation")
if len(location) > 0 || (len(asyncoperation) > 0 && resp.StatusCode != 200) {
@@ -399,7 +354,7 @@ func _jsonRequest(client *autorest.Client, method, version, domain, baseUrl stri
continue
}
if asyncResp.ContentLength == 0 {
return jsonutils.NewDict(), nil
return nil, nil
}
data, err := ioutil.ReadAll(asyncResp.Body)
if err != nil {
@@ -412,17 +367,71 @@ func _jsonRequest(client *autorest.Client, method, version, domain, baseUrl stri
if len(asyncoperation) > 0 && asyncData.Contains("status") {
status, _ := asyncData.GetString("status")
if status == "InProgress" {
log.Debugf("process %s %s InProgress", req.Method, req.URL.String())
time.Sleep(time.Second * 5)
continue
}
if status == "Succeeded" {
break
log.Debugf("process %s %s Succeeded", req.Method, req.URL.String())
return nil, nil
}
return nil, fmt.Errorf("Create %s failed: %s", body, data)
return nil, fmt.Errorf("Create failed: %s", data)
}
log.Debugf("process %s %s return: %s", req.Method, req.URL.String(), data)
return asyncData, nil
}
}
return nil, nil
}
func _jsonRequest(client *autorest.Client, method, domain, baseURL, body string) (result jsonutils.JSONObject, err error) {
version := AZURE_API_VERSION
for resourceType, _version := range DEFAULT_API_VERSION {
if strings.Index(strings.ToLower(baseURL), strings.ToLower(resourceType)) > 0 {
version = _version
}
}
url := fmt.Sprintf("%s%s?api-version=%s", domain, baseURL, version)
if strings.Index(baseURL, "?") > 0 {
url = fmt.Sprintf("%s%s&api-version=%s", domain, baseURL, version)
}
req := &http.Request{}
if len(body) != 0 {
req, err = http.NewRequest(method, url, strings.NewReader(body))
if err != nil {
log.Errorf("Azure %s new request: %s body: %s error: %v", method, url, body, err)
return nil, err
}
} else {
req, err = http.NewRequest(method, url, nil)
if err != nil {
log.Errorf("Azure %s new request: %s error: %v", method, url, err)
return nil, err
}
}
req.Header.Add("Content-Type", "application/json; charset=utf-8")
resp, err := client.Do(req)
if err != nil {
log.Errorf("Azure %s request: %s \nbody: %s error: %v", req.Method, req.URL.String(), body, err)
return nil, err
}
if resp.StatusCode == 404 {
data := []byte{}
if resp.ContentLength != 0 {
data, _ = ioutil.ReadAll(resp.Body)
}
log.Errorf("failed find %s error: %s", url, string(data))
return nil, cloudprovider.ErrNotFound
}
asyncData, err := waitForComplatetion(client, req, resp)
if err != nil {
return nil, err
}
if asyncData != nil {
return asyncData, nil
}
if resp.ContentLength == 0 {
return jsonutils.NewDict(), nil
}
@@ -436,6 +445,7 @@ func _jsonRequest(client *autorest.Client, method, version, domain, baseUrl stri
return nil, err
}
if result.Contains("error") {
log.Errorf("Azure %s request: %s \nbody: %s error: %v", req.Method, req.URL.String(), body, err)
return nil, fmt.Errorf(result.String())
}
return result, nil
+78 -40
View File
@@ -1,11 +1,11 @@
package azure
import (
"fmt"
"strings"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
)
@@ -18,51 +18,84 @@ type SClassicDisk struct {
OperatingSystem string
IoType string
DiskSizeGB int32
DiskSize int32
diskSizeMB int32
CreatedTime string
SourceImageName string
VhdUri string
diskType string
StorageAccount SubResource
}
func (self *SRegion) GetStorageAccountsDisksWithSnapshots(storageaccounts ...SStorageAccount) ([]SClassicDisk, []SClassicSnapshot, error) {
disks, snapshots := []SClassicDisk{}, []SClassicSnapshot{}
for i := 0; i < len(storageaccounts); i++ {
_disks, _snapshots, err := self.GetStorageAccountDisksWithSnapshots(storageaccounts[i])
if err != nil {
return nil, nil, err
}
disks = append(disks, _disks...)
snapshots = append(snapshots, _snapshots...)
}
return disks, snapshots, nil
}
func (self *SRegion) GetStorageAccountDisksWithSnapshots(storageaccount SStorageAccount) ([]SClassicDisk, []SClassicSnapshot, error) {
disks, snapshots := []SClassicDisk{}, []SClassicSnapshot{}
containers, err := storageaccount.GetContainers()
if err != nil {
return nil, nil, err
}
for _, container := range containers {
if container.Name == "vhds" {
files, err := container.ListFiles()
if err != nil {
log.Errorf("List storage %s container %s files error: %v", storageaccount.Name, container.Name, err)
return nil, nil, err
}
for _, file := range files {
if strings.HasSuffix(file.Name, ".vhd") {
diskType := models.DISK_TYPE_DATA
if _diskType, ok := file.Metadata["microsoftazurecompute_disktype"]; ok && _diskType == "OSDisk" {
diskType = models.DISK_TYPE_SYS
}
diskName := file.Name
if _diskName, ok := file.Metadata["microsoftazurecompute_diskname"]; ok {
diskName = _diskName
}
if file.Snapshot.IsZero() {
disks = append(disks, SClassicDisk{
DiskName: diskName,
diskType: diskType,
DiskSizeGB: int32(file.Properties.ContentLength / 1024 / 1024 / 1024),
diskSizeMB: int32(file.Properties.ContentLength / 1024 / 1024),
VhdUri: file.GetURL(),
})
} else {
snapshots = append(snapshots, SClassicSnapshot{
region: self,
Name: file.Snapshot.String(),
sizeMB: int32(file.Properties.ContentLength / 1024 / 1024),
diskID: file.GetURL(),
diskName: diskName,
})
}
}
}
}
}
return disks, snapshots, nil
}
func (self *SRegion) GetClassicDisks() ([]SClassicDisk, error) {
storageaccounts, err := self.GetClassicStorageAccounts()
if err != nil {
return nil, err
}
disks := []SClassicDisk{}
for _, storageaccount := range storageaccounts {
containers, err := storageaccount.GetContainers()
if err != nil {
return nil, err
}
baseUrl := storageaccount.GetBlobBaseUrl()
if len(baseUrl) == 0 {
return nil, fmt.Errorf("failed to find storageaccount %s blob endpoint", storageaccount.Name)
}
storage := SClassicStorage{
Name: storageaccount.Name,
ID: storageaccount.ID,
Location: storageaccount.Location,
Type: storageaccount.Type,
}
for _, container := range containers {
if container.Name == "vhds" {
files, err := container.ListFiles()
if err != nil {
return nil, err
}
for _, file := range files {
if strings.HasSuffix(file.Name, ".vhd") {
disks = append(disks, SClassicDisk{
storage: &storage,
DiskName: file.Name,
DiskSizeGB: int32(file.Properties.ContentLength / 1024 / 1024 / 1024),
VhdUri: baseUrl + file.Name,
})
}
}
}
}
disks, _, err := self.GetStorageAccountsDisksWithSnapshots(storageaccounts...)
if err != nil {
return nil, err
}
return disks, nil
}
@@ -108,7 +141,10 @@ func (self *SClassicDisk) GetDiskFormat() string {
}
func (self *SClassicDisk) GetDiskSizeMB() int {
return int(self.DiskSizeGB * 1024)
if self.DiskSizeGB > 0 {
return int(self.DiskSizeGB * 1024)
}
return int(self.diskSizeMB)
}
func (self *SClassicDisk) GetIsAutoDelete() bool {
@@ -120,10 +156,7 @@ func (self *SClassicDisk) GetTemplateId() string {
}
func (self *SClassicDisk) GetDiskType() string {
if len(self.OperatingSystem) > 0 {
return models.DISK_TYPE_SYS
}
return models.DISK_TYPE_DATA
return self.diskType
}
func (self *SClassicDisk) GetExpiredAt() time.Time {
@@ -142,6 +175,11 @@ func (self *SClassicDisk) GetISnapshot(snapshotId string) (cloudprovider.ICloudS
return nil, cloudprovider.ErrNotSupported
}
func (region *SRegion) GetClassicSnapShots(diskId string) ([]SClassicSnapshot, error) {
result := []SClassicSnapshot{}
return result, nil
}
func (self *SClassicDisk) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
return nil, cloudprovider.ErrNotSupported
}
+4 -4
View File
@@ -130,12 +130,12 @@ func (self *SClassicHost) GetIStorages() ([]cloudprovider.ICloudStorage, error)
}
func (self *SClassicHost) GetIVMById(instanceId string) (cloudprovider.ICloudVM, error) {
if instance, err := self.zone.region.GetClassicInstance(instanceId); err != nil {
instance, err := self.zone.region.GetClassicInstance(instanceId)
if err != nil {
return nil, err
} else {
instance.host = self
return instance, nil
}
instance.host = self
return instance, nil
}
func (self *SClassicHost) GetStorageSizeMB() int {
+66 -62
View File
@@ -34,7 +34,8 @@ type SubResource struct {
Type string
}
type OperatingSystemDisk struct {
type ClassicDisk struct {
Lun int32
DiskName string
Caching string
OperatingSystem string
@@ -42,24 +43,13 @@ type OperatingSystemDisk struct {
CreatedTime string
SourceImageName string
VhdUri string
StorageAccount SubResource
}
type ClassicDataDisk struct {
Lun int32
DiskName string
Caching string
OperatingSystem string
IoType string
CreatedTime string
VhdUri string
DiskSize int32 `json:"diskSize,omitempty"`
StorageAccount SubResource
}
type ClassicStorageProfile struct {
OperatingSystemDisk OperatingSystemDisk `json:"operatingSystemDisk,omitempty"`
DataDisks *[]ClassicDataDisk `json:"aataDisks,omitempty"`
OperatingSystemDisk ClassicDisk `json:"operatingSystemDisk,omitempty"`
DataDisks *[]ClassicDisk `json:"aataDisks,omitempty"`
}
type ClassicHardwareProfile struct {
@@ -158,46 +148,44 @@ func (self *SRegion) GetClassicInstance(instanceId string) (*SClassicInstance, e
return &instance, self.client.Get(fmt.Sprintf("%s?$expand=instanceView", instanceId), &instance)
}
type ClassicInstanceDiskProperties struct {
DiskName string
Caching string
OperatingSystem string
IoType string
DiskSize int32
SourceImageName string
VhdUri string
}
type ClassicInstanceDisk struct {
Properties ClassicInstanceDiskProperties
ID string
Name string
Type string
}
func (self *SClassicInstance) getDisks() ([]SClassicDisk, error) {
disks := []SClassicDisk{}
osDisk := self.Properties.StorageProfile.OperatingSystemDisk
store, err := self.host.zone.region.GetStorageAccountDetail(osDisk.StorageAccount.ID)
body, err := self.host.zone.region.client.jsonRequest("GET", fmt.Sprintf("%s/disks", self.ID), "")
if err != nil {
return nil, err
}
storage := SClassicStorage{zone: self.host.zone, Name: store.Name, Location: store.Location, ID: store.ID, Type: store.Type}
disks = append(disks, SClassicDisk{
storage: &storage,
DiskName: osDisk.DiskName,
Caching: osDisk.Caching,
OperatingSystem: osDisk.OperatingSystem,
IoType: osDisk.IoType,
CreatedTime: osDisk.CreatedTime,
SourceImageName: osDisk.SourceImageName,
VhdUri: osDisk.VhdUri,
StorageAccount: osDisk.StorageAccount,
})
if self.Properties.StorageProfile.DataDisks != nil {
for _, disk := range *self.Properties.StorageProfile.DataDisks {
store, err := self.host.zone.region.GetStorageAccountDetail(disk.StorageAccount.ID)
if err != nil {
return nil, err
}
storage := SClassicStorage{zone: self.host.zone, Name: store.Name, Location: store.Location, ID: store.ID, Type: store.Type}
disks = append(disks, SClassicDisk{
storage: &storage,
DiskName: disk.DiskName,
DiskSizeGB: disk.DiskSize,
Caching: disk.Caching,
OperatingSystem: disk.OperatingSystem,
IoType: disk.IoType,
CreatedTime: disk.CreatedTime,
VhdUri: disk.VhdUri,
StorageAccount: osDisk.StorageAccount,
})
_disks, err := body.GetArray("value")
if err != nil {
return nil, err
}
for i := 0; i < len(_disks); i++ {
disk := SClassicDisk{}
err = _disks[i].Unmarshal(&disk, "properties")
if err != nil {
return nil, err
}
storage := SClassicStorage{zone: self.host.zone, Name: disk.StorageAccount.Name, ID: disk.StorageAccount.ID}
disk.DiskSizeGB = disk.DiskSize
disk.storage = &storage
disks = append(disks, disk)
}
return disks, nil
}
@@ -232,28 +220,34 @@ func (self *SClassicInstance) getNics() ([]SClassicInstanceNic, error) {
}
func (self *SClassicInstance) Refresh() error {
if instance, err := self.host.zone.region.GetClassicInstance(self.ID); err != nil {
instance, err := self.host.zone.region.GetClassicInstance(self.ID)
if err != nil {
return err
} else {
return jsonutils.Update(self, instance)
}
return jsonutils.Update(self, instance)
}
func (self *SClassicInstance) GetStatus() string {
if self.Properties.InstanceView != nil {
switch self.Properties.InstanceView.Status {
case "StoppedDeallocated":
return models.VM_READY
case "ReadyRole":
return models.VM_RUNNING
case "Stopped":
return models.VM_READY
default:
log.Errorf("Unknow instance %s status %s", self.Name, self.Properties.InstanceView.Status)
if self.Properties.InstanceView == nil {
err := self.Refresh()
if err != nil {
log.Errorf("failed to get status for classic instance %s", self.Name)
return models.VM_UNKNOWN
}
}
return models.VM_UNKNOWN
switch self.Properties.InstanceView.Status {
case "StoppedDeallocated":
return models.VM_READY
case "ReadyRole":
return models.VM_RUNNING
case "Stopped":
return models.VM_READY
case "RoleStateUnknown":
return models.VM_UNKNOWN
default:
log.Errorf("Unknow classic instance %s status %s", self.Name, self.Properties.InstanceView.Status)
return models.VM_UNKNOWN
}
}
func (self *SClassicInstance) GetIHost() cloudprovider.ICloudHost {
@@ -407,12 +401,18 @@ func (self *SClassicInstance) StartVM() error {
}
func (self *SClassicInstance) StopVM(isForce bool) error {
if err := self.host.zone.region.StopVM(self.ID, isForce); err != nil {
err := self.host.zone.region.StopClassicVM(self.ID, isForce)
if err != nil {
return err
}
return cloudprovider.WaitStatus(self, models.VM_READY, 10*time.Second, 300*time.Second)
}
func (self *SRegion) StopClassicVM(instanceId string, isForce bool) error {
_, err := self.client.PerformAction(instanceId, "shutdown")
return err
}
func (self *SClassicInstance) SyncSecurityGroup(secgroupId string, name string, rules []secrules.SecurityRule) error {
return cloudprovider.ErrNotSupported
}
@@ -423,6 +423,10 @@ func (self *SClassicInstance) GetIEIP() (cloudprovider.ICloudEIP, error) {
eip, err := self.host.zone.region.GetClassicEip(reserveIp.ID)
if err == nil {
eip.instanceId = self.ID
if eip.Properties.AttachedTo != nil && eip.Properties.AttachedTo.ID != self.ID {
//一般是此实例deallocate, eip被绑到其他机器上了.
return nil, nil
}
return eip, nil
}
log.Errorf("failed find eip %s for classic instance %s", reserveIp.Name, self.Name)
+1 -2
View File
@@ -51,8 +51,7 @@ func (self *SClassicNetwork) Delete() error {
}
subnets = append(subnets, network)
}
_, err := self.wire.vpc.region.client.Update(jsonutils.Marshal(vpc))
return err
return self.wire.vpc.region.client.Update(jsonutils.Marshal(vpc), self.wire.vpc)
}
func (self *SClassicNetwork) GetGateway() string {
+2 -4
View File
@@ -228,8 +228,7 @@ func (region *SRegion) updateClassicSecurityGroupRules(secgroupId string, rules
}
secgroup.Properties.SecurityRules = &securityRules
secgroup.Properties.ProvisioningState = ""
_, err = region.client.Update(jsonutils.Marshal(secgroup))
return secgroup.ID, err
return secgroup.ID, region.client.Update(jsonutils.Marshal(secgroup), nil)
}
func (region *SRegion) AssiginClassicSecurityGroup(instanceId, secgroupId string) error {
@@ -246,8 +245,7 @@ func (region *SRegion) AssiginClassicSecurityGroup(instanceId, secgroupId string
Name: secgroup.Name,
Type: secgroup.Type,
}
_, err = region.client.Update(jsonutils.Marshal(instance))
return err
return region.client.Update(jsonutils.Marshal(instance), nil)
}
func (self *SRegion) syncClassicSecgroupRules(secgroupId string, rules []secrules.SecurityRule) (string, error) {
+74
View File
@@ -0,0 +1,74 @@
package azure
import (
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
)
type SClassicSnapshot struct {
region *SRegion
Name string
sizeMB int32
diskID string
diskName string
}
func (self *SClassicSnapshot) GetId() string {
return fmt.Sprintf("%s?snapshot=%s", self.diskID, self.Name)
}
func (self *SClassicSnapshot) GetGlobalId() string {
return self.GetId()
}
func (self *SClassicSnapshot) GetMetadata() *jsonutils.JSONDict {
return nil
}
func (self *SClassicSnapshot) GetName() string {
return fmt.Sprintf("%s-%s", self.diskName, self.Name)
}
func (self *SClassicSnapshot) GetStatus() string {
return models.SNAPSHOT_READY
}
func (self *SClassicSnapshot) IsEmulated() bool {
return false
}
func (self *SRegion) CreateClassicSnapshot(diskId, snapName, desc string) (*SClassicSnapshot, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SClassicSnapshot) Delete() error {
return self.region.DeleteClassicSnapshot(self.GetId())
}
func (self *SClassicSnapshot) GetSize() int32 {
return self.sizeMB
}
func (self *SRegion) DeleteClassicSnapshot(snapshotId string) error {
return cloudprovider.ErrNotImplemented
}
func (self *SClassicSnapshot) Refresh() error {
return nil
}
func (self *SClassicSnapshot) GetDiskId() string {
return self.diskID
}
func (self *SClassicSnapshot) GetManagerId() string {
return self.region.client.providerId
}
func (self *SClassicSnapshot) GetRegionId() string {
return self.region.GetId()
}
+6 -28
View File
@@ -1,9 +1,7 @@
package azure
import (
"fmt"
"strings"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/cloudprovider"
@@ -19,7 +17,7 @@ type ClassicStorageProperties struct {
StatusOfPrimaryRegion string
GeoSecondaryRegion string
StatusOfSecondaryRegion string
CreationTime time.Time
//CreationTime time.Time
}
type SClassicStorage struct {
@@ -83,34 +81,14 @@ func (self *SClassicStorage) GetIDisk(diskId string) (cloudprovider.ICloudDisk,
func (self *SClassicStorage) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
storageaccount, err := self.zone.region.GetStorageAccountDetail(self.ID)
disks, _, err := self.zone.region.GetStorageAccountDisksWithSnapshots(*storageaccount)
if err != nil {
return nil, err
}
containers, err := storageaccount.GetContainers()
if err != nil {
return nil, err
}
baseUrl := storageaccount.GetBlobBaseUrl()
if len(baseUrl) == 0 {
return nil, fmt.Errorf("failed to find storageaccount %s blob endpoint", storageaccount.Name)
}
idisks := make([]cloudprovider.ICloudDisk, 0)
for _, container := range containers {
if container.Name == "vhds" {
files, err := container.ListFiles()
if err != nil {
return nil, err
}
for _, file := range files {
if strings.HasSuffix(file.Name, ".vhd") {
idisks = append(idisks, &SClassicDisk{
storage: self,
DiskName: file.Name,
VhdUri: baseUrl + file.Name,
})
}
}
}
idisks := make([]cloudprovider.ICloudDisk, len(disks))
for i := 0; i < len(disks); i++ {
disks[i].storage = self
idisks[i] = &disks[i]
}
return idisks, nil
}
+60 -47
View File
@@ -101,22 +101,24 @@ func (self *SRegion) DeleteDisk(diskId string) error {
}
func (self *SRegion) deleteDisk(diskId string) error {
return self.client.Delete(diskId)
if !strings.HasPrefix(diskId, "https://") {
return self.client.Delete(diskId)
}
//TODO
return cloudprovider.ErrNotImplemented
}
func (self *SRegion) ResizeDisk(diskId string, sizeGb int32) error {
return self.resizeDisk(diskId, sizeGb)
}
func (self *SRegion) resizeDisk(diskId string, sizeGb int32) error {
disk, err := self.GetDisk(diskId)
if err != nil {
return err
if !strings.HasPrefix(diskId, "https://") {
disk, err := self.GetDisk(diskId)
if err != nil {
return err
}
disk.Properties.DiskSizeGB = sizeGb
disk.Properties.ProvisioningState = ""
return self.client.Update(jsonutils.Marshal(disk), nil)
}
disk.Properties.DiskSizeGB = sizeGb
disk.Properties.ProvisioningState = ""
_, err = self.client.Update(jsonutils.Marshal(disk))
return err
return cloudprovider.ErrNotSupported
}
func (self *SRegion) GetDisk(diskId string) (*SDisk, error) {
@@ -126,7 +128,6 @@ func (self *SRegion) GetDisk(diskId string) (*SDisk, error) {
func (self *SRegion) GetDisks() ([]SDisk, error) {
result := []SDisk{}
//self.client.ListClassicDisks()
disks := []SDisk{}
err := self.client.ListAll("Microsoft.Compute/disks", &disks)
if err != nil {
@@ -147,16 +148,19 @@ func (self *SDisk) GetMetadata() *jsonutils.JSONDict {
}
func (self *SDisk) GetStatus() string {
status := self.Properties.ProvisioningState
switch status {
case "Updating":
return models.DISK_ALLOCATING
case "Succeeded":
return models.DISK_READY
default:
log.Errorf("Unknow azure disk status: %s", status)
return models.DISK_UNKNOWN
if !strings.HasPrefix(self.ID, "https://") {
status := self.Properties.ProvisioningState
switch status {
case "Updating":
return models.DISK_ALLOCATING
case "Succeeded":
return models.DISK_READY
default:
log.Errorf("Unknow azure disk %s status: %s", self.ID, status)
return models.DISK_UNKNOWN
}
}
return models.DISK_READY
}
func (self *SDisk) GetId() string {
@@ -164,11 +168,14 @@ func (self *SDisk) GetId() string {
}
func (self *SDisk) Refresh() error {
if disk, err := self.storage.zone.region.GetDisk(self.ID); err != nil {
return cloudprovider.ErrNotFound
} else {
if !strings.HasPrefix(self.ID, "https://") {
disk, err := self.storage.zone.region.GetDisk(self.ID)
if err != nil {
return cloudprovider.ErrNotFound
}
return jsonutils.Update(self, disk)
}
return nil
}
func (self *SDisk) Delete() error {
@@ -176,7 +183,7 @@ func (self *SDisk) Delete() error {
}
func (self *SDisk) Resize(size int64) error {
return self.storage.zone.region.resizeDisk(self.ID, int32(size))
return self.storage.zone.region.ResizeDisk(self.ID, int32(size))
}
func (self *SDisk) GetName() string {
@@ -255,15 +262,18 @@ func (self *SDisk) GetISnapshot(snapshotId string) (cloudprovider.ICloudSnapshot
}
func (self *SDisk) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
if snapshots, err := self.storage.zone.region.GetSnapShots(self.ID); err != nil {
return nil, err
} else {
isnapshots := make([]cloudprovider.ICloudSnapshot, len(snapshots))
isnapshots := make([]cloudprovider.ICloudSnapshot, 0)
if !strings.HasPrefix(self.ID, "https://") {
snapshots, err := self.storage.zone.region.GetSnapShots(self.ID)
if err != nil {
return nil, err
}
for i := 0; i < len(snapshots); i++ {
isnapshots[i] = &snapshots[i]
isnapshots = append(isnapshots, &snapshots[i])
}
return isnapshots, nil
}
return isnapshots, nil
}
func (self *SDisk) GetBillingType() string {
@@ -275,13 +285,14 @@ func (self *SDisk) GetExpiredAt() time.Time {
}
func (self *SDisk) GetSnapshotDetail(snapshotId string) (*SSnapshot, error) {
if snapshot, err := self.storage.zone.region.GetSnapshotDetail(snapshotId); err != nil {
snapshot, err := self.storage.zone.region.GetSnapshotDetail(snapshotId)
if err != nil {
return nil, err
} else if snapshot.Properties.CreationData.SourceResourceID != self.ID {
return nil, cloudprovider.ErrNotFound
} else {
return snapshot, nil
}
if snapshot.Properties.CreationData.SourceResourceID != self.ID {
return nil, cloudprovider.ErrNotFound
}
return snapshot, nil
}
func (region *SRegion) GetSnapshotDetail(snapshotId string) (*SSnapshot, error) {
@@ -291,16 +302,18 @@ func (region *SRegion) GetSnapshotDetail(snapshotId string) (*SSnapshot, error)
func (region *SRegion) GetSnapShots(diskId string) ([]SSnapshot, error) {
result := []SSnapshot{}
snapshots := []SSnapshot{}
err := region.client.ListAll("Microsoft.Compute/snapshots", &snapshots)
if err != nil {
return nil, err
}
for i := 0; i < len(snapshots); i++ {
if snapshots[i].Location == region.Name {
if len(diskId) == 0 || diskId == snapshots[i].Properties.CreationData.SourceResourceID {
snapshots[i].region = region
result = append(result, snapshots[i])
if !strings.HasPrefix(diskId, "https://") {
snapshots := []SSnapshot{}
err := region.client.ListAll("Microsoft.Compute/snapshots", &snapshots)
if err != nil {
return nil, err
}
for i := 0; i < len(snapshots); i++ {
if snapshots[i].Location == region.Name {
if len(diskId) == 0 || diskId == snapshots[i].Properties.CreationData.SourceResourceID {
snapshots[i].region = region
result = append(result, snapshots[i])
}
}
}
}
+2 -4
View File
@@ -84,8 +84,7 @@ func (region *SRegion) AssociateEip(eipId string, instanceId string) error {
return err
}
nic.Properties.IPConfigurations[0].Properties.PublicIPAddress.ID = eipId
_, err = region.client.Update(jsonutils.Marshal(nic))
return err
return region.client.Update(jsonutils.Marshal(nic), nil)
}
func (region *SRegion) GetIEipById(eipId string) (cloudprovider.ICloudEIP, error) {
@@ -123,8 +122,7 @@ func (region *SRegion) DissociateEip(eipId string) error {
return err
}
nic.Properties.IPConfigurations[0].Properties.PublicIPAddress.ID = ""
_, err = region.client.Update(jsonutils.Marshal(nic))
return err
return region.client.Update(jsonutils.Marshal(nic), nil)
}
func (self *SEipAddress) GetAssociationExternalId() string {
+14 -15
View File
@@ -146,7 +146,6 @@ func (self *SHost) _createVM(name string, imgId string, sysDiskSize int, cpu int
for _, profile := range self.zone.region.getHardwareProfile(cpu, memMB) {
instance.Properties.HardwareProfile.VMSize = profile
log.Errorf("instance: %s", jsonutils.Marshal(instance).PrettyString())
log.Debugf("Try HardwareProfile : %s", profile)
err := self.zone.region.client.Create(jsonutils.Marshal(instance), &instance)
if err != nil {
@@ -207,16 +206,16 @@ func (self *SHost) GetSysInfo() jsonutils.JSONObject {
}
func (self *SHost) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
return self.zone.GetIStorages()
return self.zone.istorages, nil
}
func (self *SHost) GetIVMById(instanceId string) (cloudprovider.ICloudVM, error) {
if instance, err := self.zone.region.GetInstance(instanceId); err != nil {
instance, err := self.zone.region.GetInstance(instanceId)
if err != nil {
return nil, err
} else {
instance.host = self
return instance, nil
}
instance.host = self
return instance, nil
}
func (self *SHost) GetStorageSizeMB() int {
@@ -232,17 +231,17 @@ func (self *SHost) GetSN() string {
}
func (self *SHost) GetIVMs() ([]cloudprovider.ICloudVM, error) {
if vms, err := self.zone.region.GetInstances(); err != nil {
vms, err := self.zone.region.GetInstances()
if err != nil {
return nil, err
} else {
ivms := make([]cloudprovider.ICloudVM, len(vms))
for i := 0; i < len(vms); i++ {
vms[i].host = self
ivms[i] = &vms[i]
log.Debugf("find vm %s for host %s", vms[i].GetName(), self.GetName())
}
return ivms, nil
}
ivms := make([]cloudprovider.ICloudVM, len(vms))
for i := 0; i < len(vms); i++ {
vms[i].host = self
ivms[i] = &vms[i]
log.Debugf("find vm %s for host %s", vms[i].GetName(), self.GetName())
}
return ivms, nil
}
func (self *SHost) GetIWires() ([]cloudprovider.ICloudWire, error) {
+139 -97
View File
@@ -197,6 +197,11 @@ func (self *SRegion) GetInstance(instanceId string) (*SInstance, error) {
return &instance, self.client.Get(fmt.Sprintf("%s?$expand=instanceView", instanceId), &instance)
}
func (self *SRegion) GetInstanceScaleSets() ([]SInstance, error) {
instance := []SInstance{}
return instance, self.client.ListAll("Microsoft.Compute/virtualMachineScaleSets", &instance)
}
func (self *SRegion) GetInstances() ([]SInstance, error) {
result := []SInstance{}
instances := []SInstance{}
@@ -261,18 +266,18 @@ func (self *SInstance) getOsDisk() (*SDisk, error) {
}
}
func (self *SInstance) getClassicStorageInfoByUri(uri string) (*SClassicStorage, error) {
func (self *SInstance) getStorageInfoByUri(uri string) (*SStorage, *SClassicStorage, error) {
_storageName := strings.Split(strings.Replace(uri, "https://", "", -1), ".")
storageName := ""
if len(_storageName) > 0 {
storageName = _storageName[0]
}
if len(storageName) == 0 {
return nil, fmt.Errorf("bad uri %s for search storageaccount", uri)
return nil, nil, fmt.Errorf("bad uri %s for search storageaccount", uri)
}
storageaccounts, err := self.host.zone.region.GetClassicStorageAccounts()
if err != nil {
return nil, err
return nil, nil, err
}
for i := 0; i < len(storageaccounts); i++ {
if storageaccounts[i].Name == storageName {
@@ -283,27 +288,57 @@ func (self *SInstance) getClassicStorageInfoByUri(uri string) (*SClassicStorage,
Type: storageaccounts[i].Type,
Location: storageaccounts[i].Type,
}
return &storage, nil
return nil, &storage, nil
}
}
return nil, fmt.Errorf("failed to found classic storageaccount for %s", uri)
storageaccounts, err = self.host.zone.region.GetStorageAccounts()
if err != nil {
return nil, nil, err
}
for i := 0; i < len(storageaccounts); i++ {
if storageaccounts[i].Name == storageName {
storage := SStorage{
zone: self.host.zone,
Name: storageName,
storageType: storageaccounts[i].Sku.Name,
}
return &storage, nil, nil
}
}
return nil, nil, fmt.Errorf("failed to found classic storageaccount for %s", uri)
}
func (self *SInstance) getDisks() ([]SDisk, []SClassicDisk, error) {
disks, classicDisk := []SDisk{}, []SClassicDisk{}
if self.Properties.StorageProfile.OsDisk.Vhd != nil {
disk := self.Properties.StorageProfile.OsDisk
storage, err := self.getClassicStorageInfoByUri(disk.Vhd.Uri)
storage, classicStorage, err := self.getStorageInfoByUri(disk.Vhd.Uri)
if err != nil {
return nil, nil, err
}
classicDisk = append(classicDisk, SClassicDisk{
storage: storage,
DiskName: disk.Name,
DiskSizeGB: disk.DiskSizeGB,
Caching: disk.Caching,
VhdUri: disk.Vhd.Uri,
})
if classicStorage != nil {
classicDisk = append(classicDisk, SClassicDisk{
storage: classicStorage,
DiskName: disk.Name,
DiskSizeGB: disk.DiskSizeGB,
Caching: disk.Caching,
VhdUri: disk.Vhd.Uri,
})
}
if storage != nil {
disks = append(disks, SDisk{
storage: storage,
ID: disk.Vhd.Uri,
Name: disk.Name,
Properties: DiskProperties{
OsType: disk.OsType,
CreationData: CreationData{
CreateOption: disk.CreateOption,
},
DiskSizeGB: disk.DiskSizeGB,
},
})
}
} else if self.Properties.StorageProfile.OsDisk.ManagedDisk != nil {
disk, err := self.getDiskWithStore(self.Properties.StorageProfile.OsDisk.ManagedDisk.ID)
if err != nil {
@@ -314,21 +349,36 @@ func (self *SInstance) getDisks() ([]SDisk, []SClassicDisk, error) {
}
for _, _disk := range *self.Properties.StorageProfile.DataDisks {
if _disk.Vhd != nil {
storage, err := self.getClassicStorageInfoByUri(_disk.Vhd.Uri)
storage, classicStorage, err := self.getStorageInfoByUri(_disk.Vhd.Uri)
if err != nil {
return nil, nil, err
}
classicDisk = append(classicDisk, SClassicDisk{
storage: storage,
DiskName: _disk.Name,
DiskSizeGB: _disk.DiskSizeGB,
Caching: _disk.Caching,
VhdUri: _disk.Vhd.Uri,
})
} else if self.Properties.StorageProfile.OsDisk.ManagedDisk != nil {
disk, err := self.getDiskWithStore(self.Properties.StorageProfile.OsDisk.ManagedDisk.ID)
if classicStorage != nil {
classicDisk = append(classicDisk, SClassicDisk{
storage: classicStorage,
DiskName: _disk.Name,
DiskSizeGB: _disk.DiskSizeGB,
Caching: _disk.Caching,
VhdUri: _disk.Vhd.Uri,
})
}
if storage != nil {
disks = append(disks, SDisk{
storage: storage,
ID: _disk.Vhd.Uri,
Name: _disk.Name,
Properties: DiskProperties{
CreationData: CreationData{
CreateOption: _disk.CreateOption,
},
DiskSizeGB: _disk.DiskSizeGB,
},
})
}
} else if _disk.ManagedDisk != nil {
disk, err := self.getDiskWithStore(_disk.ManagedDisk.ID)
if err != nil {
log.Errorf("Failed to find instance %s os disk: %s", self.Name, self.Properties.StorageProfile.OsDisk.ManagedDisk.ID)
log.Errorf("Failed to find instance %s os disk: %s", self.Name, _disk.ManagedDisk.ID)
return nil, nil, err
}
disks = append(disks, *disk)
@@ -352,40 +402,43 @@ func (self *SInstance) getNics() ([]SInstanceNic, error) {
}
func (self *SInstance) Refresh() error {
if instance, err := self.host.zone.region.GetInstance(self.ID); err != nil {
instance, err := self.host.zone.region.GetInstance(self.ID)
if err != nil {
return err
} else {
return jsonutils.Update(self, instance)
}
return jsonutils.Update(self, instance)
}
func (self *SInstance) GetStatus() string {
if self.Properties.InstanceView != nil {
for _, statuses := range self.Properties.InstanceView.Statuses {
if code := strings.Split(statuses.Code, "/"); len(code) == 2 {
if code[0] == "PowerState" {
switch code[1] {
case "stopped":
return models.VM_READY
case "deallocated":
return models.VM_DEALLOCATED
case "running":
return models.VM_RUNNING
case "stopping":
return models.VM_START_STOP
case "starting":
return models.VM_STARTING
case "deleting":
return models.VM_DELETING
default:
log.Errorf("Unknow instance status %s", code[1])
return models.VM_UNKNOWN
}
if self.Properties.InstanceView == nil {
err := self.Refresh()
if err != nil {
log.Errorf("failed to get status for instance %s", self.Name)
return models.VM_UNKNOWN
}
}
for _, statuses := range self.Properties.InstanceView.Statuses {
if code := strings.Split(statuses.Code, "/"); len(code) == 2 {
if code[0] == "PowerState" {
switch code[1] {
case "stopped", "deallocated":
return models.VM_READY
case "running":
return models.VM_RUNNING
case "stopping":
return models.VM_START_STOP
case "starting":
return models.VM_STARTING
case "deleting":
return models.VM_DELETING
default:
log.Errorf("Unknow instance status %s", code[1])
return models.VM_UNKNOWN
}
}
if statuses.Level == "Error" {
log.Errorf("Find error code: [%s] message: %s", statuses.Code, statuses.Message)
}
}
if statuses.Level == "Error" {
log.Errorf("Find error code: [%s] message: %s", statuses.Code, statuses.Message)
}
}
return models.VM_UNKNOWN
@@ -428,8 +481,7 @@ func (region *SRegion) AttachDisk(instanceId, diskId string) error {
},
})
instance.Properties.ProvisioningState = ""
_, err = region.client.Update(jsonutils.Marshal(instance))
return err
return region.client.Update(jsonutils.Marshal(instance), nil)
}
func (self *SInstance) DetachDisk(diskId string) error {
@@ -460,8 +512,7 @@ func (region *SRegion) DetachDisk(instanceId, diskId string) error {
}
}
instance.Properties.ProvisioningState = ""
_, err = region.client.Update(jsonutils.Marshal(instance))
return err
return region.client.Update(jsonutils.Marshal(instance), nil)
}
func (self *SInstance) ChangeConfig(instanceId string, ncpu int, vmem int) error {
@@ -469,7 +520,7 @@ func (self *SInstance) ChangeConfig(instanceId string, ncpu int, vmem int) error
self.Properties.HardwareProfile.VMSize = vmSize
self.Properties.ProvisioningState = ""
log.Debugf("Try HardwareProfile : %s", vmSize)
_, err := self.host.zone.region.client.Update(jsonutils.Marshal(self))
err := self.host.zone.region.client.Update(jsonutils.Marshal(self), nil)
if err == nil {
return cloudprovider.WaitStatus(self, self.GetStatus(), 10*time.Second, 300*time.Second)
}
@@ -535,19 +586,17 @@ func (region *SRegion) resetPassword(instanceId, username, password string) erro
}
func (region *SRegion) DeployVM(instanceId, name, password, publicKey string, deleteKeypair bool, description string) error {
if instance, err := region.GetInstance(instanceId); err != nil {
instance, err := region.GetInstance(instanceId)
if err != nil {
return err
} else {
if deleteKeypair {
return nil
}
if len(publicKey) > 0 {
return region.resetPublicKey(instanceId, instance.Properties.OsProfile.AdminUsername, publicKey)
} else {
return region.resetPassword(instanceId, instance.Properties.OsProfile.AdminUsername, password)
}
}
if deleteKeypair {
return nil
}
if len(publicKey) > 0 {
return region.resetPublicKey(instanceId, instance.Properties.OsProfile.AdminUsername, publicKey)
}
return region.resetPassword(instanceId, instance.Properties.OsProfile.AdminUsername, password)
}
func (self *SInstance) RebuildRoot(imageId string, passwd string, publicKey string, sysSizeGB int) (string, error) {
@@ -564,7 +613,7 @@ func (region *SRegion) ReplaceSystemDisk(instanceId, imageId, passwd, publicKey
if err != nil {
return "", err
}
err = region.stopVM(instanceId)
err = region.StopVM(instanceId, true)
if err != nil {
return "", err
}
@@ -597,7 +646,7 @@ func (region *SRegion) ReplaceSystemDisk(instanceId, imageId, passwd, publicKey
}
}
instance.Properties.ProvisioningState = ""
_, err = region.client.Update(jsonutils.Marshal(instance))
err = region.client.Update(jsonutils.Marshal(instance), nil)
if err != nil {
return "", err
}
@@ -627,14 +676,6 @@ func (self *SInstance) GetGlobalId() string {
return strings.ToLower(self.ID)
}
func (self *SRegion) GetInstanceStatus(instanceId string) (string, error) {
instance, err := self.GetInstance(instanceId)
if err != nil {
return "", err
}
return instance.GetStatus(), nil
}
func (self *SRegion) DeleteVM(instanceId string) error {
return self.doDeleteVM(instanceId)
}
@@ -679,8 +720,9 @@ func (self *SInstance) fetchDisks() error {
self.idisks[i] = &disks[i]
}
for i := 0; i < len(classicDisks); i++ {
self.idisks[i] = &classicDisks[i]
self.idisks[len(disks)+i] = &classicDisks[i]
}
return nil
}
@@ -707,7 +749,6 @@ func (self *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) {
_nics[i].instance = self
nics = append(nics, &_nics[i])
}
log.Errorf("get nic count %d for %s", len(nics), self.Name)
return nics, nil
}
@@ -748,7 +789,7 @@ func (self *SInstance) GetVcpuCount() int8 {
err := self.fetchVMSize()
if err != nil {
log.Errorf("fetchVMSize error: %v", err)
return 1
return 0
}
return int8(self.vmSize.NumberOfCores)
}
@@ -757,7 +798,7 @@ func (self *SInstance) GetVmemSizeMB() int {
err := self.fetchVMSize()
if err != nil {
log.Errorf("fetchVMSize error: %v", err)
return 2048
return 0
}
return int(self.vmSize.MemoryInMB)
}
@@ -784,18 +825,15 @@ func (self *SInstance) StartVM() error {
}
func (self *SInstance) StopVM(isForce bool) error {
if err := self.host.zone.region.StopVM(self.ID, isForce); err != nil {
err := self.host.zone.region.StopVM(self.ID, isForce)
if err != nil {
return err
}
return cloudprovider.WaitStatus(self, models.VM_READY, 10*time.Second, 300*time.Second)
}
func (self *SRegion) StopVM(instanceId string, isForce bool) error {
return self.stopVM(instanceId)
}
func (self *SRegion) stopVM(instanceId string) error {
_, err := self.client.PerformAction(instanceId, "shutdown")
_, err := self.client.PerformAction(instanceId, "deallocate")
return err
}
@@ -810,13 +848,15 @@ func (self *SInstance) SyncSecurityGroup(secgroupId string, name string, rules [
return err
}
}
} else if extId, err := self.host.zone.region.syncSecurityGroup(secgroupId, name, rules); err != nil {
return nil
}
extId, err := self.host.zone.region.syncSecurityGroup(secgroupId, name, rules)
if err != nil {
return err
} else {
for _, nic := range nics {
if err := nic.assignSecurityGroup(extId); err != nil {
return err
}
}
for _, nic := range nics {
if err := nic.assignSecurityGroup(extId); err != nil {
return err
}
}
return nil
@@ -829,12 +869,14 @@ func (self *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) {
}
for _, nic := range nics {
for _, ip := range nic.Properties.IPConfigurations {
if len(ip.Properties.PublicIPAddress.ID) > 0 {
eip, err := self.host.zone.region.GetEip(ip.Properties.PublicIPAddress.ID)
if err == nil {
return eip, nil
if ip.Properties.PublicIPAddress != nil {
if len(ip.Properties.PublicIPAddress.ID) > 0 {
eip, err := self.host.zone.region.GetEip(ip.Properties.PublicIPAddress.ID)
if err == nil {
return eip, nil
}
log.Errorf("find eip for instance %s failed: %v", self.Name, err)
}
log.Errorf("find eip for instance %s failed: %v", self.Name, err)
}
}
}
+1 -2
View File
@@ -82,8 +82,7 @@ func (self *SInstanceNic) updateSecurityGroup(secgroupId string) error {
if len(secgroupId) > 0 {
self.Properties.NetworkSecurityGroup = &SSecurityGroup{ID: secgroupId}
}
_, err := region.client.Update(jsonutils.Marshal(self))
return err
return region.client.Update(jsonutils.Marshal(self), nil)
}
func (self *SInstanceNic) revokeSecurityGroup() error {
+4 -8
View File
@@ -12,12 +12,11 @@ import (
type SNetwork struct {
wire *SWire
AvailableIpAddressCount int
AvailableIpAddressCount *int `json:"availableIpAddressCount,omitempty"`
ID string
Name string
Properties SubnetPropertiesFormat
AddressPrefix string `json:"addressPrefix,omitempty"`
// Status string
}
func (self *SNetwork) GetMetadata() *jsonutils.JSONDict {
@@ -41,10 +40,7 @@ func (self *SNetwork) IsEmulated() bool {
}
func (self *SNetwork) GetStatus() string {
if strings.ToLower(self.Properties.ProvisioningState) == "succeeded" || len(self.AddressPrefix) > 0 {
return "available"
}
return "disabled"
return "available"
}
func (self *SNetwork) Delete() error {
@@ -58,8 +54,8 @@ func (self *SNetwork) Delete() error {
subnets = append(subnets, (*vpc.Properties.Subnets)[i])
}
vpc.Properties.Subnets = &subnets
_, err := self.wire.vpc.region.client.Update(jsonutils.Marshal(vpc))
return err
vpc.Properties.ProvisioningState = ""
return self.wire.vpc.region.client.Update(jsonutils.Marshal(vpc), nil)
}
return nil
}
+14 -3
View File
@@ -2,6 +2,7 @@ package azure
import (
"fmt"
"regexp"
"yunion.io/x/jsonutils"
)
@@ -26,9 +27,9 @@ func (self *SRegion) GetNetworkInterfaces() ([]SInstanceNic, error) {
return result, nil
}
func (self *SRegion) isNetworkInstanceNameAvaliable(nicName string) (bool, error) {
func (self *SRegion) isNetworkInstanceNameAvaliable(resourceGroupName, nicName string) (bool, error) {
nics := []SInstanceNic{}
err := self.client.ListByType("Microsoft.Network/networkInterfaces", &nics)
err := self.client.ListByTypeWithResourceGroup(resourceGroupName, "Microsoft.Network/networkInterfaces", &nics)
if err != nil {
return false, err
}
@@ -40,6 +41,15 @@ func (self *SRegion) isNetworkInstanceNameAvaliable(nicName string) (bool, error
return true, nil
}
func getResourceGroupNameByID(id string) string {
reg := regexp.MustCompile("/resourceGroups/(.+)/providers/")
_resourceGroup := reg.FindStringSubmatch(id)
if len(_resourceGroup) == 2 {
return _resourceGroup[1]
}
return ""
}
func (self *SRegion) CreateNetworkInterface(nicName string, ipAddr string, subnetId string, secgrpId string) (*SInstanceNic, error) {
secgroup, err := self.GetSecurityGroupDetails(secgrpId)
if err != nil {
@@ -47,9 +57,10 @@ func (self *SRegion) CreateNetworkInterface(nicName string, ipAddr string, subne
}
secgroup.Properties.ProvisioningState = ""
resourceGroupName := getResourceGroupNameByID(subnetId)
nicNameBase := nicName
for i := 0; i < 5; i++ {
ok, err := self.isNetworkInstanceNameAvaliable(nicName)
ok, err := self.isNetworkInstanceNameAvaliable(resourceGroupName, nicName)
if err != nil {
return nil, err
}
+12 -35
View File
@@ -1,7 +1,6 @@
package azure
import (
"context"
"fmt"
"yunion.io/x/jsonutils"
@@ -9,9 +8,6 @@ import (
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/util/seclib2"
"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2018-06-01/network"
"github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage"
)
type SVMSize struct {
@@ -130,25 +126,18 @@ func (self *SRegion) GetStatus() string {
}
func (self *SRegion) CreateIVpc(name string, desc string, cidr string) (cloudprovider.ICloudVpc, error) {
vpcClient := network.NewVirtualNetworksClientWithBaseURI(self.client.baseUrl, self.client.subscriptionId)
vpcClient.Authorizer = self.client.authorizer
addressPrefixes := []string{cidr}
addressSpace := network.AddressSpace{AddressPrefixes: &addressPrefixes}
properties := network.VirtualNetworkPropertiesFormat{AddressSpace: &addressSpace}
parameters := network.VirtualNetwork{Name: &name, Location: &self.Name, VirtualNetworkPropertiesFormat: &properties}
vpcId, resourceGroup, vpcName := pareResourceGroupWithName(name, VPC_RESOURCE)
self.CreateResourceGroup(resourceGroup)
if result, err := vpcClient.CreateOrUpdate(context.Background(), resourceGroup, vpcName, parameters); err != nil {
return nil, err
} else if err := result.WaitForCompletion(context.Background(), vpcClient.Client); err != nil {
return nil, err
} else if err := self.fetchInfrastructure(); err != nil {
return nil, err
} else if vpc, err := self.GetIVpcById(vpcId); err != nil {
return nil, err
} else {
return vpc, nil
vpc := SVpc{
region: self,
Name: name,
Location: self.Name,
Properties: VirtualNetworkPropertiesFormat{
AddressSpace: AddressSpace{
AddressPrefixes: []string{cidr},
},
},
Type: "Microsoft.Network/virtualNetworks",
}
return &vpc, self.client.Create(jsonutils.Marshal(vpc), &vpc)
}
func (self *SRegion) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
@@ -232,7 +221,7 @@ func (self *SRegion) getZoneById(id string) (*SZone, error) {
}
func (self *SRegion) fetchZones() error {
if self.izones == nil {
if self.izones == nil || len(self.izones) == 0 {
self.izones = make([]cloudprovider.ICloudZone, 1)
zone := SZone{region: self, Name: self.Name}
self.izones[0] = &zone
@@ -256,18 +245,6 @@ func (self *SRegion) getStoragecache() *SStoragecache {
return self.storageCache
}
func (self *SRegion) getStorage() ([]SStorage, error) {
storages := make([]SStorage, 0)
storageClient := storage.NewAccountsClientWithBaseURI(self.client.baseUrl, self.client.subscriptionId)
storageClient.Authorizer = self.client.authorizer
if storageList, err := storageClient.List(context.Background()); err != nil {
return nil, err
} else if err := jsonutils.Update(&storages, storageList.Value); err != nil {
return storages, err
}
return storages, nil
}
func (self *SRegion) getVpcs() ([]SVpc, error) {
result := []SVpc{}
vpcs := []SVpc{}
+2 -4
View File
@@ -308,8 +308,7 @@ func (region *SRegion) updateSecurityGroupRules(secgroupId string, rules []secru
}
secgroup.Properties.SecurityRules = &securityRules
secgroup.Properties.ProvisioningState = ""
_, err = region.client.Update(jsonutils.Marshal(secgroup))
return secgroup.ID, err
return secgroup.ID, region.client.Update(jsonutils.Marshal(secgroup), nil)
}
func (region *SRegion) AttachSecurityToInterfaces(secgroupId string, nicIds []string) error {
@@ -323,8 +322,7 @@ func (region *SRegion) AttachSecurityToInterfaces(secgroupId string, nicIds []st
}
secgroup.Properties.NetworkInterfaces = &interfaces
secgroup.Properties.ProvisioningState = ""
_, err = region.client.Update(jsonutils.Marshal(secgroup))
return err
return region.client.Update(jsonutils.Marshal(secgroup), nil)
}
func (region *SRegion) AssiginSecurityGroup(instanceId, secgroupId string) error {
+11 -3
View File
@@ -9,9 +9,10 @@ import (
func init() {
type InstanceListOptions struct {
Classic bool `help:"List classic instance"`
Limit int `help:"page size"`
Offset int `help:"page offset"`
Classic bool `help:"List classic instance"`
ScaleSets bool `help:"List Scale Sets instance"`
Limit int `help:"page size"`
Offset int `help:"page offset"`
}
shellutils.R(&InstanceListOptions{}, "instance-list", "List intances", func(cli *azure.SRegion, args *InstanceListOptions) error {
if args.Classic {
@@ -21,6 +22,13 @@ func init() {
}
printList(instances, len(instances), args.Offset, args.Limit, []string{})
return nil
} else if args.ScaleSets {
instances, err := cli.GetInstanceScaleSets()
if err != nil {
return err
}
printList(instances, len(instances), args.Offset, args.Limit, []string{})
return nil
}
instances, err := cli.GetInstances()
if err != nil {
+45 -12
View File
@@ -8,7 +8,9 @@ import (
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-04-01/compute"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
)
type SnapshotSku struct {
@@ -44,7 +46,13 @@ func (self *SSnapshot) GetName() string {
}
func (self *SSnapshot) GetStatus() string {
return ""
switch self.Properties.ProvisioningState {
case "Succeeded":
return models.SNAPSHOT_READY
default:
log.Errorf("Unknow azure snapshot %s status: %s", self.ID, self.Properties.ProvisioningState)
return models.SNAPSHOT_UNKNOWN
}
}
func (self *SSnapshot) IsEmulated() bool {
@@ -104,28 +112,53 @@ func (self *SRegion) GrantAccessSnapshot(snapshotId string) (string, error) {
}
func (self *SSnapshot) Refresh() error {
if snapshot, err := self.region.GetSnapshotDetail(self.ID); err != nil {
return err
} else if err := jsonutils.Update(self, snapshot); err != nil {
snapshot, err := self.region.GetSnapshotDetail(self.ID)
if err != nil {
return err
}
return nil
return jsonutils.Update(self, snapshot)
}
func (self *SRegion) GetISnapshotById(snapshotId string) (cloudprovider.ICloudSnapshot, error) {
if strings.HasPrefix(snapshotId, "https://") {
//TODO
return nil, cloudprovider.ErrNotImplemented
}
return self.GetSnapshotDetail(snapshotId)
}
func (self *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
if snapshots, err := self.GetSnapShots(""); err != nil {
snapshots, err := self.GetSnapShots("")
if err != nil {
return nil, err
} else {
isnapshots := make([]cloudprovider.ICloudSnapshot, len(snapshots))
for i := 0; i < len(snapshots); i++ {
isnapshots[i] = &snapshots[i]
}
return isnapshots, nil
}
classicSnapshots := []SClassicSnapshot{}
storages, err := self.GetStorageAccounts()
if err != nil {
return nil, err
}
_, _classicSnapshots, err := self.GetStorageAccountsDisksWithSnapshots(storages...)
if err != nil {
return nil, err
}
classicSnapshots = append(classicSnapshots, _classicSnapshots...)
classicStorages, err := self.GetClassicStorageAccounts()
if err != nil {
return nil, err
}
_, _classicSnapshots, err = self.GetStorageAccountsDisksWithSnapshots(classicStorages...)
if err != nil {
return nil, err
}
classicSnapshots = append(classicSnapshots, _classicSnapshots...)
isnapshots := make([]cloudprovider.ICloudSnapshot, len(snapshots)+len(classicSnapshots))
for i := 0; i < len(snapshots); i++ {
isnapshots[i] = &snapshots[i]
}
for i := 0; i < len(classicSnapshots); i++ {
isnapshots[len(snapshots)+i] = &classicSnapshots[i]
}
return isnapshots, nil
}
func (self *SSnapshot) GetDiskId() string {
+32 -13
View File
@@ -86,24 +86,43 @@ func (self *SStorage) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
idisks := make([]cloudprovider.ICloudDisk, 0)
for i := 0; i < len(disks); i++ {
storageType := strings.ToLower(string(disks[i].Sku.Name))
if storageType == self.storageType {
if storageType == strings.ToLower(self.storageType) {
disks[i].storage = self
idisks = append(idisks, &disks[i])
log.Debugf("find disk %s for storage %s", disks[i].GetName(), self.GetName())
}
}
// classicDisks, err := self.zone.region.GetClassicDisks()
// if err != nil {
// return nil, err
// }
// for i := 0; i < len(classicDisks); i++ {
// storageType := strings.ToLower(string(classicDisks[i].storage.storageType))
// if storageType == self.storageType {
// disks[i].storage = self
// idisks = append(idisks, &disks[i])
// log.Debugf("find disk %s for storage %s", disks[i].GetName(), self.GetName())
// }
// }
storageaccounts, err := self.zone.region.GetStorageAccounts()
if err != nil {
log.Errorf("List storage account for get idisks error: %v", err)
return nil, err
}
for i := 0; i < len(storageaccounts); i++ {
storageType := strings.ToLower(storageaccounts[i].Sku.Name)
if strings.ToLower(self.storageType) != storageType {
continue
}
disks, _, err := self.zone.region.GetStorageAccountDisksWithSnapshots(storageaccounts[i])
if err != nil {
return nil, err
}
for i := 0; i < len(disks); i++ {
disk := SDisk{
storage: self,
Sku: DiskSku{
Name: storageaccounts[i].Sku.Name,
Tier: storageaccounts[i].Sku.Tier,
},
Properties: DiskProperties{
DiskSizeGB: disks[i].DiskSizeGB,
OsType: disks[i].diskType,
},
ID: disks[i].VhdUri,
Name: disks[i].DiskName,
}
idisks = append(idisks, &disk)
}
}
return idisks, nil
}
+121 -23
View File
@@ -3,10 +3,13 @@ package azure
import (
"fmt"
"math/rand"
"path"
"strings"
"time"
"github.com/Azure/azure-sdk-for-go/storage"
"github.com/Microsoft/azure-vhd-utils/vhdcore/common"
"github.com/Microsoft/azure-vhd-utils/vhdcore/diskstream"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
@@ -24,19 +27,19 @@ type Identity struct {
Type string
}
type PrimaryEndpoints struct {
Blob string
Queue string
Table string
File string
}
type AccountProperties struct {
//classic
ClassicStorageProperties
// Status string
// Endpoints []string
// AccountType string
// GeoPrimaryRegion string
// StatusOfPrimaryRegion string
// GeoSecondaryRegion string
// StatusOfSecondaryRegion string
// CreationTime time.Time
//normal
PrimaryEndpoints PrimaryEndpoints `json:"primaryEndpoints,omitempty"`
ProvisioningState string
PrimaryLocation string
SecondaryLocation string
@@ -63,17 +66,15 @@ type SStorageAccount struct {
func (self *SRegion) GetStorageAccounts() ([]SStorageAccount, error) {
result := []SStorageAccount{}
for _, resourceType := range []string{"Microsoft.ClassicStorage/storageAccounts", "Microsoft.Storage/storageAccounts"} {
accounts := []SStorageAccount{}
err := self.client.ListAll(resourceType, &accounts)
if err != nil {
return nil, err
}
for i := 0; i < len(accounts); i++ {
if accounts[i].Location == self.Name {
accounts[i].region = self
result = append(result, accounts[i])
}
accounts := []SStorageAccount{}
err := self.client.ListAll("Microsoft.Storage/storageAccounts", &accounts)
if err != nil {
return nil, err
}
for i := 0; i < len(accounts); i++ {
if accounts[i].Location == self.Name {
accounts[i].region = self
result = append(result, accounts[i])
}
}
return result, nil
@@ -207,6 +208,9 @@ func (self *SStorageAccount) GetAccountKey() (accountKey string, err error) {
}
func (self *SStorageAccount) GetBlobBaseUrl() string {
if self.Type == "Microsoft.Storage/storageAccounts" {
return self.Properties.PrimaryEndpoints.Blob
}
for _, url := range self.Properties.Endpoints {
if strings.Contains(url, ".blob.") {
return url
@@ -215,6 +219,25 @@ func (self *SStorageAccount) GetBlobBaseUrl() string {
return ""
}
func (self *SStorageAccount) CreateContainer(containerName string) (*SContainer, error) {
accessKey, err := self.GetAccountKey()
if err != nil {
return nil, err
}
client, err := storage.NewBasicClientOnSovereignCloud(self.Name, accessKey, self.region.client.env)
if err != nil {
return nil, err
}
container := SContainer{storageaccount: self}
blobService := client.GetBlobService()
containerRef := blobService.GetContainerReference(containerName)
err = containerRef.Create(&storage.CreateContainerOptions{})
if err != nil {
return nil, err
}
return &container, jsonutils.Update(&container, containerRef)
}
func (self *SStorageAccount) GetContainers() ([]SContainer, error) {
accessKey, err := self.GetAccountKey()
if err != nil {
@@ -270,17 +293,92 @@ type SContainerFile struct {
Metadata map[string]string
}
func (self *SContainer) ListFiles() ([]SContainerFile, error) {
files := []SContainerFile{}
func (self *SContainer) ListFiles() ([]storage.Blob, error) {
storageaccount := self.storageaccount
client, err := storage.NewBasicClientOnSovereignCloud(storageaccount.Name, storageaccount.accountKey, storageaccount.region.client.env)
if err != nil {
return nil, err
}
blobService := client.GetBlobService()
result, err := blobService.GetContainerReference(self.Name).ListBlobs(storage.ListBlobsParameters{})
result, err := blobService.GetContainerReference(self.Name).ListBlobs(storage.ListBlobsParameters{Include: &storage.IncludeBlobDataset{Snapshots: true, Metadata: true}})
if err != nil {
return nil, err
}
return files, jsonutils.Update(&files, result.Blobs)
return result.Blobs, nil
}
func (self *SContainer) UploadFile(filePath string) (string, error) {
storageaccount := self.storageaccount
client, err := storage.NewBasicClientOnSovereignCloud(storageaccount.Name, storageaccount.accountKey, storageaccount.region.client.env)
if err != nil {
return "", err
}
blobService := client.GetBlobService()
containerRef := blobService.GetContainerReference(self.Name)
err = ensureVHDSanity(filePath)
if err != nil {
return "", err
}
diskStream, err := diskstream.CreateNewDiskStream(filePath)
if err != nil {
return "", err
}
defer diskStream.Close()
blobName := path.Base(filePath)
blobRef := containerRef.GetBlobReference(blobName)
blobRef.Properties.ContentLength = diskStream.GetSize()
err = blobRef.PutPageBlob(&storage.PutBlobOptions{})
if err != nil {
return "", err
}
var rangesToSkip []*common.IndexRange
uploadableRanges, err := LocateUploadableRanges(diskStream, rangesToSkip, DefaultReadBlockSize)
if err != nil {
return "", err
}
uploadableRanges, err = DetectEmptyRanges(diskStream, uploadableRanges)
if err != nil {
return "", err
}
cxt := &DiskUploadContext{
VhdStream: diskStream,
UploadableRanges: uploadableRanges,
AlreadyProcessedBytes: common.TotalRangeLength(rangesToSkip),
BlobServiceClient: blobService,
ContainerName: self.Name,
BlobName: blobName,
Parallelism: 3,
Resume: false,
MD5Hash: []byte(""), //localMetaData.FileMetaData.MD5Hash,
}
if err := Upload(cxt); err != nil {
return "", err
}
return blobRef.GetURL(), nil
}
func (self *SStorageAccount) UploadFile(containerName string, filePath string) (string, error) {
containers, err := self.GetContainers()
if err != nil {
return "", err
}
container := &SContainer{}
find := false
for i := 0; i < len(containers); i++ {
if containers[i].Name == containerName {
container = &containers[i]
find = true
break
}
}
if !find {
container, err = self.CreateContainer(containerName)
if err != nil {
return "", err
}
}
return container.UploadFile(filePath)
}
+35 -12
View File
@@ -100,9 +100,40 @@ func (self *SStoragecache) UploadImage(userCred mcclient.TokenCredential, imageI
return self.uploadImage(userCred, imageId, osArch, osType, osDist, isForce)
}
func (self *SStoragecache) checkStorageAccount() (*SStorageAccount, error) {
storageaccount := &SStorageAccount{}
storageaccounts, err := self.region.GetStorageAccounts()
if err != nil {
return nil, err
}
if len(storageaccounts) == 0 {
storageaccount, err = self.region.CreateStorageAccount(self.region.Name)
if err != nil {
return nil, err
}
} else {
for i := 0; i < len(storageaccounts); i++ {
if id, ok := storageaccounts[i].Tags["id"]; ok && id == self.region.Name {
storageaccount = &storageaccounts[i]
break
}
}
if id, ok := storageaccount.Tags["id"]; !ok || id == self.region.Name {
if storageaccount.Tags == nil {
storageaccount.Tags = map[string]string{}
}
storageaccount.Tags["id"] = self.region.Name
err = self.region.client.Update(jsonutils.Marshal(storageaccount), nil)
if err != nil {
return nil, err
}
}
}
return storageaccount, nil
}
func (self *SStoragecache) uploadImage(userCred mcclient.TokenCredential, imageId string, osArch, osType, osDist string, isForce bool) (string, error) {
s := auth.GetAdminSession(options.Options.Region, "")
if meta, reader, err := modules.Images.Download(s, imageId); err != nil {
return "", err
} else {
@@ -123,27 +154,19 @@ func (self *SStoragecache) uploadImage(userCred mcclient.TokenCredential, imageI
if _, err := io.Copy(f, reader); err != nil {
return "", err
}
storageAccount := fmt.Sprintf("%s%s", self.region.Name, DefaultStorageAccount)
log.Debugf("Create storageAccount: %s", storageAccount)
storage, err := self.region.CreateStorageAccount(storageAccount)
storageaccount, err := self.checkStorageAccount()
if err != nil {
return "", err
}
log.Debugf("Create Container: %s", DefaultContainer)
if _, err := self.region.CreateContainer(storage, DefaultContainer); err != nil {
blobURI, err := storageaccount.UploadFile("image-cache", tmpFile)
if err != nil {
return "", err
}
size, _ := meta.Int("size")
blobURI, err := self.region.UploadVHD(storage, DefaultContainer, tmpFile)
if err != nil {
log.Errorf("uploadContainerFileByPath error: %v", err)
return "", err
}
imageBaseName := imageId
if imageBaseName[0] >= '0' && imageBaseName[0] <= '9' {
imageBaseName = fmt.Sprintf("img%s", imageId)
+12 -13
View File
@@ -9,12 +9,12 @@ import (
)
type AddressSpace struct {
AddressPrefixes []string
AddressPrefixes []string `json:"addressPrefixes,omitempty"`
}
type SubnetPropertiesFormat struct {
AddressPrefix string
ProvisioningState string
AddressPrefix string `json:"addressPrefix,omitempty"`
//ProvisioningState string
}
type Subnet struct {
@@ -27,9 +27,8 @@ type VirtualNetworkPropertiesFormat struct {
ProvisioningState string
Status string
VirtualNetworkSiteName string
InUse bool
AddressSpace AddressSpace
Subnets *[]SNetwork
AddressSpace AddressSpace `json:"addressSpace,omitempty"`
Subnets *[]SNetwork `json:"subnets,omitempty"`
}
type SVpc struct {
@@ -38,7 +37,7 @@ type SVpc struct {
iwires []cloudprovider.ICloudWire
secgroups []cloudprovider.ICloudSecurityGroup
IsDefault bool
isDefault bool
ID string
Name string
@@ -46,7 +45,7 @@ type SVpc struct {
Type string
Location string
Tags map[string]string
Properties VirtualNetworkPropertiesFormat
Properties VirtualNetworkPropertiesFormat `json:"properties,omitempty"`
}
func (self *SVpc) GetMetadata() *jsonutils.JSONDict {
@@ -58,10 +57,7 @@ func (self *SVpc) GetId() string {
}
func (self *SVpc) GetName() string {
if len(self.Name) > 0 {
return self.Name
}
return self.ID
return self.Name
}
func (self *SVpc) GetGlobalId() string {
@@ -73,7 +69,7 @@ func (self *SVpc) IsEmulated() bool {
}
func (self *SVpc) GetIsDefault() bool {
return self.IsDefault
return self.isDefault
}
func (self *SVpc) GetCidrBlock() string {
@@ -150,6 +146,9 @@ func (self *SVpc) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGroup, err
func (self *SVpc) fetchWires() error {
networks := make([]cloudprovider.ICloudNetwork, len(*self.Properties.Subnets))
if len(self.region.izones) == 0 {
self.region.fetchZones()
}
wire := SWire{zone: self.region.izones[0].(*SZone), vpc: self, inetworks: networks}
for i, _network := range *self.Properties.Subnets {
network := SNetwork{wire: &wire}
+15 -6
View File
@@ -72,17 +72,26 @@ func (self *SRegion) createNetwork(vpc *SVpc, subnetName string, cidr string, de
} else {
*vpc.Properties.Subnets = append(*vpc.Properties.Subnets, subnet)
}
_, err := self.client.Update(jsonutils.Marshal(vpc))
return &subnet, err
vpc.Properties.ProvisioningState = ""
err := self.client.Update(jsonutils.Marshal(vpc), vpc)
if err != nil {
return nil, err
}
for i := 0; i < len(*vpc.Properties.Subnets); i++ {
if (*vpc.Properties.Subnets)[i].Name == subnetName {
subnet.ID = (*vpc.Properties.Subnets)[i].ID
}
}
return &subnet, nil
}
func (self *SWire) CreateINetwork(name string, cidr string, desc string) (cloudprovider.ICloudNetwork, error) {
if network, err := self.zone.region.createNetwork(self.vpc, name, cidr, desc); err != nil {
network, err := self.zone.region.createNetwork(self.vpc, name, cidr, desc)
if err != nil {
return nil, err
} else {
network.wire = self
return network, nil
}
network.wire = self
return network, nil
}
func (self *SWire) GetBandwidth() int {
+53 -28
View File
@@ -12,14 +12,16 @@ import (
type SZone struct {
region *SRegion
iwires []cloudprovider.ICloudWire
iclassicWires []cloudprovider.ICloudWire
istorages []cloudprovider.ICloudStorage
iwires []cloudprovider.ICloudWire
iclassicWires []cloudprovider.ICloudWire
istorages []cloudprovider.ICloudStorage
iclassicStorages []cloudprovider.ICloudStorage
storageTypes []string
Name string
host *SHost
classicHost *SClassicHost
storageTypes []string
classicStorageTypes []string
Name string
host *SHost
classicHost *SClassicHost
}
func (self *SZone) GetMetadata() *jsonutils.JSONDict {
@@ -101,21 +103,12 @@ func (self *SZone) GetIRegion() cloudprovider.ICloudRegion {
return self.region
}
func (self *SZone) fetchStorages() error {
if len(self.storageTypes) == 0 {
if err := self.getStorageTypes(); err != nil {
return err
}
}
self.istorages = make([]cloudprovider.ICloudStorage, len(self.storageTypes))
for i, storageType := range self.storageTypes {
storage := SStorage{zone: self, storageType: storageType}
self.istorages[i] = &storage
}
func (self *SZone) fetchClassicStorages() error {
storageaccounts, err := self.region.GetClassicStorageAccounts()
if err != nil {
return err
}
self.iclassicStorages = make([]cloudprovider.ICloudStorage, len(storageaccounts))
for i := 0; i < len(storageaccounts); i++ {
storage := SClassicStorage{
zone: self,
@@ -125,16 +118,34 @@ func (self *SZone) fetchStorages() error {
Location: storageaccounts[i].Location,
Properties: storageaccounts[i].Properties.ClassicStorageProperties,
}
self.istorages = append(self.istorages, &storage)
self.iclassicStorages[i] = &storage
}
return nil
}
func (self *SZone) fetchStorages() error {
if len(self.storageTypes) == 0 {
err := self.getStorageTypes()
if err != nil {
return err
}
}
self.istorages = make([]cloudprovider.ICloudStorage, len(self.storageTypes))
for i, storageType := range self.storageTypes {
storage := SStorage{zone: self, storageType: storageType}
self.istorages[i] = &storage
}
return nil
}
func (self *SZone) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
if err := self.fetchStorages(); err != nil {
err := self.fetchStorages()
if err != nil {
return nil, err
}
return self.istorages, nil
self.fetchClassicStorages()
istorages := append(self.istorages, self.iclassicStorages...)
return istorages, nil
}
func (self *SZone) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
@@ -150,14 +161,28 @@ func (self *SZone) GetIStorageById(id string) (cloudprovider.ICloudStorage, erro
}
func (self *SZone) getStorageByType(storageType string) (*SStorage, error) {
if storages, err := self.GetIStorages(); err != nil {
_, err := self.GetIStorages()
if err != nil {
return nil, err
} else {
for i := 0; i < len(storages); i += 1 {
_storage := storages[i].(*SStorage)
if strings.ToLower(_storage.storageType) == strings.ToLower(storageType) {
return _storage, nil
}
}
for i := 0; i < len(self.istorages); i += 1 {
storage := self.istorages[i].(*SStorage)
if strings.ToLower(storage.storageType) == strings.ToLower(storageType) {
return storage, nil
}
}
return nil, cloudprovider.ErrNotFound
}
func (self *SZone) getClassicStorageByType(storageType string) (*SClassicStorage, error) {
_, err := self.GetIStorages()
if err != nil {
return nil, err
}
for i := 0; i < len(self.iclassicStorages); i += 1 {
storage := self.iclassicStorages[i].(*SClassicStorage)
if strings.ToLower(storage.Properties.AccountType) == strings.ToLower(storageType) {
return storage, nil
}
}
return nil, cloudprovider.ErrNotFound