guestscreendump.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package models
  2. import (
  3. "context"
  4. "encoding/base64"
  5. "fmt"
  6. "io"
  7. "net/http"
  8. "strings"
  9. "yunion.io/x/cloudmux/pkg/multicloud/objectstore"
  10. "yunion.io/x/jsonutils"
  11. "yunion.io/x/pkg/errors"
  12. "yunion.io/x/sqlchemy"
  13. api "yunion.io/x/onecloud/pkg/apis/compute"
  14. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  15. "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
  16. "yunion.io/x/onecloud/pkg/httperrors"
  17. "yunion.io/x/onecloud/pkg/mcclient"
  18. "yunion.io/x/onecloud/pkg/util/logclient"
  19. )
  20. type SGuestScreenDumpManager struct {
  21. db.SResourceBaseManager
  22. }
  23. var GuestScreenDumpManager *SGuestScreenDumpManager
  24. func init() {
  25. db.InitManager(func() {
  26. GuestScreenDumpManager = &SGuestScreenDumpManager{
  27. SResourceBaseManager: db.NewResourceBaseManager(
  28. SGuestScreenDump{},
  29. "guest_screen_dumps_tbl",
  30. "guest_screen_dump",
  31. "guest_screen_dumps",
  32. ),
  33. }
  34. GuestScreenDumpManager.SetVirtualObject(GuestScreenDumpManager)
  35. GuestScreenDumpManager.TableSpec().AddIndex(true, "guest_id")
  36. })
  37. }
  38. type SGuestScreenDump struct {
  39. db.SResourceBase
  40. RowId int64 `primary:"true" auto_increment:"true" list:"user"`
  41. GuestId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required"`
  42. Name string `width:"64" charset:"ascii" nullable:"true" list:"user"`
  43. // s3 config
  44. S3AccessKey string `width:"64" charset:"ascii" nullable:"true"`
  45. S3SecretKey string `width:"64" charset:"ascii" nullable:"true"`
  46. S3Endpoint string `width:"64" charset:"ascii" nullable:"true" list:"user"`
  47. S3BucketName string `width:"64" charset:"ascii" nullable:"true" list:"user"`
  48. S3UseSsl bool `default:"false" list:"user" create:"optional"`
  49. }
  50. func (manager *SGuestScreenDumpManager) ListItemFilter(
  51. ctx context.Context,
  52. q *sqlchemy.SQuery,
  53. userCred mcclient.TokenCredential,
  54. query api.GuestScreenDumpListInput,
  55. ) (*sqlchemy.SQuery, error) {
  56. if query.Server != "" {
  57. iGuest, err := GuestManager.FetchByIdOrName(ctx, userCred, query.Server)
  58. if err != nil {
  59. return q, errors.Wrap(err, "fetch guest")
  60. }
  61. q = q.Equals("guest_id", iGuest.GetId())
  62. }
  63. return q, nil
  64. }
  65. func (self *SGuestScreenDump) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
  66. return db.DeleteModel(ctx, userCred, self)
  67. }
  68. func (self *SGuest) SaveGuestScreenDump(ctx context.Context, userCred mcclient.TokenCredential, screenDumpInfo *api.SGuestScreenDumpInfo) (*SGuestScreenDump, error) {
  69. sd := new(SGuestScreenDump)
  70. sd.SetModelManager(GuestScreenDumpManager, sd)
  71. sd.GuestId = self.GetId()
  72. sd.S3SecretKey = base64.StdEncoding.EncodeToString([]byte(screenDumpInfo.S3SecretKey))
  73. sd.S3Endpoint = screenDumpInfo.S3Endpoint
  74. sd.S3BucketName = screenDumpInfo.S3BucketName
  75. sd.S3AccessKey = base64.StdEncoding.EncodeToString([]byte(screenDumpInfo.S3AccessKey))
  76. sd.Name = screenDumpInfo.S3ObjectName
  77. lockman.LockClass(ctx, GuestScreenDumpManager, self.ProjectId)
  78. defer lockman.ReleaseClass(ctx, GuestScreenDumpManager, self.ProjectId)
  79. err := GuestScreenDumpManager.TableSpec().Insert(ctx, sd)
  80. if err != nil {
  81. return nil, errors.Wrap(err, "save guest screen_dump")
  82. }
  83. db.OpsLog.LogEvent(self, db.ACT_GUEST_SCREEN_DUMP, sd.Name, userCred)
  84. logclient.AddSimpleActionLog(self, logclient.ACT_GUEST_SCREEN_DUMP, sd.Name, userCred, true)
  85. return sd, nil
  86. }
  87. func (self *SGuest) GetDetailsScreenDumpShow(ctx context.Context, userCred mcclient.TokenCredential, input *api.GetDetailsGuestScreenDumpInput) (*api.GetDetailsGuestScreenDumpOutput, error) {
  88. if input.ObjectName == "" {
  89. return nil, httperrors.NewMissingParameterError("object_name")
  90. }
  91. q := GuestScreenDumpManager.Query()
  92. q = q.Equals("guest_id", self.Id)
  93. q = q.Equals("name", input.ObjectName)
  94. screenDump := new(SGuestScreenDump)
  95. err := q.First(screenDump)
  96. if err != nil {
  97. return nil, errors.Wrap(err, "query screenDump")
  98. }
  99. ak, _ := base64.StdEncoding.DecodeString(screenDump.S3AccessKey)
  100. sk, _ := base64.StdEncoding.DecodeString(screenDump.S3SecretKey)
  101. url := screenDump.S3Endpoint
  102. if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
  103. prefix := "http://"
  104. if screenDump.S3UseSsl {
  105. prefix = "https://"
  106. }
  107. url = prefix + url
  108. }
  109. cfg := objectstore.NewObjectStoreClientConfig(url, string(ak), string(sk))
  110. s3Client, err := objectstore.NewObjectStoreClient(cfg)
  111. if err != nil {
  112. return nil, errors.Wrap(err, "new minio client")
  113. }
  114. bucket, err := s3Client.GetIBucketByName(screenDump.S3BucketName)
  115. if err != nil {
  116. return nil, errors.Wrapf(err, "get bucket %s", screenDump.S3BucketName)
  117. }
  118. irc, err := bucket.GetObject(ctx, screenDump.Name, nil)
  119. if err != nil {
  120. return nil, errors.Wrapf(err, "get object %s", screenDump.Name)
  121. }
  122. defer irc.Close()
  123. obj, err := io.ReadAll(irc)
  124. if err != nil {
  125. return nil, errors.Wrapf(err, "read object %s", screenDump.Name)
  126. }
  127. ret := new(api.GetDetailsGuestScreenDumpOutput)
  128. contentType := http.DetectContentType(obj)
  129. base64Encoded := base64.StdEncoding.EncodeToString(obj)
  130. ret.ScreenDump = fmt.Sprintf("data:%s;base64,%s", contentType, base64Encoded)
  131. ret.ScreenDump = base64.StdEncoding.EncodeToString(obj)
  132. ret.GuestId = self.Id
  133. ret.Name = screenDump.Name
  134. return ret, nil
  135. }
  136. func (self *SGuest) PerformScreenDump(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject,
  137. data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  138. if self.PowerStates != api.VM_POWER_STATES_ON {
  139. return nil, httperrors.NewBadRequestError("can't use qga in vm status: %s", self.Status)
  140. }
  141. host, _ := self.GetHost()
  142. driver, err := self.GetDriver()
  143. if err != nil {
  144. return nil, err
  145. }
  146. return driver.RequestGuestScreenDump(ctx, userCred, nil, host, self)
  147. }