diff --git a/libvirt/domain.go b/libvirt/domain.go index f646f3cc0..e13454201 100644 --- a/libvirt/domain.go +++ b/libvirt/domain.go @@ -361,6 +361,18 @@ func setGraphics(d *schema.ResourceData, domainDef *libvirtxml.Domain, arch stri VNC: &libvirtxml.DomainGraphicVNC{}, } domainDef.Devices.Graphics[0].VNC.AutoPort = formatBoolYesNo(autoport) + if autoport == false { + // If autoport is false, the port should be defined + if port, ok := d.GetOk(prefix + ".port"); ok { + domainDef.Devices.Graphics[0].VNC.Port = port.(int) + } else { + // If autoport is set to false, but port is undefined, then set to -1 (auto-allocation) + domainDef.Devices.Graphics[0].VNC.Port = -1 + } + } + if password, ok := d.GetOk(prefix + ".password"); ok { + domainDef.Devices.Graphics[0].VNC.Passwd = password.(string) + } domainDef.Devices.Graphics[0].VNC.Listeners = []libvirtxml.DomainGraphicListener{ listener, } diff --git a/libvirt/resource_libvirt_domain.go b/libvirt/resource_libvirt_domain.go index e71270285..b3003c3ac 100644 --- a/libvirt/resource_libvirt_domain.go +++ b/libvirt/resource_libvirt_domain.go @@ -283,6 +283,14 @@ func resourceLibvirtDomain() *schema.Resource { Default: "127.0.0.1", ForceNew: true, }, + "password": { + Type: schema.TypeString, + Optional: true, + }, + "port": { + Type: schema.TypeInt, + Optional: true, + }, "websocket": { Type: schema.TypeInt, Optional: true, diff --git a/libvirt/resource_libvirt_domain_test.go b/libvirt/resource_libvirt_domain_test.go index 550402a1f..f1e5bebe4 100644 --- a/libvirt/resource_libvirt_domain_test.go +++ b/libvirt/resource_libvirt_domain_test.go @@ -792,6 +792,144 @@ func TestAccLibvirtDomain_Graphics(t *testing.T) { }) } +func TestAccLibvirtDomain_Graphics_VNC(t *testing.T) { + var domain libvirt.Domain + + randomDomainName := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha) + randomVolumeName := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha) + randomPoolName := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha) + randomPoolPath := "/tmp/terraform-provider-libvirt-pool-" + randomPoolName + config := fmt.Sprintf(` + resource "libvirt_pool" "%s" { + name = "%s" + type = "dir" + path = "%s" + } + + resource "libvirt_volume" "%s" { + name = "%s" + pool = "${libvirt_pool.%s.name}" + } + + resource "libvirt_domain" "%s" { + name = "%s" + graphics { + type = "vnc" + autoport = "true" + listen_type = "none" + } + }`, randomPoolName, randomPoolName, randomPoolPath, randomVolumeName, randomVolumeName, randomPoolName, randomDomainName, randomDomainName) + + configPassword := fmt.Sprintf(` + resource "libvirt_pool" "%s" { + name = "%s" + type = "dir" + path = "%s" + } + + resource "libvirt_volume" "%s" { + name = "%s" + pool = "${libvirt_pool.%s.name}" + } + + resource "libvirt_domain" "%s" { + name = "%s" + graphics { + type = "vnc" + autoport = "true" + listen_type = "address" + password = "mypasswd" + } + }`, randomPoolName, randomPoolName, randomPoolPath, randomVolumeName, randomVolumeName, randomPoolName, randomDomainName, randomDomainName) + + + configStaticPort := fmt.Sprintf(` + resource "libvirt_pool" "%s" { + name = "%s" + type = "dir" + path = "%s" + } + + resource "libvirt_volume" "%s" { + name = "%s" + pool = "${libvirt_pool.%s.name}" + } + + resource "libvirt_domain" "%s" { + name = "%s" + graphics { + type = "vnc" + autoport = "false" + listen_type = "address" + port = 12345 + } + }`, randomPoolName, randomPoolName, randomPoolPath, randomVolumeName, randomVolumeName, randomPoolName, randomDomainName, randomDomainName) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckLibvirtDomainDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testAccCheckLibvirtDomainExists("libvirt_domain."+randomDomainName, &domain), + resource.TestCheckResourceAttr( + "libvirt_domain."+randomDomainName, "graphics.0.type", "vnc"), + resource.TestCheckResourceAttr( + "libvirt_domain."+randomDomainName, "graphics.0.autoport", "true"), + resource.TestCheckResourceAttr( + "libvirt_domain."+randomDomainName, "graphics.0.listen_type", "none"), + ), + }, + }, + }) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckLibvirtDomainDestroy, + Steps: []resource.TestStep{ + { + Config: configPassword, + Check: resource.ComposeTestCheckFunc( + testAccCheckLibvirtDomainExists("libvirt_domain."+randomDomainName, &domain), + resource.TestCheckResourceAttr( + "libvirt_domain."+randomDomainName, "graphics.0.type", "vnc"), + resource.TestCheckResourceAttr( + "libvirt_domain."+randomDomainName, "graphics.0.autoport", "true"), + resource.TestCheckResourceAttr( + "libvirt_domain."+randomDomainName, "graphics.0.listen_type", "address"), + resource.TestCheckResourceAttr( + "libvirt_domain."+randomDomainName, "graphics.0.password", "mypasswd"), + ), + }, + }, + }) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckLibvirtDomainDestroy, + Steps: []resource.TestStep{ + { + Config: configStaticPort, + Check: resource.ComposeTestCheckFunc( + testAccCheckLibvirtDomainExists("libvirt_domain."+randomDomainName, &domain), + resource.TestCheckResourceAttr( + "libvirt_domain."+randomDomainName, "graphics.0.type", "vnc"), + resource.TestCheckResourceAttr( + "libvirt_domain."+randomDomainName, "graphics.0.autoport", "false"), + resource.TestCheckResourceAttr( + "libvirt_domain."+randomDomainName, "graphics.0.listen_type", "address"), + resource.TestCheckResourceAttr( + "libvirt_domain."+randomDomainName, "graphics.0.port", "12345"), + ), + }, + }, + }) +} + func TestAccLibvirtDomain_IgnitionObject(t *testing.T) { var domain libvirt.Domain var volume libvirt.StorageVol diff --git a/website/docs/r/domain.html.markdown b/website/docs/r/domain.html.markdown index 63a0b05d9..b43d13e91 100644 --- a/website/docs/r/domain.html.markdown +++ b/website/docs/r/domain.html.markdown @@ -408,6 +408,8 @@ The block supports: * `listen_type` - "listen type", defaults to "none" * `listen_address` - (Optional) IP Address where the VNC listener should be started if `listen_type` is set to `address`. Defaults to 127.0.0.1 +* `password` - (Optional) Password to set for VNC Access +* `port` - (Optional) Port on which to run VNC when autoport is set to false * `websocket` - (Optional) Port to listen on for VNC WebSocket functionality (-1 meaning auto-allocation) On occasion we have found it necessary to set a `type` of `vnc` and a @@ -428,6 +430,21 @@ resource "libvirt_domain" "my_machine" { } ``` +VNC can be configured with an optional static port or password as follows: + +```hcl +resource "libvirt_domain" "my_machine" { + ... + graphics { + type = "vnc" + listen_type = "address" + autoport = false + port = 12345 + password = "mypasswd" + } +} +``` + The video card type can be changed from libvirt default `cirrus` to `vga` or others as described in [Video Card Elements](https://libvirt.org/formatdomain.html#elementsVideo)