yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/incloudsphere/host.go (about)

     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  
    15  package incloudsphere
    16  
    17  import (
    18  	"fmt"
    19  	"net"
    20  	"net/url"
    21  	"strings"
    22  
    23  	"yunion.io/x/jsonutils"
    24  	"yunion.io/x/pkg/errors"
    25  
    26  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    27  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    28  	"yunion.io/x/cloudmux/pkg/multicloud"
    29  )
    30  
    31  type SHost struct {
    32  	multicloud.SHostBase
    33  	InCloudSphereTags
    34  	zone *SZone
    35  
    36  	Id                    string  `json:"id"`
    37  	IP                    string  `json:"ip"`
    38  	SwitchUplinkPortDto   string  `json:"switchUplinkPortDto"`
    39  	UplinkTopoDto         string  `json:"uplinkTopoDto"`
    40  	Pnics                 string  `json:"pnics"`
    41  	Disks                 string  `json:"disks"`
    42  	Name                  string  `json:"name"`
    43  	HostName              string  `json:"hostName"`
    44  	NodeVersion           string  `json:"nodeVersion"`
    45  	Password              string  `json:"password"`
    46  	DataCenterId          string  `json:"dataCenterId"`
    47  	DataCenterName        string  `json:"dataCenterName"`
    48  	ClusterName           string  `json:"clusterName"`
    49  	ClusterId             string  `json:"clusterId"`
    50  	Status                string  `json:"status"`
    51  	CPUSocket             int64   `json:"cpuSocket"`
    52  	CPUCorePerSocket      int64   `json:"cpuCorePerSocket"`
    53  	CPUThreadPerCore      int64   `json:"cpuThreadPerCore"`
    54  	LogicCPUNum           int64   `json:"logicCpuNum"`
    55  	LogicalProcessor      int64   `json:"logicalProcessor"`
    56  	CPUFrequency          float64 `json:"cpuFrequency"`
    57  	CPUUsage              float64 `json:"cpuUsage"`
    58  	CPUTotalHz            int64   `json:"cpuTotalHz"`
    59  	FreeCPU               int64   `json:"freeCpu"`
    60  	UsedCPU               int64   `json:"usedCpu"`
    61  	TotalMem              float64 `json:"totalMem"`
    62  	LogicTotalMem         int64   `json:"logicTotalMem"`
    63  	MemoryUsage           float64 `json:"memoryUsage"`
    64  	FreeMemory            int64   `json:"freeMemory"`
    65  	UsedMemory            int64   `json:"usedMemory"`
    66  	LogicUsedMemory       int64   `json:"logicUsedMemory"`
    67  	LogicFreeMemory       int64   `json:"logicFreeMemory"`
    68  	PnicNum               int64   `json:"pnicNum"`
    69  	NormalRunTime         int64   `json:"normalRunTime"`
    70  	Model                 string  `json:"model"`
    71  	CPUType               string  `json:"cpuType"`
    72  	VTDegree              int64   `json:"vtDegree"`
    73  	Powerstate            string  `json:"powerstate"`
    74  	HostBmcDto            string  `json:"hostBmcDto"`
    75  	MountPath             string  `json:"mountPath"`
    76  	MonMountState         string  `json:"monMountState"`
    77  	CPUModel              string  `json:"cpuModel"`
    78  	NetworkDtos           string  `json:"networkDtos"`
    79  	PortIP                string  `json:"portIp"`
    80  	Monstatus             bool    `json:"monstatus"`
    81  	HostIqn               string  `json:"hostIqn"`
    82  	VxlanPortDto          string  `json:"vxlanPortDto"`
    83  	SDNUpLinks            string  `json:"sdnUpLinks"`
    84  	AllPNicsCount         int64   `json:"allPNicsCount"`
    85  	AvailablePNicsCount   int64   `json:"availablePNicsCount"`
    86  	CfsDomainStatus       string  `json:"cfsDomainStatus"`
    87  	SerialNumber          string  `json:"serialNumber"`
    88  	Manufacturer          string  `json:"manufacturer"`
    89  	IndicatorStatus       string  `json:"indicatorStatus"`
    90  	EntryTemperature      string  `json:"entryTemperature"`
    91  	MulticastEnabled      bool    `json:"multicastEnabled"`
    92  	BroadcastLimitEnabled bool    `json:"broadcastLimitEnabled"`
    93  	Pcies                 string  `json:"pcies"`
    94  	VgpuEnable            bool    `json:"vgpuEnable"`
    95  	SSHEnable             bool    `json:"sshEnable"`
    96  	SpecialFailover       bool    `json:"specialFailover"`
    97  	VswitchDtos           string  `json:"vswitchDtos"`
    98  	HotfixVersion         string  `json:"hotfixVersion"`
    99  	VMMigBandWidth        string  `json:"vmMigBandWidth"`
   100  	VMMigBandWidthFlag    bool    `json:"vmMigBandWidthFlag"`
   101  	DpdkEnabled           bool    `json:"dpdkEnabled"`
   102  	HugePageTotal         int64   `json:"hugePageTotal"`
   103  	HugePageUsed          int64   `json:"hugePageUsed"`
   104  	HugePageFree          int64   `json:"hugePageFree"`
   105  	StorageUsage          int64   `json:"storageUsage"`
   106  	NodeForm              string  `json:"nodeForm"`
   107  	CPUArchType           string  `json:"cpuArchType"`
   108  	LogPartitionSize      int64   `json:"logPartitionSize"`
   109  	RootPartitionSize     int64   `json:"rootPartitionSize"`
   110  	Cpuflags              string  `json:"cpuflags"`
   111  }
   112  
   113  func (self *SHost) GetId() string {
   114  	return self.Id
   115  }
   116  
   117  func (self *SHost) GetGlobalId() string {
   118  	return self.Id
   119  }
   120  
   121  func (self *SHost) GetName() string {
   122  	return self.HostName
   123  }
   124  
   125  func (self *SHost) GetEnabled() bool {
   126  	return true
   127  }
   128  
   129  func (self *SHost) GetHostStatus() string {
   130  	return api.HOST_ONLINE
   131  }
   132  
   133  func (self *SHost) GetStatus() string {
   134  	return api.HOST_STATUS_RUNNING
   135  }
   136  
   137  func (self *SHost) GetAccessIp() string {
   138  	return self.Name
   139  }
   140  
   141  func (self *SHost) GetAccessMac() string {
   142  	return ""
   143  }
   144  
   145  func (self *SHost) GetSysInfo() jsonutils.JSONObject {
   146  	return jsonutils.NewDict()
   147  }
   148  
   149  func (self *SHost) GetSN() string {
   150  	return self.SerialNumber
   151  }
   152  
   153  func (self *SHost) GetCpuCount() int {
   154  	return int(self.CPUCorePerSocket)
   155  }
   156  
   157  func (self *SHost) GetNodeCount() int8 {
   158  	return int8(self.CPUSocket)
   159  }
   160  
   161  func (self *SHost) GetCpuDesc() string {
   162  	return self.CPUType
   163  }
   164  
   165  func (self *SHost) GetCpuMhz() int {
   166  	return int(self.CPUFrequency * 1024)
   167  }
   168  
   169  func (self *SHost) GetCpuCmtbound() float32 {
   170  	return 1
   171  }
   172  
   173  func (self *SHost) GetMemSizeMB() int {
   174  	return int(self.TotalMem)
   175  }
   176  
   177  func (self *SHost) GetMemCmtbound() float32 {
   178  	return 1
   179  }
   180  
   181  func (self *SHost) GetReservedMemoryMb() int {
   182  	return 0
   183  }
   184  
   185  func (self *SHost) GetStorageSizeMB() int {
   186  	return 0
   187  }
   188  
   189  func (self *SHost) GetStorageType() string {
   190  	return api.STORAGE_LOCAL
   191  }
   192  
   193  func (self *SHost) GetHostType() string {
   194  	return api.HOST_TYPE_INCLOUD_SPHERE
   195  }
   196  
   197  func (self *SHost) GetIsMaintenance() bool {
   198  	return false
   199  }
   200  
   201  func (self *SHost) GetVersion() string {
   202  	return self.NodeVersion
   203  }
   204  
   205  func (self *SHost) CreateVM(opts *cloudprovider.SManagedVMCreateConfig) (cloudprovider.ICloudVM, error) {
   206  	storages, err := self.zone.region.GetImageStorages(self.zone.Id)
   207  	if err != nil {
   208  		return nil, errors.Wrapf(err, "GetImageStorages")
   209  	}
   210  	var image *SImage = nil
   211  	storageCache := &SStoragecache{zone: self.zone}
   212  	for i := range storages {
   213  		images, err := self.zone.region.GetImageList(storages[i].Id)
   214  		if err != nil {
   215  			return nil, err
   216  		}
   217  		for j := range images {
   218  			images[j].cache = storageCache
   219  			if images[j].GetGlobalId() == opts.ExternalImageId {
   220  				image = &images[j]
   221  				break
   222  			}
   223  		}
   224  	}
   225  	if image == nil {
   226  		return nil, errors.Wrapf(cloudprovider.ErrNotFound, opts.ExternalImageId)
   227  	}
   228  	format := "RAW"
   229  	if strings.HasSuffix(opts.ExternalImageId, "qcow2") {
   230  		format = "QCOW2"
   231  	}
   232  	sizeGb := float64((image.GetSizeByte() + 1024/2) / 1024 / 1024 / 1024)
   233  	disks := []Disks{}
   234  	disks = append(disks, Disks{
   235  		BusModel:       "IDE",
   236  		ReadWriteModel: "NONE",
   237  		QueueNum:       1,
   238  		Volume: Volume{
   239  			Bootable:     true,
   240  			DataStoreId:  opts.SysDisk.StorageExternalId,
   241  			Format:       format,
   242  			Size:         sizeGb,
   243  			VolumePolicy: "THIN",
   244  			VvSourceDto: VvSourceDto{
   245  				FilePath:   fmt.Sprintf("%s/%s", image.Path, image.Name),
   246  				SourceType: "IMAGE_STORAGE",
   247  				FtpServerHost: FtpServerHost{
   248  					Id: image.ServerID,
   249  					Ip: image.FTPServer,
   250  				},
   251  			},
   252  		},
   253  	})
   254  	for i := range opts.DataDisks {
   255  		disks = append(disks, Disks{
   256  			BusModel:       "IDE",
   257  			ReadWriteModel: "NONE",
   258  			QueueNum:       1,
   259  			Volume: Volume{
   260  				Bootable:     false,
   261  				DataStoreId:  opts.DataDisks[i].StorageExternalId,
   262  				Format:       "RAW",
   263  				Size:         float64(opts.DataDisks[i].SizeGB),
   264  				VolumePolicy: "THIN",
   265  			},
   266  		})
   267  	}
   268  	imageTree, err := self.zone.region.GetImageTrees()
   269  	if err != nil {
   270  		return nil, errors.Wrapf(err, "GetImageTrees")
   271  	}
   272  	guestLabel, guestosType := "CentOS 7.9(2009) 64bit", "CentOS"
   273  	for i := range imageTree {
   274  		images := imageTree[i].ToList()
   275  		for j := range images {
   276  			if images[j].IsEquals(image.Name) {
   277  				guestLabel = images[j].Model
   278  				guestosType = images[j].OsDist
   279  				break
   280  			}
   281  		}
   282  	}
   283  	nic := SInstanceNic{
   284  		AutoGenerated: true,
   285  		DeviceId:      opts.ExternalNetworkId,
   286  		DeviceType:    "NETWORK",
   287  		Model:         "E1000",
   288  		Queues:        1,
   289  	}
   290  	network, err := self.zone.region.GetNetwork(opts.ExternalNetworkId)
   291  	if err != nil {
   292  		return nil, errors.Wrapf(err, "GetNetwork")
   293  	}
   294  	if network.DhcpEnabled {
   295  		nic.Dhcp = true
   296  		nic.DhcpEnabled = true
   297  		nic.DhcpIP = opts.IpAddr
   298  	} else if len(opts.IpAddr) > 0 {
   299  		nic.IP = opts.IpAddr
   300  		mask := net.CIDRMask(int(network.GetIpMask()), 32)
   301  		nic.Netmask = fmt.Sprintf("%d.%d.%d.%d", mask[0], mask[1], mask[2], mask[3])
   302  		nic.Gateway = network.GetGateway()
   303  		if len(nic.Gateway) == 0 {
   304  			info := strings.Split(opts.IpAddr, ".")
   305  			if len(info) == 4 {
   306  				info[3] = "1"
   307  				nic.Gateway = strings.Join(info, ".")
   308  			}
   309  		}
   310  	}
   311  	body := map[string]interface{}{
   312  		"boot":               "HD",
   313  		"bootMode":           "BIOS",
   314  		"clockModel":         "LOCALTIME",
   315  		"cpuBindType":        "NOBIND",
   316  		"cpuCore":            opts.Cpu,
   317  		"cpuHotplugEnabled":  false,
   318  		"cpuLimit":           -1,
   319  		"cpuModelType":       "SELF_ADAPTING",
   320  		"cpuNum":             opts.Cpu,
   321  		"cpuReservation":     0,
   322  		"cpuShares":          1024,
   323  		"cpuSocket":          1,
   324  		"dataCenterId":       self.zone.Id,
   325  		"dataStoreId":        opts.SysDisk.StorageExternalId,
   326  		"deacription":        opts.Description,
   327  		"disks":              disks,
   328  		"enableHugeMemPage":  false,
   329  		"enableReplicate":    false,
   330  		"graphicsCardMemory": 16384,
   331  		"graphicsCardModel":  "VGA",
   332  		"guestosLabel":       guestLabel,
   333  		"guestosType":        guestosType,
   334  		"hostBinded":         false,
   335  		"hostId":             self.Id,
   336  		"maxCpuNum":          128,
   337  		"maxMemory":          4194304,
   338  		"memory":             opts.MemoryMB,
   339  		"memoryShow":         4,
   340  		"memoryUnit":         "GB",
   341  		"name":               opts.Name,
   342  		"nics": []SInstanceNic{
   343  			nic,
   344  		},
   345  		"panickPolicy":        "NO_ACTION",
   346  		"replicate":           1,
   347  		"socketLimit":         24,
   348  		"startPriority":       "DEFAULT",
   349  		"supportCpuHotPlug":   true,
   350  		"supportMemHotPlug":   true,
   351  		"supportUefiBootMode": true,
   352  		"vcpuPin":             "all",
   353  		"version":             "V2",
   354  	}
   355  	resp, err := self.zone.region.post("/vms", jsonutils.Marshal(body))
   356  	if err != nil {
   357  		return nil, err
   358  	}
   359  	taskId, err := resp.GetString("taskId")
   360  	if err != nil {
   361  		return nil, errors.Wrapf(err, "taskId")
   362  	}
   363  	vmId, err := self.zone.region.client.waitTask(taskId)
   364  	if err != nil {
   365  		return nil, err
   366  	}
   367  	vm, err := self.zone.region.GetInstance(vmId)
   368  	if err != nil {
   369  		return nil, err
   370  	}
   371  	vm.host = self
   372  	return vm, nil
   373  }
   374  
   375  func (self *SHost) GetIHostNics() ([]cloudprovider.ICloudHostNetInterface, error) {
   376  	return nil, cloudprovider.ErrNotImplemented
   377  }
   378  
   379  func (self *SHost) GetIVMs() ([]cloudprovider.ICloudVM, error) {
   380  	vms, err := self.zone.region.GetInstances(self.Id)
   381  	if err != nil {
   382  		return nil, errors.Wrapf(err, "GetInstances")
   383  	}
   384  	ret := []cloudprovider.ICloudVM{}
   385  	for i := range vms {
   386  		vms[i].host = self
   387  		ret = append(ret, &vms[i])
   388  	}
   389  	return ret, nil
   390  }
   391  
   392  func (self *SHost) GetIVMById(id string) (cloudprovider.ICloudVM, error) {
   393  	vm, err := self.zone.region.GetInstance(id)
   394  	if err != nil {
   395  		return nil, err
   396  	}
   397  	if vm.HostId != self.Id {
   398  		return nil, cloudprovider.ErrNotFound
   399  	}
   400  	vm.host = self
   401  	return vm, nil
   402  }
   403  
   404  func (self *SHost) GetIWires() ([]cloudprovider.ICloudWire, error) {
   405  	wires, err := self.zone.region.GetWiresByDs(self.DataCenterId)
   406  	if err != nil {
   407  		return nil, err
   408  	}
   409  	ret := []cloudprovider.ICloudWire{}
   410  	for i := range wires {
   411  		wires[i].region = self.zone.region
   412  		ret = append(ret, &wires[i])
   413  	}
   414  	return ret, nil
   415  }
   416  
   417  func (self *SHost) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
   418  	storages, err := self.zone.region.GetStoragesByHost(self.Id)
   419  	if err != nil {
   420  		return nil, err
   421  	}
   422  	ret := []cloudprovider.ICloudStorage{}
   423  	for i := range storages {
   424  		storages[i].zone = self.zone
   425  		ret = append(ret, &storages[i])
   426  	}
   427  	return ret, nil
   428  }
   429  
   430  func (self *SHost) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
   431  	storage, err := self.zone.region.GetStorage(id)
   432  	if err != nil {
   433  		return nil, err
   434  	}
   435  	storage.zone = self.zone
   436  	if storage.HostId != self.Id {
   437  		return nil, cloudprovider.ErrNotFound
   438  	}
   439  	return storage, nil
   440  }
   441  
   442  func (self *SRegion) GetHosts(dcId string) ([]SHost, error) {
   443  	hosts := []SHost{}
   444  	res := fmt.Sprintf("/datacenters/%s/hosts", dcId)
   445  	return hosts, self.list(res, url.Values{}, &hosts)
   446  }
   447  
   448  func (self *SRegion) GetHost(id string) (*SHost, error) {
   449  	ret := &SHost{}
   450  	res := fmt.Sprintf("/hosts/%s", id)
   451  	return ret, self.get(res, url.Values{}, ret)
   452  }