From 4dd3945804adb08d94dd32285e7b643a39ee79a2 Mon Sep 17 00:00:00 2001 From: Yousong Zhou Date: Mon, 14 Dec 2020 22:46:07 +0800 Subject: [PATCH] feat(region): guestdrivers: guest forward open, close, list methods --- pkg/compute/guestdrivers/base.go | 13 ++ pkg/compute/guestdrivers/kvm.go | 102 ++++++++++++ pkg/compute/guestdrivers/types/doc.go | 1 + .../guestdrivers/types/guest_forward.go | 150 ++++++++++++++++++ pkg/compute/models/guestdrivers.go | 5 + 5 files changed, 271 insertions(+) create mode 100644 pkg/compute/guestdrivers/types/doc.go create mode 100644 pkg/compute/guestdrivers/types/guest_forward.go diff --git a/pkg/compute/guestdrivers/base.go b/pkg/compute/guestdrivers/base.go index 41ed88c43b..b0fcb6a6bf 100644 --- a/pkg/compute/guestdrivers/base.go +++ b/pkg/compute/guestdrivers/base.go @@ -27,6 +27,7 @@ import ( "yunion.io/x/onecloud/pkg/cloudcommon/db/quotas" "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" "yunion.io/x/onecloud/pkg/cloudprovider" + guestdriver_types "yunion.io/x/onecloud/pkg/compute/guestdrivers/types" "yunion.io/x/onecloud/pkg/compute/models" "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" @@ -115,6 +116,18 @@ func (self *SBaseGuestDriver) RequestAttachDisk(ctx context.Context, guest *mode return nil } +func (self *SBaseGuestDriver) RequestOpenForward(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, req *guestdriver_types.OpenForwardRequest) (*guestdriver_types.OpenForwardResponse, error) { + return nil, cloudprovider.ErrNotImplemented +} + +func (self *SBaseGuestDriver) RequestListForward(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, req *guestdriver_types.ListForwardRequest) (*guestdriver_types.ListForwardResponse, error) { + return nil, cloudprovider.ErrNotImplemented +} + +func (self *SBaseGuestDriver) RequestCloseForward(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, req *guestdriver_types.CloseForwardRequest) (*guestdriver_types.CloseForwardResponse, error) { + return nil, cloudprovider.ErrNotImplemented +} + func (self *SBaseGuestDriver) RequestSaveImage(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, task taskman.ITask) error { return errors.Wrapf(cloudprovider.ErrNotImplemented, "RequestSaveImage") } diff --git a/pkg/compute/guestdrivers/kvm.go b/pkg/compute/guestdrivers/kvm.go index 2d05c8075f..a6cd7a9dd8 100644 --- a/pkg/compute/guestdrivers/kvm.go +++ b/pkg/compute/guestdrivers/kvm.go @@ -28,11 +28,13 @@ import ( "yunion.io/x/sqlchemy" api "yunion.io/x/onecloud/pkg/apis/compute" + host_api "yunion.io/x/onecloud/pkg/apis/host" "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman" "yunion.io/x/onecloud/pkg/cloudcommon/db/quotas" "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" "yunion.io/x/onecloud/pkg/cloudprovider" + guestdriver_types "yunion.io/x/onecloud/pkg/compute/guestdrivers/types" "yunion.io/x/onecloud/pkg/compute/models" "yunion.io/x/onecloud/pkg/compute/options" "yunion.io/x/onecloud/pkg/httperrors" @@ -444,6 +446,106 @@ func (self *SKVMGuestDriver) RequestSaveImage(ctx context.Context, userCred mccl return disks.Root.StartDiskSaveTask(ctx, userCred, opts, task.GetTaskId()) } +func (self *SKVMGuestDriver) RequestOpenForward(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, req *guestdriver_types.OpenForwardRequest) (*guestdriver_types.OpenForwardResponse, error) { + var ( + host = guest.GetHost() + url = fmt.Sprintf("%s/servers/%s/open-forward", host.ManagerUri, guest.Id) + httpClient = httputils.GetDefaultClient() + header = mcclient.GetTokenHeaders(userCred) + hostreq = &host_api.GuestOpenForwardRequest{ + NetworkId: req.NetworkId, + Proto: req.Proto, + Addr: req.Addr, + Port: req.Port, + } + body = jsonutils.Marshal(hostreq) + ) + _, respBody, err := httputils.JSONRequest(httpClient, ctx, "POST", url, header, body, false) + if err != nil { + return nil, errors.Wrap(err, "host request") + } + hostresp := &host_api.GuestOpenForwardResponse{} + if err := respBody.Unmarshal(hostresp); err != nil { + return nil, errors.Wrap(err, "unmarshal host response") + } + resp := &guestdriver_types.OpenForwardResponse{ + Proto: hostresp.Proto, + ProxyAddr: hostresp.ProxyAddr, + ProxyPort: hostresp.ProxyPort, + Addr: hostresp.Addr, + Port: hostresp.Port, + } + return resp, nil +} + +func (self *SKVMGuestDriver) RequestCloseForward(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, req *guestdriver_types.CloseForwardRequest) (*guestdriver_types.CloseForwardResponse, error) { + var ( + host = guest.GetHost() + url = fmt.Sprintf("%s/servers/%s/close-forward", host.ManagerUri, guest.Id) + httpClient = httputils.GetDefaultClient() + header = mcclient.GetTokenHeaders(userCred) + hostreq = &host_api.GuestCloseForwardRequest{ + NetworkId: req.NetworkId, + Proto: req.Proto, + ProxyAddr: req.ProxyAddr, + ProxyPort: req.ProxyPort, + } + body = jsonutils.Marshal(hostreq) + ) + _, respBody, err := httputils.JSONRequest(httpClient, ctx, "POST", url, header, body, false) + if err != nil { + return nil, errors.Wrap(err, "host request") + } + hostresp := &host_api.GuestCloseForwardResponse{} + if err := respBody.Unmarshal(hostresp); err != nil { + return nil, errors.Wrap(err, "unmarshal host response") + } + resp := &guestdriver_types.CloseForwardResponse{ + Proto: hostresp.Proto, + ProxyAddr: hostresp.ProxyAddr, + ProxyPort: hostresp.ProxyPort, + } + return resp, nil +} + +func (self *SKVMGuestDriver) RequestListForward(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, req *guestdriver_types.ListForwardRequest) (*guestdriver_types.ListForwardResponse, error) { + var ( + host = guest.GetHost() + url = fmt.Sprintf("%s/servers/%s/list-forward", host.ManagerUri, guest.Id) + httpClient = httputils.GetDefaultClient() + header = mcclient.GetTokenHeaders(userCred) + hostreq = &host_api.GuestListForwardRequest{ + NetworkId: req.NetworkId, + Proto: req.Proto, + Addr: req.Addr, + Port: req.Port, + } + body = jsonutils.Marshal(hostreq) + ) + _, respBody, err := httputils.JSONRequest(httpClient, ctx, "POST", url, header, body, false) + if err != nil { + return nil, errors.Wrap(err, "host request") + } + hostresp := &host_api.GuestListForwardResponse{} + if err := respBody.Unmarshal(hostresp); err != nil { + return nil, errors.Wrap(err, "unmarshal host response") + } + var respForwards []guestdriver_types.OpenForwardResponse + for i := range hostresp.Forwards { + respForwards = append(respForwards, guestdriver_types.OpenForwardResponse{ + Proto: hostresp.Forwards[i].Proto, + ProxyAddr: hostresp.Forwards[i].ProxyAddr, + ProxyPort: hostresp.Forwards[i].ProxyPort, + Addr: hostresp.Forwards[i].Addr, + Port: hostresp.Forwards[i].Port, + }) + } + resp := &guestdriver_types.ListForwardResponse{ + Forwards: respForwards, + } + return resp, nil +} + func (self *SKVMGuestDriver) GetDetachDiskStatus() ([]string, error) { return []string{api.VM_READY, api.VM_RUNNING}, nil } diff --git a/pkg/compute/guestdrivers/types/doc.go b/pkg/compute/guestdrivers/types/doc.go new file mode 100644 index 0000000000..a1d847e385 --- /dev/null +++ b/pkg/compute/guestdrivers/types/doc.go @@ -0,0 +1 @@ +package types // import "yunion.io/x/onecloud/pkg/compute/guestdrivers/types" diff --git a/pkg/compute/guestdrivers/types/guest_forward.go b/pkg/compute/guestdrivers/types/guest_forward.go new file mode 100644 index 0000000000..56405155da --- /dev/null +++ b/pkg/compute/guestdrivers/types/guest_forward.go @@ -0,0 +1,150 @@ +// Copyright 2019 Yunion +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "yunion.io/x/jsonutils" + + compute_api "yunion.io/x/onecloud/pkg/apis/compute" + "yunion.io/x/onecloud/pkg/cloudcommon/validators" + "yunion.io/x/onecloud/pkg/httperrors" +) + +type OpenForwardRequest struct { + NetworkId string `json:"network_id"` + Proto string `json:"proto"` + Addr string `json:"addr"` + Port int `json:"port"` +} + +type OpenForwardResponse struct { + Proto string `json:"proto"` + ProxyAddr string `json:"proxy_addr"` + ProxyPort int `json:"proxy_port"` + Addr string `json:"addr"` + Port int `json:"port"` +} + +func NewOpenForwardRequestFromJSON(data jsonutils.JSONObject) (*OpenForwardRequest, error) { + dict, ok := data.(*jsonutils.JSONDict) + if !ok { + return nil, httperrors.ErrInputParameter + } + var ( + protoV = validators.NewStringChoicesValidator("proto", compute_api.GuestForwardProtoChoices) + portV = validators.NewPortValidator("port") + ) + for _, v := range []validators.IValidator{ + protoV.Default(compute_api.GuestForwardProtoTCP), + portV, + } { + if err := v.Validate(dict); err != nil { + return nil, err + } + } + req := &OpenForwardRequest{ + Proto: protoV.Value, + Port: int(portV.Value), + } + return req, nil +} + +func (resp *OpenForwardResponse) JSON() jsonutils.JSONObject { + return jsonutils.Marshal(resp) +} + +type CloseForwardRequest struct { + NetworkId string `json:"network_id"` + Proto string `json:"proto"` + ProxyAddr string `json:"addr"` + ProxyPort int `json:"port"` +} + +type CloseForwardResponse struct { + NetworkId string `json:"network_id"` + Proto string `json:"proto"` + ProxyAddr string `json:"addr"` + ProxyPort int `json:"port"` +} + +func NewCloseForwardRequestFromJSON(data jsonutils.JSONObject) (*CloseForwardRequest, error) { + dict, ok := data.(*jsonutils.JSONDict) + if !ok { + return nil, httperrors.ErrInputParameter + } + var ( + protoV = validators.NewStringChoicesValidator("proto", compute_api.GuestForwardProtoChoices) + proxyAddrV = validators.NewIPv4AddrValidator("proxy_addr") + proxyPortV = validators.NewPortValidator("proxy_port") + ) + for _, v := range []validators.IValidator{ + protoV, + proxyAddrV, + proxyPortV, + } { + if err := v.Validate(dict); err != nil { + return nil, err + } + } + req := &CloseForwardRequest{ + Proto: protoV.Value, + ProxyAddr: proxyAddrV.IP.String(), + ProxyPort: int(proxyPortV.Value), + } + return req, nil +} + +func (resp *CloseForwardResponse) JSON() jsonutils.JSONObject { + return jsonutils.Marshal(resp) +} + +type ListForwardRequest struct { + NetworkId string `json:"network_id"` + Proto string `json:"proto"` + Addr string `json:"addr"` + Port int `json:"port"` +} + +type ListForwardResponse struct { + Forwards []OpenForwardResponse `json:"forwards"` +} + +func NewListForwardRequestFromJSON(data jsonutils.JSONObject) (*ListForwardRequest, error) { + dict, ok := data.(*jsonutils.JSONDict) + if !ok { + return nil, httperrors.ErrInputParameter + } + var ( + protoV = validators.NewStringChoicesValidator("proto", compute_api.GuestForwardProtoChoices) + portV = validators.NewPortValidator("port") + ) + for _, v := range []validators.IValidator{ + protoV.Optional(true), + portV.Optional(true), + } { + if err := v.Validate(dict); err != nil { + return nil, err + } + } + req := &ListForwardRequest{ + Proto: protoV.Value, + Port: int(portV.Value), + } + return req, nil +} + +func (resp *ListForwardResponse) JSON() jsonutils.JSONObject { + return jsonutils.Marshal(resp) +} diff --git a/pkg/compute/models/guestdrivers.go b/pkg/compute/models/guestdrivers.go index bb7d5e8214..5009b6a9cd 100644 --- a/pkg/compute/models/guestdrivers.go +++ b/pkg/compute/models/guestdrivers.go @@ -25,6 +25,7 @@ import ( "yunion.io/x/onecloud/pkg/cloudcommon/db/quotas" "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" "yunion.io/x/onecloud/pkg/cloudprovider" + guestdriver_types "yunion.io/x/onecloud/pkg/compute/guestdrivers/types" "yunion.io/x/onecloud/pkg/mcclient" "yunion.io/x/onecloud/pkg/util/billing" "yunion.io/x/onecloud/pkg/util/rbacutils" @@ -207,6 +208,10 @@ type IGuestDriver interface { RequestLiveMigrate(ctx context.Context, guest *SGuest, userCred mcclient.TokenCredential, data *jsonutils.JSONDict, task taskman.ITask) error RequestRemoteUpdate(ctx context.Context, guest *SGuest, userCred mcclient.TokenCredential, replaceTags bool) error + + RequestOpenForward(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, req *guestdriver_types.OpenForwardRequest) (*guestdriver_types.OpenForwardResponse, error) + RequestListForward(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, req *guestdriver_types.ListForwardRequest) (*guestdriver_types.ListForwardResponse, error) + RequestCloseForward(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, req *guestdriver_types.CloseForwardRequest) (*guestdriver_types.CloseForwardResponse, error) } var guestDrivers map[string]IGuestDriver