diff --git a/pkg/cloudprovider/instance.go b/pkg/cloudprovider/instance.go index 6532a9c9ed..f43b6619a4 100644 --- a/pkg/cloudprovider/instance.go +++ b/pkg/cloudprovider/instance.go @@ -62,6 +62,8 @@ type SManagedVMCreateConfig struct { Account string Password string UserData string + ProjectId string + ProjectName string BillingCycle *billing.SBillingCycle } diff --git a/pkg/compute/guestdrivers/managedvirtual.go b/pkg/compute/guestdrivers/managedvirtual.go index 630d4eb2a8..3b8d5333a8 100644 --- a/pkg/compute/guestdrivers/managedvirtual.go +++ b/pkg/compute/guestdrivers/managedvirtual.go @@ -73,6 +73,23 @@ func (self *SManagedVirtualizedGuestDriver) GetJsonDescAtHost(ctx context.Contex config.IpAddr = nics[0].IpAddr } + provider := host.GetCloudprovider() + projects, _ := provider.GetExternalProjects() + if projects != nil && len(projects) > 0 { + for _, project := range projects { + config.ProjectId = project.ExternalId + config.ProjectName = project.Name + if project.ProjectId == guest.ProjectId { + break + } + } + } else { + project, _ := db.TenantCacheManager.FetchById(guest.ProjectId) + if project != nil { + config.ProjectName = project.GetName() + } + } + disks := guest.GetDisks() config.DataDisks = []cloudprovider.SDiskInfo{} diff --git a/pkg/compute/models/cloudproviders.go b/pkg/compute/models/cloudproviders.go index ee04aaa6cd..95c0bd6ad2 100644 --- a/pkg/compute/models/cloudproviders.go +++ b/pkg/compute/models/cloudproviders.go @@ -1597,3 +1597,13 @@ func (provider *SCloudprovider) GetChangeOwnerCandidateDomainIds() []string { } return []string{} } + +func (self *SCloudprovider) GetExternalProjects() ([]SExternalProject, error) { + q := ExternalProjectManager.Query().Equals("manager_id", self.Id) + projects := []SExternalProject{} + err := db.FetchModelObjects(ExternalProjectManager, q, &projects) + if err != nil { + return nil, errors.Wrap(err, "FetchModelObjects") + } + return projects, nil +} diff --git a/pkg/multicloud/azure/azure.go b/pkg/multicloud/azure/azure.go index ca7670e3a3..373d5ea4dc 100644 --- a/pkg/multicloud/azure/azure.go +++ b/pkg/multicloud/azure/azure.go @@ -49,10 +49,11 @@ type SAzureClient struct { domain string baseUrl string - ressourceGroups []SResourceGroup - fetchResourceGroups bool - env azureenv.Environment - authorizer autorest.Authorizer + ressourceGroups []SResourceGroup + currentResourceGroup string + fetchResourceGroups bool + env azureenv.Environment + authorizer autorest.Authorizer iregions []cloudprovider.ICloudRegion iBuckets []cloudprovider.ICloudBucket @@ -388,6 +389,27 @@ func (self *SAzureClient) PerformAction(resourceId string, action string, body s return jsonRequest(cli, "POST", self.domain, url, self.subscriptionId, body) } +func (self *SAzureClient) createAndSetResourceGroup(resourceGroup, location string) error { + cli, err := self.getDefaultClient() + if err != nil { + return errors.Wrap(err, "getDefaultClient") + } + //Create Default resourceGroup + _url := fmt.Sprintf("/subscriptions/%s/resourcegroups/%s", self.subscriptionId, resourceGroup) + body, err := jsonRequest(cli, "PUT", self.domain, _url, self.subscriptionId, fmt.Sprintf(`{"name": "%s", "location": "%s"}`, resourceGroup, location)) + if err != nil { + return err + } + group := SResourceGroup{} + err = body.Unmarshal(&resourceGroup) + if err != nil { + return err + } + self.ressourceGroups = []SResourceGroup{group} + self.currentResourceGroup = resourceGroup + return nil +} + func (self *SAzureClient) fetchResourceGroup(cli *autorest.Client, location string) error { if !self.fetchResourceGroups { err := self.List("resourcegroups", &self.ressourceGroups) @@ -398,18 +420,9 @@ func (self *SAzureClient) fetchResourceGroup(cli *autorest.Client, location stri 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, self.subscriptionId, fmt.Sprintf(`{"name": "Default", "location": "%s"}`, location)) - if err != nil { - return err - } - resourceGroup := SResourceGroup{} - err = body.Unmarshal(&resourceGroup) - if err != nil { - return err - } - self.ressourceGroups = []SResourceGroup{resourceGroup} + return self.createAndSetResourceGroup("Default", location) + } else { + self.currentResourceGroup = self.ressourceGroups[0].Name } return nil } @@ -464,6 +477,26 @@ func (self *SAzureClient) getUniqName(cli *autorest.Client, resourceType, name s return "", "", fmt.Errorf("not find uniq name for %s[%s]", resourceType, name) } +func (self *SAzureClient) CreateAndSetResourceGroup(resourceGroup, location string) error { + cli, err := self.getDefaultClient() + if err != nil { + return errors.Wrap(err, "getDefaultClient") + } + if !self.fetchResourceGroups { + err := self.fetchResourceGroup(cli, location) + if err != nil { + return errors.Wrap(err, "fetchResourceGroup") + } + } + for _, group := range self.ressourceGroups { + if group.Name == resourceGroup { + self.currentResourceGroup = resourceGroup + return nil + } + } + return self.createAndSetResourceGroup(resourceGroup, location) +} + func (self *SAzureClient) Create(body jsonutils.JSONObject, retVal interface{}) error { cli, err := self.getDefaultClient() if err != nil { diff --git a/pkg/multicloud/azure/host.go b/pkg/multicloud/azure/host.go index ad8bf8cef0..c3989f35dc 100644 --- a/pkg/multicloud/azure/host.go +++ b/pkg/multicloud/azure/host.go @@ -146,6 +146,9 @@ func (self *SHost) _createVM(desc *cloudprovider.SManagedVMCreateConfig, nicId s if len(computeName) > 15 { computeName = computeName[:15] } + if len(desc.ProjectName) > 0 { + self.zone.region.CreateAndSetResourceGroup(desc.ProjectName) + } instance := SInstance{ Name: desc.Name, Location: self.zone.region.Name, diff --git a/pkg/multicloud/azure/region.go b/pkg/multicloud/azure/region.go index eec9752dbd..29f8a0bd79 100644 --- a/pkg/multicloud/azure/region.go +++ b/pkg/multicloud/azure/region.go @@ -689,3 +689,7 @@ func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket func (region *SRegion) GetCapabilities() []string { return region.client.GetCapabilities() } + +func (region *SRegion) CreateAndSetResourceGroup(resourceGroup string) error { + return region.client.CreateAndSetResourceGroup(resourceGroup, region.Name) +}