Esempio n. 1
0
func (s *networkerSuite) TestNewNetworkerReturnsErrorWithoutConfig(c *gc.C) {
	_, err := os.Stat(networker.ConfigFileName)
	c.Assert(err, jc.Satisfies, os.IsNotExist)
	nw, err := networker.NewNetworker(s.networkerState, agentConfig(s.machine.Tag()))
	c.Assert(err, gc.ErrorMatches, `missing ".*" config file`)
	c.Assert(nw, gc.IsNil)
}
Esempio n. 2
0
func (s *MachineSuite) TestMachineAgentRunsSafeNetworkerWhenNetworkManagementIsDisabled(c *gc.C) {
	attrs := coretesting.Attrs{"disable-network-management": true}
	err := s.BackingState.UpdateEnvironConfig(attrs, nil, nil)
	c.Assert(err, gc.IsNil)

	started := make(chan struct{}, 1)
	nonSafeStarted := make(chan struct{}, 1)
	s.agentSuite.PatchValue(&newSafeNetworker, func(st *apinetworker.State, conf agent.Config, confDir string) (*networker.Networker, error) {
		select {
		case started <- struct{}{}:
		default:
		}
		return networker.NewSafeNetworker(st, conf, confDir)
	})
	s.agentSuite.PatchValue(&newNetworker, func(st *apinetworker.State, conf agent.Config, confDir string) (*networker.Networker, error) {
		select {
		case nonSafeStarted <- struct{}{}:
		default:
		}
		return networker.NewNetworker(st, conf, confDir)
	})
	m, _, _ := s.primeAgent(c, version.Current, state.JobHostUnits)
	a := s.newAgent(c, m)
	defer a.Stop()
	go func() {
		c.Check(a.Run(nil), gc.IsNil)
	}()
	select {
	case <-started:
	case <-nonSafeStarted:
		c.Fatalf("expected to start safe networker, but started a normal one")
	case <-time.After(coretesting.LongWait):
		c.Fatalf("timed out waiting for the safe networker worker to be started")
	}
}
Esempio n. 3
0
func (s *networkerSuite) newCustomNetworker(
	c *gc.C,
	facade apinetworker.State,
	machineId string,
	intrusiveMode bool,
	initInterfaces bool,
) (*networker.Networker, string) {
	if initInterfaces {
		s.upInterfaces = set.NewStrings("lo", "eth0")
		s.interfacesWithAddress = set.NewStrings("lo", "eth0")
	}
	s.lastCommands = make(chan []string)
	s.vlanModuleLoaded = false
	configDir := c.MkDir()

	nw, err := networker.NewNetworker(facade, agentConfig(machineId), intrusiveMode, configDir)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(nw, gc.NotNil)

	return nw, configDir
}
Esempio n. 4
0
func (s *networkerSuite) newCustomNetworker(c *gc.C, facade *apinetworker.State, machineId string, canWriteConfig, initInterfaces bool) (*networker.Networker, string) {

	if initInterfaces {
		s.upInterfaces = set.NewStrings("lo", "eth0")
		s.interfacesWithAddress = set.NewStrings("lo", "eth0")
	}
	s.lastCommands = make(chan []string)
	s.vlanModuleLoaded = false
	configDir := c.MkDir()

	var nw *networker.Networker
	var err error
	if canWriteConfig {
		nw, err = networker.NewNetworker(facade, agentConfig(machineId), configDir)
	} else {
		nw, err = networker.NewSafeNetworker(facade, agentConfig(machineId), configDir)
	}
	c.Assert(err, gc.IsNil)
	c.Assert(nw, gc.NotNil)

	return nw, configDir
}
Esempio n. 5
0
func (s *networkerSuite) TestNetworker(c *gc.C) {
	// Create a sample interfaces file (MAAS configuration)
	interfacesFileContents := fmt.Sprintf(sampleInterfacesFile, networker.ConfigDirName)
	err := utils.AtomicWriteFile(networker.ConfigFileName, []byte(interfacesFileContents), 0644)
	c.Assert(err, gc.IsNil)
	err = utils.AtomicWriteFile(filepath.Join(networker.ConfigDirName, "eth0.config"), []byte(sampleEth0DotConfigFile), 0644)
	c.Assert(err, gc.IsNil)

	// Patch the network interface functions
	s.PatchValue(&networker.InterfaceIsUp,
		func(name string) bool {
			return readyInterfaces.Contains(name)
		})
	s.PatchValue(&networker.InterfaceHasAddress,
		func(name string) bool {
			return interfacesWithAddress.Contains(name)
		})

	// Patch the command executor function
	s.configStates = []*configState{}
	s.PatchValue(&networker.ExecuteCommands,
		func(commands []string) error {
			return executeCommandsHook(c, s, commands)
		},
	)

	// Create and setup networker.
	s.executed = make(chan bool)
	nw, err := networker.NewNetworker(s.networkerState, agentConfig(s.machine.Tag()))
	c.Assert(err, gc.IsNil)
	defer func() { c.Assert(worker.Stop(nw), gc.IsNil) }()

	executeCount := 0
loop:
	for {
		select {
		case <-s.executed:
			executeCount++
			if executeCount == 3 {
				break loop
			}
		case <-time.After(coretesting.ShortWait):
			fmt.Printf("%#v\n", s.configStates)
			c.Fatalf("command not executed")
		}
	}

	// Verify the executed commands from SetUp()
	expectedConfigFiles := networker.ConfigFiles{
		networker.ConfigFileName: {
			Data: fmt.Sprintf(expectedInterfacesFile, networker.ConfigSubDirName,
				networker.ConfigSubDirName, networker.ConfigSubDirName, networker.ConfigSubDirName),
		},
		networker.IfaceConfigFileName("br0"): {
			Data: "auto br0\niface br0 inet dhcp\n  bridge_ports eth0\n",
		},
		networker.IfaceConfigFileName("eth0"): {
			Data: "auto eth0\niface eth0 inet manual\n",
		},
		networker.IfaceConfigFileName("wlan0"): {
			Data: "auto wlan0\niface wlan0 inet dhcp\n",
		},
	}
	c.Assert(s.configStates[0].files, gc.DeepEquals, expectedConfigFiles)
	expectedCommands := []string(nil)
	c.Assert(s.configStates[0].commands, gc.DeepEquals, expectedCommands)
	c.Assert(s.configStates[0].readyInterfaces, gc.DeepEquals, []string{"br0", "eth0", "wlan0"})
	c.Assert(s.configStates[0].interfacesWithAddress, gc.DeepEquals, []string{"br0", "wlan0"})

	// Verify the executed commands from Handle()
	c.Assert(s.configStates[1].files, gc.DeepEquals, expectedConfigFiles)
	expectedCommands = []string(nil)
	c.Assert(s.configStates[1].commands, gc.DeepEquals, expectedCommands)
	c.Assert(s.configStates[1].readyInterfaces, gc.DeepEquals, []string{"br0", "eth0", "wlan0"})
	c.Assert(s.configStates[1].interfacesWithAddress, gc.DeepEquals, []string{"br0", "wlan0"})

	// Verify the executed commands from Handle()
	expectedConfigFiles[networker.IfaceConfigFileName("eth0.69")] = &networker.ConfigFile{
		Data: "# Managed by Juju, don't change.\nauto eth0.69\niface eth0.69 inet dhcp\n\tvlan-raw-device eth0\n",
	}
	expectedConfigFiles[networker.IfaceConfigFileName("eth1")] = &networker.ConfigFile{
		Data: "# Managed by Juju, don't change.\nauto eth1\niface eth1 inet dhcp\n",
	}
	expectedConfigFiles[networker.IfaceConfigFileName("eth1.42")] = &networker.ConfigFile{
		Data: "# Managed by Juju, don't change.\nauto eth1.42\niface eth1.42 inet dhcp\n\tvlan-raw-device eth1\n",
	}
	expectedConfigFiles[networker.IfaceConfigFileName("eth2")] = &networker.ConfigFile{
		Data: "# Managed by Juju, don't change.\nauto eth2\niface eth2 inet dhcp\n",
	}
	for k, _ := range s.configStates[2].files {
		c.Check(s.configStates[2].files[k], gc.DeepEquals, expectedConfigFiles[k])
	}
	c.Assert(s.configStates[2].files, gc.DeepEquals, expectedConfigFiles)
	expectedCommands = []string{
		"dpkg-query -s vlan || apt-get --option Dpkg::Options::=--force-confold --assume-yes install vlan",
		"lsmod | grep -q 8021q || modprobe 8021q",
		"grep -q 8021q /etc/modules || echo 8021q >> /etc/modules",
		"vconfig set_name_type DEV_PLUS_VID_NO_PAD",
		"ifup eth0.69",
		"ifup eth1",
		"ifup eth1.42",
		"ifup eth2",
	}
	c.Assert(s.configStates[2].commands, gc.DeepEquals, expectedCommands)
	c.Assert(s.configStates[2].readyInterfaces, gc.DeepEquals,
		[]string{"br0", "eth0", "eth0.69", "eth1", "eth1.42", "eth2", "wlan0"})
	c.Assert(s.configStates[2].interfacesWithAddress, gc.DeepEquals,
		[]string{"br0", "eth0.69", "eth1", "eth1.42", "eth2", "wlan0"})
}
Esempio n. 6
0
// APIWorker returns a Worker that connects to the API and starts any
// workers that need an API connection.
func (a *MachineAgent) APIWorker() (worker.Worker, error) {
	agentConfig := a.CurrentConfig()
	st, entity, err := openAPIState(agentConfig, a)
	if err != nil {
		return nil, err
	}
	reportOpenedAPI(st)

	// Refresh the configuration, since it may have been updated after opening state.
	agentConfig = a.CurrentConfig()

	for _, job := range entity.Jobs() {
		if job.NeedsState() {
			info, err := st.Agent().StateServingInfo()
			if err != nil {
				return nil, fmt.Errorf("cannot get state serving info: %v", err)
			}
			err = a.ChangeConfig(func(config agent.ConfigSetter) error {
				config.SetStateServingInfo(info)
				return nil
			})
			if err != nil {
				return nil, err
			}
			agentConfig = a.CurrentConfig()
			break
		}
	}

	rsyslogMode := rsyslog.RsyslogModeForwarding
	runner := newRunner(connectionIsFatal(st), moreImportant)
	var singularRunner worker.Runner
	for _, job := range entity.Jobs() {
		if job == params.JobManageEnviron {
			rsyslogMode = rsyslog.RsyslogModeAccumulate
			conn := singularAPIConn{st, st.Agent()}
			singularRunner, err = newSingularRunner(runner, conn)
			if err != nil {
				return nil, fmt.Errorf("cannot make singular API Runner: %v", err)
			}
			break
		}
	}

	// Run the upgrader and the upgrade-steps worker without waiting for
	// the upgrade steps to complete.
	runner.StartWorker("upgrader", func() (worker.Worker, error) {
		return upgrader.NewUpgrader(st.Upgrader(), agentConfig), nil
	})
	runner.StartWorker("upgrade-steps", func() (worker.Worker, error) {
		return a.upgradeWorkerContext.Worker(a, st, entity.Jobs()), nil
	})

	// All other workers must wait for the upgrade steps to complete
	// before starting.
	a.startWorkerAfterUpgrade(runner, "machiner", func() (worker.Worker, error) {
		return machiner.NewMachiner(st.Machiner(), agentConfig), nil
	})
	a.startWorkerAfterUpgrade(runner, "apiaddressupdater", func() (worker.Worker, error) {
		return apiaddressupdater.NewAPIAddressUpdater(st.Machiner(), a), nil
	})
	a.startWorkerAfterUpgrade(runner, "logger", func() (worker.Worker, error) {
		return workerlogger.NewLogger(st.Logger(), agentConfig), nil
	})
	a.startWorkerAfterUpgrade(runner, "machineenvironmentworker", func() (worker.Worker, error) {
		return machineenvironmentworker.NewMachineEnvironmentWorker(st.Environment(), agentConfig), nil
	})
	a.startWorkerAfterUpgrade(runner, "rsyslog", func() (worker.Worker, error) {
		return newRsyslogConfigWorker(st.Rsyslog(), agentConfig, rsyslogMode)
	})
	if networker.CanStart() {
		a.startWorkerAfterUpgrade(runner, "networker", func() (worker.Worker, error) {
			return networker.NewNetworker(st.Networker(), agentConfig)
		})
	} else {
		logger.Infof("not starting networker - missing /etc/network/interfaces")
	}

	// If not a local provider bootstrap machine, start the worker to
	// manage SSH keys.
	providerType := agentConfig.Value(agent.ProviderType)
	if providerType != provider.Local || a.MachineId != bootstrapMachineId {
		a.startWorkerAfterUpgrade(runner, "authenticationworker", func() (worker.Worker, error) {
			return authenticationworker.NewWorker(st.KeyUpdater(), agentConfig), nil
		})
	}

	// Perform the operations needed to set up hosting for containers.
	if err := a.setupContainerSupport(runner, st, entity, agentConfig); err != nil {
		return nil, fmt.Errorf("setting up container support: %v", err)
	}
	for _, job := range entity.Jobs() {
		switch job {
		case params.JobHostUnits:
			a.startWorkerAfterUpgrade(runner, "deployer", func() (worker.Worker, error) {
				apiDeployer := st.Deployer()
				context := newDeployContext(apiDeployer, agentConfig)
				return deployer.NewDeployer(apiDeployer, context), nil
			})
		case params.JobManageEnviron:
			a.startWorkerAfterUpgrade(singularRunner, "environ-provisioner", func() (worker.Worker, error) {
				return provisioner.NewEnvironProvisioner(st.Provisioner(), agentConfig), nil
			})
			// TODO(axw) 2013-09-24 bug #1229506
			// Make another job to enable the firewaller. Not all
			// environments are capable of managing ports
			// centrally.
			a.startWorkerAfterUpgrade(singularRunner, "firewaller", func() (worker.Worker, error) {
				return firewaller.NewFirewaller(st.Firewaller())
			})
			a.startWorkerAfterUpgrade(singularRunner, "charm-revision-updater", func() (worker.Worker, error) {
				return charmrevisionworker.NewRevisionUpdateWorker(st.CharmRevisionUpdater()), nil
			})
		case params.JobManageStateDeprecated:
			// Legacy environments may set this, but we ignore it.
		default:
			// TODO(dimitern): Once all workers moved over to using
			// the API, report "unknown job type" here.
		}
	}
	return newCloseWorker(runner, st), nil // Note: a worker.Runner is itself a worker.Worker.
}