mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-21 14:19:49 +08:00
减少API调用次数
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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
@@ -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])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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{}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user