From 79e8a4ee25dfec9ecbeb0b65f0caed38e15da67c Mon Sep 17 00:00:00 2001 From: Flavio Castelli Date: Tue, 20 Feb 2018 09:37:39 +0100 Subject: Handle keyword-less kernel params Allow kernel params that don't have a key/value structure to be handled. Also allow params with nested equal signs, like `root=UUID=aa52d618-a2c4-4aad-aeb7-68d9e3a2c91d` Signed-off-by: Flavio Castelli --- libvirt/resource_libvirt_domain.go | 9 ++++++++- libvirt/utils_domain_def.go | 16 +++++++++++++--- libvirt/utils_domain_def_test.go | 21 ++++++++------------- website/docs/r/domain.html.markdown | 11 ++++++++++- 4 files changed, 39 insertions(+), 18 deletions(-) diff --git a/libvirt/resource_libvirt_domain.go b/libvirt/resource_libvirt_domain.go index 8d9be0e1..f7d7a074 100644 --- a/libvirt/resource_libvirt_domain.go +++ b/libvirt/resource_libvirt_domain.go @@ -992,7 +992,14 @@ func setCmdlineArgs(d *schema.ResourceData, domainDef *libvirtxml.Domain) { var cmdlineArgs []string for i := 0; i < d.Get("cmdline.#").(int); i++ { for k, v := range d.Get(fmt.Sprintf("cmdline.%d", i)).(map[string]interface{}) { - cmdlineArgs = append(cmdlineArgs, fmt.Sprintf("%s=%v", k, v)) + var cmd string + if k == "_" { + // keyless cmd (eg: nosplash) + cmd = fmt.Sprintf("%v", v) + } else { + cmd = fmt.Sprintf("%s=%v", k, v) + } + cmdlineArgs = append(cmdlineArgs, cmd) } } sort.Strings(cmdlineArgs) diff --git a/libvirt/utils_domain_def.go b/libvirt/utils_domain_def.go index 40d31a09..95c6c0d6 100644 --- a/libvirt/utils_domain_def.go +++ b/libvirt/utils_domain_def.go @@ -60,12 +60,17 @@ func splitKernelCmdLine(cmdLine string) ([]map[string]string, error) { } currCmdLine := make(map[string]string) + keylessCmdLineArgs := []string{} + argVals := strings.Split(cmdLine, " ") for _, argVal := range argVals { - kv := strings.Split(argVal, "=") - if len(kv) != 2 { - return nil, fmt.Errorf("Can't parse kernel command line: '%s'", cmdLine) + if !strings.Contains(argVal, "=") { + // keyless cmd line (eg: nosplash) + keylessCmdLineArgs = append(keylessCmdLineArgs, argVal) + continue } + + kv := strings.SplitN(argVal, "=", 2) k, v := kv[0], kv[1] // if the key is duplicate, start a new map if _, ok := currCmdLine[k]; ok { @@ -77,5 +82,10 @@ func splitKernelCmdLine(cmdLine string) ([]map[string]string, error) { if len(currCmdLine) > 0 { cmdLines = append(cmdLines, currCmdLine) } + if len(keylessCmdLineArgs) > 0 { + cl := make(map[string]string) + cl["_"] = strings.Join(keylessCmdLineArgs, " ") + cmdLines = append(cmdLines, cl) + } return cmdLines, nil } diff --git a/libvirt/utils_domain_def_test.go b/libvirt/utils_domain_def_test.go index 7ff57203..3b3061c5 100644 --- a/libvirt/utils_domain_def_test.go +++ b/libvirt/utils_domain_def_test.go @@ -12,8 +12,14 @@ func init() { } func TestSplitKernelCmdLine(t *testing.T) { - e := []map[string]string{{"foo": "bar"}, {"foo": "bar", "key": "val"}} - r, err := splitKernelCmdLine("foo=bar foo=bar key=val") + e := []map[string]string{ + {"foo": "bar"}, + { + "foo": "bar", + "key": "val", + "root": "UUID=aa52d618-a2c4-4aad-aeb7-68d9e3a2c91d"}, + {"_": "nosplash rw"}} + r, err := splitKernelCmdLine("foo=bar foo=bar key=val root=UUID=aa52d618-a2c4-4aad-aeb7-68d9e3a2c91d nosplash rw") if !reflect.DeepEqual(r, e) { t.Fatalf("got='%s' expected='%s'", spew.Sdump(r), spew.Sdump(e)) } @@ -22,17 +28,6 @@ func TestSplitKernelCmdLine(t *testing.T) { } } -func TestSplitKernelInvalidCmdLine(t *testing.T) { - v := "foo=barfoo=bar" - r, err := splitKernelCmdLine(v) - if r != nil { - t.Fatalf("got='%s' expected='%s'", spew.Sdump(r), err) - } - if err == nil { - t.Errorf("Expected error for parsing '%s'", v) - } -} - func TestSplitKernelEmptyCmdLine(t *testing.T) { var e []map[string]string r, err := splitKernelCmdLine("") diff --git a/website/docs/r/domain.html.markdown b/website/docs/r/domain.html.markdown index ff9ab0a3..acc795b0 100644 --- a/website/docs/r/domain.html.markdown +++ b/website/docs/r/domain.html.markdown @@ -85,7 +85,7 @@ resource "libvirt_domain" "domain-suse" { } ``` -* `kernel` - (Optional) The path of the initrd to boot. +* `initrd` - (Optional) The path of the initrd to boot. You can use it in the same way as the kernel. @@ -102,10 +102,15 @@ resource "libvirt_domain" "domain-suse" { cmdline { arg1 = "value1" arg2 = "value2" + "_" = "rw nosplash" } } ``` +Kernel params that don't have a keyword identifier can be specified using the +special `"_"` keyword. Multiple keyword-less params have to be specified using +the same `"_"` keyword, like in the example above. + Also note that the `cmd` block is actually a list of maps, so it is possible to declare several of them by using either the literal list and map syntax as in the following examples: @@ -151,6 +156,10 @@ resource "libvirt_domain" "my_machine" { } ``` +~> **Note well:** `kernel` and `initrd` have to be specified at the same time; `cmdline` + arguments can be specified only when `kernel` and `initrd` have been defined. + Otherwise libvirt will refuse to start the domain. + ### UEFI images Some extra arguments are also provided for using UEFI images: -- cgit v1.2.3