Skip to content

Commit

Permalink
Support for preseeding networks in "lxd init"
Browse files Browse the repository at this point in the history
This is a minimal implementation of the "networks:" section of the lxd
init preseed YAML. It will print a warning if any of the given
networks already exists (but continue to create the non-existing
ones).

Signed-off-by: Free Ekanayaka <[email protected]>
  • Loading branch information
freeekanayaka committed May 17, 2017
1 parent ad8417c commit 766f4ca
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 9 deletions.
40 changes: 31 additions & 9 deletions lxd/main_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -473,11 +473,6 @@ they otherwise would.
data.Config["images.auto_update_interval"] = "0"
}

err = cmd.run(c, data)
if err != nil {
return nil
}

if bridgeName != "" {
bridgeConfig := map[string]string{}
bridgeConfig["ipv4.address"] = bridgeIPv4
Expand All @@ -494,11 +489,15 @@ they otherwise would.
network := api.NetworksPost{
Name: bridgeName}
network.Config = bridgeConfig
data.Networks = []api.NetworksPost{network}
}

err = c.CreateNetwork(network)
if err != nil {
return err
}
err = cmd.run(c, data)
if err != nil {
return nil
}

if bridgeName != "" {

props := map[string]string{
"type": "nic",
Expand Down Expand Up @@ -532,6 +531,12 @@ func (cmd *CmdInit) run(client lxd.ContainerServer, data *cmdInitData) error {
if err != nil {
return err
}

err = cmd.initNetworks(client, data.Networks)
if err != nil {
return err
}

return nil
}

Expand Down Expand Up @@ -568,6 +573,22 @@ func (cmd *CmdInit) initConfig(client lxd.ContainerServer, config map[string]int
return client.UpdateServer(server.Writable(), etag)
}

// Create the given networks if they don't exist yet.
func (cmd *CmdInit) initNetworks(client lxd.ContainerServer, networks []api.NetworksPost) error {
for _, network := range networks {
_, _, err := client.GetNetwork(network.Name)
if err == nil {
logger.Warnf("Network '%s' already exists, skipping.", network.Name)
continue
}
err = client.CreateNetwork(network)
if err != nil {
return err
}
}
return nil
}

// Check that the arguments passed via command line are consistent,
// and no invalid combination is provided.
func (cmd *CmdInit) validateArgs() error {
Expand Down Expand Up @@ -647,6 +668,7 @@ func (cmd *CmdInit) setProfileConfigItem(c lxd.ContainerServer, profileName stri
// the auto/interactive modes.
type cmdInitData struct {
api.ServerPut `yaml:",inline"`
Networks []api.NetworksPost
}

func cmdInit() error {
Expand Down
54 changes: 54 additions & 0 deletions lxd/main_init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"testing"

"github.com/lxc/lxd/client"
"github.com/lxc/lxd/shared/cmd"
"github.com/stretchr/testify/suite"
)
Expand All @@ -13,6 +14,7 @@ type cmdInitTestSuite struct {
context *cmd.Context
args *CmdInitArgs
command *CmdInit
client lxd.ContainerServer
}

func (suite *cmdInitTestSuite) SetupTest() {
Expand All @@ -29,6 +31,9 @@ func (suite *cmdInitTestSuite) SetupTest() {
RunningInUserns: false,
SocketPath: suite.d.UnixSocket.Socket.Addr().String(),
}
client, err := lxd.ConnectLXDUnix(suite.command.SocketPath, nil)
suite.Req.Nil(err)
suite.client = client
}

// If any argument intended for --auto is passed in interactive mode, an
Expand Down Expand Up @@ -174,6 +179,47 @@ func (suite *cmdInitTestSuite) TestCmdInit_ImagesAutoUpdatePreseed() {
suite.Req.Equal("15", key.Get())
}

// It's possible to configure a network bridge interactively.
func (suite *cmdInitTestSuite) TestCmdInit_NetworkInteractive() {
answers := &cmdInitAnswers{
WantNetworkBridge: true,
BridgeName: "foo",
BridgeIPv4: "auto",
BridgeIPv6: "auto",
}
answers.Render(suite.streams)

suite.Req.Nil(suite.command.Run())

network, _, err := suite.client.GetNetwork("foo")
suite.Req.Nil(err)
suite.Req.Equal("bridge", network.Type)
suite.Req.Nil(networkValidAddressCIDRV4(network.Config["ipv4.address"]))
suite.Req.Nil(networkValidAddressCIDRV6(network.Config["ipv6.address"]))
}

// Preseed a network of type bridge.
func (suite *cmdInitTestSuite) TestCmdInit_NetworkPreseed() {
suite.args.Preseed = true
suite.streams.InputAppend(`networks:
- name: bar
type: bridge
config:
ipv4.address: 10.48.159.1/24
ipv4.nat: true
ipv6.address: none
`)

suite.Req.Nil(suite.command.Run())

network, _, err := suite.client.GetNetwork("bar")
suite.Req.Nil(err)
suite.Req.Equal("bridge", network.Type)
suite.Req.Equal("10.48.159.1/24", network.Config["ipv4.address"])
suite.Req.Equal("true", network.Config["ipv4.nat"])
suite.Req.Equal("none", network.Config["ipv6.address"])
}

// Convenience for building the input text a user would enter for a certain
// sequence of answers.
type cmdInitAnswers struct {
Expand All @@ -183,6 +229,9 @@ type cmdInitAnswers struct {
BindToPort string
WantImageAutoUpdate bool
WantNetworkBridge bool
BridgeName string
BridgeIPv4 string
BridgeIPv6 string
}

// Render the input text the user would type for the desired answers, populating
Expand All @@ -196,6 +245,11 @@ func (answers *cmdInitAnswers) Render(streams *cmd.MemoryStreams) {
}
streams.InputAppendBoolAnswer(answers.WantImageAutoUpdate)
streams.InputAppendBoolAnswer(answers.WantNetworkBridge)
if answers.WantNetworkBridge {
streams.InputAppendLine(answers.BridgeName)
streams.InputAppendLine(answers.BridgeIPv4)
streams.InputAppendLine(answers.BridgeIPv6)
}
}

func TestCmdInitTestSuite(t *testing.T) {
Expand Down
5 changes: 5 additions & 0 deletions lxd/networks.go
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,11 @@ func (n *network) Rename(name string) error {
}

func (n *network) Start() error {
// If we are in mock mode, just no-op.
if n.daemon.MockMode {
return nil
}

// Create directory
if !shared.PathExists(shared.VarPath("networks", n.name)) {
err := os.MkdirAll(shared.VarPath("networks", n.name), 0711)
Expand Down
8 changes: 8 additions & 0 deletions test/suites/init_preseed.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,18 @@ test_init_preseed() {
config:
core.https_address: 127.0.0.1:9999
images.auto_update_interval: 15
networks:
- name: lxdt$$
type: bridge
config:
ipv4.address: none
ipv6.address: none
EOF

LXD_DIR=${LXD_INIT_DIR} lxc info | grep -q 'core.https_address: 127.0.0.1:9999'
LXD_DIR=${LXD_INIT_DIR} lxc info | grep -q 'images.auto_update_interval: "15"'
LXD_DIR=${LXD_INIT_DIR} lxc network list | grep -q "lxdt$$"
LXD_DIR=${LXD_INIT_DIR} lxc network delete lxdt$$

kill_lxd "${LXD_INIT_DIR}"

Expand Down

0 comments on commit 766f4ca

Please sign in to comment.