diff --git a/cmd/cloudinit/cloudinit.go b/cmd/cloudinit/cloudinit.go index 9eb0658f..e5e82e97 100644 --- a/cmd/cloudinit/cloudinit.go +++ b/cmd/cloudinit/cloudinit.go @@ -22,7 +22,6 @@ import ( "os" "strings" "sync" - "syscall" "time" yaml "github.com/cloudfoundry-incubator/candiedyaml" @@ -169,32 +168,12 @@ func fetchUserData() ([]byte, datasource.Metadata, error) { return userDataBytes, metadata, nil } -func SetHostname(cc *rancherConfig.CloudConfig) (string, error) { - name, _ := os.Hostname() - if cc.Hostname != "" { - name = cc.Hostname - } - if name != "" { - //set hostname - if err := syscall.Sethostname([]byte(name)); err != nil { - log.WithFields(log.Fields{"err": err, "hostname": name}).Error("Error setting hostname") - return "", err - } - } - - return name, nil -} - func executeCloudConfig() error { cc, err := rancherConfig.LoadConfig() if err != nil { return err } - if _, err := SetHostname(cc); err != nil { - return err - } - if len(cc.SSHAuthorizedKeys) > 0 { authorizeSSHKeys("rancher", cc.SSHAuthorizedKeys, sshKeyName) authorizeSSHKeys("docker", cc.SSHAuthorizedKeys, sshKeyName) diff --git a/cmd/network/network.go b/cmd/network/network.go index b8474de7..d7f9b50c 100644 --- a/cmd/network/network.go +++ b/cmd/network/network.go @@ -1,19 +1,16 @@ package network import ( - "bufio" "flag" - "io/ioutil" "os" "os/exec" - "strings" log "github.com/Sirupsen/logrus" "github.com/docker/libnetwork/resolvconf" "github.com/rancher/netconf" - "github.com/rancher/os/cmd/cloudinit" "github.com/rancher/os/config" + "github.com/rancher/os/hostname" ) const ( @@ -49,39 +46,25 @@ func Main() { log.Fatal(err) } - hostname, _ := cloudinit.SetHostname(cfg) // ignore error - log.Infof("Network: hostname: '%s'", hostname) - if _, err := resolvconf.Build("/etc/resolv.conf", cfg.Rancher.Network.Dns.Nameservers, cfg.Rancher.Network.Dns.Search, nil); err != nil { log.Error(err) } + if err := hostname.SetHostnameFromCloudConfig(cfg); err != nil { + log.Error(err) + } + if err := netconf.ApplyNetworkConfigs(&cfg.Rancher.Network); err != nil { log.Error(err) } - hostname, _ = cloudinit.SetHostname(cfg) // ignore error - log.Infof("Network: hostname: '%s' (from DHCP, if not set by cloud-config)", hostname) - if hostname != "" { - hosts, err := os.Open("/etc/hosts") - defer hosts.Close() - if err != nil { - log.Fatal(err) - } - lines := bufio.NewScanner(hosts) - hostsContent := "" - for lines.Scan() { - line := strings.TrimSpace(lines.Text()) - fields := strings.Fields(line) - if len(fields) > 0 && fields[0] == "127.0.1.1" { - hostsContent += "127.0.1.1 " + hostname + "\n" - continue - } - hostsContent += line + "\n" - } - if err := ioutil.WriteFile("/etc/hosts", []byte(hostsContent), 0600); err != nil { - log.Error(err) - } + dhcpHostname := cfg.Hostname == "" + if err := netconf.RunDhcp(&cfg.Rancher.Network, dhcpHostname); err != nil { + log.Error(err) + } + + if err := hostname.SyncHostname(); err != nil { + log.Error(err) } if f, err := os.Create(NETWORK_DONE); err != nil { diff --git a/config/types.go b/config/types.go index ee708af7..7854df55 100644 --- a/config/types.go +++ b/config/types.go @@ -71,6 +71,7 @@ type CloudConfig struct { SSHAuthorizedKeys []string `yaml:"ssh_authorized_keys"` WriteFiles []config.File `yaml:"write_files"` Hostname string `yaml:"hostname"` + DefaultHostname string `yaml:"default_hostname"` Rancher RancherConfig `yaml:"rancher,omitempty"` } diff --git a/hostname/hostname.go b/hostname/hostname.go new file mode 100644 index 00000000..5fd16f0f --- /dev/null +++ b/hostname/hostname.go @@ -0,0 +1,62 @@ +package hostname + +import ( + "bufio" + "github.com/rancher/os/config" + "io/ioutil" + "os" + "strings" + "syscall" +) + +func SetHostnameFromCloudConfig(cc *config.CloudConfig) error { + var hostname string + if cc.Hostname == "" { + hostname = cc.DefaultHostname + } else { + hostname = cc.Hostname + } + + if hostname == "" { + return nil + } + + // set hostname + if err := syscall.Sethostname([]byte(hostname)); err != nil { + return err + } + + return nil +} + +func SyncHostname() error { + hostname, err := os.Hostname() + if err != nil { + return err + } + if hostname == "" { + return nil + } + + hosts, err := os.Open("/etc/hosts") + defer hosts.Close() + if err != nil { + return err + } + lines := bufio.NewScanner(hosts) + hostsContent := "" + for lines.Scan() { + line := strings.TrimSpace(lines.Text()) + fields := strings.Fields(line) + if len(fields) > 0 && fields[0] == "127.0.1.1" { + hostsContent += "127.0.1.1 " + hostname + "\n" + continue + } + hostsContent += line + "\n" + } + if err := ioutil.WriteFile("/etc/hosts", []byte(hostsContent), 0600); err != nil { + return err + } + + return nil +} diff --git a/os-config.tpl.yml b/os-config.tpl.yml index f0a0e817..1ea550f2 100644 --- a/os-config.tpl.yml +++ b/os-config.tpl.yml @@ -1,4 +1,4 @@ -hostname: {{.HOSTNAME_DEFAULT}} +default_hostname: {{.HOSTNAME_DEFAULT}} rancher: bootstrap: state-script: diff --git a/tests/integration/assets/test_12/cloud-config.yml b/tests/integration/assets/test_12/cloud-config.yml new file mode 100644 index 00000000..164579e4 --- /dev/null +++ b/tests/integration/assets/test_12/cloud-config.yml @@ -0,0 +1,3 @@ +#cloud-config +ssh_authorized_keys: + - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDUlsWAL5Rf0Wis/A7k7Tlqx0fZS60VzCZrPZYbP/wkL95jv0XzCx8bd1rZHeybblHPDNpND3BLv4qPY5DxRyexF4seGuzcJI/pOvGUGjQondeMPgDTFEo5w939gSdeTZcfXzQ0wAVhzwDbgH4zPfMzbdoo8Aiu9jkKljXw8IFju0gh+t6iKkGZCIjKT9o7zza1vGfkodhvi2V3VzPdNO28gaxZaRNtmBYUoVnGyR6nXN1Q3CJaVuh5o6GPCOqrhHNbYOFZKBpDiHbxPhVpxHQD2+8yUSGTG7WW75FfZePja5y8d0c/O5L37ZYx4AZAd3KgQYDBT2XCEJGQNawNbfpt diff --git a/tests/integration/assets/test_13/cloud-config.yml b/tests/integration/assets/test_13/cloud-config.yml new file mode 100644 index 00000000..749199c8 --- /dev/null +++ b/tests/integration/assets/test_13/cloud-config.yml @@ -0,0 +1,4 @@ +#cloud-config +hostname: rancher-test +ssh_authorized_keys: + - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDUlsWAL5Rf0Wis/A7k7Tlqx0fZS60VzCZrPZYbP/wkL95jv0XzCx8bd1rZHeybblHPDNpND3BLv4qPY5DxRyexF4seGuzcJI/pOvGUGjQondeMPgDTFEo5w939gSdeTZcfXzQ0wAVhzwDbgH4zPfMzbdoo8Aiu9jkKljXw8IFju0gh+t6iKkGZCIjKT9o7zza1vGfkodhvi2V3VzPdNO28gaxZaRNtmBYUoVnGyR6nXN1Q3CJaVuh5o6GPCOqrhHNbYOFZKBpDiHbxPhVpxHQD2+8yUSGTG7WW75FfZePja5y8d0c/O5L37ZYx4AZAd3KgQYDBT2XCEJGQNawNbfpt diff --git a/tests/integration/rostest/test_12_dhcp_hostname.py b/tests/integration/rostest/test_12_dhcp_hostname.py new file mode 100644 index 00000000..92ba3453 --- /dev/null +++ b/tests/integration/rostest/test_12_dhcp_hostname.py @@ -0,0 +1,21 @@ +import pytest +import rostest.util as u +from rostest.util import SSH + +ssh_command = ['./scripts/ssh', '--qemu', '--key', './tests/integration/assets/test.key'] +cloud_config_path = './tests/integration/assets/test_12/cloud-config.yml' + + +@pytest.fixture(scope="module") +def qemu(request): + q = u.run_qemu(request, ['--cloud-config', cloud_config_path]) + u.flush_out(q.stdout) + return q + + +@pytest.mark.timeout(40) +def test_dhcp_hostname(qemu): + SSH(qemu, ssh_command).check_call(''' +hostname | grep rancher-dev +cat /etc/hosts | grep rancher-dev + ''') diff --git a/tests/integration/rostest/test_13_cloud_config_hostname.py b/tests/integration/rostest/test_13_cloud_config_hostname.py new file mode 100644 index 00000000..bd607932 --- /dev/null +++ b/tests/integration/rostest/test_13_cloud_config_hostname.py @@ -0,0 +1,21 @@ +import pytest +import rostest.util as u +from rostest.util import SSH + +ssh_command = ['./scripts/ssh', '--qemu', '--key', './tests/integration/assets/test.key'] +cloud_config_path = './tests/integration/assets/test_13/cloud-config.yml' + + +@pytest.fixture(scope="module") +def qemu(request): + q = u.run_qemu(request, ['--cloud-config', cloud_config_path]) + u.flush_out(q.stdout) + return q + + +@pytest.mark.timeout(40) +def test_cloud_config_hostname(qemu): + SSH(qemu, ssh_command).check_call(''' +hostname | grep rancher-test +cat /etc/hosts | grep rancher-test + ''') diff --git a/trash.yml b/trash.yml index 317be887..dada9bf9 100644 --- a/trash.yml +++ b/trash.yml @@ -70,7 +70,7 @@ import: version: v1.10.3 - package: github.com/rancher/netconf - version: 6cd9ea0b3a45482c9e9aee9be9ca88c96b2f71e6 + version: 6a771a0593c146f35634c405ab9ccfec50db65e1 - package: github.com/ryanuber/go-glob version: 0067a9abd927e50aed5190662702f81231413ae0 diff --git a/vendor/github.com/rancher/netconf/netconf_linux.go b/vendor/github.com/rancher/netconf/netconf_linux.go index 2ed5cbb7..99f08153 100644 --- a/vendor/github.com/rancher/netconf/netconf_linux.go +++ b/vendor/github.com/rancher/netconf/netconf_linux.go @@ -23,7 +23,7 @@ const ( ) var ( - defaultDhcpArgs = []string{"dhcpcd", "-MA4", "-e", "force_hostname=true"} + defaultDhcpArgs = []string{"dhcpcd", "-MA4"} ) func createInterfaces(netCfg *NetworkConfig) { @@ -168,36 +168,48 @@ func ApplyNetworkConfigs(netCfg *NetworkConfig) error { return err } - dhcpLinks := map[string]string{} - //apply network config for _, link := range links { linkName := link.Attrs().Name - if match, ok := findMatch(link, netCfg); ok { - if match.DHCP { - dhcpLinks[link.Attrs().Name] = match.DHCPArgs - } else if err = applyInterfaceConfig(link, match); err != nil { + if match, ok := findMatch(link, netCfg); ok && !match.DHCP { + if err := applyInterfaceConfig(link, match); err != nil { log.Errorf("Failed to apply settings to %s : %v", linkName, err) } } } + runCmds(netCfg.PostCmds, "") + return err +} + +func RunDhcp(netCfg *NetworkConfig, dhcpHostname bool) error { + links, err := netlink.LinkList() + if err != nil { + return err + } + + dhcpLinks := map[string]string{} + for _, link := range links { + if match, ok := findMatch(link, netCfg); ok && match.DHCP { + dhcpLinks[link.Attrs().Name] = match.DHCPArgs + } + } + //run dhcp wg := sync.WaitGroup{} for iface, args := range dhcpLinks { wg.Add(1) go func(iface, args string) { - runDhcp(netCfg, iface, args) + runDhcp(netCfg, iface, args, dhcpHostname) wg.Done() }(iface, args) } wg.Wait() - runCmds(netCfg.PostCmds, "") return err } -func runDhcp(netCfg *NetworkConfig, iface string, argstr string) { +func runDhcp(netCfg *NetworkConfig, iface string, argstr string, dhcpHostname bool) { log.Infof("Running DHCP on %s", iface) args := []string{} if argstr != "" { @@ -215,6 +227,10 @@ func runDhcp(netCfg *NetworkConfig, iface string, argstr string) { args = append(args, "--nohook", "resolv.conf") } + if dhcpHostname { + args = append(args, "-e", "force_hostname=true") + } + args = append(args, iface) cmd := exec.Command(args[0], args[1:]...) cmd.Stdout = os.Stdout