mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-10-24 12:32:55 +08:00
feature: 1. baremetal server reuse host ip 2. server name use expression
This commit is contained in:
@@ -2199,7 +2199,7 @@ func (s *SBaremetalServer) DoPartitionDisk(term *ssh.Client) ([]*disktool.Partit
|
||||
rootSize, _ := rootDisk.Int("size")
|
||||
err = s.doCreateRoot(term, tool.GetRootDisk().GetDevName())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Failed to create root")
|
||||
return nil, errors.Wrap(err, "Failed to create root")
|
||||
}
|
||||
tool.RetrievePartitionInfo()
|
||||
parts := tool.GetPartitions()
|
||||
|
||||
@@ -1058,6 +1058,12 @@ func _doCreateItem(
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
// save generateName
|
||||
if len(generateName) > 0 {
|
||||
if standaloneMode, ok := model.(IStandaloneModel); ok {
|
||||
standaloneMode.SetMetadata(ctx, "generate_name", generateName, userCred)
|
||||
}
|
||||
}
|
||||
// HACK: set data same as dataDict
|
||||
data.(*jsonutils.JSONDict).Update(dataDict)
|
||||
return model, nil
|
||||
|
||||
@@ -256,12 +256,23 @@ type IStandaloneModel interface {
|
||||
|
||||
GetIStandaloneModel() IStandaloneModel
|
||||
ClearSchedDescCache() error
|
||||
|
||||
GetMetadata(key string, userCred mcclient.TokenCredential) string
|
||||
GetMetadataJson(key string, userCred mcclient.TokenCredential) jsonutils.JSONObject
|
||||
SetMetadata(ctx context.Context, key string, value interface{}, userCred mcclient.TokenCredential) error
|
||||
SetAllMetadata(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error
|
||||
SetUserMetadataValues(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error
|
||||
SetUserMetadataAll(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error
|
||||
SetCloudMetadataAll(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error
|
||||
RemoveMetadata(ctx context.Context, key string, userCred mcclient.TokenCredential) error
|
||||
RemoveAllMetadata(ctx context.Context, userCred mcclient.TokenCredential) error
|
||||
GetAllMetadata(userCred mcclient.TokenCredential) (map[string]string, error)
|
||||
}
|
||||
|
||||
type IMetadataModel interface {
|
||||
IStandaloneModel
|
||||
|
||||
GetAllMetadata(userCred mcclient.TokenCredential) (map[string]string, error)
|
||||
// GetAllMetadata(userCred mcclient.TokenCredential) (map[string]string, error)
|
||||
GetMetadataHideKeys() []string
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ func CheckSync(autoSync bool) bool {
|
||||
}
|
||||
}
|
||||
for modelName, modelMan := range globalTables {
|
||||
log.Infof("check model %s SQL", modelName)
|
||||
tableSpec := modelMan.TableSpec()
|
||||
sqls := tableSpec.SyncSQL()
|
||||
if len(sqls) > 0 {
|
||||
|
||||
@@ -127,7 +127,7 @@ func (self *SBaremetalGuestDriver) ValidateResizeDisk(guest *models.SGuest, disk
|
||||
return httperrors.NewUnsupportOperationError("Cannot resize disk for baremtal")
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) GetNamedNetworkConfiguration(guest *models.SGuest, userCred mcclient.TokenCredential, host *models.SHost, netConfig *api.NetworkConfig) (*models.SNetwork, []models.SNicConfig, api.IPAllocationDirection) {
|
||||
func (self *SBaremetalGuestDriver) GetNamedNetworkConfiguration(guest *models.SGuest, ctx context.Context, userCred mcclient.TokenCredential, host *models.SHost, netConfig *api.NetworkConfig) (*models.SNetwork, []models.SNicConfig, api.IPAllocationDirection, bool) {
|
||||
netifs, net := host.GetNetinterfacesWithIdAndCredential(netConfig.Network, userCred, netConfig.Reserved)
|
||||
if netifs != nil {
|
||||
nicCnt := 1
|
||||
@@ -136,7 +136,8 @@ func (self *SBaremetalGuestDriver) GetNamedNetworkConfiguration(guest *models.SG
|
||||
}
|
||||
if len(netifs) < nicCnt {
|
||||
if netConfig.RequireTeaming {
|
||||
return net, nil, ""
|
||||
log.Errorf("not enough network interfaces, want %d got %d", nicCnt, len(netifs))
|
||||
return net, nil, "", false
|
||||
}
|
||||
nicCnt = len(netifs)
|
||||
}
|
||||
@@ -149,9 +150,17 @@ func (self *SBaremetalGuestDriver) GetNamedNetworkConfiguration(guest *models.SG
|
||||
}
|
||||
nicConfs = append(nicConfs, nicConf)
|
||||
}
|
||||
return net, nicConfs, api.IPAllocationStepup
|
||||
reuseAddr := false
|
||||
hn := host.GetAttach2Network(netConfig.Network)
|
||||
if hn != nil && netConfig.Address == "" && options.Options.BaremetalServerReuseHostIp {
|
||||
// try to reuse host network IP address
|
||||
netConfig.Address = hn.IpAddr
|
||||
reuseAddr = true
|
||||
}
|
||||
|
||||
return net, nicConfs, api.IPAllocationStepup, reuseAddr
|
||||
}
|
||||
return net, nil, ""
|
||||
return net, nil, "", false
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) GetRandomNetworkTypes() []string {
|
||||
@@ -190,10 +199,10 @@ func (self *SBaremetalGuestDriver) Attach2RandomNetwork(guest *models.SGuest, ct
|
||||
}
|
||||
if net != nil {
|
||||
netsAvaiable = append(netsAvaiable, *net)
|
||||
if _, exist := netifIndexs[net.Id]; !exist {
|
||||
netifIndexs[net.Id] = make([]models.SNetInterface, 0)
|
||||
if _, exist := netifIndexs[net.WireId]; !exist {
|
||||
netifIndexs[net.WireId] = make([]models.SNetInterface, 0)
|
||||
}
|
||||
netifIndexs[net.Id] = append(netifIndexs[net.Id], netifs[idx])
|
||||
netifIndexs[net.WireId] = append(netifIndexs[net.WireId], netifs[idx])
|
||||
}
|
||||
}
|
||||
if len(netsAvaiable) == 0 {
|
||||
@@ -201,7 +210,7 @@ func (self *SBaremetalGuestDriver) Attach2RandomNetwork(guest *models.SGuest, ct
|
||||
}
|
||||
net := models.ChooseCandidateNetworks(netsAvaiable, netConfig.Exit, netTypes)
|
||||
if net != nil {
|
||||
netifs := netifIndexs[net.Id]
|
||||
netifs := netifIndexs[net.WireId]
|
||||
nicConfs := make([]models.SNicConfig, 0)
|
||||
nicCnt := 1
|
||||
if netConfig.RequireTeaming || netConfig.TryTeaming {
|
||||
@@ -221,7 +230,15 @@ func (self *SBaremetalGuestDriver) Attach2RandomNetwork(guest *models.SGuest, ct
|
||||
}
|
||||
nicConfs = append(nicConfs, nicConf)
|
||||
}
|
||||
return guest.Attach2Network(ctx, userCred, net, pendingUsage, "", netConfig.Driver, netConfig.BwLimit, netConfig.Vip, false, api.IPAllocationStepup, false, nicConfs)
|
||||
address := ""
|
||||
reuseAddr := false
|
||||
hn := host.GetAttach2Network(net.Id)
|
||||
if hn != nil && options.Options.BaremetalServerReuseHostIp {
|
||||
// try to reuse host network IP address
|
||||
address = hn.IpAddr
|
||||
reuseAddr = true
|
||||
}
|
||||
return guest.Attach2Network(ctx, userCred, net, pendingUsage, address, netConfig.Driver, netConfig.BwLimit, netConfig.Vip, false, api.IPAllocationStepup, false, reuseAddr, nicConfs)
|
||||
}
|
||||
return nil, fmt.Errorf("No appropriate host virtual network...")
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ func (self *SVirtualizedGuestDriver) PrepareDiskRaidConfig(userCred mcclient.Tok
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SVirtualizedGuestDriver) GetNamedNetworkConfiguration(guest *models.SGuest, userCred mcclient.TokenCredential, host *models.SHost, netConfig *api.NetworkConfig) (*models.SNetwork, []models.SNicConfig, api.IPAllocationDirection) {
|
||||
func (self *SVirtualizedGuestDriver) GetNamedNetworkConfiguration(guest *models.SGuest, ctx context.Context, userCred mcclient.TokenCredential, host *models.SHost, netConfig *api.NetworkConfig) (*models.SNetwork, []models.SNicConfig, api.IPAllocationDirection, bool) {
|
||||
net, _ := host.GetNetworkWithIdAndCredential(netConfig.Network, userCred, netConfig.Reserved)
|
||||
nicConfs := []models.SNicConfig{
|
||||
{
|
||||
@@ -68,7 +68,7 @@ func (self *SVirtualizedGuestDriver) GetNamedNetworkConfiguration(guest *models.
|
||||
Ifname: "",
|
||||
})
|
||||
}
|
||||
return net, nicConfs, api.IPAllocationStepdown
|
||||
return net, nicConfs, api.IPAllocationStepdown, false
|
||||
}
|
||||
|
||||
func (self *SVirtualizedGuestDriver) GetRandomNetworkTypes() []string {
|
||||
@@ -147,7 +147,7 @@ func (self *SVirtualizedGuestDriver) Attach2RandomNetwork(guest *models.SGuest,
|
||||
}
|
||||
nicConfs = append(nicConfs, nicConf)
|
||||
}
|
||||
gn, err := guest.Attach2Network(ctx, userCred, selNet, pendingUsage, netConfig.Address, netConfig.Driver, netConfig.BwLimit, netConfig.Vip, netConfig.Reserved, api.IPAllocationDefault, netConfig.RequireDesignatedIP, nicConfs)
|
||||
gn, err := guest.Attach2Network(ctx, userCred, selNet, pendingUsage, netConfig.Address, netConfig.Driver, netConfig.BwLimit, netConfig.Vip, netConfig.Reserved, api.IPAllocationDefault, netConfig.RequireDesignatedIP, false, nicConfs)
|
||||
return gn, err
|
||||
}
|
||||
|
||||
|
||||
@@ -271,7 +271,7 @@ func (self *SDynamicschedtag) PerformEvaluate(ctx context.Context, userCred mccl
|
||||
|
||||
log.V(10).Debugf("Dynamicschedtag evaluate input: %s", params.PrettyString())
|
||||
|
||||
meet, err := conditionparser.Eval(self.Condition, params)
|
||||
meet, err := conditionparser.EvalBool(self.Condition, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ type IGuestDriver interface {
|
||||
|
||||
PrepareDiskRaidConfig(userCred mcclient.TokenCredential, host *SHost, params []*api.BaremetalDiskConfig, disks []*api.DiskConfig) ([]*api.DiskConfig, error)
|
||||
|
||||
GetNamedNetworkConfiguration(guest *SGuest, userCred mcclient.TokenCredential, host *SHost, netConfig *api.NetworkConfig) (*SNetwork, []SNicConfig, api.IPAllocationDirection)
|
||||
GetNamedNetworkConfiguration(guest *SGuest, ctx context.Context, userCred mcclient.TokenCredential, host *SHost, netConfig *api.NetworkConfig) (*SNetwork, []SNicConfig, api.IPAllocationDirection, bool)
|
||||
|
||||
Attach2RandomNetwork(guest *SGuest, ctx context.Context, userCred mcclient.TokenCredential, host *SHost, netConfig *api.NetworkConfig, pendingUsage quotas.IQuota) ([]SGuestnetwork, error)
|
||||
GetRandomNetworkTypes() []string
|
||||
|
||||
@@ -151,9 +151,13 @@ func (manager *SGuestnetworkManager) GenerateMac(netId string, suggestion string
|
||||
}
|
||||
|
||||
func (manager *SGuestnetworkManager) newGuestNetwork(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, network *SNetwork,
|
||||
index int8, address string, mac string, driver string, bwLimit int, virtual bool, reserved bool,
|
||||
allocDir api.IPAllocationDirection, requiredDesignatedIp bool, ifname string, teamWithMac string) (*SGuestnetwork, error) {
|
||||
|
||||
index int8, address string, mac string, driver string, bwLimit int,
|
||||
virtual bool, reserved bool,
|
||||
allocDir api.IPAllocationDirection,
|
||||
requiredDesignatedIp bool,
|
||||
reUseAddr bool,
|
||||
ifname string, teamWithMac string,
|
||||
) (*SGuestnetwork, error) {
|
||||
gn := SGuestnetwork{}
|
||||
gn.SetModelManager(GuestnetworkManager, &gn)
|
||||
|
||||
@@ -182,16 +186,29 @@ func (manager *SGuestnetworkManager) newGuestNetwork(ctx context.Context, userCr
|
||||
}
|
||||
gn.MacAddr = macAddr
|
||||
if !virtual {
|
||||
addrTable := network.GetUsedAddresses()
|
||||
recentAddrTable := manager.getRecentlyReleasedIPAddresses(network.Id, network.getAllocTimoutDuration())
|
||||
ipAddr, err := network.GetFreeIP(ctx, userCred, addrTable, recentAddrTable, address, allocDir, reserved)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if len(address) > 0 && reUseAddr {
|
||||
ipAddr, err := netutils.NewIPV4Addr(address)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Reuse invalid address %s", address)
|
||||
}
|
||||
if !network.IsAddressInRange(ipAddr) {
|
||||
return nil, errors.Wrapf(httperrors.ErrOutOfRange, "%s not in network address range", address)
|
||||
}
|
||||
// if reuse Ip address, no need to check address availability
|
||||
// assign it anyway
|
||||
gn.IpAddr = address
|
||||
} else {
|
||||
addrTable := network.GetUsedAddresses()
|
||||
recentAddrTable := manager.getRecentlyReleasedIPAddresses(network.Id, network.getAllocTimoutDuration())
|
||||
ipAddr, err := network.GetFreeIP(ctx, userCred, addrTable, recentAddrTable, address, allocDir, reserved)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(address) > 0 && ipAddr != address && requiredDesignatedIp {
|
||||
return nil, fmt.Errorf("candidate ip %s is occupied!", address)
|
||||
}
|
||||
gn.IpAddr = ipAddr
|
||||
}
|
||||
if len(address) > 0 && ipAddr != address && requiredDesignatedIp {
|
||||
return nil, fmt.Errorf("candidate ip %s is occupied!", address)
|
||||
}
|
||||
gn.IpAddr = ipAddr
|
||||
}
|
||||
ifname, err = gn.checkOrAllocateIfname(network, ifname)
|
||||
if err != nil {
|
||||
|
||||
@@ -2504,15 +2504,23 @@ func (self *SGuest) GetOSProfile() osprofile.SOSProfile {
|
||||
return osProf
|
||||
}
|
||||
|
||||
func (self *SGuest) Attach2Network(ctx context.Context, userCred mcclient.TokenCredential, network *SNetwork,
|
||||
func (self *SGuest) Attach2Network(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
network *SNetwork,
|
||||
pendingUsage quotas.IQuota,
|
||||
address string,
|
||||
driver string, bwLimit int, virtual bool,
|
||||
reserved bool, allocDir api.IPAllocationDirection, requireDesignatedIP bool,
|
||||
nicConfs []SNicConfig) ([]SGuestnetwork, error) {
|
||||
reserved bool,
|
||||
allocDir api.IPAllocationDirection,
|
||||
requireDesignatedIP bool,
|
||||
reUseAddr bool,
|
||||
nicConfs []SNicConfig,
|
||||
) ([]SGuestnetwork, error) {
|
||||
|
||||
firstNic, err := self.attach2NetworkOnce(ctx, userCred, network, pendingUsage, address, driver, bwLimit, virtual,
|
||||
reserved, allocDir, requireDesignatedIP, nicConfs[0], "")
|
||||
firstNic, err := self.attach2NetworkOnce(ctx, userCred, network, pendingUsage,
|
||||
address, driver, bwLimit, virtual,
|
||||
reserved, allocDir, requireDesignatedIP, reUseAddr, nicConfs[0], "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "self.attach2NetworkOnce")
|
||||
}
|
||||
@@ -2524,7 +2532,7 @@ func (self *SGuest) Attach2Network(ctx context.Context, userCred mcclient.TokenC
|
||||
nicConfs[i].Mac = firstMac.Add(i).String()
|
||||
}
|
||||
gn, err := self.attach2NetworkOnce(ctx, userCred, network, pendingUsage, "", firstNic.Driver, 0, true,
|
||||
false, allocDir, false, nicConfs[i], firstNic.MacAddr)
|
||||
false, allocDir, false, false, nicConfs[i], firstNic.MacAddr)
|
||||
if err != nil {
|
||||
return retNics, errors.Wrap(err, "self.attach2NetworkOnce")
|
||||
}
|
||||
@@ -2534,12 +2542,19 @@ func (self *SGuest) Attach2Network(ctx context.Context, userCred mcclient.TokenC
|
||||
return retNics, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) attach2NetworkOnce(ctx context.Context, userCred mcclient.TokenCredential, network *SNetwork,
|
||||
func (self *SGuest) attach2NetworkOnce(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
network *SNetwork,
|
||||
pendingUsage quotas.IQuota,
|
||||
address string,
|
||||
driver string, bwLimit int, virtual bool,
|
||||
reserved bool, allocDir api.IPAllocationDirection, requireDesignatedIP bool,
|
||||
nicConf SNicConfig, teamWithMac string) (*SGuestnetwork, error) {
|
||||
reserved bool,
|
||||
allocDir api.IPAllocationDirection,
|
||||
requireDesignatedIP bool,
|
||||
reUseAddr bool,
|
||||
nicConf SNicConfig, teamWithMac string,
|
||||
) (*SGuestnetwork, error) {
|
||||
/*
|
||||
allow a guest attach to a network 2 times
|
||||
*/
|
||||
@@ -2556,9 +2571,11 @@ func (self *SGuest) attach2NetworkOnce(ctx context.Context, userCred mcclient.To
|
||||
lockman.LockClass(ctx, QuotaManager, self.ProjectId)
|
||||
defer lockman.ReleaseClass(ctx, QuotaManager, self.ProjectId)
|
||||
|
||||
guestnic, err := GuestnetworkManager.newGuestNetwork(ctx, userCred, self, network,
|
||||
guestnic, err := GuestnetworkManager.newGuestNetwork(ctx, userCred,
|
||||
self, network,
|
||||
nicConf.Index, address, nicConf.Mac, driver, bwLimit, virtual, reserved,
|
||||
allocDir, requireDesignatedIP, nicConf.Ifname, teamWithMac)
|
||||
allocDir, requireDesignatedIP, reUseAddr,
|
||||
nicConf.Ifname, teamWithMac)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GuestnetworkManager.newGuestNetwork")
|
||||
}
|
||||
@@ -2723,7 +2740,7 @@ func (self *SGuest) SyncVMNics(ctx context.Context, userCred mcclient.TokenCrede
|
||||
}
|
||||
// always try allocate from reserved pool
|
||||
_, err = self.Attach2Network(ctx, userCred, add.net, nil, ipStr,
|
||||
add.nic.GetDriver(), 0, false, true, api.IPAllocationDefault, true, []SNicConfig{nicConf})
|
||||
add.nic.GetDriver(), 0, false, true, api.IPAllocationDefault, true, false, []SNicConfig{nicConf})
|
||||
if err != nil {
|
||||
result.AddError(err)
|
||||
} else {
|
||||
@@ -3025,12 +3042,12 @@ func (self *SGuest) CreateNetworksOnHost(
|
||||
if len(netArray) == 0 {
|
||||
netConfig := self.getDefaultNetworkConfig()
|
||||
_, err := self.attach2RandomNetwork(ctx, userCred, host, netConfig, pendingUsage)
|
||||
return err
|
||||
return errors.Wrap(err, "self.attach2RandomNetwork")
|
||||
}
|
||||
for idx, netConfig := range netArray {
|
||||
netConfig, err := parseNetworkInfo(userCred, netConfig)
|
||||
for idx := range netArray {
|
||||
netConfig, err := parseNetworkInfo(userCred, netArray[idx])
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrapf(err, "parseNetworkInfo at %d", idx)
|
||||
}
|
||||
var candidateNet *schedapi.CandidateNet
|
||||
if len(candidateNets) > idx {
|
||||
@@ -3042,7 +3059,7 @@ func (self *SGuest) CreateNetworksOnHost(
|
||||
}
|
||||
_, err = self.attach2NetworkDesc(ctx, userCred, host, netConfig, pendingUsage, networkIds)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "self.attach2NetworkDesc")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -3087,12 +3104,12 @@ func (self *SGuest) attach2NetworkDesc(
|
||||
|
||||
func (self *SGuest) attach2NamedNetworkDesc(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, netConfig *api.NetworkConfig, pendingUsage quotas.IQuota) ([]SGuestnetwork, error) {
|
||||
driver := self.GetDriver()
|
||||
net, nicConfs, allocDir := driver.GetNamedNetworkConfiguration(self, userCred, host, netConfig)
|
||||
net, nicConfs, allocDir, reuseAddr := driver.GetNamedNetworkConfiguration(self, ctx, userCred, host, netConfig)
|
||||
if net != nil {
|
||||
if len(nicConfs) == 0 {
|
||||
return nil, fmt.Errorf("no avaialble network interface?")
|
||||
}
|
||||
gn, err := self.Attach2Network(ctx, userCred, net, pendingUsage, netConfig.Address, netConfig.Driver, netConfig.BwLimit, netConfig.Vip, netConfig.Reserved, allocDir, netConfig.RequireDesignatedIP, nicConfs)
|
||||
gn, err := self.Attach2Network(ctx, userCred, net, pendingUsage, netConfig.Address, netConfig.Driver, netConfig.BwLimit, netConfig.Vip, netConfig.Reserved, allocDir, netConfig.RequireDesignatedIP, reuseAddr, nicConfs)
|
||||
if err != nil {
|
||||
log.Errorf("Attach2Network fail %s", err)
|
||||
return nil, err
|
||||
@@ -4009,6 +4026,8 @@ func (self *SGuest) GetShortDesc(ctx context.Context) *jsonutils.JSONDict {
|
||||
var billingInfo SCloudBillingInfo
|
||||
|
||||
if host != nil {
|
||||
desc.Set("host", jsonutils.NewString(host.Name))
|
||||
desc.Set("host_id", jsonutils.NewString(host.Id))
|
||||
billingInfo.SCloudProviderInfo = host.getCloudProviderInfo()
|
||||
}
|
||||
|
||||
|
||||
@@ -1274,9 +1274,9 @@ func (self *SHost) GetBaremetalnetworks() []SHostnetwork {
|
||||
return hns
|
||||
}
|
||||
|
||||
func (self *SHost) GetAttach2Network(network *SNetwork) *SHostnetwork {
|
||||
func (self *SHost) GetAttach2Network(netId string) *SHostnetwork {
|
||||
q := self.GetBaremetalnetworksQuery()
|
||||
q = q.Equals("network_id", network.Id)
|
||||
q = q.Equals("network_id", netId)
|
||||
hn := SHostnetwork{}
|
||||
hn.SetModelManager(HostnetworkManager, &hn)
|
||||
|
||||
@@ -1289,7 +1289,7 @@ func (self *SHost) GetAttach2Network(network *SNetwork) *SHostnetwork {
|
||||
}
|
||||
|
||||
func (self *SHost) isAttach2Network(network *SNetwork) bool {
|
||||
hn := self.GetAttach2Network(network)
|
||||
hn := self.GetAttach2Network(network.Id)
|
||||
return hn != nil
|
||||
}
|
||||
|
||||
|
||||
@@ -208,7 +208,7 @@ func (self *SSchedpolicy) PerformEvaluate(ctx context.Context, userCred mcclient
|
||||
|
||||
log.V(10).Debugf("Schedpolicy evaluate input: %s", params.PrettyString())
|
||||
|
||||
meet, err := conditionparser.Eval(self.Condition, params)
|
||||
meet, err := conditionparser.EvalBool(self.Condition, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -226,7 +226,7 @@ func matchResourceSchedPolicy(
|
||||
policy SSchedpolicy,
|
||||
input *jsonutils.JSONDict,
|
||||
) bool {
|
||||
meet, err := conditionparser.Eval(policy.Condition, input)
|
||||
meet, err := conditionparser.EvalBool(policy.Condition, input)
|
||||
if err != nil {
|
||||
log.Errorf("Eval Condition %s error: %v", policy.Condition, err)
|
||||
return false
|
||||
|
||||
@@ -117,6 +117,8 @@ type ComputeOptions struct {
|
||||
|
||||
DisconnectedCloudAccountRetryProbeIntervalHours int `help:"interval to wait to probe status of a disconnected cloud account" default:"24"`
|
||||
|
||||
BaremetalServerReuseHostIp bool `help:"baremetal server reuse host IP address, default true" default:"true"`
|
||||
|
||||
SCapabilityOptions
|
||||
common_options.CommonOptions
|
||||
common_options.DBOptions
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/conditionparser"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
@@ -75,6 +76,32 @@ func (self *GuestBatchCreateTask) allocateGuestOnHost(ctx context.Context, guest
|
||||
log.Errorf("GetPendingUsage fail %s", err)
|
||||
}
|
||||
|
||||
if conditionparser.IsTemplate(guest.Name) {
|
||||
guestInfo := guest.GetShortDesc(ctx)
|
||||
generateName := guest.GetMetadata("generate_name", self.UserCred)
|
||||
if len(generateName) == 0 {
|
||||
generateName = guest.Name
|
||||
}
|
||||
newGenName, err := conditionparser.EvalTemplate(generateName, guestInfo)
|
||||
if err == nil {
|
||||
newName, err := db.GenerateName2(models.GuestManager,
|
||||
guest.GetOwnerId(), newGenName, guest, 1)
|
||||
if err == nil {
|
||||
_, err = db.Update(guest, func() error {
|
||||
guest.Name = newName
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("guest update name fail %s", err)
|
||||
}
|
||||
} else {
|
||||
log.Errorf("db.GenerateName2 fail %s", err)
|
||||
}
|
||||
} else {
|
||||
log.Errorf("conditionparser.EvalTemplate fail %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
host := guest.GetHost()
|
||||
|
||||
quotaCpuMem := models.SQuota{Count: 1, Cpu: int(guest.VcpuCount), Memory: guest.VmemSize}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
package conditionparser
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
@@ -24,16 +24,16 @@ import (
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/utils"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidOp = errors.New("invalid operation")
|
||||
ErrFieldNotFound = errors.New("field not found")
|
||||
ErrOutOfIndex = errors.New("out of index")
|
||||
ErrFuncArgument = errors.New("invalid function arguments")
|
||||
ErrMethodNotFound = errors.New("method not found")
|
||||
ErrInvalidOp = errors.Error("invalid operation")
|
||||
ErrFieldNotFound = errors.Error("field not found")
|
||||
ErrOutOfIndex = errors.Error("out of index")
|
||||
ErrFuncArgument = errors.Error("invalid function arguments")
|
||||
ErrMethodNotFound = errors.Error("method not found")
|
||||
)
|
||||
|
||||
func IsValid(exprStr string) bool {
|
||||
@@ -44,22 +44,45 @@ func IsValid(exprStr string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func Eval(exprStr string, input interface{}) (bool, error) {
|
||||
func EvalString(exprStr string, input interface{}) (string, error) {
|
||||
if len(exprStr) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
expr, err := parser.ParseExpr(exprStr)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "parse expr %s error", exprStr)
|
||||
}
|
||||
result, err := eval(expr, input)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "eval")
|
||||
}
|
||||
switch strVal := result.(type) {
|
||||
case string:
|
||||
return strVal, nil
|
||||
case *jsonutils.JSONString:
|
||||
return strVal.GetString()
|
||||
default:
|
||||
return fmt.Sprintf("%s", strVal), nil
|
||||
}
|
||||
}
|
||||
|
||||
func EvalBool(exprStr string, input interface{}) (bool, error) {
|
||||
if len(exprStr) == 0 {
|
||||
return true, nil
|
||||
}
|
||||
expr, err := parser.ParseExpr(exprStr)
|
||||
if err != nil {
|
||||
log.Errorf("parse expr %s error %s", exprStr, err)
|
||||
return false, err
|
||||
return false, errors.Wrapf(err, "parse expr %s", exprStr)
|
||||
}
|
||||
result, err := eval(expr, input)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return false, errors.Wrap(err, "eval")
|
||||
}
|
||||
switch result.(type) {
|
||||
case bool, *jsonutils.JSONBool:
|
||||
return getBool(result), nil
|
||||
switch bVal := result.(type) {
|
||||
case bool:
|
||||
return bVal, nil
|
||||
case *jsonutils.JSONBool:
|
||||
return bVal.Bool()
|
||||
case []interface{}, *jsonutils.JSONArray:
|
||||
arrX := getArray(result)
|
||||
for i := 0; i < len(arrX); i += 1 {
|
||||
|
||||
@@ -49,7 +49,7 @@ func TestAst(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
result, err := Eval(c.in, input)
|
||||
result, err := EvalBool(c.in, input)
|
||||
if err != nil {
|
||||
t.Errorf("eval expr %s error %s", c.in, err)
|
||||
return
|
||||
@@ -108,7 +108,7 @@ func TestEval2(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
result, err := Eval(c.in, input)
|
||||
result, err := EvalBool(c.in, input)
|
||||
if err != nil {
|
||||
t.Errorf("eval expr %s error %s", c.in, err)
|
||||
return
|
||||
@@ -165,7 +165,7 @@ func TestEval3(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
result, err := Eval(c.in, input)
|
||||
result, err := EvalBool(c.in, input)
|
||||
if err != nil {
|
||||
t.Errorf("eval expr %s error %s", c.in, err)
|
||||
return
|
||||
@@ -177,3 +177,45 @@ func TestEval3(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvalString(t *testing.T) {
|
||||
input := jsonutils.NewDict()
|
||||
input.Add(jsonutils.NewString("myname"), "name")
|
||||
input.Add(jsonutils.NewString("myhostname"), "host", "name")
|
||||
input.Add(jsonutils.NewString("myproject"), "project", "name")
|
||||
input.Add(jsonutils.NewString("myprojectId"), "project", "id")
|
||||
|
||||
cases := []struct {
|
||||
input string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
input: "host.name",
|
||||
want: "myhostname",
|
||||
},
|
||||
{
|
||||
input: "project.id",
|
||||
want: "myprojectId",
|
||||
},
|
||||
{
|
||||
input: "project.name",
|
||||
want: "myproject",
|
||||
},
|
||||
{
|
||||
input: "name",
|
||||
want: "myname",
|
||||
},
|
||||
{
|
||||
input: `name+"/"+project.name`,
|
||||
want: "myname/myproject",
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
got, err := EvalString(c.input, input)
|
||||
if err != nil {
|
||||
t.Errorf("Eval %s fail: %s", c.input, err)
|
||||
} else if got != c.want {
|
||||
t.Errorf("Eval %s want %s got %s", c.input, c.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package conditionparser
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
tempPattern = regexp.MustCompile(`\$\{[\w\d._-]*\}`)
|
||||
)
|
||||
|
||||
func IsTemplate(template string) bool {
|
||||
return tempPattern.MatchString(template)
|
||||
}
|
||||
|
||||
func EvalTemplate(template string, input interface{}) (string, error) {
|
||||
var output strings.Builder
|
||||
matches := tempPattern.FindAllStringSubmatchIndex(template, -1)
|
||||
offset := 0
|
||||
for _, match := range matches {
|
||||
output.WriteString(template[offset:match[0]])
|
||||
o, err := EvalString(template[match[0]+2:match[1]-1], input)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, template[match[0]+2:match[1]])
|
||||
}
|
||||
output.WriteString(o)
|
||||
offset = match[1]
|
||||
}
|
||||
if offset < len(template) {
|
||||
output.WriteString(template[offset:])
|
||||
}
|
||||
return output.String(), nil
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package conditionparser
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
)
|
||||
|
||||
func TestEvalTemplate(t *testing.T) {
|
||||
input := jsonutils.NewDict()
|
||||
input.Add(jsonutils.NewString("myhost"), "host")
|
||||
input.Add(jsonutils.NewString("jxq"), "zone")
|
||||
input.Add(jsonutils.NewString("myprojId"), "project", "id")
|
||||
input.Add(jsonutils.NewString("my"), "project", "name")
|
||||
input.Add(jsonutils.NewString("my"), "proj_name")
|
||||
cases := []struct {
|
||||
input string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
input: "${host}-1",
|
||||
want: "myhost-1",
|
||||
},
|
||||
{
|
||||
input: "${zone}-${host}-1",
|
||||
want: "jxq-myhost-1",
|
||||
},
|
||||
{
|
||||
input: "${zone}-${host}-${project.name}-1",
|
||||
want: "jxq-myhost-my-1",
|
||||
},
|
||||
{
|
||||
input: "${zone}-${host}-${proj_name}-1",
|
||||
want: "jxq-myhost-my-1",
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
got, err := EvalTemplate(c.input, input)
|
||||
if err != nil {
|
||||
t.Errorf("EvalTemplate %s error %s", c.input, err)
|
||||
} else if got != c.want {
|
||||
t.Errorf("EvalTemplate %s got %s want %s", c.input, got, c.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user