From 4098440c8f9c7319af2eebbdfa00bd03bcb6abf7 Mon Sep 17 00:00:00 2001 From: Zexi Li Date: Wed, 21 Nov 2018 17:49:36 +0800 Subject: [PATCH 01/19] climc: make k8s repo sharable --- cmd/climc/shell/k8s/repos.go | 18 ++++++++++++++++++ pkg/mcclient/options/k8s/repo.go | 6 +++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/cmd/climc/shell/k8s/repos.go b/cmd/climc/shell/k8s/repos.go index 5744130ccb..d61e07045b 100644 --- a/cmd/climc/shell/k8s/repos.go +++ b/cmd/climc/shell/k8s/repos.go @@ -67,4 +67,22 @@ func initRepo() { printObject(repo) return nil }) + + R(&o.RepoGetOptions{}, cmdN("public"), "Make repository public", func(s *mcclient.ClientSession, args *o.RepoGetOptions) error { + repo, err := k8s.Repos.PerformAction(s, args.NAME, "public", nil) + if err != nil { + return err + } + printObject(repo) + return nil + }) + + R(&o.RepoGetOptions{}, cmdN("private"), "Make repository private", func(s *mcclient.ClientSession, args *o.RepoGetOptions) error { + repo, err := k8s.Repos.PerformAction(s, args.NAME, "private", nil) + if err != nil { + return err + } + printObject(repo) + return nil + }) } diff --git a/pkg/mcclient/options/k8s/repo.go b/pkg/mcclient/options/k8s/repo.go index 5c42277134..52d0b890ec 100644 --- a/pkg/mcclient/options/k8s/repo.go +++ b/pkg/mcclient/options/k8s/repo.go @@ -16,13 +16,17 @@ type RepoGetOptions struct { type RepoCreateOptions struct { RepoGetOptions - URL string `help:"Repository url"` + URL string `help:"Repository url"` + Public bool `help:"Make repostitory public"` } func (o RepoCreateOptions) Params() *jsonutils.JSONDict { params := jsonutils.NewDict() params.Add(jsonutils.NewString(o.NAME), "name") params.Add(jsonutils.NewString(o.URL), "url") + if o.Public { + params.Add(jsonutils.JSONTrue, "is_public") + } return params } From 2ed294eaa83dba6a19e92ed341030963614359b2 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Thu, 22 Nov 2018 12:02:21 +0800 Subject: [PATCH 02/19] =?UTF-8?q?RBAC=E8=BF=94=E5=9B=9E=E5=80=BC=E5=90=8C?= =?UTF-8?q?=E6=97=B6=E6=90=BA=E5=B8=A6=E8=B5=84=E6=BA=90=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/cloudcommon/policy/policy.go | 36 +++++++++++++++++++------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/pkg/cloudcommon/policy/policy.go b/pkg/cloudcommon/policy/policy.go index 56418e3550..d4a61ff041 100644 --- a/pkg/cloudcommon/policy/policy.go +++ b/pkg/cloudcommon/policy/policy.go @@ -203,20 +203,10 @@ func (manager *SPolicyManager) Allow(isAdmin bool, userCred mcclient.TokenCreden return currentPriv } -func (manager *SPolicyManager) explainPolicy(userCred mcclient.TokenCredential, policyReq jsonutils.JSONObject) (rbacutils.TRbacResult, error) { +func (manager *SPolicyManager) explainPolicy(userCred mcclient.TokenCredential, policyReq jsonutils.JSONObject) ([]string, rbacutils.TRbacResult, error) { policySeq, err := policyReq.GetArray() if err != nil { - return rbacutils.Deny, httperrors.NewInputParameterError("invalid format") - } - isAdmin, _ := policySeq[0].Bool() - if !consts.IsRbacEnabled() { - if !isAdmin { - return rbacutils.OwnerAllow, nil - } else if isAdmin && userCred.IsSystemAdmin() { - return rbacutils.AdminAllow, nil - } else { - return rbacutils.Deny, httperrors.NewForbiddenError("operation not allowed") - } + return nil, rbacutils.Deny, httperrors.NewInputParameterError("invalid format") } service := rbacutils.WILD_MATCH resource := rbacutils.WILD_MATCH @@ -238,7 +228,22 @@ func (manager *SPolicyManager) explainPolicy(userCred mcclient.TokenCredential, } } - return manager.Allow(isAdmin, userCred, service, resource, action, extra...), nil + reqStrs := []string{service, resource, action} + if len(extra) > 0 { + reqStrs = append(reqStrs, extra...) + } + + isAdmin, _ := policySeq[0].Bool() + if !consts.IsRbacEnabled() { + if !isAdmin { + return reqStrs, rbacutils.OwnerAllow, nil + } else if isAdmin && userCred.IsSystemAdmin() { + return reqStrs, rbacutils.AdminAllow, nil + } else { + return reqStrs, rbacutils.Deny, httperrors.NewForbiddenError("operation not allowed") + } + } + return reqStrs, manager.Allow(isAdmin, userCred, service, resource, action, extra...), nil } func (manager *SPolicyManager) ExplainRpc(userCred mcclient.TokenCredential, params jsonutils.JSONObject) (jsonutils.JSONObject, error) { @@ -248,11 +253,12 @@ func (manager *SPolicyManager) ExplainRpc(userCred mcclient.TokenCredential, par } ret := jsonutils.NewDict() for key, policyReq := range paramDict { - result, err := manager.explainPolicy(userCred, policyReq) + reqStrs, result, err := manager.explainPolicy(userCred, policyReq) if err != nil { return nil, err } - ret.Add(jsonutils.NewString(string(result)), key) + reqStrs = append(reqStrs, string(result)) + ret.Add(jsonutils.NewStringArray(reqStrs), key) } return ret, nil } From 78cede69e5d0b9339c853a6cb70272ed6845cbfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B1=88=E8=BD=A9?= Date: Thu, 22 Nov 2018 20:23:00 +0800 Subject: [PATCH 03/19] =?UTF-8?q?=E8=A1=A5=E5=85=85Azure=20disk=20metadata?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/util/azure/classic_disk.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/util/azure/classic_disk.go b/pkg/util/azure/classic_disk.go index 8946493c8e..dd11cf71b7 100644 --- a/pkg/util/azure/classic_disk.go +++ b/pkg/util/azure/classic_disk.go @@ -101,7 +101,9 @@ func (self *SRegion) GetClassicDisks() ([]SClassicDisk, error) { } func (self *SClassicDisk) GetMetadata() *jsonutils.JSONDict { - return nil + data := jsonutils.NewDict() + data.Add(jsonutils.NewString(models.HYPERVISOR_AZURE), "hypervisor") + return data } func (self *SClassicDisk) CreateISnapshot(name, desc string) (cloudprovider.ICloudSnapshot, error) { From e6d68a947c1ea62a1aea4bc1d436dcf892236514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B1=88=E8=BD=A9?= Date: Thu, 22 Nov 2018 20:56:42 +0800 Subject: [PATCH 04/19] =?UTF-8?q?=E5=85=BC=E5=AE=B9=E4=BB=8E2.3.0=E9=99=8D?= =?UTF-8?q?=E7=BA=A7=E5=88=B02.2.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/compute/models/cloudaccounts.go | 23 +++++++++++---- pkg/compute/models/cloudproviders.go | 43 +++++++++------------------- pkg/util/azure/azure.go | 3 +- 3 files changed, 33 insertions(+), 36 deletions(-) diff --git a/pkg/compute/models/cloudaccounts.go b/pkg/compute/models/cloudaccounts.go index 32b4762ff5..8dea136422 100644 --- a/pkg/compute/models/cloudaccounts.go +++ b/pkg/compute/models/cloudaccounts.go @@ -230,6 +230,9 @@ func (self *SCloudaccount) PerformUpdateCredential(ctx context.Context, userCred changed := false secret, _ := data.GetString("secret") account, _ := data.GetString("account") + if len(account) > 0 && self.Provider == CLOUD_PROVIDER_AZURE { + return nil, httperrors.NewInputParameterError("not allow update azure tenant info") + } accessUrl, _ := data.GetString("access_url") if len(secret) > 0 || len(account) > 0 || len(accessUrl) > 0 { // check duplication @@ -276,6 +279,11 @@ func (self *SCloudaccount) PerformUpdateCredential(ctx context.Context, userCred if err != nil { return nil, err } + + for _, provider := range self.GetCloudproviders() { + provider.savePassword(secret) + } + changed = true } @@ -385,6 +393,7 @@ func (self *SCloudaccount) ImportSubAccount(ctx context.Context, userCred mcclie newCloudprovider.Account = subAccount.Account newCloudprovider.CloudaccountId = self.Id newCloudprovider.Provider = self.Provider + newCloudprovider.AccessUrl = self.AccessUrl newCloudprovider.Enabled = true newCloudprovider.Status = CLOUD_PROVIDER_CONNECTED newCloudprovider.Name = subAccount.Name @@ -400,6 +409,13 @@ func (self *SCloudaccount) ImportSubAccount(ctx context.Context, userCred mcclie return nil, isNew, err } + passwd, err := self.getPassword() + if err != nil { + return nil, isNew, err + } + + newCloudprovider.savePassword(passwd) + if autoCreateProject { err = newCloudprovider.syncProject(ctx) if err != nil { @@ -492,12 +508,12 @@ func (self *SCloudaccount) GetExtraDetails(ctx context.Context, userCred mcclien } func migrateCloudprovider(cloudprovider *SCloudprovider) error { - mainAccount, providerAccount, providerName := cloudprovider.Account, cloudprovider.Account, cloudprovider.Name + mainAccount, providerName := cloudprovider.Account, cloudprovider.Name if cloudprovider.Provider == CLOUD_PROVIDER_AZURE { accountInfo := strings.Split(cloudprovider.Account, "/") if len(accountInfo) == 2 { - mainAccount, providerAccount = accountInfo[0], accountInfo[1] + mainAccount = accountInfo[0] if len(cloudprovider.Description) > 0 { providerName = cloudprovider.Description } @@ -549,9 +565,6 @@ func migrateCloudprovider(cloudprovider *SCloudprovider) error { _, err = CloudproviderManager.TableSpec().Update(cloudprovider, func() error { cloudprovider.CloudaccountId = account.Id - cloudprovider.Account = providerAccount - cloudprovider.Secret = "" - cloudprovider.Name = providerName return nil }) if err != nil { diff --git a/pkg/compute/models/cloudproviders.go b/pkg/compute/models/cloudproviders.go index 5b25fb1cbb..c40905d109 100644 --- a/pkg/compute/models/cloudproviders.go +++ b/pkg/compute/models/cloudproviders.go @@ -378,47 +378,30 @@ func (self *SCloudprovider) GetDriver() (cloudprovider.ICloudProvider, error) { return nil, fmt.Errorf("Cloud provider is not enabled") } - account, err := self.getAccount() + passwd, err := self.getPassword() if err != nil { return nil, err } - return cloudprovider.GetProvider(self.Id, self.Name, account.AccessUrl, account.Account, account.Secret, self.Provider) + return cloudprovider.GetProvider(self.Id, self.Name, self.AccessUrl, self.Account, passwd, self.Provider) } -type SAccount struct { - AccessUrl string - Account string - Secret string +func (self *SCloudprovider) savePassword(secret string) error { + sec, err := utils.EncryptAESBase64(self.Id, secret) + if err != nil { + return err + } + + _, err = self.GetModelManager().TableSpec().Update(self, func() error { + self.Secret = sec + return nil + }) + return err } func (self *SCloudprovider) GetCloudaccount() *SCloudaccount { return CloudaccountManager.FetchCloudaccountById(self.CloudaccountId) } -func (self *SCloudprovider) getAccount() (SAccount, error) { - account := SAccount{} - - cloudaccount := self.GetCloudaccount() - if cloudaccount == nil { - return account, fmt.Errorf("fail to find cloudaccount???") - } - - passwd, err := cloudaccount.getPassword() - if err != nil { - return account, err - } - - account.Account = cloudaccount.Account - account.AccessUrl = cloudaccount.AccessUrl - account.Secret = passwd - - if len(self.Account) > 0 && self.Account != account.Account { - account.Account = fmt.Sprintf("%s/%s", account.Account, self.Account) - } - - return account, nil -} - func (self *SCloudprovider) SaveSysInfo(info jsonutils.JSONObject) { self.GetModelManager().TableSpec().Update(self, func() error { self.Sysinfo = info diff --git a/pkg/util/azure/azure.go b/pkg/util/azure/azure.go index ad7268feb6..9d459333a5 100644 --- a/pkg/util/azure/azure.go +++ b/pkg/util/azure/azure.go @@ -626,10 +626,11 @@ func (self *SAzureClient) GetSubAccounts() (subAccounts []cloudprovider.SSubAcco } subAccounts = make([]cloudprovider.SSubAccount, len(subscriptions)) for i, subscription := range subscriptions { - subAccounts[i].Account, err = subscription.GetString("subscriptionId") + subscriptionId, err := subscription.GetString("subscriptionId") if err != nil { return nil, err } + subAccounts[i].Account = fmt.Sprintf("%s/%s", self.tenantId, subscriptionId) subAccounts[i].State, err = subscription.GetString("state") if err != nil { return nil, err From e4b771cb8229849161a6e8b9432235aa54aba8d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B1=88=E8=BD=A9?= Date: Thu, 22 Nov 2018 22:02:11 +0800 Subject: [PATCH 05/19] =?UTF-8?q?=E9=81=BF=E5=85=8D=E6=B2=A1=E6=9C=89objs?= =?UTF-8?q?=E6=97=B6=E6=95=B0=E7=BB=84=E8=AE=BF=E9=97=AE=E8=B6=8A=E7=95=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/cloudcommon/db/taskman/tasks.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/cloudcommon/db/taskman/tasks.go b/pkg/cloudcommon/db/taskman/tasks.go index 0cc20d85da..d976d91cac 100644 --- a/pkg/cloudcommon/db/taskman/tasks.go +++ b/pkg/cloudcommon/db/taskman/tasks.go @@ -216,6 +216,10 @@ func (manager *STaskManager) NewParallelTask(ctx context.Context, taskName strin return nil, fmt.Errorf("task %s not found", taskName) } + if len(objs) == 0 { + return nil, fmt.Errorf("failed to do task %s with zero objs", taskName) + } + log.Debugf("number of objs: %d", len(objs)) lockman.LockClass(ctx, objs[0].GetModelManager(), userCred.GetProjectId()) defer lockman.ReleaseClass(ctx, objs[0].GetModelManager(), userCred.GetProjectId()) From d91f347602986d46b94b34ea380fbe241e987537 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Thu, 22 Nov 2018 22:45:05 +0800 Subject: [PATCH 06/19] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=EF=BC=9A=E5=9C=A8?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E5=AE=8Cvm=E7=9A=84=E7=BD=91=E7=BB=9C?= =?UTF-8?q?=E5=92=8C=E7=A3=81=E7=9B=98=E4=BF=A1=E6=81=AF=E5=90=8E=EF=BC=8C?= =?UTF-8?q?=E5=86=8D=E8=AE=B0=E5=BD=95=E5=90=8C=E6=AD=A5=E7=9A=84=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/compute/tasks/cloud_provider_sync_info_task.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/compute/tasks/cloud_provider_sync_info_task.go b/pkg/compute/tasks/cloud_provider_sync_info_task.go index e3093c1df6..97014615ad 100644 --- a/pkg/compute/tasks/cloud_provider_sync_info_task.go +++ b/pkg/compute/tasks/cloud_provider_sync_info_task.go @@ -425,6 +425,8 @@ func syncHostVMs(ctx context.Context, provider *models.SCloudprovider, task *Clo syncVMNics(ctx, provider, task, localHost, &localVMs[i], remoteVMs[i]) syncVMDisks(ctx, provider, task, localHost, &localVMs[i], remoteVMs[i]) syncVMEip(ctx, provider, task, &localVMs[i], remoteVMs[i]) + + db.OpsLog.LogEvent(&localVMs[i], db.ACT_SYNC_CLOUD_SERVER, localVMs[i].GetShortDesc(), task.UserCred) } } From 8223e63250a347af76f35a2b51b8ca241999a320 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Fri, 23 Nov 2018 01:51:03 +0800 Subject: [PATCH 07/19] remove old log --- pkg/compute/models/guests.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/compute/models/guests.go b/pkg/compute/models/guests.go index c9c6e9aab2..f7558befba 100644 --- a/pkg/compute/models/guests.go +++ b/pkg/compute/models/guests.go @@ -1567,7 +1567,7 @@ func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient. } } - db.OpsLog.LogEvent(&guest, db.ACT_SYNC_CLOUD_SERVER, guest.GetShortDesc(), userCred) + // db.OpsLog.LogEvent(&guest, db.ACT_SYNC_CLOUD_SERVER, guest.GetShortDesc(), userCred) return &guest, nil } From 7d80c3f250f66ec51f9837a9f0dfd403d15f8e6e Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Fri, 23 Nov 2018 01:53:29 +0800 Subject: [PATCH 08/19] Change workermanager backlog to 1024 --- pkg/appsrv/appsrv.go | 2 +- pkg/cloudcommon/db/taskman/handler.go | 2 +- pkg/cloudcommon/db/taskman/localtaskworker.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/appsrv/appsrv.go b/pkg/appsrv/appsrv.go index d37034ed08..aad546371d 100644 --- a/pkg/appsrv/appsrv.go +++ b/pkg/appsrv/appsrv.go @@ -37,7 +37,7 @@ type Application struct { } const ( - DEFAULT_BACKLOG = 256 + DEFAULT_BACKLOG = 1024 DEFAULT_IDLE_TIMEOUT = 10 * time.Second DEFAULT_READ_TIMEOUT = 0 DEFAULT_READ_HEADER_TIMEOUT = 10 * time.Second diff --git a/pkg/cloudcommon/db/taskman/handler.go b/pkg/cloudcommon/db/taskman/handler.go index 23dc6dff15..84a80d6550 100644 --- a/pkg/cloudcommon/db/taskman/handler.go +++ b/pkg/cloudcommon/db/taskman/handler.go @@ -11,7 +11,7 @@ import ( var taskWorkMan *appsrv.SWorkerManager func init() { - taskWorkMan = appsrv.NewWorkerManager("TaskWorkerManager", 4, 100) + taskWorkMan = appsrv.NewWorkerManager("TaskWorkerManager", 4, 1024) } func AddTaskHandler(prefix string, app *appsrv.Application) { diff --git a/pkg/cloudcommon/db/taskman/localtaskworker.go b/pkg/cloudcommon/db/taskman/localtaskworker.go index 57eaf00fb5..f7681f0979 100644 --- a/pkg/cloudcommon/db/taskman/localtaskworker.go +++ b/pkg/cloudcommon/db/taskman/localtaskworker.go @@ -12,7 +12,7 @@ import ( var localTaskWorkerMan *appsrv.SWorkerManager func init() { - localTaskWorkerMan = appsrv.NewWorkerManager("LocalTaskWorkerManager", 4, 10) + localTaskWorkerMan = appsrv.NewWorkerManager("LocalTaskWorkerManager", 4, 1024) } func Error2TaskData(err error) jsonutils.JSONObject { From 90818b81125e9d1ec4df1ad9a491b4cbbf06a342 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Fri, 23 Nov 2018 02:02:52 +0800 Subject: [PATCH 09/19] =?UTF-8?q?=E6=94=B9=E4=B8=BA=E8=A1=A5=E4=B8=80?= =?UTF-8?q?=E6=9D=A1START=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/compute/models/guests.go | 2 +- pkg/compute/tasks/cloud_provider_sync_info_task.go | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/compute/models/guests.go b/pkg/compute/models/guests.go index f7558befba..c9c6e9aab2 100644 --- a/pkg/compute/models/guests.go +++ b/pkg/compute/models/guests.go @@ -1567,7 +1567,7 @@ func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient. } } - // db.OpsLog.LogEvent(&guest, db.ACT_SYNC_CLOUD_SERVER, guest.GetShortDesc(), userCred) + db.OpsLog.LogEvent(&guest, db.ACT_SYNC_CLOUD_SERVER, guest.GetShortDesc(), userCred) return &guest, nil } diff --git a/pkg/compute/tasks/cloud_provider_sync_info_task.go b/pkg/compute/tasks/cloud_provider_sync_info_task.go index 97014615ad..ea0367931f 100644 --- a/pkg/compute/tasks/cloud_provider_sync_info_task.go +++ b/pkg/compute/tasks/cloud_provider_sync_info_task.go @@ -426,7 +426,9 @@ func syncHostVMs(ctx context.Context, provider *models.SCloudprovider, task *Clo syncVMDisks(ctx, provider, task, localHost, &localVMs[i], remoteVMs[i]) syncVMEip(ctx, provider, task, &localVMs[i], remoteVMs[i]) - db.OpsLog.LogEvent(&localVMs[i], db.ACT_SYNC_CLOUD_SERVER, localVMs[i].GetShortDesc(), task.UserCred) + if localVMs[i].Status == models.VM_RUNNING { + db.OpsLog.LogEvent(&localVMs[i], db.ACT_START, localVMs[i].GetShortDesc(), task.UserCred) + } } } From f2522b980cc46ae1740fa84ba1abeb44ee16a6bd Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Fri, 23 Nov 2018 09:48:50 +0800 Subject: [PATCH 10/19] 1. resize opslog notes to VARCHAR(2048) 2. cloudaccount sync status check --- pkg/cloudcommon/db/opslog.go | 2 +- pkg/compute/models/cloudaccounts.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/cloudcommon/db/opslog.go b/pkg/cloudcommon/db/opslog.go index cae57239f9..acc19deefe 100644 --- a/pkg/cloudcommon/db/opslog.go +++ b/pkg/cloudcommon/db/opslog.go @@ -153,7 +153,7 @@ type SOpsLog struct { ObjId string `width:"128" charset:"ascii" nullable:"false" list:"user"` // = Column(VARCHAR(ID_LENGTH, charset='ascii'), nullable=False) ObjName string `width:"128" charset:"utf8" nullable:"false" list:"user"` //= Column(VARCHAR(128, charset='utf8'), nullable=False) Action string `width:"32" charset:"ascii" nullable:"false" list:"user"` //= Column(VARCHAR(32, charset='ascii'), nullable=False) - Notes string `width:"1024" charset:"utf8" list:"user"` // = Column(VARCHAR(1024, charset='utf8')) + Notes string `width:"2048" charset:"utf8" list:"user"` // = Column(VARCHAR(1024, charset='utf8')) ProjectId string `name:"tenant_id" width:"128" charset:"ascii" list:"user"` // = Column(VARCHAR(ID_LENGTH, charset='ascii')) Project string `name:"tenant" width:"128" charset:"utf8" list:"user"` // tenant = Column(VARCHAR(128, charset='utf8')) UserId string `width:"128" charset:"ascii" list:"user"` // = Column(VARCHAR(ID_LENGTH, charset='ascii')) diff --git a/pkg/compute/models/cloudaccounts.go b/pkg/compute/models/cloudaccounts.go index 8dea136422..1713f5495c 100644 --- a/pkg/compute/models/cloudaccounts.go +++ b/pkg/compute/models/cloudaccounts.go @@ -187,7 +187,7 @@ func (self *SCloudaccount) getPassword() (string, error) { } func (self *SCloudaccount) CanSync() bool { - if self.Status == CLOUD_PROVIDER_SYNCING { + if self.Status == CLOUD_PROVIDER_SYNCING || self.Status == CLOUD_PROVIDER_START_SYNC { if self.LastSync.IsZero() || time.Now().Sub(self.LastSync) > 900*time.Second { return true } else { From 0ae3ebdb6c7bf49c8a59d2f1f43ec8f105a24bae Mon Sep 17 00:00:00 2001 From: Yousong Zhou Date: Tue, 20 Nov 2018 13:14:48 +0000 Subject: [PATCH 11/19] aliyun: rename jsonRequest to ecsRequest --- pkg/util/aliyun/aliyun.go | 8 ++++---- pkg/util/aliyun/region.go | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/util/aliyun/aliyun.go b/pkg/util/aliyun/aliyun.go index 79fb5b905e..bc85f1fd17 100644 --- a/pkg/util/aliyun/aliyun.go +++ b/pkg/util/aliyun/aliyun.go @@ -40,7 +40,7 @@ func NewAliyunClient(providerId string, providerName string, accessKey string, s return &client, nil } -func jsonRequest(client *sdk.Client, apiName string, params map[string]string) (jsonutils.JSONObject, error) { +func ecsRequest(client *sdk.Client, apiName string, params map[string]string) (jsonutils.JSONObject, error) { return _jsonRequest(client, "ecs.aliyuncs.com", ALIYUN_API_VERSION, apiName, params) } @@ -83,16 +83,16 @@ func (self *SAliyunClient) getDefaultClient() (*sdk.Client, error) { return sdk.NewClientWithAccessKey(ALIYUN_DEFAULT_REGION, self.accessKey, self.secret) } -func (self *SAliyunClient) jsonRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { +func (self *SAliyunClient) ecsRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { cli, err := self.getDefaultClient() if err != nil { return nil, err } - return jsonRequest(cli, apiName, params) + return ecsRequest(cli, apiName, params) } func (self *SAliyunClient) fetchRegions() error { - body, err := self.jsonRequest("DescribeRegions", map[string]string{"AcceptLanguage": "zh-CN"}) + body, err := self.ecsRequest("DescribeRegions", map[string]string{"AcceptLanguage": "zh-CN"}) if err != nil { log.Errorf("fetchRegions fail %s", err) return err diff --git a/pkg/util/aliyun/region.go b/pkg/util/aliyun/region.go index fecb4d90cb..b4f9faeb76 100644 --- a/pkg/util/aliyun/region.go +++ b/pkg/util/aliyun/region.go @@ -79,11 +79,11 @@ func (self *SRegion) GetOssClient() (*oss.Client, error) { } func (self *SRegion) ecsRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { - cli, err := self.getEcsClient() + client, err := self.getEcsClient() if err != nil { return nil, err } - return jsonRequest(cli, apiName, params) + return _jsonRequest(client, "ecs.aliyuncs.com", ALIYUN_API_VERSION, apiName, params) } ///////////////////////////////////////////////////////////////////////////// From 7e7f124efe47f45c4c677eaf847dbf3e3f52b32d Mon Sep 17 00:00:00 2001 From: Yousong Zhou Date: Tue, 20 Nov 2018 13:28:25 +0000 Subject: [PATCH 12/19] aliyun: region: rename ecsClient to sdkClient --- pkg/util/aliyun/region.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/util/aliyun/region.go b/pkg/util/aliyun/region.go index b4f9faeb76..e2c0905591 100644 --- a/pkg/util/aliyun/region.go +++ b/pkg/util/aliyun/region.go @@ -17,7 +17,7 @@ import ( type SRegion struct { client *SAliyunClient - ecsClient *sdk.Client + sdkClient *sdk.Client ossClient *oss.Client RegionId string @@ -44,15 +44,15 @@ func (self *SRegion) GetMetadata() *jsonutils.JSONDict { return nil } -func (self *SRegion) getEcsClient() (*sdk.Client, error) { - if self.ecsClient == nil { +func (self *SRegion) getSdkClient() (*sdk.Client, error) { + if self.sdkClient == nil { cli, err := sdk.NewClientWithAccessKey(self.RegionId, self.client.accessKey, self.client.secret) if err != nil { return nil, err } - self.ecsClient = cli + self.sdkClient = cli } - return self.ecsClient, nil + return self.sdkClient, nil } // oss endpoint @@ -79,7 +79,7 @@ func (self *SRegion) GetOssClient() (*oss.Client, error) { } func (self *SRegion) ecsRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { - client, err := self.getEcsClient() + client, err := self.getSdkClient() if err != nil { return nil, err } From cd0a1b87ef8c1e939135f54f92a07c6cc5ce7caa Mon Sep 17 00:00:00 2001 From: Yousong Zhou Date: Tue, 20 Nov 2018 13:28:48 +0000 Subject: [PATCH 13/19] aliyun: add SVpc.apiRequest() method --- pkg/util/aliyun/aliyun.go | 3 ++- pkg/util/aliyun/vpc.go | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/pkg/util/aliyun/aliyun.go b/pkg/util/aliyun/aliyun.go index bc85f1fd17..b2011e9cb1 100644 --- a/pkg/util/aliyun/aliyun.go +++ b/pkg/util/aliyun/aliyun.go @@ -16,7 +16,8 @@ const ( ALIYUN_DEFAULT_REGION = "cn-hangzhou" - ALIYUN_API_VERSION = "2014-05-26" + ALIYUN_API_VERSION = "2014-05-26" + ALIYUN_API_VERSION_VPC = "2016-04-28" ALIYUN_BSS_API_VERSION = "2017-12-14" diff --git a/pkg/util/aliyun/vpc.go b/pkg/util/aliyun/vpc.go index 91951cf029..341bab020c 100644 --- a/pkg/util/aliyun/vpc.go +++ b/pkg/util/aliyun/vpc.go @@ -45,6 +45,14 @@ type SVpc struct { VpcName string } +func (self *SVpc) apiRequest(action string, params map[string]string) (jsonutils.JSONObject, error) { + client, err := self.region.getSdkClient() + if err != nil { + return nil, err + } + return _jsonRequest(client, "vpc.aliyuncs.com", ALIYUN_API_VERSION_VPC, action, params) +} + func (self *SVpc) GetMetadata() *jsonutils.JSONDict { return nil } From 2c430b4430e4e1b30659630f33a50bea029b4532 Mon Sep 17 00:00:00 2001 From: Yousong Zhou Date: Sat, 17 Nov 2018 13:15:03 +0000 Subject: [PATCH 14/19] routetables: initial version --- cmd/climc/shell/routetables.go | 117 +++++++++++ pkg/compute/handlers.go | 1 + pkg/compute/models/routetables.go | 254 ++++++++++++++++++++++++ pkg/mcclient/modules/mod_routetables.go | 28 +++ pkg/mcclient/options/routetables.go | 133 +++++++++++++ 5 files changed, 533 insertions(+) create mode 100644 cmd/climc/shell/routetables.go create mode 100644 pkg/compute/models/routetables.go create mode 100644 pkg/mcclient/modules/mod_routetables.go create mode 100644 pkg/mcclient/options/routetables.go diff --git a/cmd/climc/shell/routetables.go b/cmd/climc/shell/routetables.go new file mode 100644 index 0000000000..32f0207830 --- /dev/null +++ b/cmd/climc/shell/routetables.go @@ -0,0 +1,117 @@ +package shell + +import ( + "fmt" + "strings" + + "yunion.io/x/jsonutils" + + "yunion.io/x/onecloud/pkg/mcclient" + "yunion.io/x/onecloud/pkg/mcclient/modules" + "yunion.io/x/onecloud/pkg/mcclient/options" +) + +func init() { + printRouteTableList := func(list *modules.ListResult, columns []string) { + data := list.Data + for _, jsonObj := range data { + jd := jsonObj.(*jsonutils.JSONDict) + routesObj, err := jd.GetArray("routes") + if err != nil { + continue + } + routes := []string{} + for _, routeObj := range routesObj { + typ, _ := routeObj.GetString("type") + cidr, _ := routeObj.GetString("cidr") + next_hop_type, _ := routeObj.GetString("next_hop_type") + next_hop, _ := routeObj.GetString("next_hop") + route := fmt.Sprintf("%8s: %18s %s", typ, cidr, next_hop_type) + if len(next_hop) > 0 { + route += fmt.Sprintf(":%s", next_hop) + } + routes = append(routes, route) + } + s := strings.Join(routes, "\n") + jd.Set("routes", jsonutils.NewString(s)) + } + printList(list, columns) + } + + R(&options.RouteTableCreateOptions{}, "routetable-create", "Create routetable", func(s *mcclient.ClientSession, opts *options.RouteTableCreateOptions) error { + params, err := opts.Params() + if err != nil { + return err + } + routetable, err := modules.RouteTables.Create(s, params) + if err != nil { + return err + } + printObjectRecursive(routetable) + return nil + }) + R(&options.RouteTableGetOptions{}, "routetable-show", "Show routetable", func(s *mcclient.ClientSession, opts *options.RouteTableGetOptions) error { + routetable, err := modules.RouteTables.Get(s, opts.ID, nil) + if err != nil { + return err + } + printObjectRecursive(routetable) + return nil + }) + R(&options.RouteTableListOptions{}, "routetable-list", "List routetables", func(s *mcclient.ClientSession, opts *options.RouteTableListOptions) error { + params, err := options.ListStructToParams(opts) + if err != nil { + return err + } + result, err := modules.RouteTables.List(s, params) + if err != nil { + return err + } + printRouteTableList(result, modules.RouteTables.GetColumns(s)) + return nil + }) + R(&options.RouteTableUpdateOptions{}, "routetable-update", "Update routetable", func(s *mcclient.ClientSession, opts *options.RouteTableUpdateOptions) error { + params, err := opts.Params() + if err != nil { + return err + } + routetable, err := modules.RouteTables.Update(s, opts.ID, params) + if err != nil { + return err + } + printObjectRecursive(routetable) + return nil + }) + R(&options.RouteTableAddRoutesOptions{}, "routetable-add-routes", "Add routes to routetable", func(s *mcclient.ClientSession, opts *options.RouteTableAddRoutesOptions) error { + params, err := opts.Params() + if err != nil { + return err + } + routetable, err := modules.RouteTables.PerformAction(s, opts.ID, "add-routes", params) + if err != nil { + return err + } + printObjectRecursive(routetable) + return nil + }) + R(&options.RouteTableDelRoutesOptions{}, "routetable-del-routes", "Del routes to routetable", func(s *mcclient.ClientSession, opts *options.RouteTableDelRoutesOptions) error { + params, err := opts.Params() + if err != nil { + return err + } + routetable, err := modules.RouteTables.PerformAction(s, opts.ID, "del-routes", params) + if err != nil { + return err + } + printObjectRecursive(routetable) + return nil + }) + R(&options.RouteTableDeleteOptions{}, "routetable-delete", "Show routetable", func(s *mcclient.ClientSession, opts *options.RouteTableDeleteOptions) error { + routetable, err := modules.RouteTables.Delete(s, opts.ID, nil) + if err != nil { + return err + } + printObjectRecursive(routetable) + return nil + }) +} diff --git a/pkg/compute/handlers.go b/pkg/compute/handlers.go index 6d7ed755f0..ad2ec0a97a 100644 --- a/pkg/compute/handlers.go +++ b/pkg/compute/handlers.go @@ -71,6 +71,7 @@ func InitHandlers(app *appsrv.Application) { models.LoadbalancerCertificateManager, models.LoadbalancerAclManager, models.LoadbalancerAgentManager, + models.RouteTableManager, models.SchedpolicyManager, models.DynamicschedtagManager, diff --git a/pkg/compute/models/routetables.go b/pkg/compute/models/routetables.go new file mode 100644 index 0000000000..a79e59219c --- /dev/null +++ b/pkg/compute/models/routetables.go @@ -0,0 +1,254 @@ +package models + +import ( + "context" + "net" + "reflect" + "strings" + + "yunion.io/x/jsonutils" + "yunion.io/x/log" + "yunion.io/x/pkg/gotypes" + "yunion.io/x/sqlchemy" + + "yunion.io/x/onecloud/pkg/cloudcommon/db" + "yunion.io/x/onecloud/pkg/cloudcommon/validators" + "yunion.io/x/onecloud/pkg/httperrors" + "yunion.io/x/onecloud/pkg/mcclient" +) + +type SRoute struct { + Type string + Cidr string + NextHopType string + NextHopId string +} + +func (route *SRoute) Validate(data *jsonutils.JSONDict) error { + if strings.Index(route.Cidr, "/") > 0 { + _, ipNet, err := net.ParseCIDR(route.Cidr) + if err != nil { + return err + } + // normalize from 192.168.1.3/24 to 192.168.1.0/24 + route.Cidr = ipNet.String() + } else { + ip := net.ParseIP(route.Cidr).To4() + if ip == nil { + return httperrors.NewInputParameterError("invalid addr %s", route.Cidr) + } + } + return nil +} + +type SRoutes []*SRoute + +func (routes *SRoutes) String() string { + return jsonutils.Marshal(routes).String() +} +func (routes *SRoutes) IsZero() bool { + if len([]*SRoute(*routes)) == 0 { + return true + } + return false +} + +func (routes *SRoutes) Validate(data *jsonutils.JSONDict) error { + found := map[string]bool{} + for _, route := range *routes { + if err := route.Validate(data); err != nil { + return err + } + if _, ok := found[route.Cidr]; ok { + // error so that the user has a chance to deal with comments + return httperrors.NewInputParameterError("duplicate route cidr %s", route.Cidr) + } + // TODO aliyun: check overlap with System type route + found[route.Cidr] = true + } + return nil +} + +type SRouteTableManager struct { + db.SVirtualResourceBaseManager +} + +var RouteTableManager *SRouteTableManager + +func init() { + gotypes.RegisterSerializable(reflect.TypeOf(&SRoutes{}), func() gotypes.ISerializable { + return &SRoutes{} + }) + RouteTableManager = &SRouteTableManager{ + SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager( + SRouteTable{}, + "route_tables_tbl", + "route_table", + "route_tables", + ), + } +} + +type SRouteTable struct { + db.SVirtualResourceBase + + VpcId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required"` + CloudregionId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"optional"` + Type string `width:"16" charset:"ascii" nullable:"false" list:"user"` + Routes *SRoutes `list:"user" update:"user" create:"required"` +} + +func (man *SRouteTableManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) { + q, err := man.SVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, query) + if err != nil { + return nil, err + } + userProjId := userCred.GetProjectId() + data := query.(*jsonutils.JSONDict) + for _, key := range []string{"vpc", "cloudregion"} { + v := validators.NewModelIdOrNameValidator(key, key, userProjId) + v.Optional(true) + q, err = v.QueryFilter(q, data) + if err != nil { + return nil, err + } + } + return q, nil +} + +func (man *SRouteTableManager) validateRoutes(data *jsonutils.JSONDict, update bool) (*jsonutils.JSONDict, error) { + routes := SRoutes{} + routesV := validators.NewStructValidator("routes", &routes) + if update { + routesV.Optional(true) + } + err := routesV.Validate(data) + if err != nil { + return nil, err + } + return data, nil +} + +func (man *SRouteTableManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerProjId string, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { + data, err := man.validateRoutes(data, false) + if err != nil { + return nil, err + } + vpcV := validators.NewModelIdOrNameValidator("vpc", "vpc", ownerProjId) + if err := vpcV.Validate(data); err != nil { + return nil, err + } + vpc := vpcV.Model.(*SVpc) + cloudregion := vpc.GetRegion() + if cloudregion == nil { + return nil, httperrors.NewConflictError("failed fetching cloudregion of vpc %s(%s)", vpc.Name, vpc.Id) + } + data.Set("cloudregion_id", jsonutils.NewString(cloudregion.Id)) + return man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, data) +} + +func (rt *SRouteTable) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { + data, err := RouteTableManager.validateRoutes(data, true) + if err != nil { + return nil, err + } + return rt.SVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, data) +} + +func (rt *SRouteTable) AllowPerformAddRoutes(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) bool { + return rt.IsOwner(userCred) || userCred.IsSystemAdmin() +} + +func (rt *SRouteTable) AllowPerformDelRoutes(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) bool { + return rt.AllowPerformAddRoutes(ctx, userCred, query, data) +} + +// PerformAddRoutes patches acl entries by adding then deleting the specified acls. +// This is intended mainly for command line operations. +func (rt *SRouteTable) PerformAddRoutes(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { + routes := gotypes.DeepCopy(rt.Routes).(SRoutes) + { + adds := SRoutes{} + addsV := validators.NewStructValidator("routes", &adds) + addsV.Optional(true) + err := addsV.Validate(data) + if err != nil { + return nil, err + } + for _, add := range adds { + found := false + for _, route := range routes { + if route.Cidr == add.Cidr { + found = true + break + } + } + if !found { + routes = append(routes, add) + } + } + } + _, err := rt.GetModelManager().TableSpec().Update(rt, func() error { + rt.Routes = &routes + return nil + }) + if err != nil { + return nil, err + } + return nil, nil +} + +func (rt *SRouteTable) PerformDelRoutes(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { + routes := gotypes.DeepCopy(rt.Routes).(SRoutes) + { + cidrs := []string{} + err := data.Unmarshal(&cidrs, "cidrs") + if err != nil { + return nil, httperrors.NewInputParameterError("unmarshaling cidrs failed: %s", err) + } + for _, cidr := range cidrs { + for i := len(routes) - 1; i >= 0; i-- { + route := routes[i] + if route.Type == "system" { + continue + } + if route.Cidr == cidr { + routes = append(routes[:i], routes[i+1:]...) + break + } + } + } + } + _, err := rt.GetModelManager().TableSpec().Update(rt, func() error { + rt.Routes = &routes + return nil + }) + if err != nil { + return nil, err + } + return nil, nil +} + +func (rt *SRouteTable) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict { + extra := rt.SVirtualResourceBase.GetCustomizeColumns(ctx, userCred, query) + vpcM, err := VpcManager.FetchById(rt.VpcId) + if err != nil { + log.Errorf("route table %s(%s): fetch vpc (%s) error: %s", + rt.Name, rt.Id, rt.VpcId, err) + return extra + } + cloudregionM, err := CloudregionManager.FetchById(rt.CloudregionId) + if err != nil { + log.Errorf("route table %s(%s): fetch cloud region (%s) error: %s", + rt.Name, rt.Id, rt.CloudregionId, err) + return extra + } + extra.Set("vpc", jsonutils.NewString(vpcM.GetName())) + extra.Set("cloudregion", jsonutils.NewString(cloudregionM.GetName())) + return extra +} + +func (rt *SRouteTable) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict { + extra := rt.GetCustomizeColumns(ctx, userCred, query) + return extra +} diff --git a/pkg/mcclient/modules/mod_routetables.go b/pkg/mcclient/modules/mod_routetables.go new file mode 100644 index 0000000000..12f965ecad --- /dev/null +++ b/pkg/mcclient/modules/mod_routetables.go @@ -0,0 +1,28 @@ +package modules + +type RouteTableManager struct { + ResourceManager +} + +var ( + RouteTables RouteTableManager +) + +func init() { + RouteTables = RouteTableManager{ + NewComputeManager( + "route_table", + "route_tables", + []string{ + "id", + "name", + "type", + "vpc", + "vpc_id", + "routes", + }, + []string{"tenant"}, + ), + } + registerCompute(&RouteTables) +} diff --git a/pkg/mcclient/options/routetables.go b/pkg/mcclient/options/routetables.go new file mode 100644 index 0000000000..c214d824b8 --- /dev/null +++ b/pkg/mcclient/options/routetables.go @@ -0,0 +1,133 @@ +package options + +import ( + "fmt" + + "yunion.io/x/jsonutils" +) + +type Route struct { + Type string + Cidr string + NextHopType string + NextHopId string +} + +type Routes []*Route + +type RoutesOptions struct { + RouteType []string + RouteCidr []string + RouteNextHopType []string + RouteNextHopId []string +} + +func (opts *RoutesOptions) Params() (jsonutils.JSONObject, error) { + len0 := len(opts.RouteType) + len1 := len(opts.RouteCidr) + if len0 != len1 || len0 != len(opts.RouteNextHopType) || len1 != len(opts.RouteNextHopId) { + return nil, fmt.Errorf("there must be equal number of options of --route-xxx") + } + routes := []*Route{} + for i := 0; i < len0; i++ { + routes = append(routes, &Route{ + Type: opts.RouteType[i], + Cidr: opts.RouteCidr[i], + NextHopType: opts.RouteNextHopType[i], + NextHopId: opts.RouteNextHopId[i], + }) + } + routesJson := jsonutils.Marshal(routes) + return routesJson, nil +} + +type RouteTableCreateOptions struct { + NAME string + Vpc string + + RoutesOptions +} + +func (opts *RouteTableCreateOptions) Params() (*jsonutils.JSONDict, error) { + params, err := optionsStructToParams(opts) + if err != nil { + return nil, err + } + routesJson, err := opts.RoutesOptions.Params() + if err != nil { + return nil, err + } + params.Set("routes", routesJson) + return params, nil +} + +type RouteTableGetOptions struct { + ID string +} + +type RouteTableUpdateOptions struct { + ID string `json:"-"` + Name string + + RoutesOptions +} + +func (opts *RouteTableUpdateOptions) Params() (*jsonutils.JSONDict, error) { + params, err := optionsStructToParams(opts) + if err != nil { + return nil, err + } + if len(opts.RouteCidr) != 0 { + routesJson, err := opts.RoutesOptions.Params() + if err != nil { + return nil, err + } + params.Set("routes", routesJson) + } + return params, nil +} + +type RouteTableAddRoutesOptions struct { + ID string `json:"-"` + + RoutesOptions +} + +func (opts *RouteTableAddRoutesOptions) Params() (*jsonutils.JSONDict, error) { + if len(opts.RouteCidr) == 0 { + return nil, fmt.Errorf("nothing to add") + } + routesJson, err := opts.RoutesOptions.Params() + if err != nil { + return nil, err + } + params := jsonutils.NewDict() + params.Set("routes", routesJson) + return params, nil +} + +type RouteTableDelRoutesOptions struct { + ID string `json:"-"` + + RouteCidr []string +} + +func (opts *RouteTableDelRoutesOptions) Params() (*jsonutils.JSONDict, error) { + if len(opts.RouteCidr) == 0 { + return nil, fmt.Errorf("nothing to del") + } + params := jsonutils.NewDict() + params.Set("cidrs", jsonutils.Marshal(opts.RouteCidr)) + return params, nil +} + +type RouteTableDeleteOptions struct { + ID string +} + +type RouteTableListOptions struct { + Vpc string + Cloudregion string + + BaseListOptions +} From 593219e0103030b781b9d9ac7b9745327d539b41 Mon Sep 17 00:00:00 2001 From: Yousong Zhou Date: Fri, 23 Nov 2018 03:05:04 +0000 Subject: [PATCH 15/19] =?UTF-8?q?aliyun:=20=E5=90=8C=E6=AD=A5routetables?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/cloudprovider/resources.go | 19 ++ pkg/compute/models/routetables.go | 122 +++++++++++ .../tasks/cloud_provider_sync_info_task.go | 19 ++ pkg/util/aliyun/routetable.go | 200 +++++++++++++++++- pkg/util/aliyun/vpc.go | 33 ++- pkg/util/aws/vpc.go | 5 + pkg/util/azure/classic_vpc.go | 5 + pkg/util/azure/vpc.go | 5 + pkg/util/qcloud/vpc.go | 5 + 9 files changed, 403 insertions(+), 10 deletions(-) diff --git a/pkg/cloudprovider/resources.go b/pkg/cloudprovider/resources.go index c5c8ccde7c..b95751ee11 100644 --- a/pkg/cloudprovider/resources.go +++ b/pkg/cloudprovider/resources.go @@ -221,6 +221,24 @@ type ICloudSecurityGroup interface { GetRules() ([]secrules.SecurityRule, error) } +type ICloudRouteTable interface { + ICloudResource + GetManagerId() string + + GetDescription() string + GetRegionId() string + GetVpcId() string + GetType() string + GetIRoutes() ([]ICloudRoute, error) +} + +type ICloudRoute interface { + GetType() string + GetCidr() string + GetNextHopType() string + GetNextHop() string +} + type ICloudDisk interface { ICloudResource IBillingResource @@ -266,6 +284,7 @@ type ICloudVpc interface { // GetStatus() string GetIWires() ([]ICloudWire, error) GetISecurityGroups() ([]ICloudSecurityGroup, error) + GetIRouteTables() ([]ICloudRouteTable, error) GetManagerId() string diff --git a/pkg/compute/models/routetables.go b/pkg/compute/models/routetables.go index a79e59219c..b14498f131 100644 --- a/pkg/compute/models/routetables.go +++ b/pkg/compute/models/routetables.go @@ -9,10 +9,12 @@ import ( "yunion.io/x/jsonutils" "yunion.io/x/log" "yunion.io/x/pkg/gotypes" + "yunion.io/x/pkg/util/compare" "yunion.io/x/sqlchemy" "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/cloudcommon/validators" + "yunion.io/x/onecloud/pkg/cloudprovider" "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" ) @@ -91,6 +93,7 @@ func init() { type SRouteTable struct { db.SVirtualResourceBase + SManagedResourceBase VpcId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required"` CloudregionId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"optional"` @@ -250,5 +253,124 @@ func (rt *SRouteTable) GetCustomizeColumns(ctx context.Context, userCred mcclien func (rt *SRouteTable) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict { extra := rt.GetCustomizeColumns(ctx, userCred, query) + extra = rt.SManagedResourceBase.getExtraDetails(ctx, extra) return extra } + +func (man *SRouteTableManager) SyncRouteTables(ctx context.Context, userCred mcclient.TokenCredential, vpc *SVpc, cloudRouteTables []cloudprovider.ICloudRouteTable) ([]SRouteTable, []cloudprovider.ICloudRouteTable, compare.SyncResult) { + localRouteTables := make([]SRouteTable, 0) + remoteRouteTables := make([]cloudprovider.ICloudRouteTable, 0) + syncResult := compare.SyncResult{} + + dbRouteTables := []SRouteTable{} + if err := db.FetchModelObjects(man, man.Query(), &dbRouteTables); err != nil { + syncResult.Error(err) + return nil, nil, syncResult + } + removed := make([]SRouteTable, 0) + commondb := make([]SRouteTable, 0) + commonext := make([]cloudprovider.ICloudRouteTable, 0) + added := make([]cloudprovider.ICloudRouteTable, 0) + if false { + for _, rt := range cloudRouteTables { + log.Errorf("%s, %s", rt.GetName(), rt.GetGlobalId()) + routes, err := rt.GetIRoutes() + if err != nil { + log.Errorf("get routes err: %s", err) + continue + } + for i, route := range routes { + log.Errorf("route %d: %#v ", i, route) + } + } + } + if err := compare.CompareSets(dbRouteTables, cloudRouteTables, &removed, &commondb, &commonext, &added); err != nil { + syncResult.Error(err) + return nil, nil, syncResult + } + + for i := 0; i < len(commondb); i += 1 { + err := commondb[i].SyncWithCloudRouteTable(userCred, vpc, commonext[i]) + if err != nil { + syncResult.UpdateError(err) + continue + } + localRouteTables = append(localRouteTables, commondb[i]) + remoteRouteTables = append(remoteRouteTables, commonext[i]) + syncResult.Update() + } + + for i := 0; i < len(added); i += 1 { + routeTableNew, err := man.insertFromCloud(userCred, vpc, added[i]) + if err != nil { + syncResult.AddError(err) + continue + } + localRouteTables = append(localRouteTables, *routeTableNew) + remoteRouteTables = append(remoteRouteTables, added[i]) + syncResult.Add() + } + return localRouteTables, remoteRouteTables, syncResult +} + +func (man *SRouteTableManager) newRouteTableFromCloud(userCred mcclient.TokenCredential, vpc *SVpc, cloudRouteTable cloudprovider.ICloudRouteTable) (*SRouteTable, error) { + routes := []*SRoute{} + { + cloudRoutes, err := cloudRouteTable.GetIRoutes() + if err != nil { + return nil, err + } + for _, cloudRoute := range cloudRoutes { + route := &SRoute{ + Type: cloudRoute.GetType(), + Cidr: cloudRoute.GetCidr(), + NextHopType: cloudRoute.GetNextHopType(), + NextHopId: cloudRoute.GetNextHop(), + } + routes = append(routes, route) + } + } + routeTable := &SRouteTable{ + CloudregionId: vpc.CloudregionId, + VpcId: vpc.Id, + Type: cloudRouteTable.GetType(), + Routes: (*SRoutes)(&routes), + } + routeTable.Name = cloudRouteTable.GetName() + routeTable.ManagerId = vpc.ManagerId + routeTable.ExternalId = cloudRouteTable.GetGlobalId() + routeTable.Description = cloudRouteTable.GetDescription() + routeTable.ProjectId = userCred.GetProjectId() + routeTable.SetModelManager(man) + return routeTable, nil +} + +func (man *SRouteTableManager) insertFromCloud(userCred mcclient.TokenCredential, vpc *SVpc, cloudRouteTable cloudprovider.ICloudRouteTable) (*SRouteTable, error) { + routeTable, err := man.newRouteTableFromCloud(userCred, vpc, cloudRouteTable) + if err != nil { + return nil, err + } + if err := man.TableSpec().Insert(routeTable); err != nil { + return nil, err + } + return routeTable, nil +} + +func (self *SRouteTable) SyncWithCloudRouteTable(userCred mcclient.TokenCredential, vpc *SVpc, cloudRouteTable cloudprovider.ICloudRouteTable) error { + man := self.GetModelManager().(*SRouteTableManager) + routeTable, err := man.newRouteTableFromCloud(userCred, vpc, cloudRouteTable) + if err != nil { + return err + } + _, err = man.TableSpec().Update(self, func() error { + self.CloudregionId = routeTable.CloudregionId + self.VpcId = vpc.Id + self.Type = routeTable.Type + self.Routes = routeTable.Routes + return nil + }) + if err != nil { + return err + } + return nil +} diff --git a/pkg/compute/tasks/cloud_provider_sync_info_task.go b/pkg/compute/tasks/cloud_provider_sync_info_task.go index 7fc8fbea5b..06dccfdd0a 100644 --- a/pkg/compute/tasks/cloud_provider_sync_info_task.go +++ b/pkg/compute/tasks/cloud_provider_sync_info_task.go @@ -209,6 +209,7 @@ func syncRegionVPCs(ctx context.Context, provider *models.SCloudprovider, task * for j := 0; j < len(localVpcs); j += 1 { syncVpcWires(ctx, provider, task, &localVpcs[j], remoteVpcs[j], syncRange) syncVpcSecGroup(ctx, provider, task, &localVpcs[j], remoteVpcs[j], syncRange) + syncVpcRouteTables(ctx, provider, task, &localVpcs[j], remoteVpcs[j], syncRange) } } @@ -230,6 +231,24 @@ func syncVpcSecGroup(ctx context.Context, provider *models.SCloudprovider, task } } +func syncVpcRouteTables(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localVpc *models.SVpc, remoteVpc cloudprovider.ICloudVpc, syncRange *models.SSyncRange) { + routeTables, err := remoteVpc.GetIRouteTables() + if err != nil { + msg := fmt.Sprintf("GetIRouteTables for vpc %s failed %s", remoteVpc.GetId(), err) + log.Errorf(msg) + logSyncFailed(provider, task, msg) + return + } + _, _, result := models.RouteTableManager.SyncRouteTables(ctx, task.GetUserCred(), localVpc, routeTables) + msg := result.Result() + notes := fmt.Sprintf("SyncRouteTables for VPC %s result: %s", localVpc.Name, msg) + log.Infof(notes) + if result.IsError() { + logSyncFailed(provider, task, msg) + return + } +} + func syncVpcWires(ctx context.Context, provider *models.SCloudprovider, task taskman.ITask, localVpc *models.SVpc, remoteVpc cloudprovider.ICloudVpc, syncRange *models.SSyncRange) { wires, err := remoteVpc.GetIWires() if err != nil { diff --git a/pkg/util/aliyun/routetable.go b/pkg/util/aliyun/routetable.go index 65e8f6101e..6f37698cb2 100644 --- a/pkg/util/aliyun/routetable.go +++ b/pkg/util/aliyun/routetable.go @@ -1,7 +1,13 @@ package aliyun import ( + "fmt" "time" + + "yunion.io/x/jsonutils" + "yunion.io/x/log" + + "yunion.io/x/onecloud/pkg/cloudprovider" ) // {"CreationTime":"2017-03-19T13:37:40Z","RouteEntrys":{"RouteEntry":[{"DestinationCidrBlock":"172.31.32.0/20","InstanceId":"","NextHopType":"local","NextHops":{"NextHop":[]},"RouteTableId":"vtb-j6c60lectdi80rk5xz43g","Status":"Available","Type":"System"},{"DestinationCidrBlock":"100.64.0.0/10","InstanceId":"","NextHopType":"service","NextHops":{"NextHop":[]},"RouteTableId":"vtb-j6c60lectdi80rk5xz43g","Status":"Available","Type":"System"}]},"RouteTableId":"vtb-j6c60lectdi80rk5xz43g","RouteTableType":"System","VRouterId":"vrt-j6c00qrol733dg36iq4qj"} @@ -11,23 +17,199 @@ type SNextHops struct { } type SRouteEntry struct { - DestinationCidrBlock string - InstanceId string - NextHopType string - NextHops SNextHops + routeTable *SRouteTable + RouteTableId string - Status string Type string + DestinationCidrBlock string + NextHopType string + InstanceId string + NextHops SNextHops +} + +func (route *SRouteEntry) GetType() string { + return route.Type +} + +func (route *SRouteEntry) GetCidr() string { + return route.DestinationCidrBlock +} + +func (route *SRouteEntry) GetNextHopType() string { + return route.NextHopType +} + +func (route *SRouteEntry) GetNextHop() string { + return route.InstanceId } type SRouteEntrys struct { - RouteEntry []SRouteEntry + RouteEntry []*SRouteEntry } type SRouteTable struct { - CreationTime time.Time - RouteEntrys SRouteEntrys + region *SRegion + vpc *SVpc + routes []cloudprovider.ICloudRoute + + VpcId string + CreationTime time.Time + RouteEntrys SRouteEntrys + VRouterId string + Description string + RouteTableId string + RouteTableName string RouteTableType string - VRouterId string + RouterId string + RouterType string + VSwitchIds SRouteTableVSwitchIds +} + +type SRouteTableVSwitchIds struct { + VSwitchId []string +} + +type sDescribeRouteTablesResponseRouteTables struct { + RouteTable []SRouteTable +} + +type sDescribeRouteTablesResponse struct { + RouteTables sDescribeRouteTablesResponseRouteTables + TotalCount int +} + +func (self *SRouteTable) GetDescription() string { + return self.Description +} + +func (self *SRouteTable) GetId() string { + return self.GetGlobalId() +} + +func (self *SRouteTable) GetGlobalId() string { + return self.RouteTableId +} + +func (self *SRouteTable) GetManagerId() string { + return self.region.client.providerId +} + +func (self *SRouteTable) GetName() string { + return self.RouteTableName +} + +func (self *SRouteTable) GetMetadata() *jsonutils.JSONDict { + return nil +} + +func (self *SRouteTable) GetRegionId() string { + return self.region.RegionId +} + +func (self *SRouteTable) GetType() string { + return self.RouteTableType +} + +func (self *SRouteTable) GetVpcId() string { + return self.VpcId +} + +func (self *SRouteTable) GetIRoutes() ([]cloudprovider.ICloudRoute, error) { + if self.routes == nil { + err := self.fetchRoutes() + if err != nil { + return nil, err + } + } + return self.routes, nil +} + +func (self *SRouteTable) GetStatus() string { + return "" +} + +func (self *SRouteTable) IsEmulated() bool { + return false +} + +func (self *SRouteTable) Refresh() error { + return nil +} + +func (self *SRouteTable) fetchRoutes() error { + routes := make([]*SRouteEntry, 0) + for { + parts, total, err := self.RemoteGetRoutes(len(routes), 50) + if err != nil { + return err + } + routes = append(routes, parts...) + if len(routes) >= total { + break + } + } + self.routes = make([]cloudprovider.ICloudRoute, len(routes)) + for i := 0; i < len(routes); i++ { + routes[i].routeTable = self + self.routes[i] = routes[i] + } + return nil +} + +func (self *SRouteTable) RemoteGetRoutes(offset int, limit int) ([]*SRouteEntry, int, error) { + if limit > 50 || limit <= 0 { + limit = 50 + } + params := make(map[string]string) + params["RouteTableId"] = self.RouteTableId + params["PageSize"] = fmt.Sprintf("%d", limit) + params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1) + + body, err := self.region.ecsRequest("DescribeRouteTables", params) + if err != nil { + log.Errorf("RemoteGetRoutes fail %s", err) + return nil, 0, err + } + + resp := sDescribeRouteTablesResponse{} + err = body.Unmarshal(&resp) + if err != nil { + log.Errorf("Unmarshal routeEntrys fail %s", err) + return nil, 0, err + } + routeTables := resp.RouteTables.RouteTable + if len(routeTables) != 1 { + return nil, 0, fmt.Errorf("expecting 1 route table, got %d", len(routeTables)) + } + routeTable := routeTables[0] + return routeTable.RouteEntrys.RouteEntry, resp.TotalCount, nil +} + +func (self *SVpc) RemoteGetRouteTableList(offset int, limit int) ([]*SRouteTable, int, error) { + if limit > 50 || limit <= 0 { + limit = 50 + } + params := make(map[string]string) + params["VpcId"] = self.VpcId + params["PageSize"] = fmt.Sprintf("%d", limit) + params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1) + + body, err := self.apiRequest("DescribeRouteTableList", params) + if err != nil { + log.Errorf("RemoteGetRouteTableList fail %s", err) + return nil, 0, err + } + + routeTables := make([]*SRouteTable, 0) + err = body.Unmarshal(&routeTables, "RouterTableList", "RouterTableListType") + if err != nil { + log.Errorf("Unmarshal routeTables fail %s", err) + return nil, 0, err + } + for _, routeTable := range routeTables { + routeTable.region = self.region + } + total, _ := body.Int("TotalCount") + return routeTables, int(total), nil } diff --git a/pkg/util/aliyun/vpc.go b/pkg/util/aliyun/vpc.go index 341bab020c..b567df76d2 100644 --- a/pkg/util/aliyun/vpc.go +++ b/pkg/util/aliyun/vpc.go @@ -30,7 +30,8 @@ type SVpc struct { iwires []cloudprovider.ICloudWire - secgroups []cloudprovider.ICloudSecurityGroup + secgroups []cloudprovider.ICloudSecurityGroup + routeTables []cloudprovider.ICloudRouteTable CidrBlock string CreationTime time.Time @@ -191,6 +192,36 @@ func (self *SVpc) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGroup, err return self.secgroups, nil } +func (self *SVpc) fetchRouteTables() error { + routeTables := make([]*SRouteTable, 0) + for { + parts, total, err := self.RemoteGetRouteTableList(len(routeTables), 50) + if err != nil { + return err + } + routeTables = append(routeTables, parts...) + if len(routeTables) >= total { + break + } + } + self.routeTables = make([]cloudprovider.ICloudRouteTable, len(routeTables)) + for i := 0; i < len(routeTables); i++ { + routeTables[i].vpc = self + self.routeTables[i] = routeTables[i] + } + return nil +} + +func (self *SVpc) GetIRouteTables() ([]cloudprovider.ICloudRouteTable, error) { + if self.routeTables == nil { + err := self.fetchRouteTables() + if err != nil { + return nil, err + } + } + return self.routeTables, nil +} + func (self *SVpc) GetManagerId() string { return self.region.client.providerId } diff --git a/pkg/util/aws/vpc.go b/pkg/util/aws/vpc.go index eb0ed59eab..ad9946ee7f 100644 --- a/pkg/util/aws/vpc.go +++ b/pkg/util/aws/vpc.go @@ -103,6 +103,11 @@ func (self *SVpc) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGroup, err return self.secgroups, nil } +func (self *SVpc) GetIRouteTables() ([]cloudprovider.ICloudRouteTable, error) { + rts := []cloudprovider.ICloudRouteTable{} + return rts, nil +} + func (self *SVpc) GetManagerId() string { return self.region.client.providerId } diff --git a/pkg/util/azure/classic_vpc.go b/pkg/util/azure/classic_vpc.go index 6e369a6617..1cb6568441 100644 --- a/pkg/util/azure/classic_vpc.go +++ b/pkg/util/azure/classic_vpc.go @@ -140,6 +140,11 @@ func (self *SClassicVpc) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGro return self.secgroups, nil } +func (self *SClassicVpc) GetIRouteTables() ([]cloudprovider.ICloudRouteTable, error) { + rts := []cloudprovider.ICloudRouteTable{} + return rts, nil +} + func (self *SClassicVpc) fetchWires() error { networks := make([]cloudprovider.ICloudNetwork, len(self.Properties.Subnets)) wire := SClassicWire{zone: self.region.izones[0].(*SZone), vpc: self} diff --git a/pkg/util/azure/vpc.go b/pkg/util/azure/vpc.go index 07060c4a4c..3d4bb02dff 100644 --- a/pkg/util/azure/vpc.go +++ b/pkg/util/azure/vpc.go @@ -148,6 +148,11 @@ func (self *SVpc) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGroup, err return self.secgroups, nil } +func (self *SVpc) GetIRouteTables() ([]cloudprovider.ICloudRouteTable, error) { + rts := []cloudprovider.ICloudRouteTable{} + return rts, nil +} + func (self *SVpc) fetchWires() error { networks := make([]cloudprovider.ICloudNetwork, len(*self.Properties.Subnets)) if len(self.region.izones) == 0 { diff --git a/pkg/util/qcloud/vpc.go b/pkg/util/qcloud/vpc.go index 5aee1b7161..ba59f5609f 100644 --- a/pkg/util/qcloud/vpc.go +++ b/pkg/util/qcloud/vpc.go @@ -86,6 +86,11 @@ func (self *SVpc) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGroup, err return isecgroups, nil } +func (self *SVpc) GetIRouteTables() ([]cloudprovider.ICloudRouteTable, error) { + rts := []cloudprovider.ICloudRouteTable{} + return rts, nil +} + func (self *SVpc) getWireByZoneId(zoneId string) *SWire { for i := 0; i <= len(self.iwires); i++ { wire := self.iwires[i].(*SWire) From 21dc71f97ccf994f97d7c4addb650f6e49f86313 Mon Sep 17 00:00:00 2001 From: Yousong Zhou Date: Thu, 22 Nov 2018 14:42:14 +0000 Subject: [PATCH 16/19] =?UTF-8?q?climc:=20loadbalanceracls:=20=E8=BD=AC?= =?UTF-8?q?=E6=8D=A2=E5=87=BA=E7=8E=B0=E5=BC=82=E5=B8=B8=E5=8D=B3=E8=BF=94?= =?UTF-8?q?=E5=9B=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/climc/shell/loadbalanceracls.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/climc/shell/loadbalanceracls.go b/cmd/climc/shell/loadbalanceracls.go index 085f116d56..70f3baf9ed 100644 --- a/cmd/climc/shell/loadbalanceracls.go +++ b/cmd/climc/shell/loadbalanceracls.go @@ -43,6 +43,7 @@ func init() { err := lbAclConvert(jd) if err != nil { printList(list, columns) + return } } printList(list, columns) From bec79cde6af9f24242ddc18bc7d79fccc030019c Mon Sep 17 00:00:00 2001 From: Zexi Li Date: Fri, 23 Nov 2018 14:18:41 +0800 Subject: [PATCH 17/19] host ping catalog add elasticsearch service --- pkg/compute/models/hosts.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/compute/models/hosts.go b/pkg/compute/models/hosts.go index 79028ba701..abdc39a9e1 100644 --- a/pkg/compute/models/hosts.go +++ b/pkg/compute/models/hosts.go @@ -2331,7 +2331,8 @@ func (self *SHost) PerformPing(ctx context.Context, userCred mcclient.TokenCrede } result := jsonutils.NewDict() result.Set("name", jsonutils.NewString(self.GetName())) - catalog := auth.GetCatalogData([]string{"ntpd", "kafka", "influxdb"}, options.Options.Region) + dependSvcs := []string{"ntpd", "kafka", "influxdb", "elasticsearch"} + catalog := auth.GetCatalogData(dependSvcs, options.Options.Region) if catalog == nil { return nil, fmt.Errorf("Get catalog error") } From 46b67e9dc97834baae30515e55170311d13450a6 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Fri, 23 Nov 2018 15:03:22 +0800 Subject: [PATCH 18/19] minor updates --- pkg/cloudcommon/db/opslog.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cloudcommon/db/opslog.go b/pkg/cloudcommon/db/opslog.go index acc19deefe..35ef9c13e2 100644 --- a/pkg/cloudcommon/db/opslog.go +++ b/pkg/cloudcommon/db/opslog.go @@ -153,7 +153,7 @@ type SOpsLog struct { ObjId string `width:"128" charset:"ascii" nullable:"false" list:"user"` // = Column(VARCHAR(ID_LENGTH, charset='ascii'), nullable=False) ObjName string `width:"128" charset:"utf8" nullable:"false" list:"user"` //= Column(VARCHAR(128, charset='utf8'), nullable=False) Action string `width:"32" charset:"ascii" nullable:"false" list:"user"` //= Column(VARCHAR(32, charset='ascii'), nullable=False) - Notes string `width:"2048" charset:"utf8" list:"user"` // = Column(VARCHAR(1024, charset='utf8')) + Notes string `width:"2048" charset:"utf8" list:"user"` // = Column(VARCHAR(2048, charset='utf8')) ProjectId string `name:"tenant_id" width:"128" charset:"ascii" list:"user"` // = Column(VARCHAR(ID_LENGTH, charset='ascii')) Project string `name:"tenant" width:"128" charset:"utf8" list:"user"` // tenant = Column(VARCHAR(128, charset='utf8')) UserId string `width:"128" charset:"ascii" list:"user"` // = Column(VARCHAR(ID_LENGTH, charset='ascii')) From 58962cf2d2694264678c07670e275641b480bdb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B1=88=E8=BD=A9?= Date: Fri, 23 Nov 2018 19:07:20 +0800 Subject: [PATCH 19/19] =?UTF-8?q?=E9=81=BF=E5=85=8Dlocaltask=20failed?= =?UTF-8?q?=E6=97=B6error=E4=B8=80=E7=9B=B4=E6=98=AFTask=20failed=20due=20?= =?UTF-8?q?to=20unknown=20remote=20errors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/cloudcommon/db/taskman/localtaskworker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cloudcommon/db/taskman/localtaskworker.go b/pkg/cloudcommon/db/taskman/localtaskworker.go index 2e5ac395e9..52c479b83e 100644 --- a/pkg/cloudcommon/db/taskman/localtaskworker.go +++ b/pkg/cloudcommon/db/taskman/localtaskworker.go @@ -18,7 +18,7 @@ func init() { func error2TaskData(err error) jsonutils.JSONObject { errJson := jsonutils.NewDict() errJson.Add(jsonutils.NewString("ERROR"), "__status__") - errJson.Add(jsonutils.NewString(err.Error()), "reason") + errJson.Add(jsonutils.NewString(err.Error()), "__reason__") return errJson }