Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for kernel/initrd/cmdline options #242

Merged
merged 14 commits into from Nov 27, 2017
Merged

Conversation

dmacvicar
Copy link
Owner

@dmacvicar dmacvicar commented Nov 17, 2017

This allows you to specify kernel, initrd, cmdline, which combined with volumes open the way for booting directly from a repository.

Originally I planned to implement AutoYaST and booting from repos in a similar way to cloud-init and ignition, replicating some code present in virt-install, and doing all the ISO creation, etc. I decided to start laying a foundation that at the beginning requires more work on the .tf file, but it reuses most of the existing infrastructure, and then start making it easier from there (eg. in the future may be allow to create an ISO to be uploaded, from local terraform files).

provider "libvirt" {
  uri = "qemu:///system"
}

// blank 10GB image for net install.
resource "libvirt_volume" "suse-qcow2" {
  name = "suse-qcow2"
  pool = "default"
  format = "qcow2"
  size = 10000000000
}

resource "libvirt_volume" "kernel" {
  source = "http://download.opensuse.org/tumbleweed/repo/oss/boot/x86_64/loader/linux"
  name = "kernel"
  pool = "default"
  format = "raw"
}

resource "libvirt_volume" "initrd" {
  source = "http://download.opensuse.org/tumbleweed/repo/oss/boot/x86_64/loader/initrd"
  name = "initrd"
  pool = "default"
  format = "raw"
}

resource "libvirt_domain" "domain-suse-qcow2" {
  name = "suse"
  memory = "1024"
  vcpu = 1

  network_interface {
       network_name = "default"
       mac = "52:54:00:b2:2f:86"
  }

  kernel = "${libvirt_volume.kernel.id}"
  initrd = "${libvirt_volume.initrd.id}"

  cmdline {
      somekernelopt = "somevalue"
  }

  disk {
      volume_id = "${libvirt_volume.suse-qcow2.id}"
  }

  graphics {
    type = "vnc"
    listen_type = "address"
  }
}

b := newDefDisk()
b := newDefDisk(0)
prettyB := spew.Sdump(b)
t.Logf("Parsed default disk:\n%s", prettyB)
Copy link
Collaborator

@MalloZup MalloZup Nov 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would like to propose that we don't print to much log details.

It becomes really difficult to have 3/5 tests that are printing so much info, and then to filter what is passing and what is not, if a test is failing.

Imho we should just print debug info when a test is failing for debugging purpose.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did I added that, or did it come from the rebase?

Copy link
Collaborator

@MalloZup MalloZup Nov 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dunno 🙄 🤣 . we removed it from the codebase, but in this case donno if it comes from your addition or maybe a missing conflict

@dmacvicar dmacvicar changed the title Add support for kernel/initrd/cmdline options WIP: Add support for kernel/initrd/cmdline options Nov 17, 2017
}

cmdlinesCount := d.Get("cmdline.#").(int)
cmdlineArgs := make([]string, 0)
Copy link
Collaborator

@MalloZup MalloZup Nov 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dmacvicar
Copy link
Owner Author

dmacvicar commented Nov 20, 2017

I have reviewed all relevant observations and tests are passing now (included tests with a real kernel/initrd fixture). Still pending to read the values back.

t.Errorf("Expected error for parsing '%s'", v)
}
func TestSplitKernelInvalidCmdLine(t *testing.T) {
v := "foo=barfoo=bar"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick can we use more expressive name then v, e, r? i know that is testsdata, but still in sake for mantainabilty

Copy link
Owner Author

@dmacvicar dmacvicar Nov 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, but golang uses t for tests. I am following the same convention/thinking ("expected", "result", "value"). Not hard to guess. The function is small, you will not get lost with it's meaning.

t.Error(err)
}
e := []map[string]string{{"foo": "bar"}, {"foo": "bar", "key": "val"}}
r, err := splitKernelCmdLine("foo=bar foo=bar key=val")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comments as above

@dmacvicar dmacvicar changed the title WIP: Add support for kernel/initrd/cmdline options Add support for kernel/initrd/cmdline options Nov 23, 2017
@dmacvicar
Copy link
Owner Author

dmacvicar commented Nov 23, 2017

Everything is implemented now. I think this should be ready to be merged.

For the reviewer: please have a look how I implemented cmdline, as a list of maps, to allow duplicate keys (kernel supports them). I think this way it is simple to define simple command line while still allowing duplicate keys. You need to know to separate them in that case, but I can't think of a simpler and ergonomic way.

@@ -170,6 +171,27 @@ func resourceLibvirtDomain() *schema.Resource {
Default: "/usr/bin/qemu-system-x86_64",
Optional: true,
},
"kernel": &schema.Schema{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick we can remove this &schema.Schema

Copy link
Collaborator

@MalloZup MalloZup left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm from my pov. a part from the small nitpick comment

@@ -267,6 +289,25 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error
}
}

if kernel, ok := d.GetOk("kernel"); ok {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could wrap this new code in a function. because the DomainCreate is a really big function.


You can use it in the same way as the kernel.

* `cmdlin` - (Optional) Arguments to the kernel
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo? cmdline maybe?


cmdlinesCount := d.Get("cmdline.#").(int)
var cmdlineArgs []string
for i := 0; i < cmdlinesCount; i++ {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just do

for i := 0; i < d.Get("cmdline.#").(int); i++ {

and get rid of line 299.

for i := 0; i < cmdlinesCount; i++ {
cmdlineKey := fmt.Sprintf("cmdline.%d", i)
cmdlineMap := d.Get(cmdlineKey).(map[string]interface{})
for k, v := range cmdlineMap {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could also shorten this if you wanted to. The variables are only used once anyway.

for k, v := range d.Get(fmt.Sprintf("cmdline.%d", i)).(map[string]interface{}) {

IMHO the code is still pretty clear.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good


* `cmdlin` - (Optional) Arguments to the kernel

resource "libvirt_domain" "domain-suse" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing "```hcl"

@@ -73,7 +166,7 @@ read-only.
domain. However, `libvirt` can manage this automatically (and this is the recommended solution)
if a mapping for the firmware to a _variables file_ exists in `/etc/libvirt/qemu.conf:nvram`.
In that case, `libvirt` will copy that variables file into a file specific for this domain.
* `template` - (Optional) path to the file used to override variables from the master NVRAM
s * `template` - (Optional) path to the file used to override variables from the master NVRAM
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This 's' does not belong here.

@dmacvicar dmacvicar merged commit b7894a8 into master Nov 27, 2017
@dmacvicar dmacvicar deleted the kernel_initrd branch November 27, 2017 07:29
@MalloZup
Copy link
Collaborator

MalloZup commented Oct 2, 2018

@dmacvicar https://serverfault.com/questions/740694/how-to-set-kvm-kernel-boot-only-once

actually i experimented this, since we are using the direct kernel boot, we end up in a infinite loop.

We might need some research how to do it properly without the loop for a network installation, e.g find out something similar as virt-install does in this cases.

@martux69
Copy link

Are there any news on this? I just stay at this problem with the infinite loop, when I try to create a vm with k3os. My plan is this:

resource "libvirt_volume" "kernel" {
  source = "https://github.com/rancher/k3os/releases/download/v0.21.5-k3s2r1/k3os-vmlinuz-amd64"
  name   = "kernel"
  pool   = "default"
  format = "raw"
}

resource "libvirt_volume" "initrd" {
  source = "https://github.com/rancher/k3os/releases/download/v0.21.5-k3s2r1/k3os-initrd-amd64"
  name   = "initrd"
  pool   = "default"
  format = "raw"
}

resource "libvirt_volume" "kzero-qcow2" {
  name = "k-zero.qcow2"
  pool = "default"
  format = "qcow2"
  size = 10000000000
}

resource "libvirt_domain" "k-zero" {
  name   = "k-zero"
  memory = "1024"
  vcpu   = 1

  kernel = "${libvirt_volume.kernel.id}"
  initrd = "${libvirt_volume.initrd.id}"

  cmdline = [
   {
    "k3os.mode" = "install"
    "k3os.install.silent" = "true"
    "k3os.install.device" = "dev/vda"
    "k3os.install.config_url" = "https://example.de/k3os/cloud-init.yaml"
    "k3os.install.iso_url" = "https://github.com/rancher/k3os/releases/download/v0.21.5-k3s2r1/k3os-amd64.iso"
    "k3os.install.no_format" = "false"
   }
  ]

  network_interface {
    network_name = "default" # List networks with virsh net-list
  }

  disk {
    volume_id = "${libvirt_volume.kzero-qcow2.id}"
  }

  console {
    type = "pty"
    target_type = "serial"
    target_port = "0"
  }

  graphics {
    type = "spice"
    listen_type = "address"
    autoport = true
  }
}

Any help is welcome :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants