summaryrefslogtreecommitdiff
path: root/libvirt
diff options
context:
space:
mode:
authorThomas Hipp <thipp@suse.de>2017-08-10 12:48:55 +0200
committerFlavio Castelli <flavio@castelli.me>2017-08-11 14:42:24 +0200
commit7fbe405ecb15e4ab22da4a74368aafcc6b0c2ea8 (patch)
tree337160720552859360c190bf890cd0dc96f8297c /libvirt
parentb76cf35ad27d3f0e49684ea58920230ebd447883 (diff)
downloadterraform-provider-libvirt-7fbe405ecb15e4ab22da4a74368aafcc6b0c2ea8.tar
terraform-provider-libvirt-7fbe405ecb15e4ab22da4a74368aafcc6b0c2ea8.tar.gz
use libvirt-go-xml for volumes
Signed-off-by: Thomas Hipp <thipp@suse.de>
Diffstat (limited to 'libvirt')
-rw-r--r--libvirt/cloudinit_def.go2
-rw-r--r--libvirt/coreos_ignition_def.go4
-rw-r--r--libvirt/resource_libvirt_volume.go6
-rw-r--r--libvirt/utils_volume.go31
-rw-r--r--libvirt/utils_volume_test.go36
-rw-r--r--libvirt/volume_def.go110
6 files changed, 85 insertions, 104 deletions
diff --git a/libvirt/cloudinit_def.go b/libvirt/cloudinit_def.go
index 4fc05507..37f4afb4 100644
--- a/libvirt/cloudinit_def.go
+++ b/libvirt/cloudinit_def.go
@@ -92,7 +92,7 @@ func (ci *defCloudInit) CreateAndUpload(virConn *libvirt.Connect) (string, error
}
volumeDef.Capacity.Unit = "B"
- volumeDef.Capacity.Amount = size
+ volumeDef.Capacity.Value = size
volumeDef.Target.Format.Type = "raw"
volumeDefXml, err := xml.Marshal(volumeDef)
diff --git a/libvirt/coreos_ignition_def.go b/libvirt/coreos_ignition_def.go
index 1ac7def9..084979fc 100644
--- a/libvirt/coreos_ignition_def.go
+++ b/libvirt/coreos_ignition_def.go
@@ -72,7 +72,7 @@ func (ign *defIgnition) CreateAndUpload(virConn *libvirt.Connect) (string, error
}
volumeDef.Capacity.Unit = "B"
- volumeDef.Capacity.Amount = size
+ volumeDef.Capacity.Value = size
volumeDef.Target.Format.Type = "raw"
volumeDefXml, err := xml.Marshal(volumeDef)
@@ -88,7 +88,7 @@ func (ign *defIgnition) CreateAndUpload(virConn *libvirt.Connect) (string, error
defer volume.Free()
// upload ignition file
- err = img.Import(newCopier(virConn, volume, volumeDef.Capacity.Amount), volumeDef)
+ err = img.Import(newCopier(virConn, volume, volumeDef.Capacity.Value), volumeDef)
if err != nil {
return "", fmt.Errorf("Error while uploading ignition file %s: %s", img.String(), err)
}
diff --git a/libvirt/resource_libvirt_volume.go b/libvirt/resource_libvirt_volume.go
index 918981e4..234772db 100644
--- a/libvirt/resource_libvirt_volume.go
+++ b/libvirt/resource_libvirt_volume.go
@@ -159,7 +159,7 @@ func resourceLibvirtVolumeCreate(d *schema.ResourceData, meta interface{}) error
} else {
log.Printf("Image %s image is: %d bytes", img, size)
volumeDef.Capacity.Unit = "B"
- volumeDef.Capacity.Amount = size
+ volumeDef.Capacity.Value = size
}
} else {
_, noSize := d.GetOk("size")
@@ -168,7 +168,7 @@ func resourceLibvirtVolumeCreate(d *schema.ResourceData, meta interface{}) error
if noSize && noBaseVol {
return fmt.Errorf("'size' needs to be specified if no 'source' or 'base_volume_id' is given.")
}
- volumeDef.Capacity.Amount = uint64(d.Get("size").(int))
+ volumeDef.Capacity.Value = uint64(d.Get("size").(int))
}
if baseVolumeId, ok := d.GetOk("base_volume_id"); ok {
@@ -250,7 +250,7 @@ func resourceLibvirtVolumeCreate(d *schema.ResourceData, meta interface{}) error
// upload source if present
if _, ok := d.GetOk("source"); ok {
- err = img.Import(newCopier(virConn, volume, volumeDef.Capacity.Amount), volumeDef)
+ err = img.Import(newCopier(virConn, volume, volumeDef.Capacity.Value), volumeDef)
if err != nil {
return fmt.Errorf("Error while uploading source %s: %s", img.String(), err)
}
diff --git a/libvirt/utils_volume.go b/libvirt/utils_volume.go
index 83596465..289ded4e 100644
--- a/libvirt/utils_volume.go
+++ b/libvirt/utils_volume.go
@@ -9,14 +9,16 @@ import (
"os"
"strconv"
"strings"
+ "time"
libvirt "github.com/libvirt/libvirt-go"
+ "github.com/libvirt/libvirt-go-xml"
)
// network transparent image
type image interface {
Size() (uint64, error)
- Import(func(io.Reader) error, defVolume) error
+ Import(func(io.Reader) error, libvirtxml.StorageVolume) error
String() string
}
@@ -41,8 +43,7 @@ func (i *localImage) Size() (uint64, error) {
return uint64(fi.Size()), nil
}
-func (i *localImage) Import(copier func(io.Reader) error, vol defVolume) error {
-
+func (i *localImage) Import(copier func(io.Reader) error, vol libvirtxml.StorageVolume) error {
file, err := os.Open(i.path)
defer file.Close()
if err != nil {
@@ -53,9 +54,8 @@ func (i *localImage) Import(copier func(io.Reader) error, vol defVolume) error {
return err
} else {
// we can skip the upload if the modification times are the same
- if vol.Target.Timestamps != nil && vol.Target.Timestamps.Modification != nil {
- modTime := UnixTimestamp{fi.ModTime()}
- if modTime == *vol.Target.Timestamps.Modification {
+ if vol.Target.Timestamps != nil && vol.Target.Timestamps.Mtime != "" {
+ if fi.ModTime() == timeFromEpoch(vol.Target.Timestamps.Mtime) {
log.Printf("Modification time is the same: skipping image copy")
return nil
}
@@ -98,13 +98,12 @@ func (i *httpImage) Size() (uint64, error) {
return uint64(length), nil
}
-func (i *httpImage) Import(copier func(io.Reader) error, vol defVolume) error {
+func (i *httpImage) Import(copier func(io.Reader) error, vol libvirtxml.StorageVolume) error {
client := &http.Client{}
req, _ := http.NewRequest("GET", i.url.String(), nil)
- if vol.Target.Timestamps != nil && vol.Target.Timestamps.Modification != nil {
- t := vol.Target.Timestamps.Modification.UTC().Format(http.TimeFormat)
- req.Header.Set("If-Modified-Since", t)
+ if vol.Target.Timestamps != nil && vol.Target.Timestamps.Mtime != "" {
+ req.Header.Set("If-Modified-Since", timeFromEpoch(vol.Target.Timestamps.Mtime).UTC().Format(http.TimeFormat))
}
response, err := client.Do(req)
defer response.Body.Close()
@@ -155,3 +154,15 @@ func newCopier(virConn *libvirt.Connect, volume *libvirt.StorageVol, size uint64
}
return copier
}
+
+func timeFromEpoch(str string) time.Time {
+ var s, ns int
+
+ ts := strings.Split(str, ".")
+ if len(ts) == 2 {
+ ns, _ = strconv.Atoi(ts[1])
+ }
+ s, _ = strconv.Atoi(ts[0])
+
+ return time.Unix(int64(s), int64(ns))
+}
diff --git a/libvirt/utils_volume_test.go b/libvirt/utils_volume_test.go
index 5d8188fb..577d6057 100644
--- a/libvirt/utils_volume_test.go
+++ b/libvirt/utils_volume_test.go
@@ -6,6 +6,9 @@ import (
"io/ioutil"
"os"
"testing"
+ "time"
+
+ "github.com/libvirt/libvirt-go-xml"
)
func TestLocalImageDownload(t *testing.T) {
@@ -24,7 +27,6 @@ func TestLocalImageDownload(t *testing.T) {
if err != nil {
t.Fatal(err)
}
-
url := fmt.Sprintf("file://%s", tmpfile.Name())
image, err := newImage(url)
if err != nil {
@@ -33,9 +35,8 @@ func TestLocalImageDownload(t *testing.T) {
t.Logf("Importing %s", url)
vol := newDefVolume()
- modTime := UnixTimestamp{tmpfileStat.ModTime()}
- vol.Target.Timestamps = &defTimestamps{
- Modification: &modTime,
+ vol.Target.Timestamps = &libvirtxml.StorageVolumeTargetTimestamps{
+ Mtime: fmt.Sprintf("%d.%d", tmpfileStat.ModTime().Unix(), tmpfileStat.ModTime().Nanosecond()),
}
copier := func(r io.Reader) error {
@@ -43,7 +44,7 @@ func TestLocalImageDownload(t *testing.T) {
return nil
}
if err = image.Import(copier, vol); err != nil {
- t.Fatal("Could not copy image from %s: %v", url, err)
+ t.Fatalf("Could not copy image from %s: %v", url, err)
}
t.Log("File not copied because modification time was the same")
}
@@ -72,17 +73,34 @@ func TestRemoteImageDownload(t *testing.T) {
t.Logf("Importing %s", url)
vol := newDefVolume()
- modTime := UnixTimestamp{tmpfileStat.ModTime()}
- vol.Target.Timestamps = &defTimestamps{
- Modification: &modTime,
+ vol.Target.Timestamps = &libvirtxml.StorageVolumeTargetTimestamps{
+ Mtime: fmt.Sprintf("%d.%d", tmpfileStat.ModTime().Unix(), tmpfileStat.ModTime().Nanosecond()),
}
copier := func(r io.Reader) error {
t.Fatalf("ERROR: starting copy of %s... but the file is the same!", url)
return nil
}
if err = image.Import(copier, vol); err != nil {
- t.Fatal("Could not copy image from %s: %v", url, err)
+ t.Fatalf("Could not copy image from %s: %v", url, err)
}
t.Log("File not copied because modification time was the same")
}
+
+func TestTimeFromEpoch(t *testing.T) {
+ if ts := timeFromEpoch(""); ts.UnixNano() > 0 {
+ t.Fatalf("expected timestamp '0.0', got %v.%v", ts.Unix(), ts.Nanosecond())
+ }
+
+ if ts := timeFromEpoch("abc"); ts.UnixNano() > 0 {
+ t.Fatalf("expected timestamp '0.0', got %v.%v", ts.Unix(), ts.Nanosecond())
+ }
+
+ if ts := timeFromEpoch("123"); ts.UnixNano() != time.Unix(123, 0).UnixNano() {
+ t.Fatalf("expected timestamp '123.0', got %v.%v", ts.Unix(), ts.Nanosecond())
+ }
+
+ if ts := timeFromEpoch("123.456"); ts.UnixNano() != time.Unix(123, 456).UnixNano() {
+ t.Fatalf("expected timestamp '123.456', got %v.%v", ts.Unix(), ts.Nanosecond())
+ }
+}
diff --git a/libvirt/volume_def.go b/libvirt/volume_def.go
index f667fe10..6d867240 100644
--- a/libvirt/volume_def.go
+++ b/libvirt/volume_def.go
@@ -3,116 +3,68 @@ package libvirt
import (
"encoding/xml"
"fmt"
- "math"
- "strconv"
- "time"
libvirt "github.com/libvirt/libvirt-go"
+ "github.com/libvirt/libvirt-go-xml"
)
-type UnixTimestamp struct{ time.Time }
-
-func (t *UnixTimestamp) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
- var content string
- if err := d.DecodeElement(&content, &start); err != nil {
- return err
- }
-
- ts, err := strconv.ParseFloat(content, 64)
- if err != nil {
- return err
+func newDefVolume() libvirtxml.StorageVolume {
+ return libvirtxml.StorageVolume{
+ Target: &libvirtxml.StorageVolumeTarget{
+ Format: &libvirtxml.StorageVolumeTargetFormat{
+ Type: "qcow2",
+ },
+ Permissions: &libvirtxml.StorageVolumeTargetPermissions{
+ Mode: "644",
+ },
+ },
+ Capacity: &libvirtxml.StorageVolumeSize{
+ Unit: "bytes",
+ Value: 1,
+ },
}
- s, ns := math.Modf(ts)
- *t = UnixTimestamp{time.Time(time.Unix(int64(s), int64(ns)))}
- return nil
-}
-
-func (t *UnixTimestamp) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
- s := t.UTC().Unix()
- ns := t.UTC().UnixNano()
- return e.EncodeElement(fmt.Sprintf("%d.%d", s, ns), start)
-}
-
-type defTimestamps struct {
- Change *UnixTimestamp `xml:"ctime,omitempty"`
- Modification *UnixTimestamp `xml:"mtime,omitempty"`
- Access *UnixTimestamp `xml:"atime,omitempty"`
-}
-
-type defBackingStore struct {
- Path string `xml:"path"`
- Format struct {
- Type string `xml:"type,attr"`
- } `xml:"format"`
- Timestamps *defTimestamps `xml:"timestamps,omitempty"`
-}
-
-type defVolume struct {
- XMLName xml.Name `xml:"volume"`
- Name string `xml:"name"`
- Target struct {
- Format struct {
- Type string `xml:"type,attr"`
- } `xml:"format"`
- Permissions struct {
- Mode int `xml:"mode,omitempty"`
- } `xml:"permissions,omitempty"`
- Timestamps *defTimestamps `xml:"timestamps,omitempty"`
- } `xml:"target"`
- Allocation int `xml:"allocation"`
- Capacity struct {
- Unit string `xml:"unit,attr"`
- Amount uint64 `xml:"chardata"`
- } `xml:"capacity"`
- BackingStore *defBackingStore `xml:"backingStore,omitempty"`
-}
-
-func newDefVolume() defVolume {
- volumeDef := defVolume{}
- volumeDef.Target.Format.Type = "qcow2"
- volumeDef.Target.Permissions.Mode = 644
- volumeDef.Capacity.Unit = "bytes"
- volumeDef.Capacity.Amount = 1
- return volumeDef
}
// Creates a volume definition from a XML
-func newDefVolumeFromXML(s string) (defVolume, error) {
- var volumeDef defVolume
+func newDefVolumeFromXML(s string) (libvirtxml.StorageVolume, error) {
+ var volumeDef libvirtxml.StorageVolume
err := xml.Unmarshal([]byte(s), &volumeDef)
if err != nil {
- return defVolume{}, err
+ return libvirtxml.StorageVolume{}, err
}
return volumeDef, nil
}
-func newDefVolumeFromLibvirt(volume *libvirt.StorageVol) (defVolume, error) {
+func newDefVolumeFromLibvirt(volume *libvirt.StorageVol) (libvirtxml.StorageVolume, error) {
name, err := volume.GetName()
if err != nil {
- return defVolume{}, fmt.Errorf("could not get name for volume: %s.", err)
+ return libvirtxml.StorageVolume{}, fmt.Errorf("could not get name for volume: %s.", err)
}
volumeDefXml, err := volume.GetXMLDesc(0)
if err != nil {
- return defVolume{}, fmt.Errorf("could not get XML description for volume %s: %s.", name, err)
+ return libvirtxml.StorageVolume{}, fmt.Errorf("could not get XML description for volume %s: %s.", name, err)
}
volumeDef, err := newDefVolumeFromXML(volumeDefXml)
if err != nil {
- return defVolume{}, fmt.Errorf("could not get a volume definition from XML for %s: %s.", volumeDef.Name, err)
+ return libvirtxml.StorageVolume{}, fmt.Errorf("could not get a volume definition from XML for %s: %s.", volumeDef.Name, err)
}
return volumeDef, nil
}
-func newDefBackingStoreFromLibvirt(baseVolume *libvirt.StorageVol) (defBackingStore, error) {
+func newDefBackingStoreFromLibvirt(baseVolume *libvirt.StorageVol) (libvirtxml.StorageVolumeBackingStore, error) {
baseVolumeDef, err := newDefVolumeFromLibvirt(baseVolume)
if err != nil {
- return defBackingStore{}, fmt.Errorf("could not get volume: %s.", err)
+ return libvirtxml.StorageVolumeBackingStore{}, fmt.Errorf("could not get volume: %s.", err)
}
baseVolPath, err := baseVolume.GetPath()
if err != nil {
- return defBackingStore{}, fmt.Errorf("could not get base image path: %s", err)
+ return libvirtxml.StorageVolumeBackingStore{}, fmt.Errorf("could not get base image path: %s", err)
+ }
+ backingStoreDef := libvirtxml.StorageVolumeBackingStore{
+ Path: baseVolPath,
+ Format: &libvirtxml.StorageVolumeTargetFormat{
+ Type: baseVolumeDef.Target.Format.Type,
+ },
}
- var backingStoreDef defBackingStore
- backingStoreDef.Path = baseVolPath
- backingStoreDef.Format.Type = baseVolumeDef.Target.Format.Type
return backingStoreDef, nil
}