qemutils.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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 qemutils
  15. import (
  16. "fmt"
  17. "path"
  18. "regexp"
  19. "sort"
  20. "strings"
  21. "yunion.io/x/log"
  22. "yunion.io/x/pkg/util/version"
  23. "yunion.io/x/onecloud/pkg/util/procutils"
  24. )
  25. const (
  26. USR_LOCAL_BIN = "/usr/local/bin"
  27. HOMEBREW_BIN = "/opt/homebrew/bin/"
  28. USR_BIN = "/usr/bin"
  29. )
  30. var qemuSystemCmd = "qemu-system-x86_64"
  31. func UseAarch64() {
  32. qemuSystemCmd = "qemu-system-aarch64"
  33. }
  34. func UseRiscv64() {
  35. qemuSystemCmd = "qemu-system-riscv64"
  36. }
  37. func GetQemu(version string) string {
  38. return getQemuCmd(qemuSystemCmd, version)
  39. }
  40. func GetQemuNbd() string {
  41. return getQemuCmd("qemu-nbd", "")
  42. }
  43. func GetQemuImg() string {
  44. return getQemuCmd("qemu-img", "")
  45. }
  46. func getQemuCmd(cmd, version string) string {
  47. if len(version) > 0 {
  48. return getQemuCmdByVersion(cmd, version)
  49. } else {
  50. return getQemuDefaultCmd(cmd)
  51. }
  52. }
  53. func getQemuCmdByVersion(cmd, version string) string {
  54. p := path.Join(fmt.Sprintf("/usr/local/qemu-%s/bin", version), cmd)
  55. if _, err := procutils.RemoteStat(p); err == nil {
  56. return p
  57. } else {
  58. log.Errorf("stat %s: %s", p, err)
  59. }
  60. cmd = cmd + "_" + version
  61. p = path.Join(USR_LOCAL_BIN, cmd)
  62. if _, err := procutils.RemoteStat(p); err == nil {
  63. return p
  64. } else {
  65. log.Errorf("stat %s: %s", p, err)
  66. }
  67. p = path.Join(USR_BIN, cmd)
  68. if _, err := procutils.RemoteStat(p); err == nil {
  69. return p
  70. } else {
  71. log.Errorf("stat %s: %s", p, err)
  72. }
  73. p = path.Join(HOMEBREW_BIN, cmd)
  74. if _, err := procutils.RemoteStat(p); err == nil {
  75. return p
  76. } else {
  77. log.Errorf("stat %s: %s", p, err)
  78. }
  79. return ""
  80. }
  81. func getQemuVersion(verString string) string {
  82. s := regexp.MustCompile(`qemu-(?P<ver>\d+(\.\d+)+)$`).FindString(verString)
  83. if len(s) == 0 {
  84. return ""
  85. }
  86. return s[len("qemu-"):]
  87. }
  88. func getCmdVersion(cmd string) string {
  89. s := regexp.MustCompile(`_(?P<ver>\d+(\.\d+)+)$`).FindString(cmd)
  90. if len(s) == 0 {
  91. return ""
  92. }
  93. return s[1:]
  94. }
  95. func getQemuDefaultCmd(cmd string) string {
  96. var qemus = make([]string, 0)
  97. if files, err := procutils.RemoteReadDir("/usr/local"); err == nil {
  98. for i := 0; i < len(files); i++ {
  99. if strings.HasPrefix(files[i].Name(), "qemu-") {
  100. qemus = append(qemus, files[i].Name())
  101. }
  102. }
  103. if len(qemus) > 0 {
  104. sort.Slice(qemus, func(i, j int) bool {
  105. return version.LT(getQemuVersion(qemus[i]),
  106. getQemuVersion(qemus[j]))
  107. })
  108. p := fmt.Sprintf("/usr/local/%s/bin/%s", qemus[len(qemus)-1], cmd)
  109. if _, err := procutils.RemoteStat(p); err == nil {
  110. return p
  111. } else {
  112. log.Errorf("stat %s: %s", p, err)
  113. }
  114. }
  115. }
  116. cmds := make([]string, 0)
  117. for _, dir := range []string{USR_LOCAL_BIN, USR_BIN, HOMEBREW_BIN} {
  118. if files, err := procutils.RemoteReadDir(dir); err == nil {
  119. for i := 0; i < len(files); i++ {
  120. if strings.HasPrefix(files[i].Name(), cmd) {
  121. cmds = append(cmds, files[i].Name())
  122. }
  123. }
  124. if len(cmds) > 0 {
  125. sort.Slice(cmds, func(i, j int) bool {
  126. return version.LT(getCmdVersion(cmds[i]),
  127. getCmdVersion(cmds[j]))
  128. })
  129. p := path.Join(dir, cmds[len(cmds)-1])
  130. if _, err := procutils.RemoteStat(p); err == nil {
  131. return p
  132. } else {
  133. log.Errorf("stat %s: %s", p, err)
  134. }
  135. }
  136. }
  137. }
  138. return ""
  139. }