vdisk.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  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 esxi
  15. import (
  16. "context"
  17. "fmt"
  18. "path"
  19. "path/filepath"
  20. "strings"
  21. "time"
  22. "github.com/vmware/govmomi/vim25/types"
  23. "yunion.io/x/log"
  24. "yunion.io/x/pkg/errors"
  25. api "yunion.io/x/cloudmux/pkg/apis/compute"
  26. "yunion.io/x/cloudmux/pkg/cloudprovider"
  27. "yunion.io/x/cloudmux/pkg/multicloud"
  28. )
  29. var driverMap = map[string]string{
  30. "ahci": "sata",
  31. "parascsi": "pvscsi",
  32. "buslogic": "scsi",
  33. "lsilogic": "scsi",
  34. "lsilogicsas": "scsi",
  35. }
  36. type SVirtualDisk struct {
  37. multicloud.SDisk
  38. multicloud.STagBase
  39. SVirtualDevice
  40. IsRoot bool
  41. }
  42. func NewVirtualDisk(vm *SVirtualMachine, dev types.BaseVirtualDevice, index int) SVirtualDisk {
  43. isRoot := dev.GetVirtualDevice().DeviceInfo.GetDescription().Label == rootDiskMark
  44. return SVirtualDisk{
  45. SDisk: multicloud.SDisk{},
  46. SVirtualDevice: NewVirtualDevice(vm, dev, index),
  47. IsRoot: isRoot,
  48. }
  49. }
  50. func (disk *SVirtualDisk) getVirtualDisk() *types.VirtualDisk {
  51. return disk.dev.(*types.VirtualDisk)
  52. }
  53. type IDiskBackingInfo interface {
  54. GetParent() IDiskBackingInfo
  55. GetUuid() string
  56. GetDiskMode() string
  57. GetPreallocation() string
  58. GetWriteThrough() bool
  59. GetFileName() string
  60. GetDatastore() *types.ManagedObjectReference
  61. }
  62. type sVirtualDiskFlatVer2BackingInfo struct {
  63. info *types.VirtualDiskFlatVer2BackingInfo
  64. }
  65. func (s *sVirtualDiskFlatVer2BackingInfo) GetParent() IDiskBackingInfo {
  66. if s.info.Parent != nil {
  67. return &sVirtualDiskFlatVer2BackingInfo{
  68. info: s.info.Parent,
  69. }
  70. }
  71. return nil
  72. }
  73. func (s *sVirtualDiskFlatVer2BackingInfo) GetUuid() string {
  74. return s.info.Uuid
  75. }
  76. func (s *sVirtualDiskFlatVer2BackingInfo) GetPreallocation() string {
  77. if s.info.ThinProvisioned != nil {
  78. if *s.info.ThinProvisioned {
  79. return api.DISK_PREALLOCATION_METADATA
  80. }
  81. if s.info.EagerlyScrub == nil || !*s.info.EagerlyScrub {
  82. return api.DISK_PREALLOCATION_FALLOC
  83. }
  84. return api.DISK_PREALLOCATION_FULL
  85. }
  86. return api.DISK_PREALLOCATION_METADATA
  87. }
  88. func (s *sVirtualDiskFlatVer2BackingInfo) GetDiskMode() string {
  89. return s.info.DiskMode
  90. }
  91. func (s *sVirtualDiskFlatVer2BackingInfo) GetWriteThrough() bool {
  92. if s.info.WriteThrough != nil && *s.info.WriteThrough == true {
  93. return true
  94. } else {
  95. return false
  96. }
  97. }
  98. func (s *sVirtualDiskFlatVer2BackingInfo) GetFileName() string {
  99. return s.info.FileName
  100. }
  101. func (s *sVirtualDiskFlatVer2BackingInfo) GetDatastore() *types.ManagedObjectReference {
  102. return s.info.Datastore
  103. }
  104. type sVirtualDiskSparseVer2BackingInfo struct {
  105. info *types.VirtualDiskSparseVer2BackingInfo
  106. }
  107. func (s *sVirtualDiskSparseVer2BackingInfo) GetParent() IDiskBackingInfo {
  108. if s.info.Parent != nil {
  109. return &sVirtualDiskSparseVer2BackingInfo{
  110. info: s.info.Parent,
  111. }
  112. }
  113. return nil
  114. }
  115. func (s *sVirtualDiskSparseVer2BackingInfo) GetUuid() string {
  116. return s.info.Uuid
  117. }
  118. func (s *sVirtualDiskSparseVer2BackingInfo) GetPreallocation() string {
  119. return api.DISK_PREALLOCATION_METADATA
  120. }
  121. func (s *sVirtualDiskSparseVer2BackingInfo) GetDiskMode() string {
  122. return s.info.DiskMode
  123. }
  124. func (s *sVirtualDiskSparseVer2BackingInfo) GetWriteThrough() bool {
  125. if s.info.WriteThrough != nil && *s.info.WriteThrough == true {
  126. return true
  127. } else {
  128. return false
  129. }
  130. }
  131. func (s *sVirtualDiskSparseVer2BackingInfo) GetFileName() string {
  132. return s.info.FileName
  133. }
  134. func (s *sVirtualDiskSparseVer2BackingInfo) GetDatastore() *types.ManagedObjectReference {
  135. return s.info.Datastore
  136. }
  137. type sVirtualDiskRawDiskMappingVer1BackingInfo struct {
  138. info *types.VirtualDiskRawDiskMappingVer1BackingInfo
  139. }
  140. func (s *sVirtualDiskRawDiskMappingVer1BackingInfo) GetParent() IDiskBackingInfo {
  141. if s.info.Parent != nil {
  142. return &sVirtualDiskRawDiskMappingVer1BackingInfo{
  143. info: s.info.Parent,
  144. }
  145. }
  146. return nil
  147. }
  148. func (s *sVirtualDiskRawDiskMappingVer1BackingInfo) GetUuid() string {
  149. return s.info.Uuid
  150. }
  151. func (s *sVirtualDiskRawDiskMappingVer1BackingInfo) GetDiskMode() string {
  152. return s.info.DiskMode
  153. }
  154. func (s *sVirtualDiskRawDiskMappingVer1BackingInfo) GetPreallocation() string {
  155. return api.DISK_PREALLOCATION_METADATA
  156. }
  157. func (s *sVirtualDiskRawDiskMappingVer1BackingInfo) GetWriteThrough() bool {
  158. return false
  159. }
  160. func (s *sVirtualDiskRawDiskMappingVer1BackingInfo) GetFileName() string {
  161. return s.info.FileName
  162. }
  163. func (s *sVirtualDiskRawDiskMappingVer1BackingInfo) GetDatastore() *types.ManagedObjectReference {
  164. return s.info.Datastore
  165. }
  166. type sVirtualDiskSparseVer1BackingInfo struct {
  167. info *types.VirtualDiskSparseVer1BackingInfo
  168. }
  169. func (s *sVirtualDiskSparseVer1BackingInfo) GetParent() IDiskBackingInfo {
  170. if s.info.Parent != nil {
  171. return &sVirtualDiskSparseVer1BackingInfo{
  172. info: s.info.Parent,
  173. }
  174. }
  175. return nil
  176. }
  177. func (s *sVirtualDiskSparseVer1BackingInfo) GetUuid() string {
  178. return s.info.Datastore.String() + s.info.FileName
  179. }
  180. func (s *sVirtualDiskSparseVer1BackingInfo) GetPreallocation() string {
  181. return api.DISK_PREALLOCATION_METADATA
  182. }
  183. func (s *sVirtualDiskSparseVer1BackingInfo) GetDiskMode() string {
  184. return s.info.DiskMode
  185. }
  186. func (s *sVirtualDiskSparseVer1BackingInfo) GetWriteThrough() bool {
  187. if s.info.WriteThrough != nil && *s.info.WriteThrough == true {
  188. return true
  189. } else {
  190. return false
  191. }
  192. }
  193. func (s *sVirtualDiskSparseVer1BackingInfo) GetFileName() string {
  194. return s.info.FileName
  195. }
  196. func (s *sVirtualDiskSparseVer1BackingInfo) GetDatastore() *types.ManagedObjectReference {
  197. return s.info.Datastore
  198. }
  199. type sVirtualDiskFlatVer1BackingInfo struct {
  200. info *types.VirtualDiskFlatVer1BackingInfo
  201. }
  202. func (s *sVirtualDiskFlatVer1BackingInfo) GetParent() IDiskBackingInfo {
  203. if s.info.Parent != nil {
  204. return &sVirtualDiskFlatVer1BackingInfo{
  205. info: s.info.Parent,
  206. }
  207. }
  208. return nil
  209. }
  210. func (s *sVirtualDiskFlatVer1BackingInfo) GetUuid() string {
  211. return s.info.Datastore.String() + s.info.FileName
  212. }
  213. func (s *sVirtualDiskFlatVer1BackingInfo) GetDiskMode() string {
  214. return s.info.DiskMode
  215. }
  216. func (s *sVirtualDiskFlatVer1BackingInfo) GetPreallocation() string {
  217. return api.DISK_PREALLOCATION_METADATA
  218. }
  219. func (s *sVirtualDiskFlatVer1BackingInfo) GetWriteThrough() bool {
  220. if s.info.WriteThrough != nil && *s.info.WriteThrough == true {
  221. return true
  222. } else {
  223. return false
  224. }
  225. }
  226. func (s *sVirtualDiskFlatVer1BackingInfo) GetFileName() string {
  227. return s.info.FileName
  228. }
  229. func (s *sVirtualDiskFlatVer1BackingInfo) GetDatastore() *types.ManagedObjectReference {
  230. return s.info.Datastore
  231. }
  232. func (disk *SVirtualDisk) getBackingInfo() IDiskBackingInfo {
  233. backing := disk.getVirtualDisk().Backing
  234. switch backing.(type) {
  235. case *types.VirtualDiskFlatVer2BackingInfo:
  236. return &sVirtualDiskFlatVer2BackingInfo{
  237. info: backing.(*types.VirtualDiskFlatVer2BackingInfo),
  238. }
  239. case *types.VirtualDeviceFileBackingInfo:
  240. case *types.VirtualDiskFlatVer1BackingInfo:
  241. return &sVirtualDiskFlatVer1BackingInfo{
  242. info: backing.(*types.VirtualDiskFlatVer1BackingInfo),
  243. }
  244. case *types.VirtualDiskLocalPMemBackingInfo:
  245. case *types.VirtualDiskRawDiskMappingVer1BackingInfo:
  246. return &sVirtualDiskRawDiskMappingVer1BackingInfo{
  247. info: backing.(*types.VirtualDiskRawDiskMappingVer1BackingInfo),
  248. }
  249. case *types.VirtualDiskSeSparseBackingInfo:
  250. case *types.VirtualDiskSparseVer1BackingInfo:
  251. return &sVirtualDiskSparseVer1BackingInfo{
  252. info: backing.(*types.VirtualDiskSparseVer1BackingInfo),
  253. }
  254. case *types.VirtualDiskSparseVer2BackingInfo:
  255. return &sVirtualDiskSparseVer2BackingInfo{
  256. info: backing.(*types.VirtualDiskSparseVer2BackingInfo),
  257. }
  258. case *types.VirtualFloppyImageBackingInfo:
  259. case *types.VirtualNVDIMMBackingInfo:
  260. case *types.VirtualParallelPortFileBackingInfo:
  261. case *types.VirtualSerialPortFileBackingInfo:
  262. case *types.VirtualCdromIsoBackingInfo:
  263. }
  264. log.Fatalf("unsupported backing info %T", backing)
  265. return nil
  266. }
  267. func (disk *SVirtualDisk) GetId() string {
  268. backing := disk.getBackingInfo()
  269. return backing.GetUuid()
  270. }
  271. func (disk *SVirtualDisk) MatchId(id string) bool {
  272. vmid := disk.vm.GetGlobalId()
  273. if !strings.HasPrefix(id, vmid) {
  274. return false
  275. }
  276. backingUuid := id[len(vmid)+1:]
  277. backing := disk.getBackingInfo()
  278. for backing != nil {
  279. if backing.GetUuid() == backingUuid {
  280. return true
  281. }
  282. backing = backing.GetParent()
  283. }
  284. return false
  285. }
  286. func (disk *SVirtualDisk) GetName() string {
  287. backing := disk.getBackingInfo()
  288. return path.Base(backing.GetFileName())
  289. }
  290. func (disk *SVirtualDisk) GetGlobalId() string {
  291. return fmt.Sprintf("%s-%s", disk.vm.GetGlobalId(), disk.GetId())
  292. }
  293. func (disk *SVirtualDisk) GetStatus() string {
  294. return api.DISK_READY
  295. }
  296. func (disk *SVirtualDisk) Refresh() error {
  297. return nil
  298. }
  299. func (disk *SVirtualDisk) IsEmulated() bool {
  300. return false
  301. }
  302. func (disk *SVirtualDisk) GetDiskSizeMB() int {
  303. capa := disk.getVirtualDisk().CapacityInBytes
  304. if capa == 0 {
  305. capa = disk.getVirtualDisk().CapacityInKB * 1024
  306. }
  307. return int(capa / 1024 / 1024)
  308. }
  309. func (disk *SVirtualDisk) GetAccessPath() string {
  310. istore, err := disk.GetIStorage()
  311. if err != nil {
  312. log.Errorf("disk.GetIStorage fail %s", err)
  313. return ""
  314. }
  315. ds := istore.(*SDatastore)
  316. return ds.GetFullPath(disk.getBackingInfo().GetFileName())
  317. }
  318. func (disk *SVirtualDisk) GetDiskFormat() string {
  319. return "vmdk"
  320. }
  321. func (disk *SVirtualDisk) GetIStorage() (cloudprovider.ICloudStorage, error) {
  322. dsObj := disk.getBackingInfo().GetDatastore()
  323. dc, err := disk.vm.GetDatacenter()
  324. if err != nil {
  325. return nil, errors.Wrapf(err, "GetDatacenter")
  326. }
  327. istorage, err := dc.GetIStorageByMoId(moRefId(*dsObj))
  328. if err != nil {
  329. return nil, err
  330. }
  331. return istorage, nil
  332. }
  333. func (disk *SVirtualDisk) GetIStorageId() string {
  334. storage, err := disk.GetIStorage()
  335. if err != nil {
  336. return ""
  337. }
  338. return storage.GetGlobalId()
  339. }
  340. func (disk *SVirtualDisk) GetIsAutoDelete() bool {
  341. return true
  342. }
  343. func (disk *SVirtualDisk) GetTemplateId() string {
  344. backing := disk.getBackingInfo()
  345. if backing.GetParent() != nil {
  346. return path.Base(backing.GetParent().GetFileName())
  347. }
  348. return ""
  349. }
  350. func (disk *SVirtualDisk) GetDiskType() string {
  351. if disk.IsRoot {
  352. return api.DISK_TYPE_SYS
  353. }
  354. return api.DISK_TYPE_DATA
  355. }
  356. func (disk *SVirtualDisk) GetFsFormat() string {
  357. return ""
  358. }
  359. func (disk *SVirtualDisk) getDiskMode() string {
  360. backing := disk.getBackingInfo()
  361. return backing.GetDiskMode()
  362. }
  363. func (disk *SVirtualDisk) GetIsNonPersistent() bool {
  364. return disk.getDiskMode() == "independent_nonpersistent"
  365. }
  366. func (disk *SVirtualDisk) GetDriver() string {
  367. controller := disk.vm.getVdev(disk.getControllerKey())
  368. name := controller.GetDriver()
  369. name = strings.Replace(name, "controller", "", -1)
  370. if driver, ok := driverMap[name]; ok {
  371. return driver
  372. }
  373. return name
  374. }
  375. func (disk *SVirtualDisk) GetCacheMode() string {
  376. backing := disk.getBackingInfo()
  377. if backing.GetWriteThrough() {
  378. return "writethrough"
  379. } else {
  380. return "none"
  381. }
  382. }
  383. func (disk *SVirtualDisk) GetMountpoint() string {
  384. return ""
  385. }
  386. func (disk *SVirtualDisk) GetPreallocation() string {
  387. backing := disk.getBackingInfo()
  388. return backing.GetPreallocation()
  389. }
  390. func (disk *SVirtualDisk) Delete(ctx context.Context) error {
  391. istorage, err := disk.GetIStorage()
  392. if err != nil {
  393. return errors.Wrapf(err, "GetIStorage")
  394. }
  395. ds := istorage.(*SDatastore)
  396. return ds.Delete2(ctx, disk.getBackingInfo().GetFileName(), false, false)
  397. }
  398. func (disk *SVirtualDisk) CreateISnapshot(ctx context.Context, name string, desc string) (cloudprovider.ICloudSnapshot, error) {
  399. return nil, cloudprovider.ErrNotImplemented
  400. }
  401. func (disk *SVirtualDisk) GetISnapshot(idStr string) (cloudprovider.ICloudSnapshot, error) {
  402. return nil, cloudprovider.ErrNotImplemented
  403. }
  404. func (disk *SVirtualDisk) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
  405. return nil, cloudprovider.ErrNotImplemented
  406. }
  407. func (disk *SVirtualDisk) Resize(ctx context.Context, newSizeMb int64) error {
  408. ndisk := disk.getVirtualDisk()
  409. ndisk.CapacityInKB = newSizeMb * 1024
  410. devSpec := types.VirtualDeviceConfigSpec{}
  411. devSpec.Device = ndisk
  412. devSpec.Operation = types.VirtualDeviceConfigSpecOperationEdit
  413. spec := types.VirtualMachineConfigSpec{}
  414. spec.DeviceChange = []types.BaseVirtualDeviceConfigSpec{&devSpec}
  415. vm := disk.vm.getVmObj()
  416. task, err := vm.Reconfigure(ctx, spec)
  417. if err != nil {
  418. return errors.Wrapf(err, "Reconfigure")
  419. }
  420. err = task.Wait(ctx)
  421. if err != nil {
  422. return errors.Wrapf(err, "task.Wait")
  423. }
  424. return err
  425. }
  426. /*
  427. func (disk *SVirtualDisk) ResizePartition(ctx context.Context, accessInfo vcenter.SVCenterAccessInfo) error {
  428. diskPath := disk.GetFilename()
  429. vmref := disk.vm.GetMoid()
  430. diskInfo := deployapi.DiskInfo{
  431. Path: diskPath,
  432. }
  433. vddkInfo := deployapi.VDDKConInfo{
  434. Host: accessInfo.Host,
  435. Port: int32(accessInfo.Port),
  436. User: accessInfo.Account,
  437. Passwd: accessInfo.Password,
  438. Vmref: vmref,
  439. }
  440. _, err := deployclient.GetDeployClient().ResizeFs(ctx, &deployapi.ResizeFsParams{
  441. DiskInfo: &diskInfo,
  442. Hypervisor: compute.HYPERVISOR_ESXI,
  443. VddkInfo: &vddkInfo,
  444. })
  445. if err != nil {
  446. return errors.Wrap(err, "unable to ResizeFs")
  447. }
  448. return nil
  449. }
  450. */
  451. func (disk *SVirtualDisk) Reset(ctx context.Context, snapshotId string) (string, error) {
  452. return "", cloudprovider.ErrNotImplemented
  453. }
  454. func (disk *SVirtualDisk) GetBillingType() string {
  455. return ""
  456. }
  457. // GetCreatedAt return create time by getting the Data of file stored at disk.GetAccessPath
  458. func (disk *SVirtualDisk) GetCreatedAt() time.Time {
  459. path, name := disk.GetAccessPath(), disk.GetFilename()
  460. storage, err := disk.GetIStorage()
  461. if err != nil {
  462. return time.Time{}
  463. }
  464. ds := storage.(*SDatastore)
  465. files, err := ds.ListDir(context.Background(), filepath.Dir(path))
  466. if err != nil {
  467. return time.Time{}
  468. }
  469. for _, file := range files {
  470. if file.Name == name {
  471. return file.Date
  472. }
  473. }
  474. return time.Time{}
  475. }
  476. func (disk *SVirtualDisk) GetExpiredAt() time.Time {
  477. return time.Time{}
  478. }
  479. func (disk *SVirtualDisk) Rebuild(ctx context.Context) error {
  480. return disk.vm.rebuildDisk(ctx, disk, "", false)
  481. }
  482. func (disk *SVirtualDisk) GetProjectId() string {
  483. return disk.vm.GetProjectId()
  484. }
  485. func (disk *SVirtualDisk) GetFilename() string {
  486. return disk.getBackingInfo().GetFileName()
  487. }