Skip to content
This repository has been archived by the owner on Jan 21, 2020. It is now read-only.

Libvirt updates #552

Merged
merged 6 commits into from
May 31, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 0 additions & 32 deletions cmd/instance/libvirt/libvirt.json

This file was deleted.

59 changes: 59 additions & 0 deletions cmd/instance/libvirt/libvirt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
ID: cattle
Properties:
Allocation:
Size: 1
Instance:
Plugin: instance-libvirt
Properties:
MetadataStoragePool: default
Domain:
Domain:
Type: kvm
Memory:
Unit: GiB
Value: 1
VCPU:
Value: 1
OS:
Type:
Arch: x86_64
Machine: pc-i440fx-2.8
Type: hvm
Initrd: ../initrd.img
Kernel: ../bzImage
KernelArgs: console=ttyS0
BIOS:
UseSerial: 'yes'
Boot:
Dev: hd
Devices:
Interfaces:
- Type: bridge
Source:
Bridge: virbr0
Model:
Type: virtio
Serials:
- Type: pty
Consoles:
- Type: pty
Target:
Type: serial
Name: "0"
Channels:
- Type: unix
Target:
Type: virtio
Name: org.qemu.guest_agent.0
OnCrash: destroy
OnPoweroff: destroy
OnReboot: restart
Flavor:
Plugin: flavor-vanilla
Properties:
Init:
- "test1"
- "test2"
Tags:
project: infrakit
tier: sample
149 changes: 67 additions & 82 deletions pkg/plugin/instance/libvirt/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import (
"bytes"
"encoding/xml"
"fmt"
"io/ioutil"
"math/rand"
"path/filepath"
"net"

log "github.com/Sirupsen/logrus"

Expand Down Expand Up @@ -106,26 +105,27 @@ func metaSetTags(meta *infrakitMetadata, tags map[string]string) {
}
}

// Properties is the struct which defines spec.Properties for this instance plugin
type Properties struct {
// Domains is the libvirt domain description
Domain libvirtxml.Domain

// MetadataStoragePool is the libvirt storage pool where metadata ISO images should be placed
MetadataStoragePool string
}

// Provision creates a new instance.
func (p libvirtPlugin) Provision(spec instance.Spec) (*instance.ID, error) {
var properties map[string]interface{}
properties := Properties{
MetadataStoragePool: "default",
}

if spec.Properties != nil {
if err := spec.Properties.Decode(&properties); err != nil {
return nil, errors.Errorf("Invalid instance properties: %s", err)
}
}

if properties["Kernel"] == nil {
return nil, errors.New("Property 'Kernel' must be set")
}
if properties["CPUs"] == nil {
properties["CPUs"] = 1
}
if properties["Memory"] == nil {
properties["Memory"] = 512
}

// The name needs to be unique on the host. In the unlikely
// event it is not then conn.DomainCreateXML below will fail,
// but we rely on infrakit to try again.
Expand All @@ -138,41 +138,10 @@ func (p libvirtPlugin) Provision(spec instance.Spec) (*instance.ID, error) {
}
defer conn.Close()

domtype, ok := properties["DomainType"].(string)
if !ok {
domtype = "kvm"
}
kernel, err := filepath.Abs(properties["Kernel"].(string))
if err != nil {
return nil, errors.Wrap(err, "Constructing path to kernel")
}
initrd := ""
if initrdprop, ok := properties["Ramdisk"].(string); ok {
initrd, err = filepath.Abs(initrdprop)
if err != nil {
return nil, errors.Wrap(err, "Constructing path to initrd")
}
}
cmdline := ""
if properties["Cmdline"] != nil {
cmdline = properties["Cmdline"].(string)
} else if properties["CmdlineFile"] != nil {
f := properties["CmdlineFile"].(string)
b, err := ioutil.ReadFile(f)
if err != nil {
return nil, errors.Wrapf(err, "Reading CmdlineFile: %s", f)
}
cmdline = string(b)
}

metadataPool := ""
metadataPool := properties.MetadataStoragePool
metadataVol := ""

if spec.Init != "" {
metadataPool = "default"
if pn, ok := properties["MetadataStoragePool"].(string); ok {
metadataPool = pn
}
p, err := conn.LookupStoragePoolByName(metadataPool)
if err != nil {
return nil, errors.Wrapf(err, "Looking up MetadataStoragePool: %s", metadataPool)
Expand Down Expand Up @@ -225,47 +194,32 @@ func (p libvirtPlugin) Provision(spec instance.Spec) (*instance.ID, error) {
}
}

// XXX Check properties.DomainChannels for a Type==unix and Target.Name == "org.qemu.guest_agent.0"

domcfg := domainWithMetadata{
Domain: libvirtxml.Domain{
Type: domtype,
VCPU: &libvirtxml.DomainVCPU{Value: int(properties["CPUs"].(float64))},
Memory: &libvirtxml.DomainMemory{Value: int(properties["Memory"].(float64)), Unit: "MiB"},
Name: string(id),
OS: &libvirtxml.DomainOS{
Type: &libvirtxml.DomainOSType{
Type: "hvm",
},
Kernel: kernel,
Initrd: initrd,
KernelArgs: string(cmdline),
BIOS: &libvirtxml.DomainBIOS{
UseSerial: "yes",
},
},
Devices: &libvirtxml.DomainDeviceList{
Serials: []libvirtxml.DomainChardev{
{
Type: "pty",
},
},
Consoles: []libvirtxml.DomainChardev{
{
Type: "pty",
Target: &libvirtxml.DomainChardevTarget{
Type: "serial",
Name: "0",
},
},
},
},
OnCrash: "destroy",
OnPoweroff: "destroy",
},
Domain: properties.Domain,
}

if properties.Domain.Name != "" {
l.Warnf("Overriding 'Name' property")
}
domcfg.Domain.Name = string(id)

logicalID := string(id)
if spec.LogicalID != nil {
logicalID = string(*spec.LogicalID)
_, err := net.ParseMAC(logicalID)
if err == nil && domcfg.Domain.Devices != nil && len(domcfg.Domain.Devices.Interfaces) > 0 {
if domcfg.Domain.Devices.Interfaces[0].MAC != nil {
l.Warnf("Overriding MAC address of first interface (%q) with logical ID (%q)",
domcfg.Domain.Devices.Interfaces[0].MAC.Address, logicalID)
}
domcfg.Domain.Devices.Interfaces[0].MAC = &libvirtxml.DomainInterfaceMAC{
Address: logicalID,
}
} else {
l.Warnf("No Network device to apply logical ID %q to", logicalID)
}
}

meta := infrakitMetadata{
Expand Down Expand Up @@ -521,11 +475,42 @@ func (p libvirtPlugin) DescribeInstances(tags map[string]string, properties bool
}
lid := instance.LogicalID(meta.LogicalID)
if allMatched {
descriptions = append(descriptions, instance.Description{
description := instance.Description{
ID: instance.ID(domcfg.Name),
LogicalID: &lid,
Tags: instanceTags,
})
}

if properties {
extra := map[string]interface{}{}

srcs := []libvirt.DomainInterfaceAddressesSource{
libvirt.DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT,
libvirt.DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE,
}

for _, src := range srcs {
if allifaces, err := d.ListAllInterfaceAddresses(src); err == nil {
ifaces := []libvirt.DomainInterface{}

for _, iface := range allifaces {
// Filter out uninteresting interfaces with no addresses
if iface.Hwaddr == "" || len(iface.Addrs) == 0 {
continue
}
ifaces = append(ifaces, iface)
}

if len(ifaces) > 0 {
extra["interfaces"] = ifaces
break
}
}
}
description.Properties = types.AnyValueMust(extra)
}

descriptions = append(descriptions, description)
}

}
Expand Down
Loading