From 3d1ba16f9559dbbf74f9d6409546ed752eb2b786 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Thu, 7 Mar 2019 11:13:58 +0800 Subject: [PATCH 1/7] fix: exi host name conversion remove ip --- pkg/util/esxi/host.go | 23 ++++++++++++++++++----- pkg/util/esxi/host_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 pkg/util/esxi/host_test.go diff --git a/pkg/util/esxi/host.go b/pkg/util/esxi/host.go index 4fa0a4b62c..ab2f265a16 100644 --- a/pkg/util/esxi/host.go +++ b/pkg/util/esxi/host.go @@ -3,6 +3,7 @@ package esxi import ( "context" "fmt" + "regexp" "strings" "github.com/vmware/govmomi/vim25/mo" @@ -77,15 +78,27 @@ func NewHost(manager *SESXiClient, host *mo.HostSystem, dc *SDatacenter) *SHost return &SHost{SManagedObject: newManagedObject(manager, host, dc)} } -func (self *SHost) GetName() string { - name := self.SManagedObject.GetName() - dotPos := strings.IndexByte(name, '.') - if dotPos > 0 && !regutils.MatchIP4Addr(name) { - name = name[:dotPos] +var ( + ip4addrPattern = regexp.MustCompile(`\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}`) +) + +func formatName(name string) string { + if ip4addrPattern.MatchString(name) { + return strings.Replace(name, ".", "-", -1) + } else { + dotPos := strings.IndexByte(name, '.') + if dotPos > 0 && !regutils.MatchIP4Addr(name) { + name = name[:dotPos] + } + return name } return name } +func (self *SHost) GetName() string { + return formatName(self.SManagedObject.GetName()) +} + func (self *SHost) GetMetadata() *jsonutils.JSONDict { return nil } diff --git a/pkg/util/esxi/host_test.go b/pkg/util/esxi/host_test.go new file mode 100644 index 0000000000..c5f22e8e5a --- /dev/null +++ b/pkg/util/esxi/host_test.go @@ -0,0 +1,27 @@ +package esxi + +import ( + "testing" +) + +func TestFormatName(t *testing.T) { + cases := []struct { + In string + Want string + }{ + { + In: "esxi-172.16.23.1", + Want: "esxi-172-16-23-1", + }, + { + In: "esxi6.yunion.cn", + Want: "esxi6", + }, + } + for _, c := range cases { + got := formatName(c.In) + if got != c.Want { + t.Errorf("got: %s want %s", got, c.Want) + } + } +} From 87284d48c83b239cd0b13d2f022d99361f7fa062 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Thu, 7 Mar 2019 15:02:08 +0800 Subject: [PATCH 2/7] fix: huawei filter excludes skus with null providers --- pkg/compute/models/skus.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/compute/models/skus.go b/pkg/compute/models/skus.go index cb8c764666..6a3e1ea687 100644 --- a/pkg/compute/models/skus.go +++ b/pkg/compute/models/skus.go @@ -134,6 +134,7 @@ func excludeSkus(q *sqlchemy.SQuery) *sqlchemy.SQuery { // 排除掉华为云对镜像有特殊要求的sku return q.Filter( sqlchemy.OR( + sqlchemy.IsNullOrEmpty(q.Field("provider")), sqlchemy.NotEquals(q.Field("provider"), CLOUD_PROVIDER_HUAWEI), sqlchemy.AND( sqlchemy.Equals(q.Field("provider"), CLOUD_PROVIDER_HUAWEI), From 98565a815b8557a72f03eff5ec1f9c1a7ed66c41 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Thu, 7 Mar 2019 22:37:17 +0800 Subject: [PATCH 3/7] fix: allow host attach to same wire with multiple interface --- pkg/compute/models/disks.go | 3 ++- pkg/compute/models/hosts.go | 14 ++++++++------ pkg/compute/models/hostwires.go | 20 +++++++++++++++++++- pkg/compute/models/netinterfaces.go | 2 +- pkg/mcclient/modules/mod_hostwires.go | 2 +- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/pkg/compute/models/disks.go b/pkg/compute/models/disks.go index eb6e852d43..ee7475b64c 100644 --- a/pkg/compute/models/disks.go +++ b/pkg/compute/models/disks.go @@ -1387,7 +1387,8 @@ func (self *SDisk) PerformPurge(ctx context.Context, userCred mcclient.TokenCred return nil, err } - if self.GetCloudprovider().Provider == CLOUD_PROVIDER_HUAWEI && self.GetSnapshotCount() > 0 { + provider := self.GetCloudprovider() + if provider != nil && provider.Provider == CLOUD_PROVIDER_HUAWEI && self.GetSnapshotCount() > 0 { return nil, httperrors.NewForbiddenError("not allow to purge. Virtual disk must not have snapshots") } diff --git a/pkg/compute/models/hosts.go b/pkg/compute/models/hosts.go index 2979db3c4c..cd1a10507e 100644 --- a/pkg/compute/models/hosts.go +++ b/pkg/compute/models/hosts.go @@ -2850,7 +2850,9 @@ func (self *SHost) addNetif(ctx context.Context, userCred mcclient.TokenCredenti } netif.Rate = rate netif.NicType = nicType - netif.Index = index + if index >= 0 { + netif.Index = index + } if !linkUp.IsNone() { netif.LinkUp = linkUp.Bool() } @@ -2904,7 +2906,7 @@ func (self *SHost) addNetif(ctx context.Context, userCred mcclient.TokenCredenti bridge = fmt.Sprintf("br%s", sw.GetName()) } var isMaster = netif.NicType == NIC_TYPE_ADMIN - ihw, err := db.FetchJointByIds(HostwireManager, self.Id, sw.Id, nil) + ihw, err := HostwireManager.FetchByIdsAndMac(self.Id, sw.Id, mac) if err != nil { hw := &SHostwire{} hw.Bridge = bridge @@ -2918,11 +2920,11 @@ func (self *SHost) addNetif(ctx context.Context, userCred mcclient.TokenCredenti return err } } else { - hw := ihw.(*SHostwire) + hw := ihw HostwireManager.TableSpec().Update(hw, func() error { hw.Bridge = bridge hw.Interface = strInterface - hw.MacAddr = mac + // hw.MacAddr = mac hw.IsMaster = isMaster return nil }) @@ -2988,7 +2990,7 @@ func (self *SHost) EnableNetif(ctx context.Context, userCred mcclient.TokenCrede if wire == nil { return fmt.Errorf("No wire attached") } - hw, err := db.FetchJointByIds(HostwireManager, self.Id, wire.Id, nil) + hw, err := HostwireManager.FetchByIdsAndMac(self.Id, wire.Id, netif.Mac) if hw == nil { return fmt.Errorf("host not attach to this wire") } @@ -3113,7 +3115,7 @@ func (self *SHost) RemoveNetif(ctx context.Context, userCred mcclient.TokenCrede log.Infof("Remove wire") others := self.GetNetifsOnWire(wire) if len(others) == 0 { - hw, _ := db.FetchJointByIds(HostwireManager, self.Id, wire.Id, nil) + hw, _ := HostwireManager.FetchByIdsAndMac(self.Id, wire.Id, netif.Mac) if hw != nil { db.OpsLog.LogDetachEvent(ctx, self, wire, userCred, jsonutils.NewString(fmt.Sprintf("disable netif %s", self.AccessMac))) log.Infof("Detach host wire because of remove netif %s", netif.Mac) diff --git a/pkg/compute/models/hostwires.go b/pkg/compute/models/hostwires.go index af5f36013f..944cc0961b 100644 --- a/pkg/compute/models/hostwires.go +++ b/pkg/compute/models/hostwires.go @@ -35,7 +35,7 @@ type SHostwire struct { Bridge string `width:"16" charset:"ascii" nullable:"false" list:"admin" update:"admin" create:"admin_required"` // Column(VARCHAR(16, charset='ascii'), nullable=False) Interface string `width:"16" charset:"ascii" nullable:"false" list:"admin" update:"admin" create:"admin_required"` // Column(VARCHAR(16, charset='ascii'), nullable=False) - IsMaster bool `nullable:"true" default:"false" update:"admin" create:"admin_optional"` // Column(Boolean, nullable=True, default=False) + IsMaster bool `nullable:"true" default:"false" list:"admin" update:"admin" create:"admin_optional"` // Column(Boolean, nullable=True, default=False) MacAddr string `width:"18" charset:"ascii" list:"admin" update:"admin" create:"admin_required"` // Column(VARCHAR(18, charset='ascii')) HostId string `width:"128" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"` // = Column(VARCHAR(ID_LENGTH, charset='ascii'), nullable=False) @@ -119,3 +119,21 @@ func (self *SHostwire) Delete(ctx context.Context, userCred mcclient.TokenCreden func (self *SHostwire) Detach(ctx context.Context, userCred mcclient.TokenCredential) error { return db.DetachJoint(ctx, userCred, self) } + +func (manager *SHostwireManager) FilterByParams(q *sqlchemy.SQuery, params jsonutils.JSONObject) *sqlchemy.SQuery { + macStr := jsonutils.GetAnyString(params, []string{"mac", "mac_addr"}) + if len(macStr) > 0 { + q = q.Filter(sqlchemy.Equals(q.Field("mac_addr"), macStr)) + } + return q +} + +func (manager *SHostwireManager) FetchByIdsAndMac(hostId string, wireId string, mac string) (*SHostwire, error) { + query := jsonutils.NewDict() + query.Add(jsonutils.NewString(mac), "mac_addr") + ihw, err := db.FetchJointByIds(manager, hostId, wireId, query) + if err != nil { + return nil, err + } + return ihw.(*SHostwire), nil +} diff --git a/pkg/compute/models/netinterfaces.go b/pkg/compute/models/netinterfaces.go index 71aa440ba2..cd02f1f321 100644 --- a/pkg/compute/models/netinterfaces.go +++ b/pkg/compute/models/netinterfaces.go @@ -219,7 +219,7 @@ func (self *SNetInterface) Remove(ctx context.Context, userCred mcclient.TokenCr host := self.GetBaremetal() wire := self.GetWire() if host != nil && wire != nil { - hw, err := db.FetchJointByIds(HostwireManager, host.Id, wire.Id, nil) + hw, err := HostwireManager.FetchByIdsAndMac(host.Id, wire.Id, self.Mac) if err != nil { log.Errorf("NetInterface remove HostwireManager.FetchByIds error %s", err) return err diff --git a/pkg/mcclient/modules/mod_hostwires.go b/pkg/mcclient/modules/mod_hostwires.go index e720da95a1..c18ddbf9e3 100644 --- a/pkg/mcclient/modules/mod_hostwires.go +++ b/pkg/mcclient/modules/mod_hostwires.go @@ -7,7 +7,7 @@ var ( func init() { Hostwires = NewJointComputeManager("hostwire", "hostwires", []string{"Host_ID", "Host", "Wire_ID", "Wire", - "Bridge", "Interface", "Mac_addr"}, + "Bridge", "Interface", "Mac_addr", "is_master"}, []string{}, &Hosts, &Wires) From 76bab2c693c6fc6f8dd4939a1469a4914edc10d4 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Thu, 7 Mar 2019 23:01:55 +0800 Subject: [PATCH 4/7] fix: 1. skip using temporary binding mac at host startup 2. active baremetal NIC index always reset to 0 --- pkg/baremetal/manager.go | 1 + pkg/baremetal/utils/ipmitool/ipmitool.go | 38 +++++++++---------- pkg/hostman/hostinfo/hostbridge/hostbridge.go | 6 +++ pkg/hostman/hostinfo/hostinfo.go | 16 +++++++- 4 files changed, 40 insertions(+), 21 deletions(-) diff --git a/pkg/baremetal/manager.go b/pkg/baremetal/manager.go index d2b119eedd..022353ad07 100644 --- a/pkg/baremetal/manager.go +++ b/pkg/baremetal/manager.go @@ -748,6 +748,7 @@ func (b *SBaremetalInstance) attachWire(mac net.HardwareAddr, wireId string, nic params.Add(jsonutils.NewString(nicType), "nic_type") } params.Add(jsonutils.NewString(wireId), "wire") + params.Add(jsonutils.NewInt(-1), "index") params.Add(jsonutils.JSONTrue, "link_up") return modules.Hosts.PerformAction(session, b.GetId(), "add-netif", params) } diff --git a/pkg/baremetal/utils/ipmitool/ipmitool.go b/pkg/baremetal/utils/ipmitool/ipmitool.go index 7080a02896..411f302978 100644 --- a/pkg/baremetal/utils/ipmitool/ipmitool.go +++ b/pkg/baremetal/utils/ipmitool/ipmitool.go @@ -251,26 +251,26 @@ func SetLanStatic( mask string, gateway string, ) error { - config, err := GetLanConfig(exector, channel) - if err != nil { - return err - } - var argss []Args - if config.IPAddr == ip && config.Netmask == mask && config.Gateway == gateway { - argss = []Args{ - newArgs("lan", "set", channel, "ipsrc", "static"), - newArgs("lan", "set", channel, "ipaddr", ip), - newArgs("lan", "set", channel, "netmask", mask), - newArgs("lan", "set", channel, "defgw", "ipaddr", gateway), - } - } else { - argss = []Args{ - newArgs("lan", "set", channel, "ipaddr", ip), - newArgs("lan", "set", channel, "defgw", "ipaddr", gateway), - newArgs("lan", "set", channel, "netmask", mask), - newArgs("lan", "set", channel, "ipsrc", "static"), - } + // config, err := GetLanConfig(exector, channel) + // if err != nil { + // return err + // } + // var argss []Args + // if config.IPAddr == ip && config.Netmask == mask && config.Gateway == gateway { + argss := []Args{ + newArgs("lan", "set", channel, "ipsrc", "static"), + newArgs("lan", "set", channel, "ipaddr", ip), + newArgs("lan", "set", channel, "netmask", mask), + newArgs("lan", "set", channel, "defgw", "ipaddr", gateway), } + // } else { + // argss = []Args{ + // newArgs("lan", "set", channel, "ipsrc", "static"), + // newArgs("lan", "set", channel, "ipaddr", ip), + // newArgs("lan", "set", channel, "netmask", mask), + // newArgs("lan", "set", channel, "defgw", "ipaddr", gateway), + // } + // } return doActions(exector, "set_lan_static", argss...) } diff --git a/pkg/hostman/hostinfo/hostbridge/hostbridge.go b/pkg/hostman/hostinfo/hostbridge/hostbridge.go index 7cbc697566..ef60953255 100644 --- a/pkg/hostman/hostinfo/hostbridge/hostbridge.go +++ b/pkg/hostman/hostinfo/hostbridge/hostbridge.go @@ -26,6 +26,7 @@ type IBridgeDriver interface { Exists() bool Interfaces() []string + FetchConfig() GetMac() string GenerateIfupScripts(scriptPath string, nic jsonutils.JSONObject) error GenerateIfdownScripts(scriptPath string, nic jsonutils.JSONObject) error @@ -56,6 +57,11 @@ func NewBaseBridgeDriver(bridge, inter, ip string) (*SBaseBridgeDriver, error) { return bd, nil } +func (d *SBaseBridgeDriver) FetchConfig() { + d.bridge.FetchConfig() + d.inter.FetchConfig() +} + func (d *SBaseBridgeDriver) GetMac() string { if len(d.bridge.Mac) == 0 { d.bridge.FetchConfig() diff --git a/pkg/hostman/hostinfo/hostinfo.go b/pkg/hostman/hostinfo/hostinfo.go index ec980dd089..d36859550d 100644 --- a/pkg/hostman/hostinfo/hostinfo.go +++ b/pkg/hostman/hostinfo/hostinfo.go @@ -677,11 +677,21 @@ func (h *SHostInfo) GetMasterIp() string { } func (h *SHostInfo) GetMasterMac() string { + return h.getMasterMacWithRefresh(false) +} + +func (h *SHostInfo) getMasterMacWithRefresh(refresh bool) string { if h.MasterNic != nil { + if refresh { + h.MasterNic.FetchConfig() + } return h.MasterNic.Mac } for _, n := range h.Nics { if len(n.Ip) > 0 { + if refresh { + n.BridgeDev.FetchConfig() + } return n.BridgeDev.GetMac() } } @@ -768,7 +778,7 @@ func (h *SHostInfo) getZoneInfo(zoneId string, standalone bool) { } func (h *SHostInfo) getHostInfo(zoneId string) { - masterMac := h.GetMasterMac() + masterMac := h.getMasterMacWithRefresh(true) if len(masterMac) == 0 { panic("master mac not found") } @@ -1011,8 +1021,10 @@ func (h *SHostInfo) doSyncNicInfo(nic *SNIC) { content := jsonutils.NewDict() content.Set("bridge", jsonutils.NewString(nic.Bridge)) content.Set("interface", jsonutils.NewString(nic.Inter)) + query := jsonutils.NewDict() + query.Set("mac_addr", jsonutils.NewString(nic.BridgeDev.GetMac())) _, err := modules.Hostwires.Update(h.GetSession(), - h.HostId, nic.Network, nil, content) + h.HostId, nic.Network, query, content) if err != nil { log.Errorln(err) h.onFail() From d23414f3f6ba8cd21e04352500d2566c86af8eaa Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Fri, 8 Mar 2019 00:01:14 +0800 Subject: [PATCH 5/7] fix: validate host status before doing renew prepaid recycle --- pkg/compute/models/host_recycle.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pkg/compute/models/host_recycle.go b/pkg/compute/models/host_recycle.go index ad44d1a900..eeece5362c 100644 --- a/pkg/compute/models/host_recycle.go +++ b/pkg/compute/models/host_recycle.go @@ -688,6 +688,15 @@ func (self *SHost) AllowPerformRenewPrepaidRecycle(ctx context.Context, userCred } func (self *SHost) PerformRenewPrepaidRecycle(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { + if !self.IsPrepaidRecycle() { + return nil, httperrors.NewInputParameterError("Not a prepaid recycle host") + } + if len(self.RealExternalId) == 0 { + return nil, httperrors.NewGeneralError(fmt.Errorf("host RealExternalId is empty")) + } + if len(self.ExternalId) == 0 { + return nil, httperrors.NewGeneralError(fmt.Errorf("host ExternalId is empty")) + } durationStr := jsonutils.GetAnyString(data, []string{"duration"}) if len(durationStr) == 0 { return nil, httperrors.NewInputParameterError("missing duration") From e62ceb5007e57d71e4f049640528b91a20ae86f6 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Fri, 8 Mar 2019 00:09:48 +0800 Subject: [PATCH 6/7] show expired_at colume for host --- pkg/mcclient/modules/mod_hosts.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/mcclient/modules/mod_hosts.go b/pkg/mcclient/modules/mod_hosts.go index f3f69078a4..4fddee1706 100644 --- a/pkg/mcclient/modules/mod_hosts.go +++ b/pkg/mcclient/modules/mod_hosts.go @@ -177,7 +177,9 @@ func init() { "mem_commit_rate", "cpu_commit_bound", "mem_commit_bound", "node_count", "sn", "storage_type", "host_type", "version", "schedtags", - "storage_size"}, + "storage_size", + "expired_at", + }, []string{})} registerCompute(&Hosts) } From 57a2a475efaea7b5b5af7438af9f6c5115d8fdae Mon Sep 17 00:00:00 2001 From: Zexi Li Date: Fri, 8 Mar 2019 19:06:08 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E4=BF=AE=E5=A4=8D:=20joint=20=E7=9A=84?= =?UTF-8?q?=E5=AF=B9=E8=B1=A1=E5=88=9B=E5=BB=BA=E6=97=B6=E6=B2=A1=E6=9C=89?= =?UTF-8?q?=E6=A3=80=E9=AA=8C=E6=98=AF=E5=90=A6=E5=AD=98=E5=9C=A8=EF=BC=8C?= =?UTF-8?q?=E4=BC=9A=E8=A2=AB=E9=87=8D=E5=A4=8D=E6=B7=BB=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/cloudcommon/db/db_joint_dispatcher.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pkg/cloudcommon/db/db_joint_dispatcher.go b/pkg/cloudcommon/db/db_joint_dispatcher.go index 01b5a41344..f20c467705 100644 --- a/pkg/cloudcommon/db/db_joint_dispatcher.go +++ b/pkg/cloudcommon/db/db_joint_dispatcher.go @@ -204,6 +204,15 @@ func (dispatcher *DBJointModelDispatcher) Attach(ctx context.Context, id1 string return nil, httperrors.NewGeneralError(err) } } + + _, _, joinItem, err := fetchJointItem(dispatcher, ctx, userCred, master.GetId(), slave.GetId(), query) + if err != nil && err != sql.ErrNoRows { + return nil, err + } + if joinItem != nil { + return nil, httperrors.NewNotAcceptableError("Object %s %s has attached %s %s", master.KeywordPlural(), master.GetId(), slave.KeywordPlural(), slave.GetId()) + } + lockman.LockJointObject(ctx, master, slave) defer lockman.ReleaseJointObject(ctx, master, slave) return attachItems(dispatcher, master.(IStandaloneModel), slave.(IStandaloneModel), ctx, userCred, query, data)