Skip to content

Commit

Permalink
Implemented CoreOS Config Drive via xscontainer
Browse files Browse the repository at this point in the history
  • Loading branch information
fabiorauber committed Aug 7, 2018
1 parent 5b3e682 commit 7ca980a
Showing 1 changed file with 137 additions and 77 deletions.
214 changes: 137 additions & 77 deletions xenserver/xenserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ type Driver struct {
CaCertPath string
PrivateKeyPath string
osTemplateLabelName string
CoreosConfigDrive bool

xenAPIClient *XenAPIClient
}
Expand Down Expand Up @@ -140,6 +141,11 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag {
Usage: "XenServer Username used to SSH into guest OS",
Value: B2D_USER,
},
mcnflag.BoolFlag{
EnvVar: "XENSERVER_COREOS_CONFIGDRIVE",
Name: "xenserver-coreos-configdrive",
Usage: "XenServer Enable CoreOS specific ConfigDrive (requires xscontainer supplemental pack)",
},

}
}
Expand Down Expand Up @@ -201,6 +207,7 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
d.ISO = d.ResolveStorePath(isoFilename)
d.TAR = d.ResolveStorePath(tarFilename)
d.osTemplateLabelName = flags.String("xenserver-os-template")
d.CoreosConfigDrive = flags.Bool("xenserver-coreos-configdrive")

return nil
}
Expand Down Expand Up @@ -337,7 +344,6 @@ func (d *Driver) Create() error {

// Only upload ISO image if using Other install media, otherwise use existing VM template
var sr *xsclient.SR
var isoVdi,diskVdi *xsclient.VDI
var isoVdiUuid,diskVdiUuid string

// Get the SR
Expand Down Expand Up @@ -367,7 +373,7 @@ func (d *Driver) Create() error {
}

// Create the VDI
isoVdi, err = sr.CreateVdi(isoFilename, isoFileInfo.Size())
isoVdi, err := sr.CreateVdi(isoFilename, isoFileInfo.Size())
if err != nil {
log.Errorf("Unable to create ISO VDI '%s': %v", isoFilename, err)
return err
Expand All @@ -390,7 +396,7 @@ func (d *Driver) Create() error {
}

// Create the VDI
diskVdi, err = sr.CreateVdi("bootdocker disk", int64(d.DiskSize)*1024*1024)
diskVdi, err := sr.CreateVdi("bootdocker disk", int64(d.DiskSize)*1024*1024)
if err != nil {
log.Errorf("Unable to create ISO VDI '%s': %v", "bootdocker disk", err)
return err
Expand All @@ -404,75 +410,6 @@ func (d *Driver) Create() error {
return err
}

} else {
log.Infof("Creating Config Drive...")

pubKey, err := ioutil.ReadFile(d.publicSSHKeyPath())
if err != nil {
return err
}
userdatatext := `#cloud-config
ssh_authorized_keys:
- ` + string(pubKey)

fakeUuid, err := pseudoUuid()
if err != nil {
return err
}

metadatatext := `{ "uuid": "` + fakeUuid + `"}`

tempDir := d.ResolveStorePath("configdrive")

//Create the folder structure inside the temp folder
path := filepath.Join(tempDir, "openstack", "latest")
os.MkdirAll(path, os.ModePerm)
f, err := os.OpenFile(filepath.Join(path, "user_data"), os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
log.Errorf("Unable to open user_data config drive file '%s': %v", path, err)
return err
}
io.WriteString(f, userdatatext)
f.Close()

fmetadata, err := os.OpenFile(filepath.Join(path, "meta_data.json"), os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
log.Errorf("Unable to open meta_data.json config drive file '%s': %v", path, err)
return err
}
io.WriteString(fmetadata, metadatatext)
fmetadata.Close()

configIsoFilename := d.ResolveStorePath("configdrive.iso")
cmd := exec.Command("/usr/bin/mkisofs", "-R", "-V", "config-2", "-o", configIsoFilename, tempDir)
err = cmd.Run()
if err != nil {
log.Errorf("Unable to create ConfigDrive ISO '%s': %v", configIsoFilename, err)
return err
}

configIsoFileInfo, err := os.Stat(configIsoFilename)
if err != nil {
return err
}

// Create the VDI
isoVdi, err = sr.CreateVdi(configIsoFilename, configIsoFileInfo.Size())
if err != nil {
log.Errorf("Unable to create ConfigDrive ISO VDI '%s': %v", configIsoFilename, err)
return err
}

// Import the VDI
log.Infof("Starting import of ConfigDrive VDI '%s'...", configIsoFilename)
if err = d.importVdi(isoVdi, configIsoFilename, time.Duration(d.UploadTimeout)*time.Second); err != nil {
return err
}

isoVdiUuid, err = isoVdi.GetUuid()
if err != nil {
return err
}
}

log.Infof("Creating VM...")
Expand Down Expand Up @@ -557,7 +494,7 @@ ssh_authorized_keys:

if d.osTemplateLabelName == "Other install media" {
log.Infof("Add ISO VDI to VM...")
diskVdi, err = c.GetVdiByUuid(isoVdiUuid)
diskVdi, err := c.GetVdiByUuid(isoVdiUuid)
if err != nil {
return err
}
Expand All @@ -578,16 +515,41 @@ ssh_authorized_keys:
return err
}
} else {
log.Infof("Add ConfigDrive ISO VDI to VM...")
diskVdi, err = c.GetVdiByUuid(isoVdiUuid)
pubKey, err := ioutil.ReadFile(d.publicSSHKeyPath())
if err != nil {
return err
}

err = vm.ConnectVdi(diskVdi, xsclient.Disk, "")
vmUuid, err := vm.GetUuid()
if err != nil {
return err
}
srUuid,err := sr.GetUuid()
if err != nil {
return err
}

if d.CoreosConfigDrive {
err := d.createCoreOSConfigDrive(pubKey, vmUuid, srUuid)
if err != nil {
return err
}
} else {
log.Infof("Creating Config Drive...")
isoVdiUuid, err := d.createGenericConfigDrive(pubKey, vmUuid, sr)
if err != nil {
return err
}

log.Infof("Add ConfigDrive ISO VDI to VM...")
diskVdi, err := c.GetVdiByUuid(isoVdiUuid)
if err != nil {
return err
}
err = vm.ConnectVdi(diskVdi, xsclient.Disk, "")
if err != nil {
return err
}
}
}

log.Infof("Add Network to VM...")
Expand Down Expand Up @@ -1009,3 +971,101 @@ func pseudoUuid() (string, error) {
uuid := fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
return uuid, nil
}

func (d *Driver) createCoreOSConfigDrive(pubKey []byte, vmuuid string, sruuid string) error {
userdatatext := `#cloud-config
hostname: %XSVMNAMETOHOSTNAME%
coreos:
units:
# XenServer Linux Guest Agent
- name: xe-linux-distribution.service
command: start
content: |
[Unit]
Description=XenServer Linux Guest Agent
After=docker.service
[Service]
ExecStartPre=/media/configdrive/agent/xe-linux-distribution /var/cache/xe-linux-distribution
Environment="XE_UPDATE_GUEST_ATTRS=/media/configdrive/agent/xe-update-guest-attrs"
ExecStart=/media/configdrive/agent/xe-daemon
ssh_authorized_keys:
# The following entry will automatically be replaced with a public key
# generated by XenServer's container management. The key-entry must exist,
# in order to enable container management for this VM.
- ssh-rsa %XSCONTAINERRSAPUB%
- ` + string(pubKey)
hosts, err := d.xenAPIClient.GetHosts()
if err != nil {
log.Errorf("Could not retrieve hosts in the pool: %s", err)
return err
}
ahost := hosts[0]
args := make(map[string]string)
args["vmuuid"] = vmuuid
args["sruuid"] = sruuid
args["configuration"] = userdatatext
ahost.CallPlugin("xscontainer","create_config_drive",args)

return nil
}

func (d *Driver) createGenericConfigDrive(pubKey []byte, vmUuid string, sr *xsclient.SR) (string, error) {
userdatatext := `#cloud-config
ssh_authorized_keys:
- ` + string(pubKey)

metadatatext := `{ "uuid": "` + vmUuid + `"}`

tempDir := d.ResolveStorePath("configdrive")

//Create the folder structure inside the temp folder
path := filepath.Join(tempDir, "openstack", "latest")
os.MkdirAll(path, os.ModePerm)
f, err := os.OpenFile(filepath.Join(path, "user_data"), os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
log.Errorf("Unable to open user_data config drive file '%s': %v", path, err)
return "", err
}
io.WriteString(f, userdatatext)
f.Close()

fmetadata, err := os.OpenFile(filepath.Join(path, "meta_data.json"), os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
log.Errorf("Unable to open meta_data.json config drive file '%s': %v", path, err)
return "", err
}
io.WriteString(fmetadata, metadatatext)
fmetadata.Close()

configIsoFilename := d.ResolveStorePath("configdrive.iso")
cmd := exec.Command("/usr/bin/mkisofs", "-R", "-V", "config-2", "-o", configIsoFilename, tempDir)
err = cmd.Run()
if err != nil {
log.Errorf("Unable to create ConfigDrive ISO '%s': %v", configIsoFilename, err)
return "", err
}
configIsoFileInfo, err := os.Stat(configIsoFilename)
if err != nil {
return "", err
}

// Create the VDI
isoVdi, err := sr.CreateVdi(configIsoFilename, configIsoFileInfo.Size())
if err != nil {
log.Errorf("Unable to create ConfigDrive ISO VDI '%s': %v", configIsoFilename, err)
return "", err
}

// Import the VDI
log.Infof("Starting import of ConfigDrive VDI '%s'...", configIsoFilename)
if err = d.importVdi(isoVdi, configIsoFilename, time.Duration(d.UploadTimeout)*time.Second); err != nil {
return "", err
}

isoVdiUuid, err := isoVdi.GetUuid()
if err != nil {
return "", err
}
return isoVdiUuid, nil
}

0 comments on commit 7ca980a

Please sign in to comment.