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 }