diff --git a/data/data/rhcos-ppc64le.json b/data/data/rhcos-ppc64le.json new file mode 100644 index 00000000000..3066939399e --- /dev/null +++ b/data/data/rhcos-ppc64le.json @@ -0,0 +1,50 @@ +{ + "baseURI": "https://releases-art-rhcos.svc.ci.openshift.org/art/storage/releases/rhcos-4.5-ppc64le/45.81.202005020554-0/ppc64le/", + "buildid": "45.81.202005020554-0", + "images": { + "initramfs": { + "path": "rhcos-45.81.202005020554-0-installer-initramfs.ppc64le.img", + "sha256": "bd6cdddbeb3b4f2b83c0e732904c59d44158ba9483d9c64f48ce5bd242d1d575" + }, + "iso": { + "path": "rhcos-45.81.202005020554-0-installer.ppc64le.iso", + "sha256": "ccdc994528a6fab5d287be90f7cf8314a0626aa0af5d0a7248cd72fe458b2481" + }, + "kernel": { + "path": "rhcos-45.81.202005020554-0-installer-kernel-ppc64le", + "sha256": "7053afc2194c998be0ec06b041d7fecc5056390a8a423981a917c5bd1b863ab1" + }, + "metal": { + "path": "rhcos-45.81.202005020554-0-metal.ppc64le.raw.gz", + "sha256": "4ec68661e9f373b3132ba853a710662d53726fa4e92fbba4aec8774dc74eb127", + "size": 869348949, + "uncompressed-sha256": "cc87c1d1bbaf2228b47270cafdff39d545d6b53515fb53d9f4f78dd2c581c8fb", + "uncompressed-size": 3913285632 + }, + "openstack": { + "path": "rhcos-45.81.202005020554-0-openstack.ppc64le.qcow2.gz", + "sha256": "df7597999ea65a09761a8bce6b51df2a9c1e9ad75b04769446ba6a3e146214d7", + "size": 868110506, + "uncompressed-sha256": "15a535c3f7f9cd8578d7f229176b334c912bf688d3d26c034aa17501fdfd64ec", + "uncompressed-size": 2514747392 + }, + "ostree": { + "path": "rhcos-45.81.202005020554-0-ostree.ppc64le.tar", + "sha256": "95065abe4d183654b55422610e9ef8479ea20dabea060d24f37f471323d429ad", + "size": 797818880 + }, + "qemu": { + "path": "rhcos-45.81.202005020554-0-qemu.ppc64le.qcow2.gz", + "sha256": "93f75e4ec3150cd26ba695a65c570ab24778c378f0bced5e66fce7454562fb87", + "size": 869589011, + "uncompressed-sha256": "44ec37eea65d3d91e74d8ec10e560cb774629c4f1908e0c098d439586a9bc79a", + "uncompressed-size": 2563309568 + } + }, + "oscontainer": { + "digest": "sha256:e2594573932c6b98fd46e0d6abad6ad99d2067619e7401c98af034b7a9e0252e", + "image": "quay.io/openshift-release-dev/ocp-v4.0-art-dev" + }, + "ostree-commit": "522dc146f92258f311dcbb5bfea5816a199cb4175c3f4f7eb6550981c2a924b1", + "ostree-version": "45.81.202005020554-0" +} \ No newline at end of file diff --git a/data/data/rhcos-s390x.json b/data/data/rhcos-s390x.json new file mode 100644 index 00000000000..5f46ddf1bb2 --- /dev/null +++ b/data/data/rhcos-s390x.json @@ -0,0 +1,57 @@ +{ + "baseURI": "https://releases-art-rhcos.svc.ci.openshift.org/art/storage/releases/rhcos-4.5-s390x/45.81.202005020555-0/s390x/", + "buildid": "45.81.202005020555-0", + "images": { + "dasd": { + "path": "rhcos-45.81.202005020555-0-dasd.s390x.raw.gz", + "sha256": "69b972efb6c26fadb4e65d3186361b012894afe33412b338de796a27b7db20ee", + "size": 797188604, + "uncompressed-sha256": "ca83c51de424fa1803117b2759b65c6e92316dd5acaa6102fac79ec834b48208", + "uncompressed-size": 3568304128 + }, + "initramfs": { + "path": "rhcos-45.81.202005020555-0-installer-initramfs.s390x.img", + "sha256": "d9cce833b56ad3444892d99a9d5386dae3c1fec91fdd35c3d2c1b55a520b4a60" + }, + "iso": { + "path": "rhcos-45.81.202005020555-0-installer.s390x.iso", + "sha256": "1f2103b9ec3ac42de396ceb02c0f31e4cfd8d1e502df09f2c6a5b92d99b2a4f3" + }, + "kernel": { + "path": "rhcos-45.81.202005020555-0-installer-kernel-s390x", + "sha256": "08906e6d627688378be7c26c614ef39430f3b837a8fa9fda698d361116d65abb" + }, + "metal": { + "path": "rhcos-45.81.202005020555-0-metal.s390x.raw.gz", + "sha256": "0ebbd895d2b56cb3fbf17e6779e29d19ec13b0c2fb2c4757b90370110db5c99e", + "size": 797100175, + "uncompressed-sha256": "83e3e251307f3cb45350a64fbea09465174cffdfb6856b70779a29b3a80d5646", + "uncompressed-size": 3568304128 + }, + "openstack": { + "path": "rhcos-45.81.202005020555-0-openstack.s390x.qcow2.gz", + "sha256": "f0b7237cbcae8cc4fee3503f158e03cd7e2e55ce557c6ab6313365f8da6f3242", + "size": 795947849, + "uncompressed-sha256": "a1aa568e92a1f28b49ad8fc394f7154687e8c54ecbfa45deca739146fadd0f6b", + "uncompressed-size": 2224816128 + }, + "ostree": { + "path": "rhcos-45.81.202005020555-0-ostree.s390x.tar", + "sha256": "3102b3d526430cc73da11494765029bf9b54fc8151b5d14cdb00df2eddb6b5f9", + "size": 745584640 + }, + "qemu": { + "path": "rhcos-45.81.202005020555-0-qemu.s390x.qcow2.gz", + "sha256": "d6e523879c7e10e0547dffdd06c12c7748c6b598d3bef43ab2a46c04217aae41", + "size": 797517829, + "uncompressed-sha256": "9e4f4a9b46ca90cb4da2b2611592ec62ade470c812e5545642ffea2bd4308315", + "uncompressed-size": 2272002048 + } + }, + "oscontainer": { + "digest": "sha256:0a05c9f97e6f08383078329634ff29dbf32700547d42e601d6156e7af0f10039", + "image": "quay.io/openshift-release-dev/ocp-v4.0-art-dev" + }, + "ostree-commit": "ae47674eca7dffb4d179b9f61589ed5c05566d9a20d4345715c3195938b693b7", + "ostree-version": "45.81.202005020555-0" +} \ No newline at end of file diff --git a/go.mod b/go.mod index c89adeadb21..7187c25b47e 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/coreos/etcd v3.3.18+incompatible // indirect github.com/coreos/go-systemd v0.0.0 // indirect github.com/coreos/ignition v0.35.0 - github.com/dmacvicar/terraform-provider-libvirt v0.6.1-0.20191216113711-1a01934a7d20 + github.com/dmacvicar/terraform-provider-libvirt v0.6.2 github.com/frankban/quicktest v1.7.2 // indirect github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 github.com/go-logr/zapr v0.1.1 // indirect diff --git a/go.sum b/go.sum index bd1465c6d89..a67593287eb 100644 --- a/go.sum +++ b/go.sum @@ -431,6 +431,8 @@ github.com/djherbis/buffer v1.0.0/go.mod h1:VwN8VdFkMY0DCALdY8o00d3IZ6Amz/UNVMWc github.com/djherbis/nio v2.0.3+incompatible/go.mod h1:v74owXPROGWsr1y28T13rlXf5Hn/bWJ1bbX8M+BqyPo= github.com/dmacvicar/terraform-provider-libvirt v0.6.1-0.20191216113711-1a01934a7d20 h1:Img6/bWq48uGHkmG4Eq2pf9HTBx6dQ9BcfRE1SVaU88= github.com/dmacvicar/terraform-provider-libvirt v0.6.1-0.20191216113711-1a01934a7d20/go.mod h1:rUzijwUJHukJWZKi6PJXo9aJqGLXeUX6NDEy6O0UATg= +github.com/dmacvicar/terraform-provider-libvirt v0.6.2 h1:jXhlKg24SNsG3EYWq45BbCocO5kNlTEOpZgpYLVhPYw= +github.com/dmacvicar/terraform-provider-libvirt v0.6.2/go.mod h1:rUzijwUJHukJWZKi6PJXo9aJqGLXeUX6NDEy6O0UATg= github.com/dnaeon/go-vcr v0.0.0-20180920040454-5637cf3d8a31/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= @@ -1619,6 +1621,7 @@ github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsO github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= github.com/mattn/go-zglob v0.0.0-20171230104132-4959821b4817/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= github.com/mattn/go-zglob v0.0.0-20180803001819-2ea3427bfa53/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= +github.com/mattn/goveralls v0.0.2 h1:7eJB6EqsPhRVxvwEXGnqdO2sJI0PTsrWoTMXEk9/OQc= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.0/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= diff --git a/hack/update-rhcos-bootimage.py b/hack/update-rhcos-bootimage.py index 24237dfe55f..36eddf0a1a0 100755 --- a/hack/update-rhcos-bootimage.py +++ b/hack/update-rhcos-bootimage.py @@ -10,7 +10,7 @@ parser = argparse.ArgumentParser() parser.add_argument("meta", action='store') -parser.add_argument("arch", action='store', choices=['amd64']) +parser.add_argument("arch", action='store', choices=['amd64', 's390x', 'ppc64le']) args = parser.parse_args() metadata_dir = os.path.join(os.path.dirname(sys.argv[0]), "../data/data") @@ -25,13 +25,15 @@ for k in ['images', 'buildid', 'oscontainer', 'ostree-commit', 'ostree-version', 'azure', 'gcp']: - newmeta[k] = meta[k] -newmeta['amis'] = { - entry['name']: { - 'hvm': entry['hvm'], + if meta.get(k): + newmeta[k] = meta[k] +if meta.get(k): + newmeta['amis'] = { + entry['name']: { + 'hvm': entry['hvm'], + } + for entry in meta['amis'] } - for entry in meta['amis'] -} newmeta['baseURI'] = urllib.parse.urljoin(args.meta, '.') with open(os.path.join(metadata_dir, 'rhcos-{}.json'.format(args.arch)), 'w') as f: diff --git a/pkg/tfvars/libvirt/libvirt.go b/pkg/tfvars/libvirt/libvirt.go index 73c0af2afe6..faa5d55dee2 100644 --- a/pkg/tfvars/libvirt/libvirt.go +++ b/pkg/tfvars/libvirt/libvirt.go @@ -52,9 +52,7 @@ func TFVars(masterConfig *v1beta1.LibvirtMachineProviderConfig, osImage string, MasterVcpu: strconv.Itoa(masterConfig.DomainVcpu), } - // Power PC systems typically require more memory because the page size is 64K and not the default 4K - // TODO: need to make ppc64le a supported architecture - https://bugzilla.redhat.com/show_bug.cgi?id=1821392 - if architecture == "ppc64le" { + if architecture == types.ArchitecturePPC64LE { cfg.BootstrapMemory = 5120 } diff --git a/pkg/types/machinepools.go b/pkg/types/machinepools.go index d42c083279a..9f4cec3faba 100644 --- a/pkg/types/machinepools.go +++ b/pkg/types/machinepools.go @@ -27,6 +27,10 @@ type Architecture string const ( // ArchitectureAMD64 indicates AMD64 (x86_64). ArchitectureAMD64 = "amd64" + // ArchitectureS390X indicates s390x (IBM System Z). + ArchitectureS390X = "s390x" + // ArchitecturePPC64LE indicates ppc64 little endian (Power PC) + ArchitecturePPC64LE = "ppc64le" ) // MachinePool is a pool of machines to be installed. diff --git a/pkg/types/validation/installconfig_test.go b/pkg/types/validation/installconfig_test.go index 1465d31c3f3..8e7d14f756b 100644 --- a/pkg/types/validation/installconfig_test.go +++ b/pkg/types/validation/installconfig_test.go @@ -925,7 +925,24 @@ func TestValidateInstallConfig(t *testing.T) { return c }(), }, - // TODO(crawford): add a test to validate that homogeneous clusters are enforced once an additional architecture is added + { + name: "cluster is not heteregenous", + installConfig: func() *types.InstallConfig { + c := validInstallConfig() + c.Compute[0].Architecture = types.ArchitectureS390X + return c + }(), + expectedError: `^compute\[0\].architecture: Invalid value: "s390x": heteregeneous multi-arch is not supported; compute pool architecture must match control plane$`, + }, + { + name: "cluster is not heteregenous", + installConfig: func() *types.InstallConfig { + c := validInstallConfig() + c.Compute[0].Architecture = types.ArchitecturePPC64LE + return c + }(), + expectedError: `^compute\[0\].architecture: Invalid value: "ppc64le": heteregeneous multi-arch is not supported; compute pool architecture must match control plane$`, + }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { diff --git a/pkg/types/validation/machinepools.go b/pkg/types/validation/machinepools.go index 6c9ed452458..7be7c9d0af6 100644 --- a/pkg/types/validation/machinepools.go +++ b/pkg/types/validation/machinepools.go @@ -33,7 +33,9 @@ var ( }() validArchitectures = map[types.Architecture]bool{ - types.ArchitectureAMD64: true, + types.ArchitectureAMD64: true, + types.ArchitectureS390X: true, + types.ArchitecturePPC64LE: true, } validArchitectureValues = func() []string { diff --git a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/coreos_ignition_def.go b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/coreos_ignition_def.go index b8154d14357..87ab3994670 100644 --- a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/coreos_ignition_def.go +++ b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/coreos_ignition_def.go @@ -8,8 +8,6 @@ import ( "io/ioutil" "log" "os" - "os/exec" - "path/filepath" "strings" libvirt "github.com/libvirt/libvirt-go" @@ -52,55 +50,17 @@ func (ign *defIgnition) CreateAndUpload(client *Client) (string, error) { volumeDef := newDefVolume() volumeDef.Name = ign.Name - tmpDir, err := ioutil.TempDir("", "ignition") + ignFile, err := ign.createFile() if err != nil { - return "", fmt.Errorf("Failed to create Ignition directory: %v", err) + return "", err } defer func() { - if err = os.RemoveAll(tmpDir); err != nil { - log.Printf("Error while removing Ignition directory: %v", err) + if err = os.Remove(ignFile); err != nil { + log.Printf("Error while removing tmp Ignition file: %v", err) } }() - ignPath, err := ign.createFile(tmpDir) - if err != nil { - return "", err - } - - arch, err := getHostArchitecture(client.libvirt) - if err != nil { - return "", fmt.Errorf("Error retrieving host architecture: %s", err) - } - - var userdataPath string - switch arch { - case "i686", "x86_64", "aarch64": - userdataPath = ignPath - case "s390", "s390x": - configDrivePath := filepath.Join(tmpDir, "config.iso") - cmd := exec.Command( - "mkisofs", - "-output", - configDrivePath, - "-volid", - "config-2", - "-root", - "openstack/latest", - "-joliet", - "-rock", - ignPath) - - log.Printf("Executing command: %+v", cmd) - if err = cmd.Run(); err != nil { - return "", fmt.Errorf("Failed to create Config Drive ISO image: %v", err) - } - - userdataPath = configDrivePath - default: - return "", fmt.Errorf("Ignition not supported on %q", arch) - } - - img, err := newImage(userdataPath) + img, err := newImage(ignFile) if err != nil { return "", err } @@ -156,12 +116,12 @@ func getIgnitionVolumeKeyFromTerraformID(id string) (string, error) { } // Dumps the Ignition object - either generated by Terraform or supplied as a file - -// to a userdata Ignition file in the provided directory -func (ign *defIgnition) createFile(dir string) (string, error) { +// to a temporary ignition file +func (ign *defIgnition) createFile() (string, error) { log.Print("Creating Ignition temporary file") - tempFile, err := os.Create(filepath.Join(dir, "user_data")) + tempFile, err := ioutil.TempFile("", ign.Name) if err != nil { - return "", fmt.Errorf("Error creating userdata file: %v", err) + return "", fmt.Errorf("Error creating tmp file: %v", err) } defer tempFile.Close() diff --git a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/domain.go b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/domain.go index e94070cfc7b..cb309d0d7a1 100644 --- a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/domain.go +++ b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/domain.go @@ -198,26 +198,14 @@ func domainGetIfacesInfo(domain libvirt.Domain, rd *schema.ResourceData) ([]libv return interfaces, nil } -func newDiskForCloudInit(virConn *libvirt.Connect, volumeKey string, arch string) (libvirtxml.DomainDisk, error) { - var target *libvirtxml.DomainDiskTarget - switch arch { - case "s390", "s390x": - target = &libvirtxml.DomainDiskTarget{ - // s390 platform doesn't support IDE controllers - Dev: "vdb", - Bus: "scsi", - } - default: - target = &libvirtxml.DomainDiskTarget{ +func newDiskForCloudInit(virConn *libvirt.Connect, volumeKey string) (libvirtxml.DomainDisk, error) { + disk := libvirtxml.DomainDisk{ + Device: "cdrom", + Target: &libvirtxml.DomainDiskTarget{ // Last device letter possible with a single IDE controller on i440FX Dev: "hdd", Bus: "ide", - } - } - - disk := libvirtxml.DomainDisk{ - Device: "cdrom", - Target: target, + }, Driver: &libvirtxml.DomainDiskDriver{ Name: "qemu", Type: "raw", @@ -269,18 +257,32 @@ func setCoreOSIgnition(d *schema.ResourceData, domainDef *libvirtxml.Domain, vir }, } } - case "s390", "s390x": - // System Z does not support any of the same pass-through - // mechanisms as Ignition. As a temporary workaround, the OpenStack - // Config Drive can be used instead. The Ignition volume already - // contains a Config Drive at this point. - - disk, err := newDiskForCloudInit(virConn, ignitionKey, arch) - if err != nil { - return err + case "s390", "s390x", "ppc64", "ppc64le": + // System Z and PowerPC do not support the Firmware Configuration + // device. After a discussion about the best way to support a similar + // method for qemu in https://github.com/coreos/ignition/issues/928, + // decided on creating a virtio-blk device with a serial of ignition + // which contains the ignition config and have ignition support for + // reading from the device which landed in https://github.com/coreos/ignition/pull/936 + igndisk := libvirtxml.DomainDisk{ + Device: "disk", + Source: &libvirtxml.DomainDiskSource{ + File: &libvirtxml.DomainDiskSourceFile{ + File: ignitionKey, + }, + }, + Target: &libvirtxml.DomainDiskTarget{ + Dev: "vdb", + Bus: "virtio", + }, + Driver: &libvirtxml.DomainDiskDriver{ + Name: "qemu", + Type: "raw", + }, + ReadOnly: &libvirtxml.DomainDiskReadOnly{}, + Serial: "ignition", } - - domainDef.Devices.Disks = append(domainDef.Devices.Disks, disk) + domainDef.Devices.Disks = append(domainDef.Devices.Disks, igndisk) default: return fmt.Errorf("Ignition not supported on %q", arch) } @@ -303,7 +305,8 @@ func setVideo(d *schema.ResourceData, domainDef *libvirtxml.Domain) error { } func setGraphics(d *schema.ResourceData, domainDef *libvirtxml.Domain, arch string) error { - if arch == "s390x" || arch == "ppc64" { + // For s390x, ppc64 and ppc64le spice is not supported + if arch == "s390x" || strings.HasPrefix(arch, "ppc64") { domainDef.Devices.Graphics = nil return nil } @@ -654,13 +657,13 @@ func setFilesystems(d *schema.ResourceData, domainDef *libvirtxml.Domain) error return nil } -func setCloudinit(d *schema.ResourceData, domainDef *libvirtxml.Domain, virConn *libvirt.Connect, arch string) error { +func setCloudinit(d *schema.ResourceData, domainDef *libvirtxml.Domain, virConn *libvirt.Connect) error { if cloudinit, ok := d.GetOk("cloudinit"); ok { cloudinitID, err := getCloudInitVolumeKeyFromTerraformID(cloudinit.(string)) if err != nil { return err } - disk, err := newDiskForCloudInit(virConn, cloudinitID, arch) + disk, err := newDiskForCloudInit(virConn, cloudinitID) if err != nil { return err } @@ -705,23 +708,58 @@ func setNetworkInterfaces(d *schema.ResourceData, domainDef *libvirtxml.Domain, } // connect to the interface to the network... first, look for the network - if n, ok := d.GetOk(prefix + ".network_name"); ok { - // when using a "network_name" we do not try to do anything: we just - // connect to that network - netIface.Source = &libvirtxml.DomainInterfaceSource{ - Network: &libvirtxml.DomainInterfaceSourceNetwork{ - Network: n.(string), - }, + var network *libvirt.Network + var err error + + if networkName, ok := d.GetOk(prefix + ".network_name"); ok { + network, err = virConn.LookupNetworkByName(networkName.(string)) + if err != nil { + return fmt.Errorf("Can't retrieve network '%s'", networkName.(string)) } + defer network.Free() + } else if networkUUID, ok := d.GetOk(prefix + ".network_id"); ok { // when using a "network_id" we are referring to a "network resource" // we have defined somewhere else... - network, err := virConn.LookupNetworkByUUIDString(networkUUID.(string)) + network, err = virConn.LookupNetworkByUUIDString(networkUUID.(string)) if err != nil { return fmt.Errorf("Can't retrieve network ID %s", networkUUID) } defer network.Free() + } else if bridgeNameI, ok := d.GetOk(prefix + ".bridge"); ok { + netIface.Source = &libvirtxml.DomainInterfaceSource{ + Bridge: &libvirtxml.DomainInterfaceSourceBridge{ + Bridge: bridgeNameI.(string), + }, + } + } else if devI, ok := d.GetOk(prefix + ".vepa"); ok { + netIface.Source = &libvirtxml.DomainInterfaceSource{ + Direct: &libvirtxml.DomainInterfaceSourceDirect{ + Dev: devI.(string), + Mode: "vepa", + }, + } + } else if devI, ok := d.GetOk(prefix + ".macvtap"); ok { + netIface.Source = &libvirtxml.DomainInterfaceSource{ + Direct: &libvirtxml.DomainInterfaceSourceDirect{ + Dev: devI.(string), + Mode: "bridge", + }, + } + } else if devI, ok := d.GetOk(prefix + ".passthrough"); ok { + netIface.Source = &libvirtxml.DomainInterfaceSource{ + Direct: &libvirtxml.DomainInterfaceSourceDirect{ + Dev: devI.(string), + Mode: "passthrough", + }, + } + } else { + // no network has been specified: we are on our own + } + + // if we got a network + if network != nil { networkName, err := network.GetName() if err != nil { return fmt.Errorf("Error retrieving network name: %s", err) @@ -762,10 +800,13 @@ func setNetworkInterfaces(d *schema.ResourceData, domainDef *libvirtxml.Domain, // have a valid lease and then read the IP we have been assigned, so we can // do the mapping log.Printf("[DEBUG] Do not have an IP for '%s' yet: will wait until DHCP provides one...", hostname) + if err != nil { + return err + } partialNetIfaces[strings.ToUpper(mac)] = &pendingMapping{ - mac: strings.ToUpper(mac), - hostname: hostname, - network: network, + mac: strings.ToUpper(mac), + hostname: hostname, + networkName: networkName, } } } @@ -776,35 +817,6 @@ func setNetworkInterfaces(d *schema.ResourceData, domainDef *libvirtxml.Domain, Network: networkName, }, } - } else if bridgeNameI, ok := d.GetOk(prefix + ".bridge"); ok { - netIface.Source = &libvirtxml.DomainInterfaceSource{ - Bridge: &libvirtxml.DomainInterfaceSourceBridge{ - Bridge: bridgeNameI.(string), - }, - } - } else if devI, ok := d.GetOk(prefix + ".vepa"); ok { - netIface.Source = &libvirtxml.DomainInterfaceSource{ - Direct: &libvirtxml.DomainInterfaceSourceDirect{ - Dev: devI.(string), - Mode: "vepa", - }, - } - } else if devI, ok := d.GetOk(prefix + ".macvtap"); ok { - netIface.Source = &libvirtxml.DomainInterfaceSource{ - Direct: &libvirtxml.DomainInterfaceSourceDirect{ - Dev: devI.(string), - Mode: "bridge", - }, - } - } else if devI, ok := d.GetOk(prefix + ".passthrough"); ok { - netIface.Source = &libvirtxml.DomainInterfaceSource{ - Direct: &libvirtxml.DomainInterfaceSourceDirect{ - Dev: devI.(string), - Mode: "passthrough", - }, - } - } else { - // no network has been specified: we are on our own } domainDef.Devices.Interfaces = append(domainDef.Devices.Interfaces, netIface) diff --git a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/resource_libvirt_domain.go b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/resource_libvirt_domain.go index 6c738df002f..ffeac872ab5 100644 --- a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/resource_libvirt_domain.go +++ b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/resource_libvirt_domain.go @@ -17,9 +17,9 @@ import ( ) type pendingMapping struct { - mac string - hostname string - network *libvirt.Network + mac string + hostname string + networkName string } func init() { @@ -45,6 +45,11 @@ func resourceLibvirtDomain() *schema.Resource { Required: true, ForceNew: true, }, + "description": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, "metadata": { Type: schema.TypeString, Optional: true, @@ -139,9 +144,10 @@ func resourceLibvirtDomain() *schema.Resource { }, }, "disk": { - Type: schema.TypeList, - Optional: true, - ForceNew: true, + Type: schema.TypeList, + Optional: true, + ForceNew: true, + ConfigMode: schema.SchemaConfigModeAttr, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "volume_id": { @@ -159,7 +165,6 @@ func resourceLibvirtDomain() *schema.Resource { "scsi": { Type: schema.TypeBool, Optional: true, - Default: false, }, "wwn": { Type: schema.TypeString, @@ -457,6 +462,7 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error domainDef.VCPU = &libvirtxml.DomainVCPU{ Value: d.Get("vcpu").(int), } + domainDef.Description = d.Get("description").(string) domainDef.OS.Kernel = d.Get("kernel").(string) domainDef.OS.Initrd = d.Get("initrd").(string) @@ -491,7 +497,7 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error return err } - if err := setCloudinit(d, &domainDef, virConn, arch); err != nil { + if err := setCloudinit(d, &domainDef, virConn); err != nil { return err } @@ -567,15 +573,19 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error } } + // We save runnig state to not mix what we have and what we want + requiredStatus := d.Get("running") + err = resourceLibvirtDomainRead(d, meta) if err != nil { return err } + d.Set("running", requiredStatus) + // we must read devices again in order to set some missing ip/MAC/host mappings for i := 0; i < d.Get("network_interface.#").(int); i++ { prefix := fmt.Sprintf("network_interface.%d", i) - mac := strings.ToUpper(d.Get(prefix + ".mac").(string)) // if we were waiting for an IP address for this MAC, go ahead. @@ -583,16 +593,26 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error // we should have the address now addressesI, ok := d.GetOk(prefix + ".addresses") if !ok { - return fmt.Errorf("Did not obtain the IP address for MAC=%s", mac) + log.Printf("Did not obtain the IP address for MAC=%s", mac) + continue + } + + network, err := virConn.LookupNetworkByName(pending.networkName) + if err != nil { + log.Printf("Can't retrieve network '%s'", pending.networkName) + continue } + for _, addressI := range addressesI.([]interface{}) { address := addressI.(string) log.Printf("[INFO] Finally adding IP/MAC/host=%s/%s/%s", address, mac, pending.hostname) - updateOrAddHost(pending.network, address, mac, pending.hostname) + + err = updateOrAddHost(network, address, mac, pending.hostname) if err != nil { - return fmt.Errorf("Could not add IP/MAC/host=%s/%s/%s: %s", address, mac, pending.hostname, err) + log.Printf("Could not add IP/MAC/host=%s/%s/%s: %s", address, mac, pending.hostname, err) } } + network.Free() } } @@ -632,12 +652,7 @@ func resourceLibvirtDomainUpdate(d *schema.ResourceData, meta interface{}) error return err } - arch, err := getHostArchitecture(virConn) - if err != nil { - return fmt.Errorf("Error retrieving host architecture: %s", err) - } - - disk, err := newDiskForCloudInit(virConn, cloudinitID, arch) + disk, err := newDiskForCloudInit(virConn, cloudinitID) if err != nil { return err } @@ -741,7 +756,13 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("Error reading domain autostart setting: %s", err) } + domainRunningNow, err := domainIsRunning(*domain) + if err != nil { + return fmt.Errorf("Error reading domain running state : %s", err) + } + d.Set("name", domainDef.Name) + d.Set("description", domainDef.Description) d.Set("vcpu", domainDef.VCPU) d.Set("memory", domainDef.Memory) d.Set("firmware", domainDef.OS.Loader) @@ -749,6 +770,7 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error { d.Set("cpu", domainDef.CPU) d.Set("arch", domainDef.OS.Type.Arch) d.Set("autostart", autostart) + d.Set("running", domainRunningNow) cmdLines, err := splitKernelCmdLine(domainDef.OS.Cmdline) if err != nil { @@ -896,6 +918,7 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error { } netIface["wait_for_lease"] = d.Get(prefix + ".wait_for_lease").(bool) + netIface["hostname"] = d.Get(prefix + ".hostname").(string) netIface["addresses"] = addressesForMac(mac) log.Printf("[DEBUG] read: addresses for '%s': %+v", mac, netIface["addresses"]) diff --git a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/resource_libvirt_network.go b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/resource_libvirt_network.go index 1ac653ca2a2..4766c2fe0b8 100644 --- a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/resource_libvirt_network.go +++ b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/resource_libvirt_network.go @@ -432,8 +432,7 @@ func resourceLibvirtNetworkCreate(d *schema.ResourceData, meta interface{}) erro if networkDef.Bridge.Name == "" { return fmt.Errorf("'bridge' must be provided when using the bridged network mode") } - // Bridges cannot forward - networkDef.Forward = nil + networkDef.Bridge.STP = "" } else { return fmt.Errorf("unsupported network mode '%s'", networkDef.Forward.Mode) } diff --git a/vendor/modules.txt b/vendor/modules.txt index acef716be1b..dfbeefa6530 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -441,7 +441,7 @@ github.com/davecgh/go-spew/spew github.com/dgrijalva/jwt-go # github.com/dimchansky/utfbom v1.1.0 github.com/dimchansky/utfbom -# github.com/dmacvicar/terraform-provider-libvirt v0.6.1-0.20191216113711-1a01934a7d20 +# github.com/dmacvicar/terraform-provider-libvirt v0.6.2 github.com/dmacvicar/terraform-provider-libvirt/libvirt github.com/dmacvicar/terraform-provider-libvirt/libvirt/helper/suppress # github.com/dustinkirkland/golang-petname v0.0.0-20191129215211-8e5a1ed0cff0