isolated_device.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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 device
  15. import (
  16. "context"
  17. "yunion.io/x/jsonutils"
  18. "yunion.io/x/pkg/errors"
  19. "yunion.io/x/pkg/util/sets"
  20. "yunion.io/x/onecloud/pkg/apis"
  21. api "yunion.io/x/onecloud/pkg/apis/compute"
  22. hostapi "yunion.io/x/onecloud/pkg/apis/host"
  23. "yunion.io/x/onecloud/pkg/compute/models"
  24. "yunion.io/x/onecloud/pkg/httperrors"
  25. "yunion.io/x/onecloud/pkg/mcclient"
  26. )
  27. func init() {
  28. models.RegisterContainerDeviceDriver(newIsolatedDevice())
  29. }
  30. type isolatedDevice struct{}
  31. func newIsolatedDevice() models.IContainerDeviceDriver {
  32. return &isolatedDevice{}
  33. }
  34. func (i isolatedDevice) GetType() apis.ContainerDeviceType {
  35. return apis.CONTAINER_DEVICE_TYPE_ISOLATED_DEVICE
  36. }
  37. func (i isolatedDevice) validateCreateData(dev *api.ContainerDevice) error {
  38. isoDev := dev.IsolatedDevice
  39. if isoDev == nil {
  40. return httperrors.NewNotEmptyError("isolated_device is nil")
  41. }
  42. if isoDev.Index == nil && isoDev.Id == "" {
  43. return httperrors.NewNotEmptyError("one of index or id is required")
  44. }
  45. if isoDev.Index != nil {
  46. if *isoDev.Index < 0 {
  47. return httperrors.NewInputParameterError("index is less than 0")
  48. }
  49. }
  50. if isoDev.CDI != nil {
  51. if isoDev.CDI.Kind == "" {
  52. return httperrors.NewNotEmptyError("cdk.kind is empty")
  53. }
  54. }
  55. return nil
  56. }
  57. func (i isolatedDevice) ValidatePodCreateData(ctx context.Context, userCred mcclient.TokenCredential, dev *api.ContainerDevice, input *api.ServerCreateInput) error {
  58. if err := i.validateCreateData(dev); err != nil {
  59. return errors.Wrapf(err, "validate create data %s", jsonutils.Marshal(dev))
  60. }
  61. isoDev := dev.IsolatedDevice
  62. if isoDev.Id != "" {
  63. return httperrors.NewInputParameterError("can't specify id %s when creating pod", isoDev.Id)
  64. }
  65. if isoDev.Index == nil {
  66. return httperrors.NewNotEmptyError("index is required")
  67. }
  68. inputDevs := input.IsolatedDevices
  69. if *isoDev.Index >= len(inputDevs) {
  70. return httperrors.NewInputParameterError("disk.index %d is large than disk size %d", isoDev.Index, len(inputDevs))
  71. }
  72. return nil
  73. }
  74. func (i isolatedDevice) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, pod *models.SGuest, dev *api.ContainerDevice) (*api.ContainerDevice, error) {
  75. if err := i.validateCreateData(dev); err != nil {
  76. return nil, errors.Wrapf(err, "validate create data %s", jsonutils.Marshal(dev))
  77. }
  78. isoDev := dev.IsolatedDevice
  79. podDevs, err := pod.GetIsolatedDevices()
  80. if err != nil {
  81. return nil, errors.Wrap(err, "get isolated devices")
  82. }
  83. if isoDev.Index != nil {
  84. index := *isoDev.Index
  85. if index >= len(podDevs) {
  86. return nil, httperrors.NewInputParameterError("index %d is large than isolated device size %d", index, len(podDevs))
  87. }
  88. isoDev.Id = podDevs[index].GetId()
  89. // remove index
  90. isoDev.Index = nil
  91. } else {
  92. if isoDev.Id == "" {
  93. return nil, httperrors.NewNotEmptyError("id is empty")
  94. }
  95. foundDisk := false
  96. for _, d := range podDevs {
  97. if d.GetId() == isoDev.Id || d.GetName() == isoDev.Id {
  98. isoDev.Id = d.GetId()
  99. foundDisk = true
  100. devType := d.DevType
  101. if !sets.NewString(api.VALID_CONTAINER_DEVICE_TYPES...).Has(devType) {
  102. return nil, httperrors.NewInputParameterError("device type %s is not supported by container", devType)
  103. }
  104. break
  105. }
  106. }
  107. if !foundDisk {
  108. return nil, httperrors.NewNotFoundError("not found pod device by %s", isoDev.Id)
  109. }
  110. }
  111. dev.IsolatedDevice = isoDev
  112. return dev, nil
  113. }
  114. func (i isolatedDevice) ToHostDevice(dev *api.ContainerDevice) (*hostapi.ContainerDevice, error) {
  115. input := dev.IsolatedDevice
  116. isoDevObj, err := models.IsolatedDeviceManager.FetchById(input.Id)
  117. if err != nil {
  118. return nil, errors.Wrapf(err, "Fetch isolated device by id %s", input.Id)
  119. }
  120. isoDev := isoDevObj.(*models.SIsolatedDevice)
  121. return &hostapi.ContainerDevice{
  122. Type: dev.Type,
  123. IsolatedDevice: &hostapi.ContainerIsolatedDevice{
  124. Id: isoDev.GetId(),
  125. Addr: isoDev.Addr,
  126. Path: isoDev.DevicePath,
  127. CardPath: isoDev.CardPath,
  128. DeviceType: isoDev.DevType,
  129. RenderPath: isoDev.RenderPath,
  130. Index: isoDev.Index,
  131. DeviceMinor: isoDev.DeviceMinor,
  132. OnlyEnv: input.OnlyEnv,
  133. CDI: input.CDI,
  134. },
  135. }, nil
  136. }