node.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  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 bingocloud
  15. import (
  16. "fmt"
  17. "strconv"
  18. "strings"
  19. "yunion.io/x/jsonutils"
  20. "yunion.io/x/log"
  21. "yunion.io/x/pkg/errors"
  22. api "yunion.io/x/cloudmux/pkg/apis/compute"
  23. "yunion.io/x/cloudmux/pkg/cloudprovider"
  24. "yunion.io/x/cloudmux/pkg/multicloud"
  25. )
  26. type SNode struct {
  27. multicloud.SHostBase
  28. multicloud.STagBase
  29. cluster *SCluster
  30. ClusterId string
  31. CpuCores int
  32. CpuMax int
  33. CpuModel string
  34. CpuNode int
  35. CpuSockets int
  36. CpuUsed int
  37. DiskMax int64
  38. DiskNode int64
  39. DiskUsed int
  40. MemNode int
  41. MemoryMax int
  42. MemoryUsed int
  43. NodeId string
  44. NodeName string
  45. ScheduleTags string
  46. Status string
  47. }
  48. func (self *SRegion) GetNodes(clusterId, nodeId string) ([]SNode, error) {
  49. params := map[string]string{}
  50. if len(clusterId) > 0 {
  51. params["ClusterId"] = clusterId
  52. }
  53. if len(clusterId) > 0 {
  54. params["NodeId"] = nodeId
  55. }
  56. resp, err := self.invoke("DescribeNodes", params)
  57. if err != nil {
  58. return nil, err
  59. }
  60. var ret []SNode
  61. return ret, resp.Unmarshal(&ret, "nodeSet")
  62. }
  63. func (self *SNode) GetId() string {
  64. return self.NodeId
  65. }
  66. func (self *SNode) GetGlobalId() string {
  67. return self.NodeId
  68. }
  69. func (self *SNode) GetName() string {
  70. return self.NodeName
  71. }
  72. func (self *SNode) GetAccessIp() string {
  73. info := strings.Split(self.NodeId, "@")
  74. if len(info) == 2 {
  75. return info[1]
  76. }
  77. return ""
  78. }
  79. func (self *SNode) GetAccessMac() string {
  80. return ""
  81. }
  82. func (self *SNode) GetSysInfo() jsonutils.JSONObject {
  83. return jsonutils.NewDict()
  84. }
  85. func (self *SNode) GetSN() string {
  86. return ""
  87. }
  88. func (self *SNode) GetCpuCount() int {
  89. return self.CpuNode
  90. }
  91. func (self *SNode) GetNodeCount() int8 {
  92. return int8(self.CpuSockets)
  93. }
  94. func (self *SNode) GetCpuDesc() string {
  95. return self.CpuModel
  96. }
  97. func (self *SNode) GetCpuMhz() int {
  98. return 0
  99. }
  100. func (self *SNode) GetCpuCmtbound() float32 {
  101. if self.CpuMax > self.CpuNode {
  102. return float32(self.CpuMax) / float32(self.CpuNode)
  103. }
  104. return 1
  105. }
  106. func (self *SNode) GetMemSizeMB() int {
  107. return self.MemNode
  108. }
  109. func (self *SNode) GetMemCmtbound() float32 {
  110. if self.MemoryMax > self.MemNode {
  111. return float32(self.MemoryMax) / float32(self.MemNode)
  112. }
  113. return 1
  114. }
  115. func (self *SNode) GetReservedMemoryMb() int {
  116. return 0
  117. }
  118. func (self *SNode) GetStorageSizeMB() int64 {
  119. if self.DiskMax > 0 {
  120. return self.DiskMax * 1024
  121. }
  122. return self.DiskNode * 1024
  123. }
  124. func (self *SNode) GetStorageType() string {
  125. return api.STORAGE_LOCAL_SSD
  126. }
  127. func (self *SNode) GetNodeType() string {
  128. return api.HOST_TYPE_BINGO_CLOUD
  129. }
  130. func (self *SNode) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
  131. return self.cluster.GetIStorages()
  132. }
  133. func (self *SNode) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
  134. return self.cluster.GetIStorageById(id)
  135. }
  136. func (self *SNode) GetEnabled() bool {
  137. return true
  138. }
  139. func (self *SNode) GetNodeStatus() string {
  140. if self.Status == "available" {
  141. return api.HOST_ONLINE
  142. }
  143. return api.HOST_OFFLINE
  144. }
  145. func (node *SNode) GetIHostNics() ([]cloudprovider.ICloudHostNetInterface, error) {
  146. wires, err := node.getIWires()
  147. if err != nil {
  148. return nil, errors.Wrap(err, "getIWires")
  149. }
  150. return cloudprovider.GetHostNetifs(node, wires), nil
  151. }
  152. func (self *SNode) GetIVMs() ([]cloudprovider.ICloudVM, error) {
  153. var vms []SInstance
  154. part, nextToken, err := self.cluster.region.GetInstances("", self.NodeId, MAX_RESULT, "")
  155. vms = append(vms, part...)
  156. for len(nextToken) > 0 {
  157. part, nextToken, err = self.cluster.region.GetInstances("", self.NodeId, MAX_RESULT, nextToken)
  158. if err != nil {
  159. return nil, err
  160. }
  161. vms = append(vms, part...)
  162. }
  163. var ret []cloudprovider.ICloudVM
  164. for i := range vms {
  165. vms[i].node = self
  166. ret = append(ret, &vms[i])
  167. }
  168. return ret, nil
  169. }
  170. func (self *SNode) GetIVMById(id string) (cloudprovider.ICloudVM, error) {
  171. vms, _, err := self.cluster.region.GetInstances(id, self.NodeId, 1, "")
  172. if err != nil {
  173. return nil, err
  174. }
  175. for i := range vms {
  176. if vms[i].GetGlobalId() == id {
  177. vms[i].node = self
  178. return &vms[i], nil
  179. }
  180. }
  181. return nil, cloudprovider.ErrNotFound
  182. }
  183. func (self *SNode) getIWires() ([]cloudprovider.ICloudWire, error) {
  184. vpcs, err := self.cluster.region.GetIVpcs()
  185. if err != nil {
  186. return nil, err
  187. }
  188. var ret []cloudprovider.ICloudWire
  189. for _, vpc := range vpcs {
  190. wires, err := vpc.GetIWires()
  191. if err != nil {
  192. return nil, err
  193. }
  194. ret = append(ret, wires...)
  195. }
  196. return ret, nil
  197. }
  198. func (self *SNode) GetIsMaintenance() bool {
  199. return self.Status == "maintain"
  200. }
  201. func (self *SNode) GetVersion() string {
  202. return ""
  203. }
  204. func (self *SNode) GetStatus() string {
  205. return api.HOST_STATUS_RUNNING
  206. }
  207. func (self *SNode) GetHostStatus() string {
  208. if self.Status != "available" {
  209. return api.HOST_OFFLINE
  210. }
  211. return api.HOST_ONLINE
  212. }
  213. func (self *SNode) GetHostType() string {
  214. return api.HOST_TYPE_BINGO_CLOUD
  215. }
  216. func (self *SCluster) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
  217. nodes, err := self.region.GetNodes(self.ClusterId, id)
  218. if err != nil {
  219. return nil, err
  220. }
  221. for i := range nodes {
  222. if nodes[i].GetGlobalId() == id {
  223. nodes[i].cluster = self
  224. return &nodes[i], nil
  225. }
  226. }
  227. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", id)
  228. }
  229. func (self *SCluster) GetIHosts() ([]cloudprovider.ICloudHost, error) {
  230. nodes, err := self.region.GetNodes(self.ClusterId, "")
  231. if err != nil {
  232. return nil, err
  233. }
  234. var ret []cloudprovider.ICloudHost
  235. for i := range nodes {
  236. nodes[i].cluster = self
  237. ret = append(ret, &nodes[i])
  238. }
  239. return ret, nil
  240. }
  241. func (self *SNode) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudprovider.ICloudVM, error) {
  242. var err error
  243. log.Debugf("Try instancetype : %s", desc.InstanceType)
  244. img, err := self.cluster.region.GetImageById(desc.ExternalImageId)
  245. if err != nil {
  246. log.Errorf("get image %s fail %s", desc.ExternalImageId, err)
  247. return nil, err
  248. }
  249. params := map[string]string{}
  250. params["InstanceName"] = desc.Name
  251. params["ImageId"] = desc.ExternalImageId
  252. params["MinCount"] = "1"
  253. params["MaxCount"] = "1"
  254. if len(desc.ExternalSecgroupIds) > 0 {
  255. for i := range desc.ExternalSecgroupIds {
  256. secGroup, err := self.cluster.region.GetISecurityGroupById(desc.ExternalSecgroupIds[i])
  257. if err != nil {
  258. return nil, err
  259. }
  260. params[fmt.Sprintf("SecurityGroup.%v", i+1)] = secGroup.GetName()
  261. }
  262. }
  263. disks := make([]SDisk, len(desc.DataDisks)+1)
  264. disks[0].Size = int(img.GetSizeGB())
  265. if desc.SysDisk.SizeGB > 0 && desc.SysDisk.SizeGB > int(img.GetSizeGB()) {
  266. disks[0].Size = desc.SysDisk.SizeGB
  267. }
  268. for i, dataDisk := range desc.DataDisks {
  269. disks[i+1].Size = dataDisk.SizeGB
  270. }
  271. for i, disk := range disks {
  272. var deviceName string
  273. var err error
  274. if i == 0 {
  275. params[fmt.Sprintf("BlockDeviceMapping.%v.Ebs.DeleteOnTermination", i+1)] = "true"
  276. params[fmt.Sprintf("BlockDeviceMapping.%v.Ebs.VolumeSize", i+1)] = strconv.Itoa(disk.Size)
  277. if len(img.RootDeviceName) > 0 {
  278. deviceName = img.RootDeviceName
  279. } else {
  280. deviceName = fmt.Sprintf("/dev/vda")
  281. }
  282. } else {
  283. params[fmt.Sprintf("BlockDeviceMapping.%v.Ebs.DeleteOnTermination", i+1)] = "true"
  284. params[fmt.Sprintf("BlockDeviceMapping.%v.Ebs.VolumeSize", i+1)] = strconv.Itoa(disk.Size)
  285. deviceName, err = nextDeviceName([]string{deviceName})
  286. if err != nil {
  287. return nil, errors.Wrap(err, "nextDeviceName")
  288. }
  289. }
  290. params[fmt.Sprintf("BlockDeviceMapping.%v.DeviceName", i+1)] = deviceName
  291. }
  292. params["InstanceType"] = desc.InstanceType
  293. params["Password"] = desc.Password
  294. params["NetworkInterface.1.VpcId"] = desc.ExternalVpcId
  295. params["NetworkInterface.1.SubnetId"] = desc.ExternalNetworkId
  296. params["AllowNodes.1"] = self.NodeId
  297. resp, err := self.cluster.region.invoke("RunInstances", params)
  298. if err != nil {
  299. return nil, err
  300. }
  301. if err != nil {
  302. return nil, errors.Wrap(err, "CreateVM")
  303. }
  304. var tmpInst = struct {
  305. InstancesSet struct {
  306. InstanceId string
  307. }
  308. }{}
  309. _ = resp.Unmarshal(&tmpInst)
  310. insets, _, err := self.cluster.region.GetInstances(tmpInst.InstancesSet.InstanceId, "", MAX_RESULT, "")
  311. if err != nil {
  312. log.Errorf("GetInstance %s: %s", "", err)
  313. return nil, errors.Wrap(err, "CreateVM")
  314. }
  315. if len(insets) > 0 {
  316. insets[0].node = self
  317. return &insets[0], nil
  318. }
  319. return nil, errors.Wrap(cloudprovider.ErrUnknown, "CreateVM")
  320. }