fix: bond interface missing default gateway (#19952)

Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
This commit is contained in:
Jian Qiu
2024-04-15 10:37:13 +08:00
committed by GitHub
co-authored by Qiu Jian
parent 5fee90bea6
commit 400fe4f430
9 changed files with 189 additions and 36 deletions
@@ -94,6 +94,7 @@ func init() {
Driver string `help:"Driver model of vNIC" choices:"virtio|e1000|vmxnet3|rtl8139"`
Index int64 `help:"Index of NIC" default:"-1"`
Ifname string `help:"Interface name of vNIC on host"`
Default bool `help:"is default nic?"`
}
R(&ServerNetworkUpdateOptions{}, "server-network-update", "Update server network settings", func(s *mcclient.ClientSession, args *ServerNetworkUpdateOptions) error {
params := jsonutils.NewDict()
@@ -106,6 +107,9 @@ func init() {
if len(args.Ifname) > 0 {
params.Add(jsonutils.NewString(args.Ifname), "ifname")
}
if args.Default {
params.Add(jsonutils.JSONTrue, "is_default")
}
if params.Size() == 0 {
return InvalidUpdateError()
}
+4 -2
View File
@@ -644,12 +644,13 @@ func (f *ResourceHandlers) updateJointHandler(ctx context.Context, w http.Respon
session := req.Session()
module := req.Mod1()
module2 := req.Mod2()
query := req.Query()
body := req.Body()
jmod, e := modulebase.GetJointModule2(session, module, module2)
var obj jsonutils.JSONObject
if e == nil { // update joint
obj, e = jmod.Update(session, req.ResID(), req.ResID2(), nil, body)
obj, e = jmod.Update(session, req.ResID(), req.ResID2(), query, body)
} else { // update in context
obj, e = module2.PutInContext(session, req.ResID2(), body, module, req.ResID())
}
@@ -669,12 +670,13 @@ func (f *ResourceHandlers) patchJointHandler(ctx context.Context, w http.Respons
session := req.Session()
module := req.Mod1()
module2 := req.Mod2()
query := req.Query()
body := req.Body()
jmod, e := modulebase.GetJointModule2(session, module, module2)
var obj jsonutils.JSONObject
if e == nil { // update joint
obj, e = jmod.Patch(session, req.ResID(), req.ResID2(), nil, body)
obj, e = jmod.Patch(session, req.ResID(), req.ResID2(), query, body)
} else { // update in context
obj, e = module2.PatchInContext(session, req.ResID2(), body, module, req.ResID())
}
+26
View File
@@ -2564,6 +2564,29 @@ func (self *SGuest) PerformDetachnetwork(
return nil, httperrors.NewMissingParameterError("net_id")
}
removeNics := make(map[string]*SGuestnetwork)
for i := range gns {
removeNics[gns[i].MacAddr] = &gns[i]
}
slaveNics, err := self.GetSlaveNetworks()
if err != nil {
return nil, errors.Wrap(err, "GetSlaveNetworks")
}
for i := range slaveNics {
teamMac := slaveNics[i].TeamWith
if len(teamMac) > 0 {
if _, ok := removeNics[teamMac]; ok {
// to remove slave's master NIC, should also remove slave itself
if _, ok2 := removeNics[slaveNics[i].MacAddr]; !ok2 {
// otherwise, report the error
return nil, errors.Wrap(errors.ErrInvalidStatus, "")
}
}
}
}
err = self.detachNetworks(ctx, userCred, gns, input.Reserve)
if err != nil {
return nil, errors.Wrap(err, "detachNetworks")
@@ -2599,6 +2622,9 @@ func (guest *SGuest) fixDefaultGateway(ctx context.Context, userCred mcclient.To
nicList := netutils2.SNicInfoList{}
nics, _ := guest.GetNetworks("")
for i := range nics {
if nics[i].Virtual || len(nics[i].TeamWith) > 0 {
continue
}
net, _ := nics[i].GetNetwork()
if net != nil {
nicList = nicList.Add(nics[i].IpAddr, nics[i].MacAddr, net.GuestGateway)
+3
View File
@@ -812,6 +812,9 @@ func (gn *SGuestnetwork) ValidateUpdateData(
}
}
if input.IsDefault != nil && *input.IsDefault {
if gn.Virtual || len(gn.TeamWith) > 0 {
return input, errors.Wrap(httperrors.ErrInvalidStatus, "cannot set virtual/slave interface as default")
}
net, err := gn.GetNetwork()
if err != nil {
return input, errors.Wrapf(err, "GetNetwork")
+10
View File
@@ -1073,6 +1073,16 @@ func (guest *SGuest) GetNetworks(netId string) ([]SGuestnetwork, error) {
return guestnics, nil
}
func (guest *SGuest) GetSlaveNetworks() ([]SGuestnetwork, error) {
guestnics := make([]SGuestnetwork, 0)
q := guest.GetNetworksQuery("").IsNotEmpty("team_with")
err := db.FetchModelObjects(GuestnetworkManager, q, &guestnics)
if err != nil {
return nil, errors.Wrapf(err, "db.FetchModelObjects")
}
return guestnics, nil
}
func (guest *SGuest) ConvertEsxiNetworks(targetGuest *SGuest) error {
gns, err := guest.GetNetworks("")
if err != nil {
+13 -23
View File
@@ -841,7 +841,7 @@ func (d *sDebianLikeRootFs) PrepareFsForTemplate(rootFs IDiskPartition) error {
netplanDir := "/etc/netplan/"
if rootFs.Exists(netplanDir, false) {
for _, f := range rootFs.ListDir(netplanDir, false) {
rootFs.Remove(netplanDir+f, false)
rootFs.Remove(filepath.Join(netplanDir, f), false)
}
}
return nil
@@ -885,16 +885,6 @@ func getNicTeamingConfigCmds(slaves []*types.SServerNic) string {
return cmds.String()
}
func (d *sDebianLikeRootFs) deployNetplanConfigFile(rootFs IDiskPartition, nics []*types.SServerNic) error {
netplanDir := "/etc/netplan/"
dirExists := rootFs.Exists(netplanDir, false)
if !dirExists {
return nil
}
return nil
}
func (d *sDebianLikeRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []*types.SServerNic) error {
if err := d.sLinuxRootFs.DeployNetworkingScripts(rootFs, nics); err != nil {
return err
@@ -914,24 +904,24 @@ func (d *sDebianLikeRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics
// ToServerNics(nics)
allNics, bondNics := convertNicConfigs(nics)
netplanDir := "/etc/netplan"
if rootFs.Exists(netplanDir, false) {
for _, f := range rootFs.ListDir(netplanDir, false) {
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")
}
}
mainNic := getMainNic(allNics)
var mainIp string
if mainNic != nil {
mainIp = mainNic.Ip
}
netplanDir := "/etc/netplan"
if rootFs.Exists(netplanDir, false) {
for _, f := range rootFs.ListDir(netplanDir, false) {
rootFs.Remove(filepath.Join(netplanDir, f), false)
}
netplanConfig := NewNetplanConfig(allNics, bondNics, mainIp)
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")
}
}
var systemdResolveConfig strings.Builder
dnss := []string{}
domains := []string{}
+13 -8
View File
@@ -24,16 +24,16 @@ import (
"yunion.io/x/onecloud/pkg/util/netutils2"
)
func NewNetplanConfig(allNics []*types.SServerNic, bondNics []*types.SServerNic) *netplan.Configuration {
network := newNetplanNetwork(allNics, bondNics)
func NewNetplanConfig(allNics []*types.SServerNic, bondNics []*types.SServerNic, mainIp string) *netplan.Configuration {
network := newNetplanNetwork(allNics, bondNics, mainIp)
return netplan.NewConfiguration(network)
}
func newNetplanNetwork(allNics []*types.SServerNic, bondNics []*types.SServerNic) *netplan.Network {
func newNetplanNetwork(allNics []*types.SServerNic, bondNics []*types.SServerNic, mainIp string) *netplan.Network {
network := netplan.NewNetwork()
for _, nic := range allNics {
nicConf := getNetplanEthernetConfig(nic, false)
nicConf := getNetplanEthernetConfig(nic, false, mainIp)
if nicConf == nil {
continue
@@ -69,7 +69,7 @@ func newNetplanNetwork(allNics []*types.SServerNic, bondNics []*types.SServerNic
network.AddEthernet(sn.Name, nicConf)
}
netConf := getNetplanEthernetConfig(bondNic, true)
netConf := getNetplanEthernetConfig(bondNic, true, mainIp)
if netConf.Mtu == 0 {
netConf.Mtu = defaultMtu
@@ -84,7 +84,7 @@ func newNetplanNetwork(allNics []*types.SServerNic, bondNics []*types.SServerNic
return network
}
func getNetplanEthernetConfig(nic *types.SServerNic, isBond bool) *netplan.EthernetConfig {
func getNetplanEthernetConfig(nic *types.SServerNic, isBond bool, mainIp string) *netplan.EthernetConfig {
var nicConf *netplan.EthernetConfig
if !isBond && (nic.TeamingMaster != nil || nic.TeamingSlaves != nil) {
@@ -94,12 +94,17 @@ 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
gateway := ""
if nic.Ip == mainIp && len(mainIp) > 0 {
gateway = nic.Gateway
}
addr6 := ""
gateway6 := ""
if len(nic.Ip6) > 0 {
addr6 = fmt.Sprintf("%s/%d", nic.Ip6, nic.Masklen6)
gateway6 = nic.Gateway6
if nic.Ip == mainIp && len(mainIp) > 0 {
gateway6 = nic.Gateway6
}
}
var routes []*netplan.Route
+114 -3
View File
@@ -25,10 +25,12 @@ import (
func TestNewNetplanConfig(t *testing.T) {
cases := []struct {
nics []*types.SServerNic
want *netplan.Configuration
mainIp string
nics []*types.SServerNic
want *netplan.Configuration
}{
{
mainIp: "10.168.222.175",
nics: []*types.SServerNic{
&types.SServerNic{
Name: "eth0",
@@ -137,10 +139,119 @@ func TestNewNetplanConfig(t *testing.T) {
},
},
},
{
mainIp: "10.168.22.175",
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",
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)
netplanConfig := NewNetplanConfig(allNics, bondNics, c.mainIp)
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())
}
@@ -121,6 +121,7 @@ func convertNicConfigs(nics []*types.SServerNic) ([]*types.SServerNic, []*types.
nnic.Ip6 = ""
nnic.Masklen6 = 0
nnic.Gateway6 = ""
nnic.IsDefault = false
tnic.Name = fmt.Sprintf("%s%d", netDevPrefix, tnic.Index)
tnic.TeamingMaster = master
tnic.Ip = ""
@@ -129,6 +130,7 @@ func convertNicConfigs(nics []*types.SServerNic) ([]*types.SServerNic, []*types.
tnic.Ip6 = ""
tnic.Masklen6 = 0
tnic.Gateway6 = ""
tnic.IsDefault = false
master.Name = fmt.Sprintf("bond%d", len(bondNics))
master.TeamingSlaves = []*types.SServerNic{&nnic, &tnic}
// why reset master.Mac?