vmdkutils.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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 vmdkutils
  15. import (
  16. "bufio"
  17. "fmt"
  18. "io"
  19. "regexp"
  20. "strconv"
  21. "strings"
  22. "yunion.io/x/pkg/utils"
  23. )
  24. type SVMDKInfo struct {
  25. ExtentFile string
  26. Heads int64
  27. Sectors int64
  28. Cylinders int64
  29. CID string
  30. LongCID string
  31. UUID string
  32. AdapterType string
  33. VirtualHWVersion string
  34. }
  35. func (info SVMDKInfo) Size() int64 {
  36. return info.Heads * info.Sectors * info.Cylinders * 512
  37. }
  38. const (
  39. //RW 20971520 VMFS "89334fec-7013-46cb-8d7b-8271cbe1a175_1-flat.vmdk"
  40. //RW 62914560 SESPARSE "89334fec-7013-46cb-8d7b-8271cbe1a175-sesparse.vmdk"
  41. extentPatternString = `^RW \d+ (VMFS|SESPARSE)\w* \"(?P<fn>[^"]+)`
  42. )
  43. var (
  44. extentPatternRegexp = regexp.MustCompile(extentPatternString)
  45. )
  46. func Parse(content string) (*SVMDKInfo, error) {
  47. return ParseStream(strings.NewReader(content))
  48. }
  49. func ParseStream(stream io.Reader) (*SVMDKInfo, error) {
  50. info := SVMDKInfo{}
  51. scanner := bufio.NewScanner(stream)
  52. findExtent := false
  53. for scanner.Scan() {
  54. line := strings.TrimSpace(scanner.Text())
  55. matches := extentPatternRegexp.FindStringSubmatch(line)
  56. if len(matches) > 0 {
  57. // log.Debugf("%#v", matches)
  58. info.ExtentFile = matches[2]
  59. findExtent = true
  60. } else {
  61. equalPos := strings.IndexByte(line, '=')
  62. if equalPos > 0 {
  63. key := strings.TrimSpace(line[:equalPos])
  64. value := utils.Unquote(strings.TrimSpace(line[equalPos+1:]))
  65. switch key {
  66. case "CID":
  67. info.CID = value
  68. case "ddb.uuid":
  69. info.UUID = value
  70. case "ddb.geometry.cylinders":
  71. info.Cylinders, _ = strconv.ParseInt(value, 10, 64)
  72. case "ddb.geometry.heads":
  73. info.Heads, _ = strconv.ParseInt(value, 10, 64)
  74. case "ddb.geometry.sectors":
  75. info.Sectors, _ = strconv.ParseInt(value, 10, 64)
  76. case "ddb.longContentID":
  77. info.LongCID = value
  78. case "ddb.adapterType":
  79. info.AdapterType = value
  80. case "ddb.virtualHWVersion":
  81. info.VirtualHWVersion = value
  82. }
  83. }
  84. }
  85. }
  86. if !findExtent {
  87. return nil, fmt.Errorf("not a vmdk file")
  88. }
  89. return &info, nil
  90. }