mirror of
https://github.com/rancher/os.git
synced 2025-07-07 20:08:37 +00:00
commit
da7abd871e
@ -1,3 +1,3 @@
|
|||||||
IMAGE_NAME=rancher/os
|
IMAGE_NAME=rancher/os
|
||||||
VERSION=v0.4.3-dev
|
VERSION=v0.4.3-dev
|
||||||
DFS_IMAGE=rancher/docker:1.10.0
|
DFS_IMAGE=rancher/docker:v1.10.0-1
|
||||||
|
@ -3,6 +3,8 @@ package cloudinit
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
yaml "github.com/cloudfoundry-incubator/candiedyaml"
|
yaml "github.com/cloudfoundry-incubator/candiedyaml"
|
||||||
@ -40,7 +42,7 @@ func enablePacketNetwork(cfg *rancherConfig.RancherConfig) {
|
|||||||
bondCfg := netconf.InterfaceConfig{
|
bondCfg := netconf.InterfaceConfig{
|
||||||
Addresses: []string{},
|
Addresses: []string{},
|
||||||
BondOpts: map[string]string{
|
BondOpts: map[string]string{
|
||||||
"lacp-rate": "1",
|
"lacp_rate": "1",
|
||||||
"xmit_hash_policy": "layer3+4",
|
"xmit_hash_policy": "layer3+4",
|
||||||
"downdelay": "200",
|
"downdelay": "200",
|
||||||
"updelay": "200",
|
"updelay": "200",
|
||||||
@ -83,6 +85,10 @@ func enablePacketNetwork(cfg *rancherConfig.RancherConfig) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := os.MkdirAll(path.Dir(rancherConfig.CloudConfigNetworkFile), 0700); err != nil {
|
||||||
|
logrus.Errorf("Failed to create directory for file %s: %v", rancherConfig.CloudConfigNetworkFile, err)
|
||||||
|
}
|
||||||
|
|
||||||
if err := rancherConfig.WriteToFile(cc, rancherConfig.CloudConfigNetworkFile); err != nil {
|
if err := rancherConfig.WriteToFile(cc, rancherConfig.CloudConfigNetworkFile); err != nil {
|
||||||
logrus.Errorf("Failed to save config file %s: %v", rancherConfig.CloudConfigNetworkFile, err)
|
logrus.Errorf("Failed to save config file %s: %v", rancherConfig.CloudConfigNetworkFile, err)
|
||||||
}
|
}
|
||||||
|
@ -64,11 +64,6 @@ rancher:
|
|||||||
network:
|
network:
|
||||||
dns:
|
dns:
|
||||||
nameservers: [8.8.8.8, 8.8.4.4]
|
nameservers: [8.8.8.8, 8.8.4.4]
|
||||||
interfaces:
|
|
||||||
eth*:
|
|
||||||
dhcp: true
|
|
||||||
lo:
|
|
||||||
address: 127.0.0.1/8
|
|
||||||
repositories:
|
repositories:
|
||||||
core:
|
core:
|
||||||
url: https://raw.githubusercontent.com/rancher/os-services/v0.4.3-dev
|
url: https://raw.githubusercontent.com/rancher/os-services/v0.4.3-dev
|
||||||
|
@ -7,6 +7,8 @@ rancher:
|
|||||||
kernel-headers: true
|
kernel-headers: true
|
||||||
network:
|
network:
|
||||||
interfaces:
|
interfaces:
|
||||||
|
eth*:
|
||||||
|
dhcp: true
|
||||||
eth1:
|
eth1:
|
||||||
address: 10.10.2.17/24
|
address: 10.10.2.17/24
|
||||||
gateway: 10.10.2.2
|
gateway: 10.10.2.2
|
||||||
|
25
tests/integration/assets/test_09/cloud-config.yml
Normal file
25
tests/integration/assets/test_09/cloud-config.yml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#cloud-config
|
||||||
|
rancher:
|
||||||
|
network:
|
||||||
|
interfaces:
|
||||||
|
eth0:
|
||||||
|
address: 10.0.2.15/24
|
||||||
|
gateway: 10.0.2.2
|
||||||
|
br0:
|
||||||
|
vlans: 100
|
||||||
|
eth1:
|
||||||
|
vlans: 100,200:foobar
|
||||||
|
eth1.100:
|
||||||
|
bridge: br0
|
||||||
|
br0.100:
|
||||||
|
address: 123.123.123.123/32
|
||||||
|
eth6:
|
||||||
|
bond: bond0
|
||||||
|
eth7:
|
||||||
|
bond: bond0
|
||||||
|
bond0:
|
||||||
|
bond_opts:
|
||||||
|
mode: 1
|
||||||
|
address: 123.123.123.124/32
|
||||||
|
ssh_authorized_keys:
|
||||||
|
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC85w9stZyiLQp/DkVO6fqwiShYcj1ClKdtCqgHtf+PLpJkFReSFu8y21y+ev09gsSMRRrjF7yt0pUHV6zncQhVeqsZtgc5WbELY2DOYUGmRn/CCvPbXovoBrQjSorqlBmpuPwsStYLr92Xn+VVsMNSUIegHY22DphGbDKG85vrKB8HxUxGIDxFBds/uE8FhSy+xsoyT/jUZDK6pgq2HnGl6D81ViIlKecpOpWlW3B+fea99ADNyZNVvDzbHE5pcI3VRw8u59WmpWOUgT6qacNVACl8GqpBvQk8sw7O/X9DSZHCKafeD9G5k+GYbAUz92fKWrx/lOXfUXPS3+c8dRIF
|
36
tests/integration/rostest/test_09_network.py
Normal file
36
tests/integration/rostest/test_09_network.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import pytest
|
||||||
|
import rostest.util as u
|
||||||
|
from rostest.util import SSH
|
||||||
|
|
||||||
|
|
||||||
|
cloud_config_path = './tests/integration/assets/test_09/cloud-config.yml'
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def qemu(request):
|
||||||
|
q = u.run_qemu(request, run_args=['--cloud-config', cloud_config_path,
|
||||||
|
'-net', 'nic,vlan=0,model=virtio',
|
||||||
|
'-net', 'nic,vlan=0,model=virtio',
|
||||||
|
'-net', 'nic,vlan=0,model=virtio',
|
||||||
|
'-net', 'nic,vlan=0,model=virtio',
|
||||||
|
'-net', 'nic,vlan=0,model=virtio',
|
||||||
|
'-net', 'nic,vlan=0,model=virtio',
|
||||||
|
'-net', 'nic,vlan=0,model=virtio'])
|
||||||
|
u.flush_out(q.stdout)
|
||||||
|
return q
|
||||||
|
|
||||||
|
|
||||||
|
def test_network_conf(qemu):
|
||||||
|
SSH(qemu).check_call('bash', '-c', '''cat > test-merge << "SCRIPT"
|
||||||
|
set -x -e
|
||||||
|
|
||||||
|
ip link show dev br0
|
||||||
|
ip link show dev br0.100 | grep br0.100@br0
|
||||||
|
ip link show dev eth1.100 | grep 'master br0'
|
||||||
|
ip link show dev eth6 | grep 'master bond0'
|
||||||
|
ip link show dev eth7 | grep 'master bond0'
|
||||||
|
[ "$(</sys/class/net/bond0/bonding/mode)" = "active-backup 1" ]
|
||||||
|
|
||||||
|
SCRIPT
|
||||||
|
sudo bash test-merge
|
||||||
|
'''.strip())
|
@ -66,10 +66,10 @@ import:
|
|||||||
version: 1349b37bd56f4f5ce2690b5b2c0f53f88a261c67
|
version: 1349b37bd56f4f5ce2690b5b2c0f53f88a261c67
|
||||||
|
|
||||||
- package: github.com/rancher/docker-from-scratch
|
- package: github.com/rancher/docker-from-scratch
|
||||||
version: 1.10.0
|
version: v1.10.0-1
|
||||||
|
|
||||||
- package: github.com/rancher/netconf
|
- package: github.com/rancher/netconf
|
||||||
version: 8080e4909627bbdf51d7f427211a7c0517136373
|
version: d7d620ef4ea62a9d04b51c7b3d9dc83fe7ffaa1b
|
||||||
|
|
||||||
- package: github.com/ryanuber/go-glob
|
- package: github.com/ryanuber/go-glob
|
||||||
version: 0067a9abd927e50aed5190662702f81231413ae0
|
version: 0067a9abd927e50aed5190662702f81231413ae0
|
||||||
|
6
vendor/github.com/rancher/docker-from-scratch/README.md
generated
vendored
6
vendor/github.com/rancher/docker-from-scratch/README.md
generated
vendored
@ -51,7 +51,7 @@ This image is really designed to run with overlay. Aufs is known to work but ot
|
|||||||
|
|
||||||
## Seriously, Why?
|
## Seriously, Why?
|
||||||
|
|
||||||
This code and the supporting files were extracted out of RancherOS into a separate library and are still used by RancherOS. RancherOS runs Docker as a PID 1 but before we can exec Docker we need to setup a minimal environment for Docker in which to run. Since RancherOS is executed by the kernel there is absolutely nothing setup in the system. At Rancher we wrote a small amount of code to setup all the required mounts and directories to launch Docker.
|
This code and the supporting files were extracted out of RancherOS into a separate library and are still used by RancherOS. RancherOS runs Docker as the first process but before we can exec Docker we need to setup a minimal environment for Docker in which to run. Since RancherOS is executed by the kernel there is absolutely nothing setup in the system. At Rancher we wrote a small amount of code to setup all the required mounts and directories to launch Docker.
|
||||||
|
|
||||||
We moved this code out into a separate project for two reasons. First was simply that we wanted to clean up and modularize the RancherOS code base. Second is that we wanted to demonstrate clearly what exactly Docker requires from the Linux user space. For the most part Docker requires the standard mounts (`/proc`, `/sys`, `/run`, `/var/run`, etc) and the cgroup mounts in `/sys/fs/cgroup` plus the following programs/files:
|
We moved this code out into a separate project for two reasons. First was simply that we wanted to clean up and modularize the RancherOS code base. Second is that we wanted to demonstrate clearly what exactly Docker requires from the Linux user space. For the most part Docker requires the standard mounts (`/proc`, `/sys`, `/run`, `/var/run`, etc) and the cgroup mounts in `/sys/fs/cgroup` plus the following programs/files:
|
||||||
|
|
||||||
@ -90,6 +90,10 @@ If you want to run with a custom bridge name you must pass both `--bip` and `-b`
|
|||||||
|
|
||||||
# Troubleshooting
|
# Troubleshooting
|
||||||
|
|
||||||
|
## Zombies
|
||||||
|
|
||||||
|
If you are running containers with `--pid=host` you can get zombies. When you launch docker-from-scratch just add `-e DOCKER_LAUNCH_REAP=true` as a parameter to the `docker run` command to fix this.
|
||||||
|
|
||||||
## Weird module loading errors
|
## Weird module loading errors
|
||||||
|
|
||||||
For various reasons Docker or iptables may try to load a kernel module. You can either manually load all the needed modules from the host or you can bind mount in the kernel modules by adding `-v /lib/modules/$(uname -r)/lib/modules/$(uname -r)` to your `docker run` command
|
For various reasons Docker or iptables may try to load a kernel module. You can either manually load all the needed modules from the host or you can bind mount in the kernel modules by adding `-v /lib/modules/$(uname -r)/lib/modules/$(uname -r)` to your `docker run` command
|
||||||
|
23
vendor/github.com/rancher/docker-from-scratch/one.go
generated
vendored
Normal file
23
vendor/github.com/rancher/docker-from-scratch/one.go
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// +build linux
|
||||||
|
package dockerlaunch
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PidOne() error {
|
||||||
|
c := make(chan os.Signal, 2048)
|
||||||
|
signal.Notify(c, syscall.SIGCHLD)
|
||||||
|
|
||||||
|
for range c {
|
||||||
|
for {
|
||||||
|
if pid, err := syscall.Wait4(-1, nil, syscall.WNOHANG, nil); err != nil || pid <= 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
16
vendor/github.com/rancher/docker-from-scratch/scratch.go
generated
vendored
16
vendor/github.com/rancher/docker-from-scratch/scratch.go
generated
vendored
@ -44,6 +44,7 @@ var (
|
|||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Fork bool
|
Fork bool
|
||||||
|
PidOne bool
|
||||||
CommandName string
|
CommandName string
|
||||||
DnsConfig netconf.DnsConfig
|
DnsConfig netconf.DnsConfig
|
||||||
BridgeName string
|
BridgeName string
|
||||||
@ -190,6 +191,12 @@ func execDocker(config *Config, docker, cmd string, args []string) (*exec.Cmd, e
|
|||||||
}
|
}
|
||||||
cmd.Env = env
|
cmd.Env = env
|
||||||
err := cmd.Start()
|
err := cmd.Start()
|
||||||
|
if err != nil {
|
||||||
|
return cmd, err
|
||||||
|
}
|
||||||
|
if config.PidOne {
|
||||||
|
PidOne()
|
||||||
|
}
|
||||||
return cmd, err
|
return cmd, err
|
||||||
} else {
|
} else {
|
||||||
err := syscall.Exec(expand(docker), append([]string{cmd}, args...), env)
|
err := syscall.Exec(expand(docker), append([]string{cmd}, args...), env)
|
||||||
@ -273,7 +280,7 @@ func setupNetworking(config *Config) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
hostname, err := os.Hostname();
|
hostname, err := os.Hostname()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -299,7 +306,7 @@ ff02::2 ip6-allrouters
|
|||||||
config.BridgeName: {
|
config.BridgeName: {
|
||||||
Address: config.BridgeAddress,
|
Address: config.BridgeAddress,
|
||||||
MTU: config.BridgeMtu,
|
MTU: config.BridgeMtu,
|
||||||
Bridge: true,
|
Bridge: "true",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
@ -578,6 +585,11 @@ func Main() {
|
|||||||
var config Config
|
var config Config
|
||||||
args = ParseConfig(&config, args...)
|
args = ParseConfig(&config, args...)
|
||||||
|
|
||||||
|
if os.Getenv("DOCKER_LAUNCH_REAP") == "true" {
|
||||||
|
config.Fork = true
|
||||||
|
config.PidOne = true
|
||||||
|
}
|
||||||
|
|
||||||
log.Debugf("Launch config %#v", config)
|
log.Debugf("Launch config %#v", config)
|
||||||
|
|
||||||
_, err := LaunchDocker(&config, os.Args[1], args...)
|
_, err := LaunchDocker(&config, os.Args[1], args...)
|
||||||
|
5
vendor/github.com/rancher/docker-from-scratch/trash.yml
generated
vendored
5
vendor/github.com/rancher/docker-from-scratch/trash.yml
generated
vendored
@ -19,7 +19,7 @@ import:
|
|||||||
version: 4f4d2c8983a18e2c9c63a3f339bc9a998c4557bc
|
version: 4f4d2c8983a18e2c9c63a3f339bc9a998c4557bc
|
||||||
|
|
||||||
- package: github.com/rancher/netconf
|
- package: github.com/rancher/netconf
|
||||||
version: 02925e7cf5a0f0bb0aa5360ee260ef7378e5eff8
|
version: bf95fd720be9de4f7aa3a4a529b70f2865dd0fc7
|
||||||
|
|
||||||
- package: github.com/ryanuber/go-glob
|
- package: github.com/ryanuber/go-glob
|
||||||
version: 0067a9abd927e50aed5190662702f81231413ae0
|
version: 0067a9abd927e50aed5190662702f81231413ae0
|
||||||
@ -32,3 +32,6 @@ import:
|
|||||||
|
|
||||||
- package: github.com/vishvananda/netlink
|
- package: github.com/vishvananda/netlink
|
||||||
version: edcd99c0881a4de0fdb3818af6b24f4ee6948464
|
version: edcd99c0881a4de0fdb3818af6b24f4ee6948464
|
||||||
|
|
||||||
|
- package: github.com/flynn/go-shlex
|
||||||
|
version: 3f9db97f856818214da2e1057f8ad84803971cff
|
||||||
|
1
vendor/github.com/rancher/netconf/.gitignore
generated
vendored
Normal file
1
vendor/github.com/rancher/netconf/.gitignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/netconf
|
114
vendor/github.com/rancher/netconf/bonding.go
generated
vendored
114
vendor/github.com/rancher/netconf/bonding.go
generated
vendored
@ -17,25 +17,20 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Bonding struct {
|
type Bonding struct {
|
||||||
err error
|
|
||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bonding) Error() error {
|
func (b *Bonding) init() error {
|
||||||
return b.err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Bonding) init() {
|
|
||||||
_, err := os.Stat(bondingMasters)
|
_, err := os.Stat(bondingMasters)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
logrus.Info("Loading bonding kernel module")
|
logrus.Info("Loading bonding kernel module")
|
||||||
cmd := exec.Command("modprobe", "bonding")
|
cmd := exec.Command("modprobe", "bonding")
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
cmd.Stdout = os.Stdin
|
cmd.Stdout = os.Stdin
|
||||||
b.err = cmd.Run()
|
err = cmd.Run()
|
||||||
if b.err != nil {
|
if err != nil {
|
||||||
for i := 0; i < 30; i++ {
|
for i := 0; i < 30; i++ {
|
||||||
if _, err := os.Stat(bondingMasters); err == nil {
|
if _, err = os.Stat(bondingMasters); err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
@ -43,9 +38,7 @@ func (b *Bonding) init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, err = os.Stat(bondingMasters)
|
_, err = os.Stat(bondingMasters)
|
||||||
if err != nil {
|
return err
|
||||||
b.err = err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func contains(file, word string) (bool, error) {
|
func contains(file, word string) (bool, error) {
|
||||||
@ -63,67 +56,88 @@ func contains(file, word string) (bool, error) {
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bonding) AddSlave(slave string) {
|
func (b *Bonding) linkDown() error {
|
||||||
if b.err != nil {
|
link, err := netlink.LinkByName(b.name)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok, err := contains(base+b.name+"/bonding/slaves", slave); err != nil {
|
|
||||||
b.err = err
|
|
||||||
return
|
|
||||||
} else if ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
link, err := netlink.LinkByName(slave)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.err = err
|
return err
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
b.err = netlink.LinkSetDown(link)
|
return netlink.LinkSetDown(link)
|
||||||
if b.err != nil {
|
}
|
||||||
return
|
|
||||||
|
func (b *Bonding) ListSlaves() ([]string, error) {
|
||||||
|
file := base + b.name + "/bonding/slaves"
|
||||||
|
words, err := ioutil.ReadFile(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result := []string{}
|
||||||
|
for _, s := range strings.Split(strings.TrimSpace(string(words)), " ") {
|
||||||
|
if s != "" {
|
||||||
|
result = append(result, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bonding) RemoveSlave(slave string) error {
|
||||||
|
if ok, err := contains(base+b.name+"/bonding/slaves", slave); err != nil {
|
||||||
|
return err
|
||||||
|
} else if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
p := base + b.name + "/bonding/slaves"
|
||||||
|
logrus.Infof("Removing slave %s from master %s", slave, b.name)
|
||||||
|
return ioutil.WriteFile(p, []byte("-"+slave), 0644)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bonding) AddSlave(slave string) error {
|
||||||
|
if ok, err := contains(base+b.name+"/bonding/slaves", slave); err != nil {
|
||||||
|
return err
|
||||||
|
} else if ok {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
p := base + b.name + "/bonding/slaves"
|
p := base + b.name + "/bonding/slaves"
|
||||||
logrus.Infof("Adding slave %s to master %s", slave, b.name)
|
logrus.Infof("Adding slave %s to master %s", slave, b.name)
|
||||||
b.err = ioutil.WriteFile(p, []byte("+"+slave), 0644)
|
return ioutil.WriteFile(p, []byte("+"+slave), 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bonding) Opt(key, value string) {
|
func (b *Bonding) Opt(key, value string) error {
|
||||||
if b.err != nil {
|
if key == "mode" {
|
||||||
return
|
// Don't care about errors here
|
||||||
|
b.linkDown()
|
||||||
|
slaves, _ := b.ListSlaves()
|
||||||
|
for _, slave := range slaves {
|
||||||
|
b.RemoveSlave(slave)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p := base + b.name + "/bonding/" + key
|
p := base + b.name + "/bonding/" + key
|
||||||
b.err = ioutil.WriteFile(p, []byte(value), 0644)
|
if err := ioutil.WriteFile(p, []byte(value), 0644); err != nil {
|
||||||
if b.err != nil {
|
logrus.Errorf("Failed to set %s=%s on %s: %v", key, value, b.name, err)
|
||||||
logrus.Errorf("Failed to set %s=%s on %s", key, value, b.name)
|
return err
|
||||||
} else {
|
} else {
|
||||||
logrus.Infof("Set %s=%s on %s", key, value, b.name)
|
logrus.Infof("Set %s=%s on %s", key, value, b.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bonding) Clear() {
|
func Bond(name string) (*Bonding, error) {
|
||||||
b.err = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Bond(name string) *Bonding {
|
|
||||||
b := &Bonding{name: name}
|
b := &Bonding{name: name}
|
||||||
b.init()
|
if err := b.init(); err != nil {
|
||||||
if b.err != nil {
|
return nil, err
|
||||||
return b
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ok, err := contains(bondingMasters, name); err != nil {
|
if ok, err := contains(bondingMasters, name); err != nil {
|
||||||
b.err = err
|
return nil, err
|
||||||
return b
|
|
||||||
} else if ok {
|
} else if ok {
|
||||||
return b
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Infof("Creating bond %s", name)
|
logrus.Infof("Creating bond %s", name)
|
||||||
b.err = ioutil.WriteFile(bondingMasters, []byte("+"+name), 0644)
|
return b, ioutil.WriteFile(bondingMasters, []byte("+"+name), 0644)
|
||||||
return b
|
|
||||||
}
|
}
|
||||||
|
48
vendor/github.com/rancher/netconf/bridge.go
generated
vendored
Normal file
48
vendor/github.com/rancher/netconf/bridge.go
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package netconf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/vishvananda/netlink"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Bridge struct {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBridge(name string) (*Bridge, error) {
|
||||||
|
b := &Bridge{name: name}
|
||||||
|
return b, b.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bridge) init() error {
|
||||||
|
link, err := netlink.LinkByName(b.name)
|
||||||
|
if err == nil {
|
||||||
|
if _, ok := link.(*netlink.Bridge); !ok {
|
||||||
|
return fmt.Errorf("%s is not a bridge device", b.name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
bridge := netlink.Bridge{}
|
||||||
|
bridge.LinkAttrs.Name = b.name
|
||||||
|
|
||||||
|
return netlink.LinkAdd(&bridge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bridge) AddLink(link netlink.Link) error {
|
||||||
|
existing, err := netlink.LinkByName(b.name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if bridge, ok := existing.(*netlink.Bridge); ok {
|
||||||
|
if link.Attrs().MasterIndex != bridge.Index {
|
||||||
|
return netlink.LinkSetMaster(link, bridge)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("%s is not a bridge", b.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
335
vendor/github.com/rancher/netconf/netconf_linux.go
generated
vendored
335
vendor/github.com/rancher/netconf/netconf_linux.go
generated
vendored
@ -3,11 +3,11 @@ package netconf
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
log "github.com/Sirupsen/logrus"
|
log "github.com/Sirupsen/logrus"
|
||||||
@ -18,142 +18,206 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CONF = "/var/lib/rancher/conf"
|
CONF = "/var/lib/rancher/conf"
|
||||||
NET_SCRIPT = "/var/lib/rancher/conf/network.sh"
|
MODE = "mode"
|
||||||
)
|
)
|
||||||
|
|
||||||
func createInterfaces(netCfg *NetworkConfig) error {
|
var (
|
||||||
for name, iface := range netCfg.Interfaces {
|
defaultDhcpArgs = []string{"dhcpcd", "-MA4", "-e", "force_hostname=true"}
|
||||||
if iface.Bridge {
|
)
|
||||||
bridge := netlink.Bridge{}
|
|
||||||
bridge.LinkAttrs.Name = name
|
|
||||||
|
|
||||||
if err := netlink.LinkAdd(&bridge); err != nil {
|
func createInterfaces(netCfg *NetworkConfig) {
|
||||||
|
configured := map[string]bool{}
|
||||||
|
|
||||||
|
for name, iface := range netCfg.Interfaces {
|
||||||
|
if iface.Bridge == "true" {
|
||||||
|
if _, err := NewBridge(name); err != nil {
|
||||||
log.Errorf("Failed to create bridge %s: %v", name, err)
|
log.Errorf("Failed to create bridge %s: %v", name, err)
|
||||||
}
|
}
|
||||||
} else if iface.Bond != "" {
|
} else if iface.Bridge != "" {
|
||||||
bondIface, ok := netCfg.Interfaces[iface.Bond]
|
if _, err := NewBridge(iface.Bridge); err != nil {
|
||||||
if !ok {
|
log.Errorf("Failed to create bridge %s: %v", iface.Bridge, err)
|
||||||
log.Errorf("Failed to find bond configuration for [%s]", iface.Bond)
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
bond := Bond(iface.Bond)
|
} else if iface.Bond != "" {
|
||||||
if bond.Error() != nil {
|
bond, err := Bond(iface.Bond)
|
||||||
log.Errorf("Failed to create bond [%s]: %v", iface.Bond, bond.Error())
|
if err != nil {
|
||||||
|
log.Errorf("Failed to create bond %s: %v", iface.Bond, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range bondIface.BondOpts {
|
if !configured[iface.Bond] {
|
||||||
bond.Opt(k, v)
|
if bondIface, ok := netCfg.Interfaces[iface.Bond]; ok {
|
||||||
bond.Clear()
|
// Other settings depends on mode, so set it first
|
||||||
|
if v, ok := bondIface.BondOpts[MODE]; ok {
|
||||||
|
bond.Opt(MODE, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range bondIface.BondOpts {
|
||||||
|
if k != MODE {
|
||||||
|
bond.Opt(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
configured[iface.Bond] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func runScript(netCfg *NetworkConfig) error {
|
func createSlaveInterfaces(netCfg *NetworkConfig) {
|
||||||
if netCfg.Script == "" {
|
links, err := netlink.LinkList()
|
||||||
return nil
|
if err != nil {
|
||||||
|
log.Errorf("Failed to list links: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := os.Stat(CONF); os.IsNotExist(err) {
|
for _, link := range links {
|
||||||
if err := os.MkdirAll(CONF, 0700); err != nil {
|
match, ok := findMatch(link, netCfg)
|
||||||
return err
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
vlanDefs, err := ParseVlanDefinitions(match.Vlans)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to create vlans on device %s: %v", link.Attrs().Name, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, vlanDef := range vlanDefs {
|
||||||
|
if _, err = NewVlan(link, vlanDef.Name, vlanDef.Id); err != nil {
|
||||||
|
log.Errorf("Failed to create vlans on device %s, id %d: %v", link.Attrs().Name, vlanDef.Id, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func findMatch(link netlink.Link, netCfg *NetworkConfig) (InterfaceConfig, bool) {
|
||||||
|
linkName := link.Attrs().Name
|
||||||
|
var match InterfaceConfig
|
||||||
|
exactMatch := false
|
||||||
|
found := false
|
||||||
|
|
||||||
|
for key, netConf := range netCfg.Interfaces {
|
||||||
|
if netConf.Match == "" {
|
||||||
|
netConf.Match = key
|
||||||
|
}
|
||||||
|
|
||||||
|
if netConf.Match == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(netConf.Match, "mac") {
|
||||||
|
haAddr, err := net.ParseMAC(netConf.Match[4:])
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to parse mac %s: %v", netConf.Match[4:], err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't match mac address of the bond because it is the same as the slave
|
||||||
|
if bytes.Compare(haAddr, link.Attrs().HardwareAddr) == 0 && link.Attrs().Name != netConf.Bond {
|
||||||
|
// MAC address match is used over all other matches
|
||||||
|
return netConf, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !exactMatch && glob.Glob(netConf.Match, linkName) {
|
||||||
|
match = netConf
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if netConf.Match == linkName {
|
||||||
|
// Found exact match, use it over wildcard match
|
||||||
|
match = netConf
|
||||||
|
exactMatch = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ioutil.WriteFile(NET_SCRIPT, []byte(netCfg.Script), 0700); err != nil {
|
return match, exactMatch || found
|
||||||
return err
|
}
|
||||||
|
|
||||||
|
func populateDefault(netCfg *NetworkConfig) {
|
||||||
|
if netCfg.Interfaces == nil {
|
||||||
|
netCfg.Interfaces = map[string]InterfaceConfig{}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.Command(NET_SCRIPT)
|
if len(netCfg.Interfaces) == 0 {
|
||||||
cmd.Stdout = os.Stdout
|
netCfg.Interfaces["eth*"] = InterfaceConfig{
|
||||||
cmd.Stderr = os.Stderr
|
DHCP: true,
|
||||||
return cmd.Run()
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := netCfg.Interfaces["lo"]; !ok {
|
||||||
|
netCfg.Interfaces["lo"] = InterfaceConfig{
|
||||||
|
Address: "127.0.0.1/8",
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ApplyNetworkConfigs(netCfg *NetworkConfig) error {
|
func ApplyNetworkConfigs(netCfg *NetworkConfig) error {
|
||||||
log.Debugf("Config: %#v", netCfg)
|
populateDefault(netCfg)
|
||||||
if err := runScript(netCfg); err != nil {
|
|
||||||
log.Errorf("Failed to run script: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := createInterfaces(netCfg); err != nil {
|
log.Debugf("Config: %#v", netCfg)
|
||||||
return err
|
runCmds(netCfg.PreCmds, "")
|
||||||
}
|
|
||||||
|
createInterfaces(netCfg)
|
||||||
|
|
||||||
|
createSlaveInterfaces(netCfg)
|
||||||
|
|
||||||
links, err := netlink.LinkList()
|
links, err := netlink.LinkList()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
dhcpLinks := []string{}
|
dhcpLinks := map[string]string{}
|
||||||
|
|
||||||
//apply network config
|
//apply network config
|
||||||
for _, link := range links {
|
for _, link := range links {
|
||||||
linkName := link.Attrs().Name
|
linkName := link.Attrs().Name
|
||||||
var match InterfaceConfig
|
if match, ok := findMatch(link, netCfg); ok {
|
||||||
|
|
||||||
for key, netConf := range netCfg.Interfaces {
|
|
||||||
if netConf.Match == "" {
|
|
||||||
netConf.Match = key
|
|
||||||
}
|
|
||||||
|
|
||||||
if netConf.Match == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(netConf.Match) > 4 && strings.ToLower(netConf.Match[:3]) == "mac" {
|
|
||||||
haAddr, err := net.ParseMAC(netConf.Match[4:])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Don't match mac address of the bond because it is the same as the slave
|
|
||||||
if bytes.Compare(haAddr, link.Attrs().HardwareAddr) == 0 && link.Attrs().Name != netConf.Bond {
|
|
||||||
// MAC address match is used over all other matches
|
|
||||||
match = netConf
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// "" means match has not been found
|
|
||||||
if match.Match == "" && matches(linkName, netConf.Match) {
|
|
||||||
match = netConf
|
|
||||||
}
|
|
||||||
|
|
||||||
if netConf.Match == linkName {
|
|
||||||
// Found exact match, use it over wildcard match
|
|
||||||
match = netConf
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if match.Match != "" {
|
|
||||||
if match.DHCP {
|
if match.DHCP {
|
||||||
dhcpLinks = append(dhcpLinks, link.Attrs().Name)
|
dhcpLinks[link.Attrs().Name] = match.DHCPArgs
|
||||||
} else if err = applyNetConf(link, match); err != nil {
|
} else if err = applyInterfaceConfig(link, match); err != nil {
|
||||||
log.Errorf("Failed to apply settings to %s : %v", linkName, err)
|
log.Errorf("Failed to apply settings to %s : %v", linkName, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(dhcpLinks) > 0 {
|
//run dhcp
|
||||||
log.Infof("Running DHCP on %v", dhcpLinks)
|
wg := sync.WaitGroup{}
|
||||||
dhcpcdArgs := append([]string{"-MA4", "-e", "force_hostname=true"}, dhcpLinks...)
|
for iface, args := range dhcpLinks {
|
||||||
cmd := exec.Command("dhcpcd", dhcpcdArgs...)
|
wg.Add(1)
|
||||||
cmd.Stdout = os.Stdout
|
go func(iface, args string) {
|
||||||
cmd.Stderr = os.Stderr
|
runDhcp(iface, args)
|
||||||
if err := cmd.Run(); err != nil {
|
wg.Done()
|
||||||
log.Error(err)
|
}(iface, args)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
runCmds(netCfg.PostCmds, "")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func runDhcp(iface string, argstr string) {
|
||||||
|
log.Infof("Running DHCP on %s", iface)
|
||||||
|
args := []string{}
|
||||||
|
if argstr != "" {
|
||||||
|
var err error
|
||||||
|
args, err = shlex.Split(argstr)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to parse [%s]: %v", argstr, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(args) == 0 {
|
||||||
if err != nil {
|
args = defaultDhcpArgs
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
args = append(args, iface)
|
||||||
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func linkUp(link netlink.Link, netConf InterfaceConfig) error {
|
func linkUp(link netlink.Link, netConf InterfaceConfig) error {
|
||||||
@ -207,15 +271,27 @@ func setGateway(gateway string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyNetConf(link netlink.Link, netConf InterfaceConfig) error {
|
func applyInterfaceConfig(link netlink.Link, netConf InterfaceConfig) error {
|
||||||
if netConf.Bond != "" {
|
if netConf.Bond != "" {
|
||||||
b := Bond(netConf.Bond)
|
b, err := Bond(netConf.Bond)
|
||||||
b.AddSlave(link.Attrs().Name)
|
if err != nil {
|
||||||
if b.Error() != nil {
|
return err
|
||||||
return b.Error()
|
|
||||||
}
|
}
|
||||||
|
if err := b.AddSlave(link.Attrs().Name); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
return linkUp(link, netConf)
|
if netConf.Bridge != "" && netConf.Bridge != "true" {
|
||||||
|
b, err := NewBridge(netConf.Bridge)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := b.AddLink(link); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if netConf.IPV4LL {
|
if netConf.IPV4LL {
|
||||||
@ -223,16 +299,18 @@ func applyNetConf(link netlink.Link, netConf InterfaceConfig) error {
|
|||||||
log.Errorf("IPV4LL set failed: %v", err)
|
log.Errorf("IPV4LL set failed: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if netConf.Address == "" && len(netConf.Addresses) == 0 {
|
|
||||||
return nil
|
|
||||||
} else {
|
} else {
|
||||||
|
addresses := []string{}
|
||||||
|
|
||||||
if netConf.Address != "" {
|
if netConf.Address != "" {
|
||||||
err := applyAddress(netConf.Address, link, netConf)
|
addresses = append(addresses, netConf.Address)
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Failed to apply address %s to %s: %v", netConf.Address, link.Attrs().Name, err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for _, address := range netConf.Addresses {
|
|
||||||
|
if len(netConf.Addresses) > 0 {
|
||||||
|
addresses = append(addresses, netConf.Addresses...)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, address := range addresses {
|
||||||
err := applyAddress(address, link, netConf)
|
err := applyAddress(address, link, netConf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Failed to apply address %s to %s: %v", address, link.Attrs().Name, err)
|
log.Errorf("Failed to apply address %s to %s: %v", address, link.Attrs().Name, err)
|
||||||
@ -247,6 +325,8 @@ func applyNetConf(link netlink.Link, netConf InterfaceConfig) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runCmds(netConf.PreUp, link.Attrs().Name)
|
||||||
|
|
||||||
if err := linkUp(link, netConf); err != nil {
|
if err := linkUp(link, netConf); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -259,30 +339,31 @@ func applyNetConf(link netlink.Link, netConf InterfaceConfig) error {
|
|||||||
log.Errorf("Fail to set gateway %s", netConf.Gateway)
|
log.Errorf("Fail to set gateway %s", netConf.Gateway)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, postUp := range netConf.PostUp {
|
runCmds(netConf.PostUp, link.Attrs().Name)
|
||||||
postUp = strings.TrimSpace(postUp)
|
|
||||||
if postUp == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
args, err := shlex.Split(strings.Replace(postUp, "$iface", link.Attrs().Name, -1))
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Failed to parse command [%s]: %v", postUp, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd := exec.Command(args[0], args[1:]...)
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
if err := cmd.Run(); err != nil {
|
|
||||||
log.Errorf("Failed to run command [%s]: %v", postUp, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func matches(link, conf string) bool {
|
func runCmds(cmds []string, iface string) {
|
||||||
return glob.Glob(conf, link)
|
for _, cmd := range cmds {
|
||||||
|
cmd = strings.TrimSpace(cmd)
|
||||||
|
if cmd == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
args, err := shlex.Split(strings.Replace(cmd, "$iface", iface, -1))
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to parse command [%s]: %v", cmd, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("Running command %s %v", args[0], args[1:])
|
||||||
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
log.Errorf("Failed to run command [%s]: %v", cmd, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
8
vendor/github.com/rancher/netconf/types.go
generated
vendored
8
vendor/github.com/rancher/netconf/types.go
generated
vendored
@ -1,24 +1,28 @@
|
|||||||
package netconf
|
package netconf
|
||||||
|
|
||||||
type NetworkConfig struct {
|
type NetworkConfig struct {
|
||||||
Script string `yaml:"script,omitempty"`
|
PreCmds []string `yaml:"pre_cmds,omitempty"`
|
||||||
Dns DnsConfig `yaml:"dns,omitempty"`
|
Dns DnsConfig `yaml:"dns,omitempty"`
|
||||||
Interfaces map[string]InterfaceConfig `yaml:"interfaces,omitempty"`
|
Interfaces map[string]InterfaceConfig `yaml:"interfaces,omitempty"`
|
||||||
|
PostCmds []string `yaml:"post_cmds,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type InterfaceConfig struct {
|
type InterfaceConfig struct {
|
||||||
Match string `yaml:"match,omitempty"`
|
Match string `yaml:"match,omitempty"`
|
||||||
DHCP bool `yaml:"dhcp,omitempty"`
|
DHCP bool `yaml:"dhcp,omitempty"`
|
||||||
|
DHCPArgs string `yaml:"dhcp_args,omitempty"`
|
||||||
Address string `yaml:"address,omitempty"`
|
Address string `yaml:"address,omitempty"`
|
||||||
Addresses []string `yaml:"addresses,omitempty"`
|
Addresses []string `yaml:"addresses,omitempty"`
|
||||||
IPV4LL bool `yaml:"ipv4ll,omitempty"`
|
IPV4LL bool `yaml:"ipv4ll,omitempty"`
|
||||||
Gateway string `yaml:"gateway,omitempty"`
|
Gateway string `yaml:"gateway,omitempty"`
|
||||||
GatewayIpv6 string `yaml:"gateway_ipv6,omitempty"`
|
GatewayIpv6 string `yaml:"gateway_ipv6,omitempty"`
|
||||||
MTU int `yaml:"mtu,omitempty"`
|
MTU int `yaml:"mtu,omitempty"`
|
||||||
Bridge bool `yaml:"bridge,omitempty"`
|
Bridge string `yaml:"bridge,omitempty"`
|
||||||
Bond string `yaml:"bond,omitempty"`
|
Bond string `yaml:"bond,omitempty"`
|
||||||
BondOpts map[string]string `yaml:"bond_opts,omitempty"`
|
BondOpts map[string]string `yaml:"bond_opts,omitempty"`
|
||||||
PostUp []string `yaml:"post_up,omitempty"`
|
PostUp []string `yaml:"post_up,omitempty"`
|
||||||
|
PreUp []string `yaml:"pre_up,omitempty"`
|
||||||
|
Vlans string `yaml:"vlans,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DnsConfig struct {
|
type DnsConfig struct {
|
||||||
|
79
vendor/github.com/rancher/netconf/vlan.go
generated
vendored
Normal file
79
vendor/github.com/rancher/netconf/vlan.go
generated
vendored
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package netconf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/vishvananda/netlink"
|
||||||
|
)
|
||||||
|
|
||||||
|
type VlanDefinition struct {
|
||||||
|
Id int
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Vlan struct {
|
||||||
|
name string
|
||||||
|
link netlink.Link
|
||||||
|
id int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewVlan(link netlink.Link, name string, id int) (*Vlan, error) {
|
||||||
|
if name == "" {
|
||||||
|
name = fmt.Sprintf("%s.%d", link.Attrs().Name, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
v := &Vlan{
|
||||||
|
name: name,
|
||||||
|
link: link,
|
||||||
|
id: id,
|
||||||
|
}
|
||||||
|
return v, v.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Vlan) init() error {
|
||||||
|
link, err := netlink.LinkByName(v.name)
|
||||||
|
if err == nil {
|
||||||
|
if _, ok := link.(*netlink.Vlan); !ok {
|
||||||
|
return fmt.Errorf("%s is not a VLAN device", v.name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
vlan := netlink.Vlan{}
|
||||||
|
vlan.ParentIndex = v.link.Attrs().Index
|
||||||
|
vlan.Name = v.name
|
||||||
|
vlan.VlanId = v.id
|
||||||
|
|
||||||
|
return netlink.LinkAdd(&vlan)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseVlanDefinitions(vlans string) ([]VlanDefinition, error) {
|
||||||
|
vlans = strings.TrimSpace(vlans)
|
||||||
|
if vlans == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result := []VlanDefinition{}
|
||||||
|
|
||||||
|
for _, vlan := range strings.Split(vlans, ",") {
|
||||||
|
idName := strings.SplitN(strings.TrimSpace(vlan), ":", 2)
|
||||||
|
id, err := strconv.Atoi(idName[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Invalid format in %s: %v", vlans, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
def := VlanDefinition{
|
||||||
|
Id: id,
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(idName) > 1 {
|
||||||
|
def.Name = idName[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
result = append(result, def)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user