remote_console.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package session
  15. import (
  16. "context"
  17. "fmt"
  18. "net/url"
  19. "os/exec"
  20. "strings"
  21. "yunion.io/x/cloudmux/pkg/cloudprovider"
  22. "yunion.io/x/jsonutils"
  23. "yunion.io/x/pkg/errors"
  24. api "yunion.io/x/onecloud/pkg/apis/webconsole"
  25. "yunion.io/x/onecloud/pkg/mcclient"
  26. modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
  27. "yunion.io/x/onecloud/pkg/webconsole/options"
  28. "yunion.io/x/onecloud/pkg/webconsole/recorder"
  29. )
  30. const (
  31. VNC = api.VNC
  32. RDP = api.RDP
  33. ALIYUN = api.ALIYUN
  34. QCLOUD = api.QCLOUD
  35. OPENSTACK = api.OPENSTACK
  36. SPICE = api.SPICE
  37. WMKS = api.WMKS
  38. WS = api.WS
  39. VMRC = api.VMRC
  40. ZSTACK = api.ZSTACK
  41. CTYUN = api.CTYUN
  42. HUAWEI = api.HUAWEI
  43. HCS = api.HCS
  44. APSARA = api.APSARA
  45. JDCLOUD = api.JDCLOUD
  46. CLOUDPODS = api.CLOUDPODS
  47. PROXMOX = api.PROXMOX
  48. VOLCENGINE = api.VOLC_ENGINE
  49. BAIDU = api.BAIDU
  50. SANGFOR = api.SANGFOR
  51. CNWARE = api.CNWARE
  52. KSYUN = api.KSYUN
  53. ECLOUD = api.ECLOUD
  54. )
  55. type RemoteConsoleInfo struct {
  56. cloudprovider.ServerVncOutput
  57. s *mcclient.ClientSession
  58. }
  59. func NewRemoteConsoleInfoByCloud(s *mcclient.ClientSession, serverId string, query jsonutils.JSONObject) (*RemoteConsoleInfo, error) {
  60. ret, err := modules.Servers.GetSpecific(s, serverId, "vnc", query)
  61. if err != nil {
  62. return nil, err
  63. }
  64. vncInfo := RemoteConsoleInfo{}
  65. err = ret.Unmarshal(&vncInfo)
  66. if err != nil {
  67. return nil, err
  68. }
  69. vncInfo.s = s
  70. if len(vncInfo.OsName) == 0 || len(vncInfo.VncPassword) == 0 {
  71. metadata, err := modules.Servers.GetSpecific(s, serverId, "metadata", nil)
  72. if err != nil {
  73. return nil, err
  74. }
  75. osName, _ := metadata.GetString("os_name")
  76. vncPasswd, _ := metadata.GetString("__vnc_password")
  77. vncInfo.OsName = osName
  78. vncInfo.VncPassword = vncPasswd
  79. }
  80. return &vncInfo, nil
  81. }
  82. // GetProtocol implements ISessionData interface
  83. func (info *RemoteConsoleInfo) GetProtocol() string {
  84. return info.Protocol
  85. }
  86. // GetCommand implements ISessionData interface
  87. func (info *RemoteConsoleInfo) GetCommand() *exec.Cmd {
  88. return nil
  89. }
  90. func (info *RemoteConsoleInfo) GetSafeCommandString() string {
  91. return ""
  92. }
  93. // Cleanup implements ISessionData interface
  94. func (info *RemoteConsoleInfo) Cleanup() error {
  95. return nil
  96. }
  97. // Connect implements ISessionData interface
  98. func (info *RemoteConsoleInfo) Connect() error {
  99. return nil
  100. }
  101. // Scan implements ISessionData interface
  102. func (info *RemoteConsoleInfo) Scan(byte, func(string)) {
  103. return
  104. }
  105. // IsNeedLogin implements ISessionData interface
  106. func (info *RemoteConsoleInfo) IsNeedLogin() (bool, error) {
  107. return false, nil
  108. }
  109. func (info *RemoteConsoleInfo) GetClientSession() *mcclient.ClientSession {
  110. return info.s
  111. }
  112. func (info *RemoteConsoleInfo) GetConnectParams() (string, error) {
  113. switch info.Protocol {
  114. case ALIYUN:
  115. return info.getAliyunURL()
  116. case APSARA:
  117. return info.getApsaraURL()
  118. case QCLOUD:
  119. return info.getQcloudURL()
  120. case CLOUDPODS:
  121. return info.getCloudpodsURL()
  122. case OPENSTACK, VMRC, ZSTACK, CTYUN, HUAWEI, HCS, JDCLOUD, PROXMOX, SANGFOR, BAIDU, CNWARE, KSYUN, ECLOUD:
  123. return info.Url, nil
  124. case VOLCENGINE:
  125. return info.getVolcEngineURL()
  126. default:
  127. return "", fmt.Errorf("Can't convert protocol %s to connect params", info.Protocol)
  128. }
  129. }
  130. func (info *RemoteConsoleInfo) GetPassword() string {
  131. if len(info.Password) != 0 {
  132. return info.Password
  133. }
  134. return info.VncPassword
  135. }
  136. func (info *RemoteConsoleInfo) GetId() string {
  137. return info.Id
  138. }
  139. func (info *RemoteConsoleInfo) getConnParamsURL(baseURL string, params url.Values) string {
  140. if params == nil {
  141. params = url.Values{}
  142. }
  143. params.Set("protocol", info.Protocol)
  144. queryURL := params.Encode()
  145. return fmt.Sprintf("%s?%s", baseURL, queryURL)
  146. }
  147. func (info *RemoteConsoleInfo) getQcloudURL() (string, error) {
  148. base := "https://img.qcloud.com/qcloud/app/active_vnc/index.html?InstanceVncUrl=" + info.Url
  149. return info.getConnParamsURL(base, nil), nil
  150. }
  151. func (info *RemoteConsoleInfo) getAliyunURL() (string, error) {
  152. isWindows := "false"
  153. if strings.EqualFold(info.OsName, "windows") {
  154. isWindows = "true"
  155. }
  156. vncUrl, err := url.QueryUnescape(info.Url)
  157. if err != nil {
  158. return "", errors.Wrap(err, "url.QueryUnescape")
  159. }
  160. return fmt.Sprintf("%s?vncUrl=%s&instanceId=%s&isWindows=%s", options.Options.AliyunConsoleAddr, vncUrl, info.InstanceId, isWindows), nil
  161. }
  162. func (info *RemoteConsoleInfo) getCloudpodsURL() (string, error) {
  163. base := fmt.Sprintf("%s/web-console/no-vnc", info.ApiServer)
  164. params := url.Values{
  165. "data": {info.ConnectParams},
  166. "instanceId": {info.InstanceId},
  167. "instanceName": {info.InstanceName},
  168. }
  169. return info.getConnParamsURL(base, params), nil
  170. }
  171. func (info *RemoteConsoleInfo) getVolcEngineURL() (string, error) {
  172. base := "https://console.volcengine.com/ecs/connect/vnc/"
  173. params := url.Values{
  174. "host": {info.Url},
  175. "Region": {info.Region},
  176. "name": {info.InstanceName},
  177. }
  178. return info.getConnParamsURL(base, params), nil
  179. }
  180. func (info *RemoteConsoleInfo) getApsaraURL() (string, error) {
  181. isWindows := "False"
  182. if info.OsName == "Windows" {
  183. isWindows = "True"
  184. }
  185. params := url.Values{
  186. "vncUrl": {info.Url},
  187. "instanceId": {info.InstanceId},
  188. "isWindows": {isWindows},
  189. "password": {info.Password},
  190. }
  191. return info.getConnParamsURL(options.Options.ApsaraConsoleAddr, params), nil
  192. }
  193. func (info *RemoteConsoleInfo) GetRecordObject() *recorder.Object {
  194. return nil
  195. }
  196. func (info *RemoteConsoleInfo) GetDisplayInfo(ctx context.Context) (*SDisplayInfo, error) {
  197. userInfo, err := fetchUserInfo(ctx, info.GetClientSession())
  198. if err != nil {
  199. return nil, errors.Wrap(err, "fetchUserInfo")
  200. }
  201. guestDetails, err := FetchServerInfo(ctx, info.GetClientSession(), info.Id)
  202. if err != nil {
  203. return nil, errors.Wrap(err, "FetchServerInfo")
  204. }
  205. dispInfo := SDisplayInfo{}
  206. dispInfo.WaterMark = fetchWaterMark(userInfo)
  207. dispInfo.fetchGuestInfo(guestDetails)
  208. return &dispInfo, nil
  209. }