vatesfr / terraform-provider-xenorchestra

Xen Orchestra provider for Terraform
MIT License
152 stars 32 forks source link

XO VM Templates do not work with the xenorchestra_vm resource #39

Closed ddelnano closed 3 years ago

ddelnano commented 4 years ago

I've been having a discussion in Discord with a user that is trying to create a xenorchestra_vm resource using one of the out of the box VM templates as the template attribute. The following code reproduces the problem.

data "xenorchestra_template" "bionic" {
  name_label = "Ubuntu Bionic Beaver 18.04"
}

data "template_file" "testing" {
  template = "${file("${path.module}/puppet_agent_cloud_config.tpl")}"
  vars = {
    hostname = "testing"
  }
}
resource "xenorchestra_cloud_config" "testing_cloud_config" {
  name = "testing"
  template = "${data.template_file.testing.rendered}"
}

resource "xenorchestra_vm" "testing" {
  memory_max = 524288
  cpus = 1
  name_label = "Testing"
  cloud_config = "${xenorchestra_cloud_config.testing_cloud_config.template}"
  template = "${data.xenorchestra_template.bionic.id}"
  network {
    network_id = "${data.xenorchestra_pif.eth0.network}"
  }

  disk {
    sr_id = "${data.xenorchestra_sr.default.id}"
    name_label = "testing label"
    size = 1073741824
  }
}

Applying this code causes the following error

xenorchestra_vm.testing: Creating...
  cloud_config:                  "" => "#cloud-config\n\nhostname: testing\nfqdn: testing.internal.ddelnano.com\n\npackages:\n- make\n- build-essential\n\nwrite_files:\n-   owner: root:root\n    path: /usr/local/bin/puppet-bundle\n    permissions: '0774'\n    content: |\n      #!/bin/bash\n\n      # Wrapper around puppet \"ominbus\" bundle\n      # Example usage:\n      #   run bundle install => puppet-bundle install\n      #   run r10k install   => puppet-bundle exec r10k install\n\n      export GEM_HOME=vendor/gem\n      export GEM_PATH=$GEM_HOME:/opt/puppetlabs/puppet/lib/ruby/gems/2.4.0:$GEM_PATH\n      export PATH=/opt/puppetlabs/puppet/bin:$PATH\n\n      bundle $*\n\nruncmd:\n - sudo /opt/puppetlabs/bin/puppet agent --waitforcert 120 --onetime --no-daemonize --debug --detailed-exitcodes\n"
  core_os:                       "" => "false"
  cpu_cap:                       "" => "0"
  cpu_weight:                    "" => "0"
  cpus:                          "" => "1"
  disk.#:                        "" => "1"
  disk.426847655.name_label:     "" => "testing label"
  disk.426847655.size:           "" => "1073741824"
  disk.426847655.sr_id:          "" => "7f469400-4a2b-5624-cf62-61e522e50ea1"
  memory_max:                    "" => "524288"
  name_label:                    "" => "Testing"
  network.#:                     "" => "1"
  network.3216304881.network_id: "" => "b347f6fd-8f2a-3de2-05b4-312fe9ffae51"
  template:                      "" => "OpaqueRef:11214068-e5e8-4f75-a0f1-5951bfa8c96e"

Error: Error applying plan:

1 error occurred:
        * xenorchestra_vm.testing: 1 error occurred:
        * xenorchestra_vm.testing: jsonrpc2: code -32000 message: unknown error from the peer

Terraform does not automatically rollback in the face of errors.
Instead, your Terraform state file has been partially updated with
any resources that successfully completed. Please address the error
above and apply again to incrementally change your infrastructure.

The user that reported this issue shared the following stack trace which links the problem back to the fact that XO can't find a SR to create the cloud config drive. The issue seems to be related to the fact that the template itself doesn't have any disks with device 0.

vm.create
{
  "CPUs": 2,
  "VIFs": [
    {
      "network": "fc7b56ff-d585-525a-6c87-b1fa5cce05c8"
    }
  ],
  "bootAfterCreate": true,
  "cloudConfig": "#cloud-init\n\nruncmd:\n - [ ls, -l, / ]\n - [ sh, -xc, \"echo $(date) ': hello world!'\" ]\n - [ sh, -c, echo \"=========hello world'=========\" ]\n - ls -l /root\n",
  "coreOs": false,
  "cpuCap": null,
  "cpuWeight": null,
  "existingDisks": {
    "0": {
      "$SR": "d63fdca7-8327-7129-c225-7a880cf39eb1",
      "name_label": "my_image",
      "size": 20000000000
    }
  },
  "memoryMax": 4000000000,
  "name_description": "Description",
  "name_label": "Name",
  "template": "OpaqueRef:e6cf8a42-227a-4310-ab5a-cde364b2c99e"
}
{
  "message": "no object with UUID or opaque ref: undefined",
  "name": "Error",
  "stack": "Error: no object with UUID or opaque ref: undefined
    at Xapi.apply (/opt/xen-orchestra/packages/xen-api/src/index.js:601:11)
    at Xapi.getObject (/opt/xen-orchestra/packages/xo-server/src/xapi/index.js:129:24)
    at Xapi.apply (/opt/xen-orchestra/packages/xo-server/src/xapi/index.js:2369:21)
    at Xapi.createCloudInitConfigDrive (/opt/xen-orchestra/node_modules/golike-defer/src/index.js:57:17)
    at Xapi.createVm (/opt/xen-orchestra/packages/xo-server/src/xapi/mixins/vm.js:262:20)
    at runNextTicks (internal/process/task_queues.js:62:5)
    at processImmediate (internal/timers.js:429:9)
    at Object.<anonymous> (/opt/xen-orchestra/packages/xo-server/src/api/vm.js:158:18)
    at Api.callApiMethod (/opt/xen-orchestra/packages/xo-server/src/xo-mixins/api.js:291:20)"

I need to investigate how these templates are properly used and see how the vm.create rpc call should be updated to handle this case. I don't run into this issue because I have hand made a VM template that works with the provider and does not need an OS iso for its first boot.

olivierlambert commented 4 years ago

VM templates without an existing disk can't use Cloudinit because it means there's no Cloudinit already installed in the VM. That's why we have 2 kind of templates: "diskless" ones, with only some metadata info (BIOS settings, sort of), and templates with existing disks (ie when you turn a VM into a template). Only the latter can be used with Cloudinit, because there's already an OS installed (hopefully with cloudinit inside, but there's no way to know from our perspective).

ddelnano commented 4 years ago

Ah I see. So the terraform provider will need to inspect the template before creating the VM (maybe later on down the line the XO api could provide a different mechanism for dealing with this?).

If the provider needs to create the VM with the "iso template" I'm still not clear on how to use the vm.create rpc call to accomplish that. From some documentation I've read on creating a VM manually with the xenserver cli it seems like some of these concept. It seems like the installation argument might be relevant and then it would require passing in a value to VDIs?

ddelnano commented 3 years ago

Users can now use diskless templates if they want (provided they supply an ISO on creation). This was implemented in #128 and the docs on terraform registry explain how to use this functionality.