| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- // 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 session
- import (
- "context"
- "yunion.io/x/jsonutils"
- "yunion.io/x/pkg/errors"
- compute_api "yunion.io/x/onecloud/pkg/apis/compute"
- "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
- "yunion.io/x/onecloud/pkg/httperrors"
- "yunion.io/x/onecloud/pkg/mcclient"
- "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
- modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
- options "yunion.io/x/onecloud/pkg/mcclient/options/compute"
- )
- type SSshConnectionInfo struct {
- IP string `json:"ip"`
- Port int `json:"port"`
- Username string `json:"username"`
- KeepUsername bool `json:"keep_username"`
- Password string `json:"password"`
- Name string `json:"name"`
- ResourceType string `json:"resource_type" choices:"host|server"`
- GuestDetails *compute_api.ServerDetails
- HostDetails *compute_api.HostDetails
- }
- func ResolveServerSSHIPPortById(ctx context.Context, s *mcclient.ClientSession, id string, ip string, port int) (string, int, *compute_api.ServerDetails, error) {
- if port <= 0 {
- port = 22
- }
- return resolveServerIPPortById(ctx, s, id, ip, port)
- }
- func resolveServerIPPortById(ctx context.Context, s *mcclient.ClientSession, id string, ip string, port int) (string, int, *compute_api.ServerDetails, error) {
- guestDetails, err := FetchServerInfo(ctx, s, id)
- if err != nil {
- return "", 0, nil, errors.Wrap(err, "fetchServerInfo")
- }
- // list all nic of a server
- input := compute_api.GuestnetworkListInput{}
- input.ServerId = guestDetails.Id
- True := true
- input.Details = &True
- input.ServerFilterListInput.Scope = "max"
- result, err := compute.Servernetworks.List(s, jsonutils.Marshal(input))
- if err != nil {
- return "", 0, nil, errors.Wrap(err, "Servernetworks.List")
- }
- if result.Total == 0 {
- // not nic found!!!
- return "", 0, nil, errors.Wrap(httperrors.ErrNotFound, "no nic on server")
- }
- // find nics
- var guestNicDetails *compute_api.GuestnetworkDetails
- if result.Total == 1 {
- gn := compute_api.GuestnetworkDetails{}
- err := result.Data[0].Unmarshal(&gn)
- if err != nil {
- return "", 0, nil, errors.Wrap(err, "Unmarshal guest network info")
- }
- if len(ip) > 0 && ip != gn.EipAddr && ip != gn.IpAddr && ip != gn.Ip6Addr && ip != guestDetails.Eip {
- return "", 0, nil, errors.Wrapf(httperrors.ErrInputParameter, "ip %s not match with server", ip)
- }
- guestNicDetails = &gn
- } else {
- if len(ip) == 0 {
- return "", 0, nil, errors.Wrap(httperrors.ErrInputParameter, "must specify ip")
- }
- for _, gnJson := range result.Data {
- gn := compute_api.GuestnetworkDetails{}
- err := gnJson.Unmarshal(&gn)
- if err != nil {
- return "", 0, nil, errors.Wrap(err, "Unmarshal guest network info")
- }
- if ip == gn.EipAddr || ip == gn.IpAddr || ip == gn.Ip6Addr {
- guestNicDetails = &gn
- break
- }
- }
- if guestNicDetails == nil {
- return "", 0, nil, errors.Wrap(httperrors.ErrInputParameter, "ip specified not match with server")
- }
- }
- if len(ip) == 0 {
- // guest ip
- if len(guestNicDetails.EipAddr) > 0 {
- ip = guestNicDetails.EipAddr
- } else if len(guestNicDetails.IpAddr) > 0 {
- ip = guestNicDetails.IpAddr
- } else if len(guestNicDetails.Ip6Addr) > 0 {
- ip = guestNicDetails.Ip6Addr
- } else {
- return "", 0, nil, errors.Wrap(httperrors.ErrNotSupported, "no valid ipv4 addr")
- }
- }
- if ip == guestNicDetails.IpAddr && len(guestNicDetails.MappedIpAddr) > 0 {
- // need to do open forward
- ip, port, err = acquireForward(ctx, s, guestDetails.Id, ip, "tcp", port)
- if err != nil {
- return "", 0, nil, errors.Wrap(err, "acquireForward")
- }
- }
- return ip, port, guestDetails, nil
- }
- func ResolveHostSSHIPPortById(ctx context.Context, s *mcclient.ClientSession, id string, ip string, port int) (string, int, *compute_api.HostDetails, error) {
- if port <= 0 {
- port = 22
- }
- hostDetails, err := FetchHostInfo(ctx, s, id)
- if err != nil {
- return "", 0, nil, errors.Wrap(err, "fetchServerInfo")
- }
- return hostDetails.AccessIp, port, hostDetails, nil
- }
- type sForwardInfo struct {
- ProxyAddr string `json:"proxy_addr"`
- ProxyPort int `json:"proxy_port"`
- }
- func acquireForward(ctx context.Context, session *mcclient.ClientSession, srvid string, ip string, proto string, port int) (string, int, error) {
- lockman.LockRawObject(ctx, "server", srvid)
- defer lockman.ReleaseRawObject(ctx, "server", srvid)
- addr, nport, err := listForward(session, srvid, ip, proto, port)
- if err == nil {
- return addr, nport, nil
- }
- if errors.Cause(err) == httperrors.ErrNotFound {
- return openForward(session, srvid, ip, proto, port)
- } else {
- return "", 0, errors.Wrap(err, "listForward")
- }
- }
- func listForward(session *mcclient.ClientSession, srvid string, ip string, proto string, port int) (string, int, error) {
- opt := &options.ServerListForwardOptions{
- ServerIdOptions: options.ServerIdOptions{
- ID: srvid,
- },
- Proto: &proto,
- Port: &port,
- Addr: &ip,
- }
- params, err := opt.Params()
- if err != nil {
- return "", 0, errors.Wrap(err, "get list forward params")
- }
- jsonItem, err := modules.Servers.PerformAction(session, opt.ID, "list-forward", params)
- if err != nil {
- return "", 0, errors.Wrap(err, "list-forward")
- }
- if jsonItem.Contains("forwards") {
- infoList := make([]sForwardInfo, 0)
- err = jsonItem.Unmarshal(&infoList, "forwards")
- if err != nil {
- return "", 0, errors.Wrap(err, "Unmarshal forwards")
- }
- if len(infoList) > 0 {
- return infoList[0].ProxyAddr, infoList[0].ProxyPort, nil
- }
- }
- return "", 0, errors.Wrap(httperrors.ErrNotFound, "no forwards")
- }
- func openForward(session *mcclient.ClientSession, srvid string, ip string, proto string, port int) (string, int, error) {
- opt := &options.ServerOpenForwardOptions{
- ServerIdOptions: options.ServerIdOptions{
- ID: srvid,
- },
- Proto: proto,
- Port: port,
- Addr: ip,
- }
- params, err := opt.Params()
- if err != nil {
- return "", 0, errors.Wrap(err, "get open forward params")
- }
- jsonItem, err := modules.Servers.PerformAction(session, opt.ID, "open-forward", params)
- if err != nil {
- return "", 0, errors.Wrap(err, "open-forward")
- }
- info := sForwardInfo{}
- err = jsonItem.Unmarshal(&info)
- if err != nil {
- return "", 0, errors.Wrap(err, "Unmarshal")
- }
- return info.ProxyAddr, info.ProxyPort, nil
- }
|