Skip to content

Commit ac9e0b6

Browse files
Merge pull request digitalocean#172 from sam-github/portable-snapshot
Snapshot portability across libvirt 3 and 6
2 parents 152a153 + f61adc1 commit ac9e0b6

File tree

2 files changed

+48
-34
lines changed

2 files changed

+48
-34
lines changed

qemu/block.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -158,13 +158,14 @@ func (bd BlockDevice) Mirror(d *Domain, dest string, timeout time.Duration) erro
158158
// Commit synchronously merges an overlay image onto a block device's
159159
// root backing image. Once the operation is complete, CompleteJob()
160160
// must be called to pivot the domain back to the original backing image.
161-
func (bd BlockDevice) Commit(d *Domain, overlay string, timeout time.Duration) error {
161+
func (bd BlockDevice) Commit(d *Domain, overlay, jobID string, timeout time.Duration) error {
162162
return waitForSignal(d, blockJobReady, timeout, func() error {
163163
cmd := qmp.Command{
164164
Execute: "block-commit",
165165
Args: map[string]string{
166-
"device": bd.Device,
166+
"device": bd.Inserted.NodeName,
167167
"top": overlay,
168+
"job-id": jobID,
168169
},
169170
}
170171

@@ -173,14 +174,14 @@ func (bd BlockDevice) Commit(d *Domain, overlay string, timeout time.Duration) e
173174
})
174175
}
175176

176-
// CancelJob cancels any active block jobs on a block device.
177-
// For block-mirror operations, this completes the block job.
178-
func (bd BlockDevice) CancelJob(d *Domain, timeout time.Duration) error {
177+
// Cancel a running block job.
178+
// For block-mirror operations, this cancels the block job.
179+
func (job BlockJob) Cancel(d *Domain, timeout time.Duration) error {
179180
return waitForSignal(d, blockJobCompleted, timeout, func() error {
180181
cmd := qmp.Command{
181182
Execute: "block-job-cancel",
182183
Args: map[string]string{
183-
"device": bd.Device,
184+
"device": job.Device,
184185
},
185186
}
186187

@@ -189,15 +190,15 @@ func (bd BlockDevice) CancelJob(d *Domain, timeout time.Duration) error {
189190
})
190191
}
191192

192-
// CompleteJob finalizes any running block jobs on the provided block device.
193+
// Complete a running block job.
193194
// For blockcommit backups, this performs the "pivot" back to the original
194195
// backing image.
195-
func (bd BlockDevice) CompleteJob(d *Domain, timeout time.Duration) error {
196+
func (job BlockJob) Complete(d *Domain, timeout time.Duration) error {
196197
return waitForSignal(d, blockJobCompleted, timeout, func() error {
197198
cmd := qmp.Command{
198199
Execute: "block-job-complete",
199200
Args: map[string]string{
200-
"device": bd.Device,
201+
"device": job.Device,
201202
},
202203
}
203204

@@ -209,12 +210,13 @@ func (bd BlockDevice) CompleteJob(d *Domain, timeout time.Duration) error {
209210
// Snapshot creates a point in time snapshot.
210211
// The disk's image is given a new QCOW2 overlay, leaving the underlying image
211212
// in a state that is considered safe for copying.
212-
func (bd BlockDevice) Snapshot(d *Domain, overlay string) error {
213+
func (bd BlockDevice) Snapshot(d *Domain, overlay, nodeName string) error {
213214
cmd := qmp.Command{
214215
Execute: "blockdev-snapshot-sync",
215216
Args: map[string]string{
216-
"device": bd.Device,
217-
"snapshot-file": overlay,
217+
"node-name": bd.Inserted.NodeName,
218+
"snapshot-node-name": nodeName,
219+
"snapshot-file": overlay,
218220
},
219221
}
220222

qemu/block_test.go

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,18 @@ func TestCancelJob(t *testing.T) {
3939
})
4040
defer done()
4141

42-
disk := BlockDevice{Device: device}
43-
err := disk.CancelJob(d, defaultTestTimeout)
42+
job := BlockJob{Device: device}
43+
err := job.Cancel(d, defaultTestTimeout)
4444
if err != nil {
4545
t.Error(err)
4646
}
4747
}
4848

4949
func TestCommit(t *testing.T) {
5050
const (
51-
device = "drive-virtio-disk0"
51+
device = "inserted[node-name] before commit"
5252
overlay = "/tmp/foo.img"
53+
jobID = "made-up-job-id-for-the-commit"
5354
)
5455
d, done := testDomain(t, func(cmd qmp.Command) (interface{}, error) {
5556
if want, got := "block-commit", cmd.Execute; want != got {
@@ -66,20 +67,24 @@ func TestCommit(t *testing.T) {
6667
t.Fatalf("unexpected device:\n- want: %q\n- got: %q",
6768
want, got)
6869
}
70+
if want, got := jobID, args["job-id"]; want != got {
71+
t.Fatalf("unexpected job-id:\n- want: %q\n- got: %q",
72+
want, got)
73+
}
6974

7075
return success{}, nil
7176
})
7277
defer done()
7378

74-
disk := BlockDevice{Device: device}
75-
err := disk.Commit(d, overlay, defaultTestTimeout)
79+
disk := BlockDevice{}
80+
disk.Inserted.NodeName = device
81+
err := disk.Commit(d, overlay, jobID, defaultTestTimeout)
7682
if err != nil {
7783
t.Error(err)
7884
}
7985
}
8086

8187
func TestCommitActiveBlockJob(t *testing.T) {
82-
const device = "drive-virtio-disk0"
8388
d, done := testDomain(t, func(_ qmp.Command) (interface{}, error) {
8489
return failure{
8590
Error: map[string]string{
@@ -89,8 +94,8 @@ func TestCommitActiveBlockJob(t *testing.T) {
8994
})
9095
defer done()
9196

92-
disk := BlockDevice{Device: device}
93-
err := disk.Commit(d, "/tmp/foo", defaultTestTimeout)
97+
disk := BlockDevice{}
98+
err := disk.Commit(d, "/tmp/foo", "job-id", defaultTestTimeout)
9499
if err == nil {
95100
t.Errorf("expected blockcommit with active blockjob to fail")
96101
}
@@ -103,8 +108,8 @@ func TestCommitBlockJobError(t *testing.T) {
103108
d.m.(*testMonitor).eventErrors = true
104109
defer done()
105110

106-
disk := BlockDevice{Device: "test"}
107-
err := disk.Commit(d, "/tmp/foo", defaultTestTimeout)
111+
disk := BlockDevice{}
112+
err := disk.Commit(d, "/tmp/foo", "job-id", defaultTestTimeout)
108113
if err == nil {
109114
t.Error("expected block job error to cause failure")
110115
}
@@ -118,7 +123,7 @@ func TestCommitTimeout(t *testing.T) {
118123
defer done()
119124

120125
disk := BlockDevice{Device: "test"}
121-
err := disk.Commit(d, "/tmp/foo", 0)
126+
err := disk.Commit(d, "/tmp/foo", "job-id", 0)
122127
if err == nil {
123128
t.Error("expected timeout")
124129
}
@@ -142,8 +147,8 @@ func TestJobComplete(t *testing.T) {
142147
})
143148
defer done()
144149

145-
disk := BlockDevice{Device: device}
146-
err := disk.CompleteJob(d, defaultTestTimeout)
150+
job := BlockJob{Device: device}
151+
err := job.Complete(d, defaultTestTimeout)
147152
if err != nil {
148153
t.Error(err)
149154
}
@@ -156,8 +161,8 @@ func TestJobCompleteEventError(t *testing.T) {
156161
d.m.(*testMonitor).eventErrors = true
157162
defer done()
158163

159-
disk := BlockDevice{Device: "test"}
160-
err := disk.CompleteJob(d, defaultTestTimeout)
164+
job := BlockJob{Device: "test"}
165+
err := job.Complete(d, defaultTestTimeout)
161166
if err == nil {
162167
t.Error("expected block job error to cause failure")
163168
}
@@ -170,8 +175,8 @@ func TestJobCompleteTimeout(t *testing.T) {
170175
d.m.(*testMonitor).eventTimeout = true
171176
defer done()
172177

173-
disk := BlockDevice{Device: "test"}
174-
err := disk.CompleteJob(d, 0)
178+
job := BlockJob{Device: "test"}
179+
err := job.Complete(d, 0)
175180
if err == nil {
176181
t.Error("expected timeout")
177182
}
@@ -229,8 +234,9 @@ func TestMirrorRelativePath(t *testing.T) {
229234

230235
func TestSnapshot(t *testing.T) {
231236
const (
232-
device = "drive-virtio-disk0"
233-
overlay = "/tmp/foo.img"
237+
device = "drive-virtio-disk0"
238+
overlay = "/tmp/foo.img"
239+
nodeName = "my-node"
234240
)
235241
d, done := testDomain(t, func(cmd qmp.Command) (interface{}, error) {
236242
if want, got := "blockdev-snapshot-sync", cmd.Execute; want != got {
@@ -239,7 +245,7 @@ func TestSnapshot(t *testing.T) {
239245
}
240246

241247
args, _ := cmd.Args.(map[string]interface{})
242-
if want, got := device, args["device"]; want != got {
248+
if want, got := device, args["node-name"]; want != got {
243249
t.Fatalf("unexpected device:\n- want: %q\n- got: %q",
244250
want, got)
245251
}
@@ -249,12 +255,18 @@ func TestSnapshot(t *testing.T) {
249255
want, got)
250256
}
251257

258+
if want, got := nodeName, args["snapshot-node-name"]; want != got {
259+
t.Fatalf("unexpected target:\n- want: %q\n- got: %q",
260+
want, got)
261+
}
262+
252263
return success{}, nil
253264
})
254265
defer done()
255266

256-
disk := BlockDevice{Device: device}
257-
err := disk.Snapshot(d, overlay)
267+
disk := BlockDevice{}
268+
disk.Inserted.NodeName = device
269+
err := disk.Snapshot(d, overlay, "my-node")
258270
if err != nil {
259271
t.Error(err)
260272
}

0 commit comments

Comments
 (0)