github.com/openshift/installer@v1.4.17/pkg/tfvars/libvirt/libvirt.go (about) 1 // Package libvirt contains libvirt-specific Terraform-variable logic. 2 package libvirt 3 4 import ( 5 "encoding/json" 6 "fmt" 7 "net" 8 "net/url" 9 "os" 10 "path/filepath" 11 "strconv" 12 13 "github.com/apparentlymart/go-cidr/cidr" 14 "github.com/pkg/errors" 15 16 "github.com/openshift/cluster-api-provider-libvirt/pkg/apis/libvirtproviderconfig/v1beta1" 17 "github.com/openshift/installer/pkg/rhcos/cache" 18 "github.com/openshift/installer/pkg/types" 19 ) 20 21 type config struct { 22 URI string `json:"libvirt_uri,omitempty"` 23 Image string `json:"os_image,omitempty"` 24 IfName string `json:"libvirt_network_if"` 25 MasterIPs []string `json:"libvirt_master_ips,omitempty"` 26 BootstrapIP string `json:"libvirt_bootstrap_ip,omitempty"` 27 MasterMemory string `json:"libvirt_master_memory,omitempty"` 28 MasterVcpu string `json:"libvirt_master_vcpu,omitempty"` 29 BootstrapMemory int `json:"libvirt_bootstrap_memory,omitempty"` 30 MasterDiskSize string `json:"libvirt_master_size,omitempty"` 31 DnsmasqOptions []map[string]string `json:"libvirt_dnsmasq_options,omitempty"` 32 } 33 34 // TFVarsSources contains the parameters to be converted into Terraform variables 35 type TFVarsSources struct { 36 MasterConfig *v1beta1.LibvirtMachineProviderConfig 37 OsImage string 38 MachineCIDR *net.IPNet 39 Bridge string 40 MasterCount int 41 Architecture types.Architecture 42 DnsmasqOptions []map[string]string 43 } 44 45 // TFVars generates libvirt-specific Terraform variables. 46 func TFVars(sources TFVarsSources) ([]byte, error) { 47 bootstrapIP, err := cidr.Host(sources.MachineCIDR, 10) 48 if err != nil { 49 return nil, errors.Errorf("failed to generate bootstrap IP: %v", err) 50 } 51 52 masterIPs, err := generateIPs("master", sources.MachineCIDR, sources.MasterCount, 11) 53 if err != nil { 54 return nil, err 55 } 56 57 osImage := sources.OsImage 58 url, err := url.Parse(osImage) 59 if err != nil { 60 return nil, errors.Wrap(err, "failed to parse image url") 61 } 62 63 if url.Scheme == "file" { 64 osImage = filepath.FromSlash(url.Path) 65 if _, err = os.Stat(osImage); err != nil { 66 return nil, errors.Wrap(err, "failed to access file or directory") 67 } 68 } else { 69 osImage, err = cache.DownloadImageFile(osImage, cache.InstallerApplicationName) 70 if err != nil { 71 return nil, errors.Wrap(err, "failed to use cached libvirt image") 72 } 73 } 74 75 cfg := &config{ 76 URI: sources.MasterConfig.URI, 77 Image: osImage, 78 IfName: sources.Bridge, 79 BootstrapIP: bootstrapIP.String(), 80 MasterIPs: masterIPs, 81 MasterMemory: strconv.Itoa(sources.MasterConfig.DomainMemory), 82 MasterVcpu: strconv.Itoa(sources.MasterConfig.DomainVcpu), 83 DnsmasqOptions: sources.DnsmasqOptions, 84 } 85 86 if sources.MasterConfig.Volume.VolumeSize != nil { 87 // As per https://github.com/hashicorp/terraform/issues/3287 the 88 // master disk size needs to be specified as the number of bytes. 89 diskSizeInBytes, converted := sources.MasterConfig.Volume.VolumeSize.AsInt64() 90 if !converted { 91 msgTemplate := "failed to convert master disk size to bytes: %s" 92 return nil, fmt.Errorf(msgTemplate, sources.MasterConfig.Volume.VolumeSize) 93 } 94 cfg.MasterDiskSize = fmt.Sprintf("%d", diskSizeInBytes) 95 } 96 97 return json.MarshalIndent(cfg, "", " ") 98 } 99 100 func generateIPs(name string, network *net.IPNet, count int, offset int) ([]string, error) { 101 var ips []string 102 for i := 0; i < count; i++ { 103 ip, err := cidr.Host(network, offset+i) 104 if err != nil { 105 return nil, fmt.Errorf("failed to generate %s IPs: %v", name, err) 106 } 107 ips = append(ips, ip.String()) 108 } 109 110 return ips, nil 111 }