core.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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 guestfs
  15. import (
  16. "fmt"
  17. "math/rand"
  18. "yunion.io/x/jsonutils"
  19. "yunion.io/x/log"
  20. "yunion.io/x/pkg/errors"
  21. "yunion.io/x/pkg/util/netutils"
  22. comapi "yunion.io/x/onecloud/pkg/apis/compute"
  23. "yunion.io/x/onecloud/pkg/hostman/guestfs/fsdriver"
  24. deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
  25. )
  26. func DetectRootFs(part fsdriver.IDiskPartition) (fsdriver.IRootFsDriver, error) {
  27. for _, newDriverFunc := range fsdriver.GetRootfsDrivers() {
  28. d := newDriverFunc(part)
  29. d.SetVirtualObject(d)
  30. if testRootfs(d) {
  31. return d, nil
  32. }
  33. }
  34. return nil, fmt.Errorf("DetectRootFs with partition %s no root fs found", part.GetPartDev())
  35. }
  36. func testRootfs(d fsdriver.IRootFsDriver) bool {
  37. caseInsensitive := d.IsFsCaseInsensitive()
  38. for _, rd := range d.RootSignatures() {
  39. if !d.GetPartition().Exists(rd, caseInsensitive) {
  40. log.Debugf("[%s] test root fs: %s not exists", d, rd)
  41. return false
  42. }
  43. }
  44. for _, rd := range d.RootExcludeSignatures() {
  45. if d.GetPartition().Exists(rd, caseInsensitive) {
  46. log.Debugf("[%s] test root fs: %s exists, test failed", d, rd)
  47. return false
  48. }
  49. }
  50. return true
  51. }
  52. func DoDeployGuestFs(rootfs fsdriver.IRootFsDriver, guestDesc *deployapi.GuestDesc, deployInfo *deployapi.DeployInfo,
  53. ) (*deployapi.DeployGuestFsResponse, error) {
  54. var (
  55. err error
  56. ret = new(deployapi.DeployGuestFsResponse)
  57. ips = make([]string, 0)
  58. hn = guestDesc.Name
  59. domain = guestDesc.Domain
  60. gid = guestDesc.Uuid
  61. nics = fsdriver.ToServerNics(guestDesc, guestDesc.Nics)
  62. nicsStandby = fsdriver.ToServerNics(guestDesc, guestDesc.NicsStandby)
  63. partition = rootfs.GetPartition()
  64. releaseInfo = rootfs.GetReleaseInfo(partition)
  65. )
  66. if len(guestDesc.Hostname) > 0 {
  67. hn = guestDesc.Hostname
  68. }
  69. for _, n := range nics {
  70. if len(n.Ip) > 0 {
  71. var addr netutils.IPV4Addr
  72. if addr, err = netutils.NewIPV4Addr(n.Ip); err != nil {
  73. return nil, errors.Wrapf(err, "Fail to get ip addr from %#v", n)
  74. }
  75. if netutils.IsPrivate(addr) {
  76. ips = append(ips, addr.String())
  77. }
  78. }
  79. if len(n.Ip6) > 0 {
  80. var addr netutils.IPV6Addr
  81. if addr, err = netutils.NewIPV6Addr(n.Ip6); err != nil {
  82. return nil, errors.Wrapf(err, "Fail to get ipv6 addr from %#v", n)
  83. }
  84. ips = append(ips, addr.String())
  85. }
  86. }
  87. if releaseInfo != nil {
  88. ret.Distro = releaseInfo.Distro
  89. if len(releaseInfo.Version) > 0 {
  90. ret.Version = releaseInfo.Version
  91. }
  92. if len(releaseInfo.Arch) > 0 {
  93. ret.Arch = releaseInfo.Arch
  94. }
  95. if len(releaseInfo.Language) > 0 {
  96. ret.Language = releaseInfo.Language
  97. }
  98. if len(releaseInfo.CurrentVersion) > 0 {
  99. ret.CurrentVersion = releaseInfo.CurrentVersion
  100. }
  101. }
  102. ret.Os = rootfs.GetOs()
  103. if IsPartitionReadonly(partition) {
  104. return ret, nil
  105. }
  106. if deployInfo.IsInit {
  107. if err := rootfs.CleanNetworkScripts(partition); err != nil {
  108. return nil, errors.Wrap(err, "Clean network scripts")
  109. }
  110. if len(deployInfo.Deploys) > 0 {
  111. if err := rootfs.DeployFiles(deployInfo.Deploys); err != nil {
  112. return nil, errors.Wrap(err, "DeployFiles")
  113. }
  114. }
  115. if len(deployInfo.UserData) > 0 {
  116. if err := rootfs.DeployUserData(deployInfo.UserData); err != nil {
  117. return nil, errors.Wrap(err, "DeployUserData")
  118. }
  119. }
  120. }
  121. if deployInfo.Telegraf != nil {
  122. if deployed, err := rootfs.DeployTelegraf(deployInfo.Telegraf.TelegrafConf); err != nil {
  123. return nil, errors.Wrap(err, "deploy telegraf")
  124. } else {
  125. ret.TelegrafDeployed = deployed
  126. }
  127. }
  128. if err := rootfs.DeployHostname(partition, hn, domain); err != nil {
  129. //return nil, errors.Wrap(err, "DeployHostname")
  130. log.Errorf("DeployHostname failed %s", err)
  131. }
  132. if err := rootfs.DeployHosts(partition, hn, domain, ips); err != nil {
  133. //return nil, errors.Wrap(err, "DeployHosts")
  134. log.Errorf("DeployHosts failed %s", err)
  135. }
  136. if guestDesc.Hypervisor == comapi.HYPERVISOR_KVM {
  137. if err := rootfs.DeployQgaService(partition); err != nil {
  138. return nil, errors.Wrap(err, "DeployQgaService")
  139. }
  140. if err := rootfs.DeployQgaBlackList(partition); err != nil {
  141. return nil, errors.Wrap(err, "DeployQgaBlackList")
  142. }
  143. }
  144. if err := rootfs.DeployNetworkingScripts(partition, nics); err != nil {
  145. return nil, errors.Wrap(err, "DeployNetworkingScripts")
  146. }
  147. if len(nicsStandby) > 0 {
  148. if err := rootfs.DeployStandbyNetworkingScripts(partition, nics, nicsStandby); err != nil {
  149. return nil, errors.Wrap(err, "DeployStandbyNetworkingScripts")
  150. }
  151. }
  152. if err := rootfs.DeployUdevSubsystemScripts(partition); err != nil {
  153. return nil, errors.Wrap(err, "DeployUdevSubsystemScripts")
  154. }
  155. if deployInfo.IsInit {
  156. if err := rootfs.DeployFstabScripts(partition, guestDesc.Disks); err != nil {
  157. return nil, errors.Wrap(err, "DeployFstabScripts")
  158. }
  159. }
  160. if len(deployInfo.Password) > 0 {
  161. account, err := rootfs.GetLoginAccount(partition, deployInfo.LoginAccount,
  162. deployInfo.DefaultRootUser, deployInfo.WindowsDefaultAdminUser)
  163. if err != nil {
  164. return nil, errors.Wrap(err, "get login account")
  165. }
  166. if len(account) > 0 {
  167. if err = rootfs.DeployPublicKey(partition, account, deployInfo.PublicKey); err != nil {
  168. return nil, errors.Wrap(err, "DeployPublicKey")
  169. }
  170. var secret string
  171. if secret, err = rootfs.ChangeUserPasswd(partition, account, gid, deployInfo.PublicKey.PublicKey, deployInfo.Password, deployInfo.IsRandomPassword); err != nil {
  172. return nil, errors.Wrap(err, "ChangeUserPasswd")
  173. }
  174. if len(secret) > 0 {
  175. ret.Key = secret
  176. }
  177. ret.Account = account
  178. }
  179. }
  180. if err := rootfs.ConfigSshd(ret.Account, deployInfo.Password, 0); err != nil {
  181. return nil, errors.Wrap(err, "ConfigSshd")
  182. }
  183. if err = rootfs.DeployYunionroot(partition, deployInfo.PublicKey, deployInfo.IsInit, deployInfo.EnableCloudInit); err != nil {
  184. return nil, errors.Wrap(err, "DeployYunionroot")
  185. }
  186. if partition.SupportSerialPorts() {
  187. if deployInfo.EnableTty {
  188. if err = rootfs.EnableSerialConsole(partition, nil); err != nil {
  189. // return nil, fmt.Errorf("EnableSerialConsole: %v", err)
  190. log.Warningf("EnableSerialConsole error: %v", err)
  191. }
  192. } else {
  193. if err = rootfs.DisableSerialConsole(partition); err != nil {
  194. // return nil, fmt.Errorf("DisableSerialConsole: %v", err)
  195. log.Warningf("DisableSerialConsole error: %v", err)
  196. }
  197. }
  198. }
  199. if err = rootfs.CommitChanges(partition); err != nil {
  200. return nil, errors.Wrap(err, "CommitChanges")
  201. }
  202. log.Infof("Deploy finished, return: %s", ret.String())
  203. return ret, nil
  204. }
  205. func DeployGuestFs(
  206. rootfs fsdriver.IRootFsDriver,
  207. desc *deployapi.GuestDesc,
  208. deployInfo *deployapi.DeployInfo,
  209. ) (jsonutils.JSONObject, error) {
  210. ret, err := DoDeployGuestFs(rootfs, desc, deployInfo)
  211. if err != nil {
  212. return nil, err
  213. }
  214. return jsonutils.Marshal(ret), nil
  215. }
  216. func IsPartitionReadonly(rootfs fsdriver.IDiskPartition) bool {
  217. var filename = fmt.Sprintf("/.%f", rand.Float32())
  218. if err := rootfs.FilePutContents(filename, fmt.Sprintf("%f", rand.Float32()), false, false); err == nil {
  219. rootfs.Remove(filename, false)
  220. log.Infof("File system %s is not readonly", rootfs.GetMountPath())
  221. return false
  222. } else {
  223. log.Errorf("File system %s is readonly: %s", rootfs.GetMountPath(), err)
  224. return true
  225. }
  226. }