From 9365da05f64000d4bfedbecb298c3820dc7ac189 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Mon, 10 Sep 2018 14:15:43 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=EF=BC=9Aserver-associate-eip?= =?UTF-8?q?/server-dissociate-eip=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/climc/shell/servers.go | 27 +++++++++++ pkg/compute/models/guests.go | 87 ++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/cmd/climc/shell/servers.go b/cmd/climc/shell/servers.go index d729f76ff5..a30a759422 100644 --- a/cmd/climc/shell/servers.go +++ b/cmd/climc/shell/servers.go @@ -392,4 +392,31 @@ func init() { printObject(results) return nil }) + + type ServerAssociateEipOptions struct { + ID string `help:"ID or name of server"` + EIP string `help:"ID or name of EIP to associate"` + } + R(&ServerAssociateEipOptions{}, "server-associate-eip", "Associate a server and an eip", func(s *mcclient.ClientSession, args *ServerAssociateEipOptions) error { + params := jsonutils.NewDict() + params.Add(jsonutils.NewString(args.EIP), "eip") + results, err := modules.Servers.PerformAction(s, args.ID, "associate-eip", params) + if err != nil { + return err + } + printObject(results) + return nil + }) + + type ServerDissociateEipOptions struct { + ID string `help:"ID or name of server"` + } + R(&ServerDissociateEipOptions{}, "server-dissociate-eip", "Dissociate an eip from a server", func(s *mcclient.ClientSession, args *ServerDissociateEipOptions) error { + result, err := modules.Servers.PerformAction(s, args.ID, "dissociate-eip", nil) + if err != nil { + return nil + } + printObject(result) + return nil + }) } diff --git a/pkg/compute/models/guests.go b/pkg/compute/models/guests.go index c13790530d..f50fa8cc3c 100644 --- a/pkg/compute/models/guests.go +++ b/pkg/compute/models/guests.go @@ -3676,6 +3676,93 @@ func (self *SGuest) GetIVM() (cloudprovider.ICloudVM, error) { return ihost.GetIVMById(self.ExternalId) } +func (self *SGuest) AllowPerformAssociateEip(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { + return self.IsOwner(userCred) +} + +func (self *SGuest) PerformAssociateEip(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { + if !utils.IsInStringArray(self.Status, []string{VM_READY, VM_RUNNING}) { + return nil, httperrors.NewInvalidStatusError("cannot associate eip in status %s", self.Status) + } + + eip, err := self.GetEip() + if err != nil { + log.Errorf("Fail to get Eip %s", err) + return nil, httperrors.NewGeneralError(err) + } + if eip != nil { + return nil, httperrors.NewInvalidStatusError("already associate with eip") + } + eipStr := jsonutils.GetAnyString(data, []string{"eip", "eip_id"}) + if len(eipStr) == 0 { + return nil, httperrors.NewInputParameterError("missing eip or eip_id") + } + eipObj, err := ElasticipManager.FetchByIdOrName(userCred.GetProjectId(), eipStr) + if err != nil { + if err == sql.ErrNoRows { + return nil, httperrors.NewResourceNotFoundError("eip %s not found", eipStr) + } else { + return nil, httperrors.NewGeneralError(err) + } + } + + eip = eipObj.(*SElasticip) + eipRegion := eip.GetRegion() + instRegion := self.getRegion() + + if eip.Mode == EIP_MODE_INSTANCE_PUBLICIP { + return nil, httperrors.NewUnsupportOperationError("fixed eip cannot be associated") + } + + eipVm := eip.getVM() + if eipVm != nil { + return nil, httperrors.NewConflictError("eip has been associated") + } + + if eipRegion.Id != instRegion.Id { + return nil, httperrors.NewInputParameterError("cannot associate eip and instance in different region") + } + + host := self.GetHost() + if host == nil { + return nil, httperrors.NewInputParameterError("server host is not found???") + } + + if host.ManagerId != eip.ManagerId { + return nil, httperrors.NewInputParameterError("cannot associate eip and instance in different provider") + } + + params := jsonutils.NewDict() + params.Add(jsonutils.NewString(self.ExternalId), "instance_external_id") + params.Add(jsonutils.NewString(self.Id), "instance_id") + params.Add(jsonutils.NewString(EIP_ASSOCIATE_TYPE_SERVER), "instance_type") + + err = eip.StartEipAssociateTask(ctx, userCred, params) + + return nil, err +} + +func (self *SGuest) AllowPerformDissociateEip(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { + return self.IsOwner(userCred) +} + +func (self *SGuest) PerformDissociateEip(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { + eip, err := self.GetEip() + if err != nil { + log.Errorf("Fail to get Eip %s", err) + return nil, httperrors.NewGeneralError(err) + } + if eip == nil { + return nil, httperrors.NewInvalidStatusError("No eip to dissociate") + } + err = eip.StartEipDissociateTask(ctx, userCred, "") + if err != nil { + log.Errorf("fail to start dissociate task %s", err) + return nil, httperrors.NewGeneralError(err) + } + return nil, nil +} + func (self *SGuest) AllowPerformCreateEip(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { return self.IsOwner(userCred) }