mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-19 10:46:58 +08:00
feat(host): support netplan configuration
This commit is contained in:
@@ -536,6 +536,14 @@ func (d *sDebianLikeRootFs) PrepareFsForTemplate(rootFs IDiskPartition) error {
|
||||
return errors.Wrap(err, "file put content /etc/network/interface")
|
||||
}
|
||||
}
|
||||
|
||||
// clean /etc/netplan/*
|
||||
netplanDir := "/etc/netplan/"
|
||||
if rootFs.Exists(netplanDir, false) {
|
||||
for _, f := range rootFs.ListDir(netplanDir, false) {
|
||||
rootFs.Remove(netplanDir+f, false)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -577,6 +585,16 @@ 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
|
||||
@@ -587,7 +605,19 @@ func (d *sDebianLikeRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics
|
||||
cmds.WriteString("iface lo inet loopback\n\n")
|
||||
|
||||
// ToServerNics(nics)
|
||||
allNics, _ := convertNicConfigs(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)
|
||||
if err := rootFs.FilePutContents(path.Join(netplanDir, "config.yaml"), netplanConfig.YAMLString(), false, false); err != nil {
|
||||
return errors.Wrap(err, "Put netplan config")
|
||||
}
|
||||
}
|
||||
|
||||
mainNic, err := getMainNic(allNics)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
// 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 (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/types"
|
||||
"yunion.io/x/onecloud/pkg/util/netplan"
|
||||
"yunion.io/x/onecloud/pkg/util/netutils2"
|
||||
)
|
||||
|
||||
func NewNetplanConfig(allNics []*types.SServerNic, bondNics []*types.SServerNic) *netplan.Configuration {
|
||||
network := newNetplanNetwork(allNics, bondNics)
|
||||
return netplan.NewConfiguration(network)
|
||||
}
|
||||
|
||||
func newNetplanNetwork(allNics []*types.SServerNic, bondNics []*types.SServerNic) *netplan.Network {
|
||||
network := netplan.NewNetwork()
|
||||
|
||||
for _, nic := range allNics {
|
||||
nicConf := getNetplanEthernetConfig(nic, false)
|
||||
|
||||
if nicConf == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
network.AddEthernet(nic.Name, nicConf)
|
||||
}
|
||||
|
||||
for _, bondNic := range bondNics {
|
||||
if len(bondNic.TeamingSlaves) < 2 {
|
||||
log.Warningf("BondNic %s slaves nic %#v less than 2", bondNic.Name, bondNic.TeamingSlaves)
|
||||
continue
|
||||
}
|
||||
|
||||
var defaultMtu = 1442
|
||||
|
||||
interfaces := make([]string, len(bondNic.TeamingSlaves))
|
||||
for i, sn := range bondNic.TeamingSlaves {
|
||||
interfaces[i] = sn.Name
|
||||
|
||||
nicConf := &netplan.EthernetConfig{
|
||||
DHCP4: false,
|
||||
MacAddress: sn.Mac,
|
||||
Match: netplan.NewEthernetConfigMatchMac(sn.Mac),
|
||||
}
|
||||
|
||||
if sn.Mtu > 0 {
|
||||
nicConf.Mtu = sn.Mtu
|
||||
} else {
|
||||
nicConf.Mtu = defaultMtu
|
||||
}
|
||||
|
||||
network.AddEthernet(sn.Name, nicConf)
|
||||
}
|
||||
|
||||
primaryNic := bondNic.TeamingSlaves[0]
|
||||
netConf := getNetplanEthernetConfig(primaryNic, true)
|
||||
netConf.MacAddress = primaryNic.Mac
|
||||
|
||||
if netConf.Mtu == 0 {
|
||||
netConf.Mtu = defaultMtu
|
||||
}
|
||||
|
||||
// TODO: implement kinds of bond mode config
|
||||
// bondConf := netplan.NewBondMode4(netConf, interfaces)
|
||||
bondConf := netplan.NewBondMode1(netConf, interfaces)
|
||||
|
||||
network.AddBond(bondNic.Name, bondConf)
|
||||
}
|
||||
|
||||
return network
|
||||
}
|
||||
|
||||
func getNetplanEthernetConfig(nic *types.SServerNic, isBond bool) *netplan.EthernetConfig {
|
||||
var nicConf *netplan.EthernetConfig
|
||||
|
||||
if !isBond && (nic.TeamingMaster != nil || nic.TeamingSlaves != nil) {
|
||||
return nil
|
||||
} else if nic.Virtual {
|
||||
addr := fmt.Sprintf("%s/32", netutils2.PSEUDO_VIP)
|
||||
nicConf = netplan.NewStaticEthernetConfig(addr, "", nil, nil, nil)
|
||||
} else if nic.Manual {
|
||||
addr := fmt.Sprintf("%s/%d", nic.Ip, nic.Masklen)
|
||||
gateway := nic.Gateway
|
||||
var routes []*netplan.Route
|
||||
|
||||
for _, route := range nic.Routes {
|
||||
routes = append(routes, &netplan.Route{
|
||||
To: route[0],
|
||||
Via: route[1],
|
||||
})
|
||||
}
|
||||
|
||||
nicConf = netplan.NewStaticEthernetConfig(
|
||||
addr, gateway,
|
||||
[]string{nic.Domain},
|
||||
netutils2.GetNicDns(nic),
|
||||
routes,
|
||||
)
|
||||
if nic.Mtu > 0 {
|
||||
nicConf.Mtu = nic.Mtu
|
||||
}
|
||||
} else {
|
||||
// dhcp
|
||||
nicConf = netplan.NewDHCP4EthernetConfig()
|
||||
}
|
||||
|
||||
return nicConf
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package netplan // import "yunion.io/x/onecloud/pkg/util/netplan"
|
||||
@@ -0,0 +1,242 @@
|
||||
// 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 netplan
|
||||
|
||||
import "yunion.io/x/jsonutils"
|
||||
|
||||
// Configuration examples reference from https://netplan.io/examples/
|
||||
// manpage: http://manpages.ubuntu.com/manpages/cosmic/man5/netplan.5.html
|
||||
type Configuration struct {
|
||||
Network *Network `json:"network"`
|
||||
}
|
||||
|
||||
func NewConfiguration(network *Network) *Configuration {
|
||||
return &Configuration{
|
||||
Network: network,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Configuration) YAMLString() string {
|
||||
return toYAMLString(c)
|
||||
}
|
||||
|
||||
type NetworkRenderer string
|
||||
|
||||
const (
|
||||
VERSION2 = 2
|
||||
NetworkRendererNetworkd NetworkRenderer = "networkd"
|
||||
)
|
||||
|
||||
type Network struct {
|
||||
Version uint `json:"version"`
|
||||
Renderer NetworkRenderer `json:"renderer"`
|
||||
Ethernets map[string]*EthernetConfig `json:"ethernets"`
|
||||
Bonds map[string]*Bond `json:"bonds"`
|
||||
}
|
||||
|
||||
type EthernetConfigMatch struct {
|
||||
MacAddress string `json:"macaddress"`
|
||||
}
|
||||
|
||||
func NewEthernetConfigMatchMac(macAddr string) *EthernetConfigMatch {
|
||||
return &EthernetConfigMatch{
|
||||
MacAddress: macAddr,
|
||||
}
|
||||
}
|
||||
|
||||
type EthernetConfig struct {
|
||||
DHCP4 bool `json:"dhcp4"`
|
||||
Addresses []string `json:"addresses"`
|
||||
Match *EthernetConfigMatch `json:"match"`
|
||||
MacAddress string `json:"macaddress"`
|
||||
Gateway4 string `json:"gateway4"`
|
||||
Routes []*Route `json:"routes"`
|
||||
Nameservers *Nameservers `json:"nameservers"`
|
||||
Mtu int `json:"mtu,omitzero"`
|
||||
}
|
||||
|
||||
type Route struct {
|
||||
To string `json:"to"`
|
||||
Via string `json:"via"`
|
||||
Metric uint `json:"metric"`
|
||||
// OnLink bool `json:"on-link"`
|
||||
}
|
||||
|
||||
type Nameservers struct {
|
||||
Search []string `json:"search"`
|
||||
Addresses []string `json:"addresses"`
|
||||
}
|
||||
|
||||
type Bond struct {
|
||||
EthernetConfig
|
||||
Interfaces []string `json:"interfaces"`
|
||||
Parameters IBondModeParams `json:"parameters"`
|
||||
}
|
||||
|
||||
func toYAMLString(obj interface{}) string {
|
||||
return jsonutils.Marshal(obj).YAMLString()
|
||||
}
|
||||
|
||||
func (b *Bond) YAMLString() string {
|
||||
return toYAMLString(b)
|
||||
}
|
||||
|
||||
type BondMode string
|
||||
|
||||
const (
|
||||
// ref: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/networking_guide/overview-of-bonding-modes-and-the-required-settings-on-the-switch
|
||||
// mode0
|
||||
bondModeBalanceRR = "balance-rr"
|
||||
// mode1
|
||||
bondModeActiveBackup = "active-backup"
|
||||
// mode4
|
||||
bondMode8023AD = "802.3ad"
|
||||
)
|
||||
|
||||
type IBondModeParams interface {
|
||||
GetMode() string
|
||||
}
|
||||
|
||||
type BondModeBaseParams struct {
|
||||
Mode string `json:"mode"`
|
||||
MiiMonitorInterval int `json:"mii-monitor-interval,omitzero"`
|
||||
GratuitiousArp int `json:"gratuitiousi-arp,omitzero"`
|
||||
}
|
||||
|
||||
func (c BondModeBaseParams) GetMode() string {
|
||||
return c.Mode
|
||||
}
|
||||
|
||||
func (c *BondModeBaseParams) SetMiiMonitorInterval(i int) {
|
||||
c.MiiMonitorInterval = i
|
||||
}
|
||||
|
||||
func (c *BondModeBaseParams) SetGratutiousArp(g int) {
|
||||
c.GratuitiousArp = g
|
||||
}
|
||||
|
||||
type BondModeActiveBackupParams struct {
|
||||
*BondModeBaseParams
|
||||
|
||||
Primary string `json:"primary"`
|
||||
}
|
||||
|
||||
func NewBondMode0Params() *BondModeBaseParams {
|
||||
return &BondModeBaseParams{
|
||||
Mode: bondModeBalanceRR,
|
||||
}
|
||||
}
|
||||
|
||||
func NewBondModeActiveBackupParams(primary string) *BondModeActiveBackupParams {
|
||||
return &BondModeActiveBackupParams{
|
||||
BondModeBaseParams: &BondModeBaseParams{
|
||||
Mode: bondModeActiveBackup,
|
||||
},
|
||||
Primary: primary,
|
||||
}
|
||||
}
|
||||
|
||||
type BondMode4Params struct {
|
||||
*BondModeBaseParams
|
||||
}
|
||||
|
||||
func NewBondMode4Params() *BondMode4Params {
|
||||
return &BondMode4Params{
|
||||
BondModeBaseParams: &BondModeBaseParams{
|
||||
Mode: bondMode8023AD,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewNetwork() *Network {
|
||||
return &Network{
|
||||
Version: VERSION2,
|
||||
Renderer: NetworkRendererNetworkd,
|
||||
Ethernets: make(map[string]*EthernetConfig),
|
||||
Bonds: make(map[string]*Bond),
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Network) AddEthernet(name string, ether *EthernetConfig) *Network {
|
||||
n.Ethernets[name] = ether
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *Network) AddBond(name string, bond *Bond) *Network {
|
||||
n.Bonds[name] = bond
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *Network) YAMLString() string {
|
||||
return toYAMLString(n)
|
||||
}
|
||||
|
||||
func NewDHCP4EthernetConfig() *EthernetConfig {
|
||||
return &EthernetConfig{
|
||||
DHCP4: true,
|
||||
}
|
||||
}
|
||||
|
||||
func NewStaticEthernetConfig(
|
||||
addr string,
|
||||
gateway string,
|
||||
search []string,
|
||||
nameservers []string,
|
||||
routes []*Route,
|
||||
) *EthernetConfig {
|
||||
return &EthernetConfig{
|
||||
DHCP4: false,
|
||||
Addresses: []string{addr},
|
||||
Gateway4: gateway,
|
||||
Routes: routes,
|
||||
Nameservers: &Nameservers{
|
||||
Search: search,
|
||||
Addresses: nameservers,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *EthernetConfig) YAMLString() string {
|
||||
return toYAMLString(c)
|
||||
}
|
||||
|
||||
func newBondModeByParams(conf *EthernetConfig, interfaces []string, params IBondModeParams) *Bond {
|
||||
return &Bond{
|
||||
EthernetConfig: *conf,
|
||||
Interfaces: interfaces,
|
||||
Parameters: params,
|
||||
}
|
||||
}
|
||||
|
||||
func NewBondMode0(conf *EthernetConfig, interfaces []string) *Bond {
|
||||
params := NewBondMode0Params()
|
||||
params.SetMiiMonitorInterval(100)
|
||||
return newBondModeByParams(conf, interfaces, params)
|
||||
}
|
||||
|
||||
func NewBondMode1(conf *EthernetConfig, interfaces []string) *Bond {
|
||||
params := NewBondModeActiveBackupParams(interfaces[0])
|
||||
params.SetMiiMonitorInterval(100)
|
||||
return newBondModeByParams(conf, interfaces, params)
|
||||
}
|
||||
func NewBondMode4(conf *EthernetConfig, interfaces []string) *Bond {
|
||||
params := NewBondMode4Params()
|
||||
// TODO: figure out what follows options related to netplan config
|
||||
// miimon: 1
|
||||
// lacp_rate: 1
|
||||
// xmit_hash_policy: 1
|
||||
params.SetMiiMonitorInterval(100)
|
||||
return newBondModeByParams(conf, interfaces, params)
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
// 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 netplan
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewEthernetConfig(t *testing.T) {
|
||||
c := NewDHCP4EthernetConfig()
|
||||
|
||||
assert := assert.New(t)
|
||||
assert.YAMLEq("dhcp4: true", c.YAMLString())
|
||||
|
||||
}
|
||||
|
||||
func TestNewBondMode4(t *testing.T) {
|
||||
c := NewBondMode4(
|
||||
&EthernetConfig{
|
||||
DHCP4: false,
|
||||
Gateway4: "192.168.1.1",
|
||||
Addresses: []string{"192.168.1.252/24"},
|
||||
Nameservers: &Nameservers{
|
||||
Search: []string{"local"},
|
||||
Addresses: []string{"8.8.8.8", "8.8.4.4"},
|
||||
},
|
||||
},
|
||||
[]string{"enp2s0", "enp3s0"},
|
||||
)
|
||||
|
||||
yamlStr := `
|
||||
addresses:
|
||||
- 192.168.1.252/24
|
||||
dhcp4: false
|
||||
gateway4: 192.168.1.1
|
||||
interfaces:
|
||||
- enp2s0
|
||||
- enp3s0
|
||||
nameservers:
|
||||
addresses:
|
||||
- 8.8.8.8
|
||||
- 8.8.4.4
|
||||
search:
|
||||
- local
|
||||
parameters:
|
||||
mii-monitor-interval: 100
|
||||
mode: "802.3ad"
|
||||
`
|
||||
|
||||
assert := assert.New(t)
|
||||
assert.YAMLEq(yamlStr, c.YAMLString())
|
||||
}
|
||||
|
||||
func TestNewNetwork(t *testing.T) {
|
||||
n := NewNetwork()
|
||||
n.AddEthernet("eth0", NewDHCP4EthernetConfig())
|
||||
n.AddEthernet("eth1", NewStaticEthernetConfig(
|
||||
"10.10.10.2/24",
|
||||
"10.10.10.1",
|
||||
[]string{"mydomain", "otherdomain"},
|
||||
[]string{"114.114.114.114"},
|
||||
nil,
|
||||
))
|
||||
|
||||
c := NewConfiguration(n)
|
||||
|
||||
yamlStr := `
|
||||
network:
|
||||
ethernets:
|
||||
eth0:
|
||||
dhcp4: true
|
||||
eth1:
|
||||
addresses:
|
||||
- 10.10.10.2/24
|
||||
dhcp4: false
|
||||
gateway4: 10.10.10.1
|
||||
nameservers:
|
||||
addresses:
|
||||
- 114.114.114.114
|
||||
search: ["mydomain", "otherdomain"]
|
||||
renderer: networkd
|
||||
version: 2
|
||||
`
|
||||
|
||||
assert := assert.New(t)
|
||||
assert.YAMLEq(yamlStr, c.YAMLString())
|
||||
}
|
||||
Reference in New Issue
Block a user