main.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. "net"
  6. "os"
  7. "path"
  8. "time"
  9. "github.com/coreos/rudder/Godeps/_workspace/src/github.com/coreos/go-systemd/daemon"
  10. log "github.com/coreos/rudder/Godeps/_workspace/src/github.com/golang/glog"
  11. "github.com/coreos/rudder/pkg/ip"
  12. "github.com/coreos/rudder/subnet"
  13. "github.com/coreos/rudder/udp"
  14. )
  15. const (
  16. defaultPort = 8285
  17. )
  18. type CmdLineOpts struct {
  19. etcdEndpoint string
  20. etcdPrefix string
  21. help bool
  22. version bool
  23. ipMasq bool
  24. port int
  25. subnetFile string
  26. iface string
  27. }
  28. var opts CmdLineOpts
  29. func init() {
  30. flag.StringVar(&opts.etcdEndpoint, "etcd-endpoint", "http://127.0.0.1:4001", "etcd endpoint")
  31. flag.StringVar(&opts.etcdPrefix, "etcd-prefix", "/coreos.com/network", "etcd prefix")
  32. flag.IntVar(&opts.port, "port", defaultPort, "port to use for inter-node communications")
  33. flag.StringVar(&opts.subnetFile, "subnet-file", "/run/rudder/subnet.env", "filename where env variables (subnet and MTU values) will be written to")
  34. flag.StringVar(&opts.iface, "iface", "", "interface to use (IP or name) for inter-host communication")
  35. flag.BoolVar(&opts.ipMasq, "ip-masq", false, "setup IP masquerade rule for traffic destined outside of overlay network")
  36. flag.BoolVar(&opts.help, "help", false, "print this message")
  37. flag.BoolVar(&opts.version, "version", false, "print version and exit")
  38. }
  39. func writeSubnet(sn ip.IP4Net, mtu int) error {
  40. // Write out the first usable IP by incrementing
  41. // sn.IP by one
  42. sn.IP += 1
  43. dir, _ := path.Split(opts.subnetFile)
  44. os.MkdirAll(dir, 0755)
  45. f, err := os.Create(opts.subnetFile)
  46. if err != nil {
  47. return err
  48. }
  49. defer f.Close()
  50. fmt.Fprintf(f, "RUDDER_SUBNET=%s\n", sn)
  51. fmt.Fprintf(f, "RUDDER_MTU=%d\n", mtu)
  52. return nil
  53. }
  54. func lookupIface() (*net.Interface, net.IP) {
  55. var iface *net.Interface
  56. var tep net.IP
  57. var err error
  58. if len(opts.iface) > 0 {
  59. if tep = net.ParseIP(opts.iface); tep != nil {
  60. iface, err = ip.GetInterfaceByIP(tep)
  61. if err != nil {
  62. log.Errorf("Error looking up interface %s: %s", opts.iface, err)
  63. return nil, nil
  64. }
  65. } else {
  66. iface, err = net.InterfaceByName(opts.iface)
  67. if err != nil {
  68. log.Errorf("Error looking up interface %s: %s", opts.iface, err)
  69. return nil, nil
  70. }
  71. }
  72. } else {
  73. log.Info("Determining IP address of default interface")
  74. for {
  75. if iface, err = ip.GetDefaultGatewayIface(); err == nil {
  76. break
  77. }
  78. log.Error("Failed to get default interface: ", err)
  79. time.Sleep(time.Second)
  80. }
  81. }
  82. if tep == nil {
  83. tep, err = ip.GetIfaceIP4Addr(iface)
  84. if err != nil {
  85. log.Error("Failed to find IPv4 address for interface ", iface.Name)
  86. }
  87. }
  88. return iface, tep
  89. }
  90. func makeSubnetManager() *subnet.SubnetManager {
  91. for {
  92. sm, err := subnet.NewSubnetManager(opts.etcdEndpoint, opts.etcdPrefix)
  93. if err == nil {
  94. return sm
  95. }
  96. log.Error("Failed to create SubnetManager: ", err)
  97. time.Sleep(time.Second)
  98. }
  99. }
  100. func main() {
  101. // glog will log to tmp files by default. override so all entries
  102. // can flow into journald (if running under systemd)
  103. flag.Set("logtostderr", "true")
  104. // now parse command line args
  105. flag.Parse()
  106. if opts.help {
  107. fmt.Fprintf(os.Stderr, "Usage: %s [OPTION]...\n", os.Args[0])
  108. flag.PrintDefaults()
  109. os.Exit(0)
  110. }
  111. if opts.version {
  112. fmt.Fprintln(os.Stderr, Version)
  113. os.Exit(0)
  114. }
  115. iface, tep := lookupIface()
  116. if iface == nil || tep == nil {
  117. return
  118. }
  119. log.Infof("Using %s to tunnel", tep)
  120. sm := makeSubnetManager()
  121. udp.Run(sm, iface, tep, opts.port, opts.ipMasq, func(sn ip.IP4Net, mtu int) {
  122. writeSubnet(sn, mtu)
  123. daemon.SdNotify("READY=1")
  124. })
  125. }