github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/lib/net/configurator/debian.go (about)

     1  package configurator
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"fmt"
     7  	"io"
     8  	"os"
     9  	"os/exec"
    10  	"path/filepath"
    11  	"strings"
    12  
    13  	"github.com/Cloud-Foundations/Dominator/lib/fsutil"
    14  )
    15  
    16  func (netconf *NetworkConfig) printDebian(writer io.Writer) error {
    17  	fmt.Fprintln(writer,
    18  		"# /etc/network/interfaces -- created by SmallStack installer")
    19  	fmt.Fprintln(writer)
    20  	fmt.Fprintln(writer, "auto lo")
    21  	fmt.Fprintln(writer, "iface lo inet loopback")
    22  	configuredInterfaces := make(map[string]struct{})
    23  	for _, iface := range netconf.normalInterfaces {
    24  		fmt.Fprintln(writer)
    25  		name := iface.netInterface.Name
    26  		if iface.subnet.Manage {
    27  			name = fmt.Sprintf("br%d", iface.subnet.VlanId)
    28  		}
    29  		fmt.Fprintf(writer, "auto %s\n", name)
    30  		fmt.Fprintf(writer, "iface %s inet static\n", name)
    31  		fmt.Fprintf(writer, "\taddress      %s\n", iface.ipAddr)
    32  		fmt.Fprintf(writer, "\tnetmask      %s\n", iface.subnet.IpMask)
    33  		if iface.subnet.IpGateway.Equal(netconf.DefaultSubnet.IpGateway) {
    34  			fmt.Fprintf(writer, "\tgateway      %s\n", iface.subnet.IpGateway)
    35  		}
    36  		if iface.subnet.Manage {
    37  			fmt.Fprintf(writer, "\thwaddress    %s\n",
    38  				iface.netInterface.HardwareAddr)
    39  			fmt.Fprintf(writer, "\tbridge_ports %s\n", iface.netInterface.Name)
    40  		}
    41  		configuredInterfaces[name] = struct{}{}
    42  	}
    43  	for _, iface := range netconf.bridgeOnlyInterfaces {
    44  		fmt.Fprintln(writer)
    45  		name := fmt.Sprintf("br@%s", iface.subnetId)
    46  		fmt.Fprintf(writer, "auto %s\n", name)
    47  		fmt.Fprintf(writer, "iface %s inet manual\n", name)
    48  		fmt.Fprintf(writer, "\thwaddress    %s\n",
    49  			iface.netInterface.HardwareAddr)
    50  		fmt.Fprintf(writer, "\tbridge_ports %s\n", iface.netInterface.Name)
    51  	}
    52  	if netconf.vlanRawDevice != "" {
    53  		if _, ok := configuredInterfaces[netconf.vlanRawDevice]; !ok {
    54  			fmt.Fprintln(writer)
    55  			fmt.Fprintf(writer, "auto %s\n", netconf.vlanRawDevice)
    56  			fmt.Fprintf(writer, "iface %s inet manual\n", netconf.vlanRawDevice)
    57  			if len(netconf.bondSlaves) > 1 {
    58  				fmt.Fprintf(writer, "\tup ip link set %s mtu 9000\n",
    59  					netconf.vlanRawDevice)
    60  				fmt.Fprintln(writer, "\tbond-mode 802.3ad")
    61  				fmt.Fprintln(writer, "\tbond-xmit_hash_policy 1")
    62  				fmt.Fprint(writer, "\tslaves")
    63  				for _, name := range netconf.bondSlaves {
    64  					fmt.Fprint(writer, " ", name)
    65  				}
    66  				fmt.Fprintln(writer)
    67  			}
    68  		}
    69  		for _, iface := range netconf.bondedInterfaces {
    70  			fmt.Fprintln(writer)
    71  			fmt.Fprintf(writer, "auto %s\n", iface.name)
    72  			fmt.Fprintf(writer, "iface %s inet static\n", iface.name)
    73  			fmt.Fprintf(writer, "\tvlan-raw-device %s\n", netconf.vlanRawDevice)
    74  			fmt.Fprintf(writer, "\taddress %s\n", iface.ipAddr)
    75  			fmt.Fprintf(writer, "\tnetmask %s\n", iface.subnet.IpMask)
    76  			if iface.subnet.IpGateway.Equal(netconf.DefaultSubnet.IpGateway) {
    77  				fmt.Fprintf(writer, "\tgateway %s\n", iface.subnet.IpGateway)
    78  			}
    79  		}
    80  		for _, vlanId := range netconf.bridges {
    81  			fmt.Fprintln(writer)
    82  			fmt.Fprintf(writer, "auto %s.%d\n", netconf.vlanRawDevice, vlanId)
    83  			fmt.Fprintf(writer, "iface %s.%d inet manual\n",
    84  				netconf.vlanRawDevice, vlanId)
    85  			fmt.Fprintf(writer, "\tvlan-raw-device %s\n", netconf.vlanRawDevice)
    86  			fmt.Fprintln(writer)
    87  			fmt.Fprintf(writer, "auto br%d\n", vlanId)
    88  			fmt.Fprintf(writer, "iface br%d inet manual\n", vlanId)
    89  			fmt.Fprintf(writer, "\tbridge_ports %s.%d\n",
    90  				netconf.vlanRawDevice, vlanId)
    91  		}
    92  	}
    93  	return nil
    94  }
    95  
    96  func (netconf *NetworkConfig) updateDebian(rootDir string) (bool, error) {
    97  	buffer := &bytes.Buffer{}
    98  	if err := netconf.printDebian(buffer); err != nil {
    99  		return false, err
   100  	}
   101  	filename := filepath.Join(rootDir, "etc", "network", "interfaces")
   102  	// Check if it was written by me.
   103  	if file, err := os.Open(filename); err != nil {
   104  		return false, err
   105  	} else {
   106  		defer file.Close()
   107  		fileBuffer := make([]byte, 256)
   108  		_, err := io.ReadFull(file, fileBuffer)
   109  		if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
   110  			return false, err
   111  		}
   112  		splitLines := strings.Split(string(fileBuffer), "\n")
   113  		if len(splitLines) < 1 {
   114  			return false, fmt.Errorf("%s is empty", filename)
   115  		}
   116  		if !strings.Contains(splitLines[0], "created by SmallStack") {
   117  			return false, fmt.Errorf("%s not created by SmallStack", filename)
   118  		}
   119  	}
   120  	if changed, err := fsutil.UpdateFile(buffer.Bytes(), filename); err != nil {
   121  		return false, err
   122  	} else if !changed {
   123  		return false, nil
   124  	}
   125  	cmd := exec.Command("ifup", "-a")
   126  	cmd.Stdout = os.Stdout
   127  	cmd.Stderr = os.Stderr
   128  	if err := cmd.Run(); err != nil {
   129  		return false, err
   130  	}
   131  	return true, nil
   132  }
   133  
   134  func (netconf *NetworkConfig) writeDebian(rootDir string) error {
   135  	filename := filepath.Join(rootDir, "etc", "network", "interfaces")
   136  	file, err := fsutil.CreateRenamingWriter(filename, fsutil.PublicFilePerms)
   137  	if err != nil {
   138  		return err
   139  	}
   140  	defer file.Close()
   141  	writer := bufio.NewWriter(file)
   142  	if err := netconf.printDebian(writer); err != nil {
   143  		return err
   144  	}
   145  	return writer.Flush()
   146  }