Skip to content

Commit

Permalink
Merge pull request #271 from crawford/image
Browse files Browse the repository at this point in the history
*: provide a default OS image for libvirt
  • Loading branch information
openshift-merge-robot authored Sep 18, 2018
2 parents 3bbf22b + 9ee45fb commit 0199eeb
Show file tree
Hide file tree
Showing 14 changed files with 46 additions and 143 deletions.
18 changes: 10 additions & 8 deletions Documentation/dev/libvirt-howto.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ git clone https://github.com/openshift/installer.git
cd installer
```

#### 1.3 Download and prepare the operating system image
#### 1.3 (Optional) Download and prepare the operating system image

*By default, the installer will download the latest RHCOS image every time it is invoked. This may be problematic for users who create a large number of clusters or who have limited network bandwidth. The installer allows a local image to be used instead.*

Download the latest RHCOS image (you will need access to the Red Hat internal build systems):

Expand Down Expand Up @@ -85,14 +87,14 @@ iptables -I INPUT -p tcp -s 192.168.124.0/24 -d 192.168.124.1 --dport 16509 \

#### 1.7 Prepare the configuration file
1. `cp examples/libvirt.yaml ./`
1. Edit the configuration file:
2. Edit the configuration file:
1. Set an email and password in the `admin` section
1. Set a `baseDomain` (to `tt.testing`)
1. Set the `sshKey` in the `admin` section to the **contents** of an ssh key (e.g. `ssh-rsa AAAA...`)
1. Set the `imagePath` to the **absolute** path of the operating system image you downloaded
1. Set the `name` (e.g. test1)
1. Look at the `podCIDR` and `serviceCIDR` fields in the `networking` section. Make sure they don't conflict with anything important.
1. Set the `pullSecret` to your JSON pull secret.
2. Set a `baseDomain` (to `tt.testing`)
3. Set the `sshKey` in the `admin` section to the **contents** of an ssh key (e.g. `ssh-rsa AAAA...`)
4. Set the `name` (e.g. test1)
5. Look at the `podCIDR` and `serviceCIDR` fields in the `networking` section. Make sure they don't conflict with anything important.
6. Set the `pullSecret` to your JSON pull secret.
7. (Optional) Change the `image` to the file URL of the operating system image you downloaded (e.g. `file:///home/user/Downloads/rhcos.qcow`). This will allow the installer to re-use that image instead of having to download it every time.

#### 1.8 Set up NetworkManager DNS overlay
This step is optional, but useful for being able to resolve cluster-internal hostnames from your host.
Expand Down
2 changes: 1 addition & 1 deletion examples/libvirt.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ libvirt:
name: tectonic
ifName: tt0
ipRange: 192.168.124.0/24
imagePath: /path/to/image
image: http://aos-ostree.rhev-ci-vms.eng.rdu2.redhat.com/rhcos/images/cloud/latest/rhcos-qemu.qcow2.gz

ca:
# (optional) The content of the PEM-encoded CA certificate, used to generate Tectonic Console's server certificate.
Expand Down
6 changes: 4 additions & 2 deletions installer/pkg/config-generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,10 +248,12 @@ func (c *ConfigGenerator) installConfig() (*types.InstallConfig, error) {
},
}
masterPlatform.Libvirt = &types.LibvirtMachinePoolPlatform{
QCOWImagePath: c.Libvirt.QCOWImagePath,
ImagePool: "default",
ImageVolume: "coreos_base",
}
workerPlatform.Libvirt = &types.LibvirtMachinePoolPlatform{
QCOWImagePath: c.Libvirt.QCOWImagePath,
ImagePool: "default",
ImageVolume: "coreos_base",
}
default:
return nil, fmt.Errorf("installconfig: invalid platform %s", c.Platform)
Expand Down
12 changes: 6 additions & 6 deletions installer/pkg/config/libvirt/libvirt.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ const (

// Libvirt encompasses configuration specific to libvirt.
type Libvirt struct {
URI string `json:"tectonic_libvirt_uri,omitempty" yaml:"uri"`
QCOWImagePath string `json:"tectonic_coreos_qcow_path,omitempty" yaml:"imagePath"`
Network `json:",inline" yaml:"network"`
MasterIPs []string `json:"tectonic_libvirt_master_ips,omitempty" yaml:"masterIPs"`
WorkerIPs []string `json:"tectonic_libvirt_worker_ips,omitempty" yaml:"workerIPs"`
BootstrapIP string `json:"tectonic_libvirt_bootstrap_ip,omitempty" yaml:"bootstrapIP"`
URI string `json:"tectonic_libvirt_uri,omitempty" yaml:"uri"`
Image string `json:"tectonic_os_image,omitempty" yaml:"image"`
Network `json:",inline" yaml:"network"`
MasterIPs []string `json:"tectonic_libvirt_master_ips,omitempty" yaml:"masterIPs"`
WorkerIPs []string `json:"tectonic_libvirt_worker_ips,omitempty" yaml:"workerIPs"`
BootstrapIP string `json:"tectonic_libvirt_bootstrap_ip,omitempty" yaml:"bootstrapIP"`
}

// Network describes a libvirt network configuration.
Expand Down
7 changes: 0 additions & 7 deletions installer/pkg/config/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@ const (
maxS3BucketNameLength = 63
)

var (
qcowMagic = []byte{'Q', 'F', 'I', 0xfb}
)

// ErrUnmatchedNodePool is returned when a nodePool was specified but not found in the nodePools list.
type ErrUnmatchedNodePool struct {
name string
Expand Down Expand Up @@ -160,9 +156,6 @@ func (c *Cluster) validateLibvirt() []error {
if err := validate.PrefixError("libvirt uri", validate.NonEmpty(c.Libvirt.URI)); err != nil {
errs = append(errs, err)
}
if err := validate.PrefixError("libvirt imagePath is not a valid QCOW image", validate.FileHeader(c.Libvirt.QCOWImagePath, qcowMagic)); err != nil {
errs = append(errs, err)
}
if err := validate.PrefixError("libvirt network name", validate.NonEmpty(c.Libvirt.Network.Name)); err != nil {
errs = append(errs, err)
}
Expand Down
55 changes: 12 additions & 43 deletions installer/pkg/config/validate_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package config

import (
"io/ioutil"
"os"
"testing"

Expand Down Expand Up @@ -444,21 +443,6 @@ func TestValidateIgnitionFiles(t *testing.T) {
}

func TestValidateLibvirt(t *testing.T) {
fValid, err := ioutil.TempFile("", "qcow")
if err != nil {
t.Fatalf("failed to create temporary file: %v", err)
}
if _, err := fValid.Write(qcowMagic); err != nil {
t.Fatalf("failed to write to temporary file: %v", err)
}
fValid.Close()
defer os.Remove(fValid.Name())
fInvalid, err := ioutil.TempFile("", "qcow")
if err != nil {
t.Fatalf("failed to create temporary file: %v", err)
}
fInvalid.Close()
defer os.Remove(fInvalid.Name())
cases := []struct {
cluster Cluster
err bool
Expand All @@ -474,24 +458,9 @@ func TestValidateLibvirt(t *testing.T) {
{
cluster: Cluster{
Libvirt: libvirt.Libvirt{
Network: libvirt.Network{},
QCOWImagePath: "",
URI: "",
},
Networking: defaultCluster.Networking,
},
err: true,
},
{
cluster: Cluster{
Libvirt: libvirt.Libvirt{
Network: libvirt.Network{
Name: "tectonic",
IfName: libvirt.DefaultIfName,
IPRange: "10.0.1.0/24",
},
QCOWImagePath: fInvalid.Name(),
URI: "baz",
Network: libvirt.Network{},
Image: "",
URI: "",
},
Networking: defaultCluster.Networking,
},
Expand All @@ -505,8 +474,8 @@ func TestValidateLibvirt(t *testing.T) {
IfName: libvirt.DefaultIfName,
IPRange: "10.0.1.0/24",
},
QCOWImagePath: fValid.Name(),
URI: "baz",
Image: "file:///foo",
URI: "baz",
},
Networking: defaultCluster.Networking,
},
Expand All @@ -520,8 +489,8 @@ func TestValidateLibvirt(t *testing.T) {
IfName: libvirt.DefaultIfName,
IPRange: "10.2.1.0/24",
},
QCOWImagePath: fValid.Name(),
URI: "baz",
Image: "file:///foo",
URI: "baz",
},
Networking: defaultCluster.Networking,
},
Expand All @@ -535,8 +504,8 @@ func TestValidateLibvirt(t *testing.T) {
IfName: libvirt.DefaultIfName,
IPRange: "x",
},
QCOWImagePath: "foo",
URI: "baz",
Image: "file:///foo",
URI: "baz",
},
Networking: defaultCluster.Networking,
},
Expand All @@ -550,12 +519,12 @@ func TestValidateLibvirt(t *testing.T) {
IfName: libvirt.DefaultIfName,
IPRange: "192.168.0.1/24",
},
QCOWImagePath: "foo",
URI: "baz",
Image: "file:///foo",
URI: "baz",
},
Networking: defaultCluster.Networking,
},
err: true,
err: false,
},
}

Expand Down
17 changes: 0 additions & 17 deletions installer/pkg/validate/validate.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package validate

import (
"bytes"
"crypto/x509"
"encoding/json"
"encoding/pem"
Expand Down Expand Up @@ -469,19 +468,3 @@ func lastIP(cidr *net.IPNet) net.IP {
}
return last
}

// FileHeader validates that the file at the specified path begins with the given string.
func FileHeader(path string, header []byte) error {
f, err := os.Open(path)
if err != nil {
return err
}
buf := make([]byte, len(header))
if _, err := f.Read(buf); err != nil {
return err
}
if !bytes.Equal(buf, header) {
return fmt.Errorf("file %q does not begin with %q", path, string(header))
}
return nil
}
49 changes: 0 additions & 49 deletions installer/pkg/validate/validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -610,52 +610,3 @@ func TestFileExists(t *testing.T) {
}
}
}

func TestFileHeader(t *testing.T) {
cases := []struct {
actual []byte
expected []byte
err bool
}{
{
actual: []byte{},
expected: []byte("foo"),
err: true,
},
{
actual: []byte("foo"),
expected: []byte("bar"),
err: true,
},
{
actual: []byte("fooooo"),
expected: []byte("foo"),
err: false,
},
{
actual: []byte("fooooo"),
expected: []byte{},
err: false,
},
}

for i, c := range cases {
f, err := ioutil.TempFile("", "fileheader")
if err != nil {
t.Errorf("test case %d: failed to create temporary file: %v", i, err)
continue
}
if _, err := f.Write(c.actual); err != nil {
t.Errorf("test case %d: failed to write to temporary file: %v", i, err)
}
f.Close()
if err := validate.FileHeader(f.Name(), c.expected); (err != nil) != c.err {
no := "no"
if c.err {
no = "an"
}
t.Errorf("test case %d: expected %s error, got %v", i, no, err)
}
os.Remove(f.Name())
}
}
3 changes: 1 addition & 2 deletions modules/libvirt/volume/main.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# Create a QCOW volume from the downloaded path
resource "libvirt_volume" "coreos_base" {
name = "coreos_base"
source = "file://${var.coreos_qcow_path}"
source = "file://${var.image}"
}
4 changes: 2 additions & 2 deletions modules/libvirt/volume/variables.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
variable "coreos_qcow_path" {
description = "The path on disk to the coreos disk image"
variable "image" {
description = "The URL of the OS disk image"
type = "string"
}
8 changes: 6 additions & 2 deletions pkg/types/machinepools.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ type EC2RootVolume struct {
// LibvirtMachinePoolPlatform stores the configuration for a machine pool
// installed on libvirt.
type LibvirtMachinePoolPlatform struct {
// QCOWImagePath
QCOWImagePath string `json:"qcowImagePath"`
// ImagePool is the name of the libvirt storage pool to which the storage
// volume containing the OS image belongs.
ImagePool string `json:"imagePool"`
// ImageVolume is the name of the libvirt storage volume containing the OS
// image.
ImageVolume string `json:"imageVolume"`
}
2 changes: 1 addition & 1 deletion steps/infra/libvirt/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ provider "libvirt" {
module "libvirt_base_volume" {
source = "../../../modules/libvirt/volume"

coreos_qcow_path = "${var.tectonic_coreos_qcow_path}"
image = "${var.tectonic_os_image}"
}

resource "libvirt_volume" "master" {
Expand Down
4 changes: 2 additions & 2 deletions steps/variables-libvirt.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ variable "tectonic_libvirt_ip_range" {
description = "IP range for the libvirt machines"
}

variable "tectonic_coreos_qcow_path" {
variable "tectonic_os_image" {
type = "string"
description = "path to a Red Hat CoreOS qcow image"
description = "The URL of the OS disk image"
}

variable "tectonic_libvirt_bootstrap_ip" {
Expand Down
2 changes: 1 addition & 1 deletion tests/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ python <<-EOF >"${CLUSTER_NAME}.yaml"
config['aws']['master']['iamRoleName'] = 'tf-tectonic-master-node'
config['aws']['worker']['iamRoleName'] = 'tf-tectonic-worker-node'
elif '${BACKEND}' == 'libvirt':
config['libvirt']['imagePath'] = '${IMAGE_PATH}'
config['libvirt']['image'] = 'file://${IMAGE_PATH}'
yaml.safe_dump(config, sys.stdout)
EOF

Expand Down

0 comments on commit 0199eeb

Please sign in to comment.