fix: host nic index should be unique

This commit is contained in:
Qiu Jian
2024-04-09 07:16:06 +08:00
parent 297611d01e
commit 74f4bc85e8
26 changed files with 340 additions and 36 deletions
+1 -1
View File
@@ -284,7 +284,7 @@ type IsolatedDeviceConfig struct {
DevType string `json:"dev_type"`
Model string `json:"model"`
Vendor string `json:"vendor"`
NetworkIndex *int8 `json:"network_index"`
NetworkIndex *int `json:"network_index"`
WireId string `json:"wire_id"`
DiskIndex *int8 `json:"disk_index"`
DevicePath string `json:"device_path"`
+1 -1
View File
@@ -101,7 +101,7 @@ type GuestnetworkBaseDesc struct {
Vlan int `json:"vlan"`
Bw int `json:"bw"`
Mtu int16 `json:"mtu"`
Index int8 `json:"index"`
Index int `json:"index"`
RxTrafficLimit int64 `json:"rx_traffic_limit"`
TxTrafficLimit int64 `json:"tx_traffic_limit"`
NicType compute.TNicType `json:"nic_type"`
+1 -1
View File
@@ -563,7 +563,7 @@ type HostAddNetifInput struct {
NicType cloudmux.TNicType `json:"nic_type"`
Index int8 `json:"index"`
Index int `json:"index"`
LinkUp string `json:"link_up"`
+1 -1
View File
@@ -125,7 +125,7 @@ type IsolatedDeviceJsonDesc struct {
Addr string `json:"addr"`
VendorDeviceId string `json:"vendor_device_id"`
Vendor string `json:"vendor"`
NetworkIndex int8 `json:"network_index"`
NetworkIndex int `json:"network_index"`
IsInfinibandNic bool `json:"is_infiniband_nic"`
OvsOffloadInterface string `json:"ovs_offload_interface"`
DiskIndex int8 `json:"disk_index"`
+2
View File
@@ -50,6 +50,8 @@ type SNic struct {
VlanId int `json:"vlan_id"`
Bandwidth int `json:"bandwidth"`
Index int `json:"index"`
}
type SRoute []string
+1 -1
View File
@@ -2158,7 +2158,7 @@ func (self *SGuest) startAttachIsolatedDevGeneral(ctx context.Context, userCred
return err
}
func (self *SGuest) attachIsolatedDevice(ctx context.Context, userCred mcclient.TokenCredential, dev *SIsolatedDevice, networkIndex, diskIndex *int8) error {
func (self *SGuest) attachIsolatedDevice(ctx context.Context, userCred mcclient.TokenCredential, dev *SIsolatedDevice, networkIndex *int, diskIndex *int8) error {
if len(dev.GuestId) > 0 {
return fmt.Errorf("Isolated device already attached to another guest: %s", dev.GuestId)
}
+3 -1
View File
@@ -126,7 +126,9 @@ func (manager *SGuestManager) FetchCustomizeColumns(
if len(fields) == 0 || fields.Contains("ips") {
ips := make([]string, 0, len(nics))
for _, nic := range nics {
ips = append(ips, nic.IpAddr)
if len(nic.IpAddr) > 0 {
ips = append(ips, nic.IpAddr)
}
if len(nic.Ip6Addr) > 0 {
ips = append(ips, nic.Ip6Addr)
}
+7 -2
View File
@@ -99,7 +99,7 @@ type SGuestnetwork struct {
TxTrafficLimit int64 `nullable:"false" default:"0" list:"user"`
TxTrafficUsed int64 `nullable:"false" default:"0" list:"user"`
// 网卡序号
Index int8 `nullable:"false" default:"0" list:"user" update:"user"`
Index int `nullable:"false" default:"0" list:"user" update:"user"`
// 是否为虚拟接口(无IP
Virtual bool `default:"false" list:"user"`
// 虚拟网卡设备名称
@@ -238,7 +238,7 @@ type newGuestNetworkArgs struct {
guest *SGuest
network *SNetwork
index int8
index int
ipAddr string
allocDir api.IPAllocationDirection
@@ -692,6 +692,11 @@ func (gn *SGuestnetwork) getJsonDesc() *api.GuestnetworkJsonDesc {
}
}
if options.Options.NetworkAlwaysManualConfig {
manual := true
desc.Manual = &manual
}
return desc
}
+4 -4
View File
@@ -3299,13 +3299,13 @@ func (self *SGuest) getAttach2NetworkCount(net *SNetwork) (int, error) {
return q.CountWithError()
}
func (self *SGuest) getUsableNicIndex() int8 {
func (self *SGuest) getUsableNicIndex() int {
nics, err := self.GetNetworks("")
if err != nil {
return -1
}
maxIndex := int8(len(nics))
for i := int8(0); i <= maxIndex; i++ {
maxIndex := len(nics)
for i := 0; i <= maxIndex; i++ {
found := true
for j := range nics {
if nics[j].Index == i {
@@ -4953,7 +4953,7 @@ func (self *SGuest) GetIsolatedDevices() ([]SIsolatedDevice, error) {
return devs, nil
}
func (self *SGuest) GetIsolatedDeviceByNetworkIndex(index int8) (*SIsolatedDevice, error) {
func (self *SGuest) GetIsolatedDeviceByNetworkIndex(index int) (*SIsolatedDevice, error) {
dev := SIsolatedDevice{}
q := IsolatedDeviceManager.Query().Equals("guest_id", self.Id).Equals("network_index", index)
if cnt, err := q.CountWithError(); err != nil {
+1 -1
View File
@@ -198,7 +198,7 @@ func (self *SGuest) doPrepaidRecycleNoLock(ctx context.Context, userCred mcclien
"",
1000,
nicType,
int8(i),
i,
tristate.True,
1500,
false,
+1 -1
View File
@@ -68,7 +68,7 @@ func (g *SGuest) getTapNicJsonDesc(ctx context.Context, p *api.GuestnetworkJsonD
return nil
}
var driver string
var index int8
var index int
if p == nil {
driver = "virtio"
index = 0
+26 -4
View File
@@ -4652,14 +4652,14 @@ func (h *SHost) PerformAddNetif(
}
}
err = h.addNetif(ctx, userCred, mac, vlan, wire, ipAddr, int(rate), nicType, int8(index), isLinkUp,
err = h.addNetif(ctx, userCred, mac, vlan, wire, ipAddr, int(rate), nicType, index, isLinkUp,
int16(mtu), reset, netIf, bridge, reserve, requireDesignatedIp)
return nil, errors.Wrap(err, "addNetif")
}
func (h *SHost) addNetif(ctx context.Context, userCred mcclient.TokenCredential,
mac string, vlanId int, wire string, ipAddr string,
rate int, nicType compute.TNicType, index int8, linkUp tristate.TriState, mtu int16,
rate int, nicType compute.TNicType, index int, linkUp tristate.TriState, mtu int16,
reset bool, strInterface *string, strBridge *string,
reserve bool, requireDesignatedIp bool,
) error {
@@ -4735,7 +4735,7 @@ func (h *SHost) addNetif(ctx context.Context, userCred mcclient.TokenCredential,
if nicType != "" && nicType != netif.NicType {
netif.NicType = nicType
}
if index >= 0 && index != netif.Index {
if index >= 0 {
netif.Index = index
}
if !linkUp.IsNone() && linkUp.Bool() != netif.LinkUp {
@@ -4750,6 +4750,28 @@ func (h *SHost) addNetif(ctx context.Context, userCred mcclient.TokenCredential,
if strBridge != nil {
netif.Bridge = *strBridge
}
// ensure index is unique on host
{
ifs := h.GetHostNetInterfaces()
dupIdx := false
var maxIdx int
for i := range ifs {
if ifs[i].Mac == netif.Mac && ifs[i].VlanId == netif.VlanId {
// find self, skip
continue
}
if netif.Index == ifs[i].Index {
// duplicate nic index
dupIdx = true
}
if maxIdx < ifs[i].Index {
maxIdx = ifs[i].Index
}
}
if dupIdx {
netif.Index = maxIdx + 1
}
}
err = NetInterfaceManager.TableSpec().InsertOrUpdate(ctx, netif)
if err != nil {
return errors.Wrap(err, "InsertOrUpdate")
@@ -5644,7 +5666,7 @@ func (host *SHost) SyncHostExternalNics(ctx context.Context, userCred mcclient.T
}
}
err = host.addNetif(ctx, userCred, extNic.GetMac(), extNic.GetVlanId(), wireId, extNic.GetIpAddr(), 0,
compute.TNicType(extNic.GetNicType()), extNic.GetIndex(),
compute.TNicType(extNic.GetNicType()), int(extNic.GetIndex()),
extNic.IsLinkUp(), int16(extNic.GetMtu()), false, strNetIf, strBridge, true, true)
if err != nil {
result.AddError(err)
+2 -2
View File
@@ -97,7 +97,7 @@ type SIsolatedDevice struct {
// 云主机Id
GuestId string `width:"36" charset:"ascii" nullable:"true" index:"true" list:"domain"`
// guest network index
NetworkIndex int8 `nullable:"true" default:"-1" list:"user" update:"user"`
NetworkIndex int `nullable:"true" default:"-1" list:"user" update:"user"`
// Nic wire id
WireId string `width:"36" charset:"ascii" nullable:"true" index:"true" list:"domain" update:"domain" create:"domain_optional"`
// Offload interface name
@@ -1115,7 +1115,7 @@ func (model *SIsolatedDevice) GetOwnerId() mcclient.IIdentityProvider {
return nil
}
func (model *SIsolatedDevice) SetNetworkIndex(idx int8) error {
func (model *SIsolatedDevice) SetNetworkIndex(idx int) error {
_, err := db.Update(model, func() error {
model.NetworkIndex = idx
return nil
+4 -1
View File
@@ -48,7 +48,8 @@ type SNetInterface struct {
NicType compute.TNicType `width:"36" charset:"ascii" nullable:"true"` // Column(VARCHAR(36, charset='ascii'), nullable=True)
Index int8 `nullable:"true"` // Column(TINYINT, nullable=True)
// SR-IOV nic index may exceed 256
Index int `nullable:"true"` // Column(TINYINT, nullable=True)
LinkUp bool `nullable:"true"` // Column(Boolean, nullable=True)
Mtu int16 `nullable:"true"` // Column(SMALLINT, nullable=True)
@@ -244,6 +245,8 @@ func (netif *SNetInterface) getBaremetalJsonDesc() *types.SNic {
LinkUp: netif.LinkUp,
Interface: netif.Interface,
Bridge: netif.Bridge,
Index: netif.Index,
}
wire := netif.GetWire()
if wire != nil {
+1 -1
View File
@@ -1031,7 +1031,7 @@ func (manager *SNetworkManager) TotalPortCount(
type SNicConfig struct {
Mac string
Index int8
Index int
Ifname string
}
+2
View File
@@ -222,6 +222,8 @@ type ComputeOptions struct {
ResourceExpiredNotifyDays []int `help:"The notify of resource expired" default:"1,3,30"`
esxi.EsxiOptions
NetworkAlwaysManualConfig bool `help:"always manually configure network settings" default:"false"`
}
type SCapabilityOptions struct {
+1
View File
@@ -920,6 +920,7 @@ func (d *sDebianLikeRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics
rootFs.Remove(netplanDir+f, false)
}
netplanConfig := NewNetplanConfig(allNics, bondNics)
log.Debugf("netplanConfig:\n %s", netplanConfig.YAMLString())
if err := rootFs.FilePutContents(path.Join(netplanDir, "config.yaml"), netplanConfig.YAMLString(), false, false); err != nil {
return errors.Wrap(err, "Put netplan config")
}
+7 -5
View File
@@ -69,9 +69,9 @@ func newNetplanNetwork(allNics []*types.SServerNic, bondNics []*types.SServerNic
network.AddEthernet(sn.Name, nicConf)
}
primaryNic := bondNic.TeamingSlaves[0]
primaryNic := bondNic
netConf := getNetplanEthernetConfig(primaryNic, true)
netConf.MacAddress = primaryNic.Mac
netConf.MacAddress = bondNic.Mac
if netConf.Mtu == 0 {
netConf.Mtu = defaultMtu
@@ -79,7 +79,7 @@ func newNetplanNetwork(allNics []*types.SServerNic, bondNics []*types.SServerNic
// TODO: implement kinds of bond mode config
// bondConf := netplan.NewBondMode4(netConf, interfaces)
bondConf := netplan.NewBondMode1(netConf, interfaces)
bondConf := netplan.NewBondMode4(netConf, interfaces)
network.AddBond(bondNic.Name, bondConf)
}
@@ -97,12 +97,14 @@ func getNetplanEthernetConfig(nic *types.SServerNic, isBond bool) *netplan.Ether
nicConf = netplan.NewStaticEthernetConfig(addr, "", "", "", nil, nil, nil)
} else if nic.Manual {
addr := fmt.Sprintf("%s/%d", nic.Ip, nic.Masklen)
gateway := nic.Gateway
addr6 := ""
gateway6 := ""
if len(nic.Ip6) > 0 {
addr6 = fmt.Sprintf("%s/%d", nic.Ip6, nic.Masklen6)
gateway6 = nic.Gateway6
}
gateway := nic.Gateway
gateway6 := nic.Gateway6
var routes []*netplan.Route
for _, route := range nic.Routes {
@@ -0,0 +1,148 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package fsdriver
import (
"testing"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/cloudcommon/types"
"yunion.io/x/onecloud/pkg/util/netplan"
)
func TestNewNetplanConfig(t *testing.T) {
cases := []struct {
nics []*types.SServerNic
want *netplan.Configuration
}{
{
nics: []*types.SServerNic{
&types.SServerNic{
Name: "eth0",
Index: 0,
Bridge: "br0",
Domain: "cloud.local",
Ip: "10.168.222.175",
Vlan: 1,
Driver: "virtio",
Masklen: 24,
Virtual: false,
Manual: true,
WireId: "399a06f3-7925-46c1-8b9f-d5a8580a74df",
NetId: "22c93412-5882-4de0-8357-45ce647ceada",
Mac: "00:24:c7:16:80:f2",
BandWidth: 1000,
Mtu: 1500,
Dns: "8.8.8.8",
Ntp: "",
Net: "vnet222",
Interface: "ens5",
Gateway: "10.168.222.1",
Ifname: "vnet222-175",
Routes: nil,
LinkUp: true,
},
&types.SServerNic{
Name: "eth1",
Index: 1,
Bridge: "br0",
Domain: "cloud.local",
Ip: "",
Vlan: 1,
Driver: "virtio",
Masklen: 0,
Virtual: true,
Manual: true,
WireId: "399a06f3-7925-46c1-8b9f-d5a8580a74df",
NetId: "22c93412-5882-4de0-8357-45ce647ceada",
Mac: "00:24:c7:16:80:f3",
BandWidth: 1000,
Mtu: 1500,
Dns: "8.8.8.8",
Ntp: "",
Net: "vnet222",
Interface: "ens5",
Gateway: "",
Ifname: "vnet222-bpg",
Routes: nil,
LinkUp: true,
TeamWith: "00:24:c7:16:80:f2",
},
},
want: &netplan.Configuration{
Network: &netplan.Network{
Version: 2,
Renderer: netplan.NetworkRendererNetworkd,
Ethernets: map[string]*netplan.EthernetConfig{
"eth0": &netplan.EthernetConfig{
MacAddress: "00:24:c7:16:80:f2",
Match: &netplan.EthernetConfigMatch{
MacAddress: "00:24:c7:16:80:f2",
},
Mtu: 1500,
},
"eth1": &netplan.EthernetConfig{
MacAddress: "00:24:c7:16:80:f3",
Match: &netplan.EthernetConfigMatch{
MacAddress: "00:24:c7:16:80:f3",
},
Mtu: 1500,
},
},
Bonds: map[string]*netplan.Bond{
"bond0": &netplan.Bond{
EthernetConfig: netplan.EthernetConfig{
Addresses: []string{
"10.168.222.175/24",
},
// MacAddress: "00:24:c7:16:80:f2",
Gateway4: "10.168.222.1",
Nameservers: &netplan.Nameservers{
Search: []string{
"cloud.local",
},
Addresses: []string{
"8.8.8.8",
},
},
Mtu: 1500,
},
Interfaces: []string{
"eth0",
"eth1",
},
Parameters: &netplan.BondMode4Params{
BondModeBaseParams: &netplan.BondModeBaseParams{
Mode: "802.3ad",
MiiMonitorInterval: 100,
},
},
},
},
},
},
},
}
for _, c := range cases {
allNics, bondNics := convertNicConfigs(c.nics)
netplanConfig := NewNetplanConfig(allNics, bondNics)
if jsonutils.Marshal(netplanConfig).String() != jsonutils.Marshal(c.want).String() {
t.Errorf("nics: %s want: %s got: %s", jsonutils.Marshal(c.nics), jsonutils.Marshal(c.want).PrettyString(), jsonutils.Marshal(netplanConfig).PrettyString())
}
}
}
+2 -2
View File
@@ -3316,7 +3316,7 @@ func (s *SKVMGuestInstance) generateDiskSetupScripts(disks []*desc.SGuestDisk) (
return cmd, nil
}
func (s *SKVMGuestInstance) GetSriovDeviceByNetworkIndex(networkIndex int8) (isolated_device.IDevice, error) {
func (s *SKVMGuestInstance) GetSriovDeviceByNetworkIndex(networkIndex int) (isolated_device.IDevice, error) {
manager := s.manager.GetHost().GetIsolatedDeviceManager()
for i := 0; i < len(s.Desc.IsolatedDevices); i++ {
if s.Desc.IsolatedDevices[i].DevType == api.NIC_TYPE &&
@@ -3360,7 +3360,7 @@ func getIbPortMac(mac string) string {
return "00:10:" + mac
}
func (s *SKVMGuestInstance) sriovNicAttachInitScript(networkIndex int8, dev isolated_device.IDevice) (string, error) {
func (s *SKVMGuestInstance) sriovNicAttachInitScript(networkIndex int, dev isolated_device.IDevice) (string, error) {
for i := range s.Desc.Nics {
if s.Desc.Nics[i].Driver == "vfio-pci" && s.Desc.Nics[i].Index == networkIndex {
cmd := s.generateSriovInitCmd(i, dev)
+1 -1
View File
@@ -804,7 +804,7 @@ func (s *SKVMGuestInstance) WriteMigrateCerts(certs map[string]string) error {
return nil
}
func (s *SKVMGuestInstance) SetNicDown(index int8) error {
func (s *SKVMGuestInstance) SetNicDown(index int) error {
var nic *desc.SGuestNetwork
for i := range s.Desc.Nics {
if s.Desc.Nics[i].Index == index {
+2 -2
View File
@@ -249,7 +249,7 @@ func (s *SGuestMonitorCollector) saveNicTraffics(reportData map[string]*GuestMet
var nicIo *NetIOMetric
for j := range data.VmNetio {
if gm.Nics[i].Index == int8(data.VmNetio[j].Meta.Index) {
if gm.Nics[i].Index == data.VmNetio[j].Meta.Index {
nicIo = data.VmNetio[j]
break
}
@@ -507,7 +507,7 @@ func (m *SGuestMonitor) SetNicDown(index int) {
if !ok {
return
}
if err := guest.SetNicDown(int8(index)); err != nil {
if err := guest.SetNicDown(index); err != nil {
log.Errorf("guest %s SetNicDown failed %s", m.Id, err)
}
}
@@ -61,10 +61,19 @@ func (p *NetBondingPredicate) Execute(ctx context.Context, u *core.Unit, c core.
continue
}
count := 0
if _, ok := bondingCount[netConf.Wire]; ok {
count = bondingCount[netConf.Wire]
wireId := netConf.Wire
if len(wireId) == 0 && len(netConf.Network) > 0 {
for _, n := range c.Getter().Networks() {
if n.Id == netConf.Network || n.Name == netConf.Network {
wireId = n.WireId
break
}
}
}
bondingCount[netConf.Wire] = count + 2
if _, ok := bondingCount[wireId]; ok {
count = bondingCount[wireId]
}
bondingCount[wireId] = count + 2
}
for wireId, count := range bondingCount {
if len(wireId) > 0 {
+42
View File
@@ -0,0 +1,42 @@
#!/bin/bash
set -e
IMG=$1
if [[ -z "$IMG" ]]; then
echo "Usage: $0 <dockerimgurl>"
exit 1
fi
NAME=$(echo -n $IMG | cut -d / -f 3)
NAME="${NAME/:/-}"
echo "Export docker iamge to $NAME"
if [[ -d $NAME ]]; then
echo "directory $NAME already exists!"
exit 1
fi
mkdir $NAME
IMGCNT=0
for arch in $(docker manifest inspect $IMG | grep -w "\"architecture\"" | awk '{print $2}' | cut -f 2 -d \")
do
echo "export to linux/$arch"
docker pull --platform "linux/$arch" $IMG
docker tag $IMG "$IMG-$arch"
docker save "$IMG-$arch" | gzip > $NAME/img-$arch.tgz
docker image rm $IMG "$IMG-$arch"
IMGCNT=$((IMGCNT+1))
done
if [ "$IMGCNT" -eq "0" ]; then
echo "This is an ordinary image"
docker pull $IMG
docker save $IMG | gzip > $NAME/img.tgz
docker image rm $IMG
fi
tar cvf $NAME.tar $NAME
+66
View File
@@ -0,0 +1,66 @@
#!/bin/bash
TAR=$1
TARGET=$2
if [[ -z "$TARGET" ]]; then
echo "Usage: $0 <tar_file> <docker_image_url>"
echo " Eg: $0 docs-ee-v3.10.10.tar registry.cn-beijing.aliyuncs.com/examplerepo/docs-ee:v3.10.10"
exit 1
fi
WORK_DIR=`mktemp -d -p "."`
if [[ ! "$WORK_DIR" || ! -d "$WORK_DIR" ]]; then
echo "Could not create temp dir"
exit 1
fi
function cleanup {
rm -rf "$WORK_DIR"
echo "Deleted temp working directory $WORK_DIR"
}
# register the cleanup function to be called on the EXIT signal
trap cleanup EXIT
tar xvf $TAR --strip-components=1 -C $WORK_DIR
echo "cd $WORK_DIR"
cd $WORK_DIR
IMGCNT=$(ls img* | wc -l)
if [ "$IMGCNT" -eq "0" ]; then
echo "Not a recognized package, give up ..."
exit 1
fi
if [ "$IMGCNT" -eq "1" ]; then
echo "This is a single image package"
IMG=$(docker load < $f | tail -n 1 | awk '{print $3}')
echo "Loading $IMG..."
docker tag $IMG $TARGET
docker push $TARGET
else
for f in $(ls img*)
do
echo $f
IMG=$(docker load < $f | tail -n 1 | awk '{print $3}')
echo "Loading $IMG..."
ARCH=$(echo -n $IMG | rev | cut -d - -f 1 | rev)
TIMG="$TARGET-$ARCH"
echo "tag $IMG to $TIMG ..."
docker tag $IMG $TIMG
docker push $TIMG
echo "$TIMG $ARCH" >> imglist
done
# create manifest
cat imglist | awk '{print $1}' | xargs docker manifest create $TARGET
cat imglist | awk '{print "docker manifest annotate '$TARGET' " $1 " --arch " $2 " --os linux"}'
docker manifest push $TARGET
fi
echo $TARGET
+1 -1
View File
@@ -260,7 +260,7 @@ show_update_cmd() {
'apimap')
spec='apiMap'
;;
'baremetal')
'baremetal-agent')
spec='baremetalagent'
name='baremetal-agent'
;;