sio_mgr.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /*
  2. Copyright 2017 The Kubernetes Authors.
  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. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package scaleio
  14. import (
  15. "errors"
  16. "strconv"
  17. "k8s.io/kubernetes/pkg/util/mount"
  18. "k8s.io/klog"
  19. siotypes "github.com/codedellemc/goscaleio/types/v1"
  20. )
  21. type sioMgr struct {
  22. client sioInterface
  23. configData map[string]string
  24. exec mount.Exec
  25. }
  26. func newSioMgr(configs map[string]string, exec mount.Exec) (*sioMgr, error) {
  27. if configs == nil {
  28. return nil, errors.New("missing configuration data")
  29. }
  30. configs[confKey.protectionDomain] = defaultString(configs[confKey.protectionDomain], "default")
  31. configs[confKey.storagePool] = defaultString(configs[confKey.storagePool], "default")
  32. configs[confKey.sdcRootPath] = defaultString(configs[confKey.sdcRootPath], sdcRootPath)
  33. configs[confKey.storageMode] = defaultString(configs[confKey.storageMode], "ThinProvisioned")
  34. mgr := &sioMgr{configData: configs, exec: exec}
  35. return mgr, nil
  36. }
  37. // getClient safely returns an sioInterface
  38. func (m *sioMgr) getClient() (sioInterface, error) {
  39. if m.client == nil {
  40. klog.V(4).Info(log("creating scaleio client"))
  41. configs := m.configData
  42. username := configs[confKey.username]
  43. password := configs[confKey.password]
  44. gateway := configs[confKey.gateway]
  45. b, err := strconv.ParseBool(configs[confKey.sslEnabled])
  46. if err != nil {
  47. klog.Error(log("failed to parse sslEnabled, must be either \"true\" or \"false\""))
  48. return nil, err
  49. }
  50. certsEnabled := b
  51. klog.V(4).Info(log("creating new client for gateway %s", gateway))
  52. client, err := newSioClient(gateway, username, password, certsEnabled, m.exec)
  53. if err != nil {
  54. klog.Error(log("failed to create scaleio client: %v", err))
  55. return nil, err
  56. }
  57. client.sysName = configs[confKey.system]
  58. client.pdName = configs[confKey.protectionDomain]
  59. client.spName = configs[confKey.storagePool]
  60. client.sdcPath = configs[confKey.sdcRootPath]
  61. client.provisionMode = configs[confKey.storageMode]
  62. client.sdcGUID = configs[confKey.sdcGUID]
  63. m.client = client
  64. klog.V(4).Info(log("client created successfully [gateway=%s]", gateway))
  65. }
  66. return m.client, nil
  67. }
  68. // CreateVolume creates a new ScaleIO volume
  69. func (m *sioMgr) CreateVolume(volName string, sizeGB int64) (*siotypes.Volume, error) {
  70. client, err := m.getClient()
  71. if err != nil {
  72. return nil, err
  73. }
  74. klog.V(4).Infof("scaleio: creating volume %s", volName)
  75. vol, err := client.CreateVolume(volName, sizeGB)
  76. if err != nil {
  77. klog.V(4).Infof("scaleio: failed creating volume %s: %v", volName, err)
  78. return nil, err
  79. }
  80. klog.V(4).Infof("scaleio: created volume %s successfully", volName)
  81. return vol, nil
  82. }
  83. // AttachVolume maps a ScaleIO volume to the running node. If flag multiMaps,
  84. // ScaleIO will allow other SDC to map to volume.
  85. func (m *sioMgr) AttachVolume(volName string, multipleMappings bool) (string, error) {
  86. client, err := m.getClient()
  87. if err != nil {
  88. klog.Error(log("attach volume failed: %v", err))
  89. return "", err
  90. }
  91. klog.V(4).Infoln(log("attaching volume %s", volName))
  92. iid, err := client.IID()
  93. if err != nil {
  94. klog.Error(log("failed to get instanceID"))
  95. return "", err
  96. }
  97. klog.V(4).Info(log("attaching volume %s to host instance %s", volName, iid))
  98. devs, err := client.Devs()
  99. if err != nil {
  100. return "", err
  101. }
  102. vol, err := client.FindVolume(volName)
  103. if err != nil {
  104. klog.Error(log("failed to find volume %s: %v", volName, err))
  105. return "", err
  106. }
  107. // handle vol if already attached
  108. if len(vol.MappedSdcInfo) > 0 {
  109. if m.isSdcMappedToVol(iid, vol) {
  110. klog.V(4).Info(log("skippping attachment, volume %s already attached to sdc %s", volName, iid))
  111. return devs[vol.ID], nil
  112. }
  113. }
  114. // attach volume, get deviceName
  115. if err := client.AttachVolume(sioVolumeID(vol.ID), multipleMappings); err != nil {
  116. klog.Error(log("attachment for volume %s failed :%v", volName, err))
  117. return "", err
  118. }
  119. device, err := client.WaitForAttachedDevice(vol.ID)
  120. if err != nil {
  121. klog.Error(log("failed while waiting for device to attach: %v", err))
  122. return "", err
  123. }
  124. klog.V(4).Info(log("volume %s attached successfully as %s to instance %s", volName, device, iid))
  125. return device, nil
  126. }
  127. // IsAttached verifies that the named ScaleIO volume is still attached
  128. func (m *sioMgr) IsAttached(volName string) (bool, error) {
  129. client, err := m.getClient()
  130. if err != nil {
  131. return false, err
  132. }
  133. iid, err := client.IID()
  134. if err != nil {
  135. klog.Error("scaleio: failed to get instanceID")
  136. return false, err
  137. }
  138. vol, err := client.FindVolume(volName)
  139. if err != nil {
  140. return false, err
  141. }
  142. return m.isSdcMappedToVol(iid, vol), nil
  143. }
  144. // DetachVolume detaches the name ScaleIO volume from an instance
  145. func (m *sioMgr) DetachVolume(volName string) error {
  146. client, err := m.getClient()
  147. if err != nil {
  148. return err
  149. }
  150. iid, err := client.IID()
  151. if err != nil {
  152. klog.Error(log("failed to get instanceID: %v", err))
  153. return err
  154. }
  155. vol, err := client.FindVolume(volName)
  156. if err != nil {
  157. return err
  158. }
  159. if !m.isSdcMappedToVol(iid, vol) {
  160. klog.Warning(log(
  161. "skipping detached, vol %s not attached to instance %s",
  162. volName, iid,
  163. ))
  164. return nil
  165. }
  166. if err := client.DetachVolume(sioVolumeID(vol.ID)); err != nil {
  167. klog.Error(log("failed to detach vol %s: %v", volName, err))
  168. return err
  169. }
  170. klog.V(4).Info(log("volume %s detached successfully", volName))
  171. return nil
  172. }
  173. // DeleteVolumes removes the ScaleIO volume
  174. func (m *sioMgr) DeleteVolume(volName string) error {
  175. client, err := m.getClient()
  176. if err != nil {
  177. return err
  178. }
  179. vol, err := client.FindVolume(volName)
  180. if err != nil {
  181. return err
  182. }
  183. if err := client.DeleteVolume(sioVolumeID(vol.ID)); err != nil {
  184. klog.Error(log("failed to delete volume %s: %v", volName, err))
  185. return err
  186. }
  187. klog.V(4).Info(log("deleted volume %s successfully", volName))
  188. return nil
  189. }
  190. // isSdcMappedToVol returns true if the sdc is mapped to the volume
  191. func (m *sioMgr) isSdcMappedToVol(sdcID string, vol *siotypes.Volume) bool {
  192. if len(vol.MappedSdcInfo) == 0 {
  193. klog.V(4).Info(log("no attachment found"))
  194. return false
  195. }
  196. for _, sdcInfo := range vol.MappedSdcInfo {
  197. if sdcInfo.SdcID == sdcID {
  198. return true
  199. }
  200. }
  201. return false
  202. }