prlbackup 1.1.3 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/prlbackup.rb +2 -0
- data/lib/prlbackup/backup.rb +66 -0
- data/lib/prlbackup/version.rb +1 -1
- data/lib/prlbackup/virtual_machine.rb +4 -8
- data/man/prlbackup.1 +1 -1
- data/spec/prlbackup/backup_spec.rb +115 -0
- data/spec/prlbackup/virtual_machine_spec.rb +21 -33
- metadata +27 -24
data/lib/prlbackup.rb
CHANGED
@@ -0,0 +1,66 @@
|
|
1
|
+
module PrlBackup
|
2
|
+
class Backup
|
3
|
+
class << self
|
4
|
+
|
5
|
+
include PrlBackup
|
6
|
+
|
7
|
+
def all(uuid)
|
8
|
+
backup_list(uuid).split("\n").map { |b| create(b) }.compact.sort
|
9
|
+
end
|
10
|
+
|
11
|
+
def backup_list(uuid)
|
12
|
+
run('prlctl', 'backup-list', uuid)
|
13
|
+
end
|
14
|
+
|
15
|
+
def create(line)
|
16
|
+
re = /^
|
17
|
+
(\{[0-9a-f-]+\}) # VM UUID
|
18
|
+
\s+
|
19
|
+
(\{[0-9a-f-]+\}[\.\d]*) # Backup UUID
|
20
|
+
\s+
|
21
|
+
(\S+) # Node
|
22
|
+
\s+
|
23
|
+
([\d\/]+\s[\d:]+) # Time
|
24
|
+
\s+
|
25
|
+
([fi]) # Type
|
26
|
+
\s+
|
27
|
+
(\d+) # Size
|
28
|
+
$/x
|
29
|
+
new(:uuid => $2, :time => $4, :type => $5) if re.match(line)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
include PrlBackup
|
34
|
+
include Comparable
|
35
|
+
|
36
|
+
attr_reader :properties
|
37
|
+
|
38
|
+
def initialize(properties)
|
39
|
+
@properties = properties
|
40
|
+
end
|
41
|
+
|
42
|
+
def uuid
|
43
|
+
properties[:uuid]
|
44
|
+
end
|
45
|
+
|
46
|
+
def time
|
47
|
+
DateTime.parse(properties[:time])
|
48
|
+
end
|
49
|
+
|
50
|
+
def full?
|
51
|
+
properties[:type] == 'f'
|
52
|
+
end
|
53
|
+
|
54
|
+
def delete
|
55
|
+
conditionally_run('prlctl', 'backup-delete', '--tag', uuid)
|
56
|
+
end
|
57
|
+
|
58
|
+
def <=>(other)
|
59
|
+
time <=> other.time
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_s
|
63
|
+
"Backup: #{time.strftime('%Y-%m-%d %H:%M:%S')}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/prlbackup/version.rb
CHANGED
@@ -38,8 +38,7 @@ module PrlBackup
|
|
38
38
|
|
39
39
|
# Cleanup (delete) old backups.
|
40
40
|
def cleanup
|
41
|
-
|
42
|
-
delete_backup(backups.shift) while backups.count > config[:keep_only]
|
41
|
+
full_backups.shift.delete while full_backups.count > config[:keep_only]
|
43
42
|
end
|
44
43
|
|
45
44
|
# Return the virtual machine's name.
|
@@ -97,14 +96,11 @@ module PrlBackup
|
|
97
96
|
update_info[/^State:\s+stopped$/]
|
98
97
|
end
|
99
98
|
|
100
|
-
#
|
99
|
+
# Cached list of virtual machine's full backups.
|
100
|
+
# @return [Array<Backup>] full backups
|
101
101
|
def full_backups
|
102
|
-
|
102
|
+
@full_backups ||= Backup.all(uuid).select { |b| b.full? }
|
103
103
|
end
|
104
104
|
|
105
|
-
# Delete the backup given by backup UUID.
|
106
|
-
def delete_backup(backup_uuid)
|
107
|
-
conditionally_run('prlctl', 'backup-delete', '--tag', backup_uuid)
|
108
|
-
end
|
109
105
|
end
|
110
106
|
end
|
data/man/prlbackup.1
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
.\" generated with Ronn/v0.7.3
|
2
2
|
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
3
3
|
.
|
4
|
-
.TH "PRLBACKUP" "1" "May 2012" "" "PRLBACKUP V1.
|
4
|
+
.TH "PRLBACKUP" "1" "May 2012" "" "PRLBACKUP V1.2.0"
|
5
5
|
.
|
6
6
|
.SH "NAME"
|
7
7
|
\fBprlbackup\fR \- an awesome backup tool for Parallels Server Virtual Machines
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module PrlBackup
|
4
|
+
describe Backup do
|
5
|
+
before do
|
6
|
+
@uuid = '{deadbeef}'
|
7
|
+
Backup.stub(:run).and_return('')
|
8
|
+
Backup.stub(:conditionally_run).and_return('')
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '.all' do
|
12
|
+
it 'should query the backup list by UUID' do
|
13
|
+
Backup.should_receive(:backup_list).with(@uuid).and_return('')
|
14
|
+
Backup.all(@uuid)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should initialize backups by line' do
|
18
|
+
Backup.stub(:backup_list).and_return("line 1\nline 2")
|
19
|
+
Backup.should_receive(:create).with('line 1')
|
20
|
+
Backup.should_receive(:create).with('line 2')
|
21
|
+
Backup.all(@uuid)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should only return successfully initialized backups' do
|
25
|
+
Backup.stub(:backup_list).and_return("line 1\nline 2\nline 3")
|
26
|
+
Backup.stub(:create).and_return(nil, 'backup', nil)
|
27
|
+
Backup.all(@uuid).should eql(['backup'])
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should return the backups sorted' do
|
31
|
+
backup1 = Backup.new(:time => '02/27/2012 13:11:31')
|
32
|
+
backup2 = Backup.new(:time => '02/27/2012 13:11:32')
|
33
|
+
backup3 = Backup.new(:time => '02/27/2012 13:11:33')
|
34
|
+
Backup.stub(:create).and_return(backup2, backup3, backup1)
|
35
|
+
Backup.stub(:backup_list).and_return("line 1\nline 2\nline 3")
|
36
|
+
Backup.all(@uuid).should eql([backup1, backup2, backup3])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '.backup_list' do
|
41
|
+
it 'should query and return the backup list by UUID' do
|
42
|
+
Backup.should_receive(:run).with('prlctl', 'backup-list', @uuid).and_return('backup list')
|
43
|
+
Backup.backup_list(@uuid).should eql('backup list')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '.create' do
|
48
|
+
it 'should initialize a backup with properties' do
|
49
|
+
line = '{deadbeef} {ae6565dd-7f8f-42cb-a088-8b1d98f5160b} psfm.example.com 02/27/2012 13:11:32 f 10537597943'
|
50
|
+
backup = Backup.create(line)
|
51
|
+
backup.properties[:uuid].should eql('{ae6565dd-7f8f-42cb-a088-8b1d98f5160b}')
|
52
|
+
backup.properties[:time].should eql('02/27/2012 13:11:32')
|
53
|
+
backup.properties[:type].should eql('f')
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should return nil when the backup line is not parsable' do
|
57
|
+
Backup.create('hello, world.').should be_nil
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '#uuid' do
|
62
|
+
it 'should return the backup uuid' do
|
63
|
+
backup = Backup.new(:uuid => '{ae6565dd-7f8f-42cb-a088-8b1d98f5160b}')
|
64
|
+
backup.uuid.should eql('{ae6565dd-7f8f-42cb-a088-8b1d98f5160b}')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '#time' do
|
69
|
+
it 'should return the time object' do
|
70
|
+
backup = Backup.new(:time => '02/27/2012 13:11:32')
|
71
|
+
backup.time.year.should eql(2012)
|
72
|
+
backup.time.month.should eql(2)
|
73
|
+
backup.time.day.should eql(27)
|
74
|
+
backup.time.hour.should eql(13)
|
75
|
+
backup.time.min.should eql(11)
|
76
|
+
backup.time.sec.should eql(32)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe '#full?' do
|
81
|
+
it 'should be true when full' do
|
82
|
+
backup = Backup.new(:type => 'f')
|
83
|
+
backup.should be_full
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should be false when incremental' do
|
87
|
+
backup = Backup.new(:type => 'i')
|
88
|
+
backup.should_not be_full
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '#delete' do
|
93
|
+
it 'should delete itself' do
|
94
|
+
backup = Backup.new(:uuid => '{some-backup-uuid}')
|
95
|
+
backup.should_receive(:conditionally_run).with('prlctl', 'backup-delete', '--tag', '{some-backup-uuid}')
|
96
|
+
backup.delete
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#<=>' do
|
101
|
+
it 'should compare backups by time' do
|
102
|
+
first_backup = Backup.new(:time => '02/27/2012 13:11:32')
|
103
|
+
last_backup = Backup.new(:time => '02/27/2012 13:11:33')
|
104
|
+
first_backup.should < last_backup
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe '#to_s' do
|
109
|
+
it 'should display the backup time' do
|
110
|
+
backup = Backup.new(:time => '02/27/2012 13:11:32')
|
111
|
+
backup.to_s.should eql('Backup: 2012-02-27 13:11:32')
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -112,55 +112,43 @@ module PrlBackup
|
|
112
112
|
|
113
113
|
it 'should delete 2 backups when there are 2 more backups than to keep' do
|
114
114
|
@vm.stub(:config).and_return({:keep_only => 0})
|
115
|
-
@
|
116
|
-
@
|
115
|
+
@old_backup.should_receive(:delete).once
|
116
|
+
@new_backup.should_receive(:delete).once
|
117
117
|
@vm.cleanup
|
118
118
|
end
|
119
119
|
|
120
120
|
it 'should delete the oldest backup when there is 1 more backup than to keep' do
|
121
121
|
@vm.stub(:config).and_return({:keep_only => 1})
|
122
|
-
@
|
123
|
-
@
|
122
|
+
@old_backup.should_receive(:delete).once
|
123
|
+
@new_backup.should_not_receive(:delete)
|
124
124
|
@vm.cleanup
|
125
125
|
end
|
126
126
|
|
127
127
|
it 'should not delete any backups when there are as many backups as to keep' do
|
128
128
|
@vm.stub(:config).and_return({:keep_only => 2})
|
129
|
-
@
|
129
|
+
@old_backup.should_not_receive(:delete)
|
130
|
+
@new_backup.should_not_receive(:delete)
|
130
131
|
@vm.cleanup
|
131
132
|
end
|
132
133
|
end
|
133
134
|
|
134
|
-
describe '#delete_backup' do
|
135
|
-
it 'should delete the virtual machines backup' do
|
136
|
-
@vm.should_receive(:conditionally_run).with('prlctl', 'backup-delete', '--tag', '{some-backup-uuid}')
|
137
|
-
@vm.instance_eval { delete_backup('{some-backup-uuid}') }
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
135
|
describe '#full_backups' do
|
142
136
|
before do
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
it 'should return a list of the virtual machines full backup UUIDs' do
|
160
|
-
@vm.instance_eval { full_backups }.should eql(['{ae6565dd-7f8f-42cb-a088-8b1d98f5160b}',
|
161
|
-
'{5f9dd263-ec56-443e-9917-dab9b40d3027}',
|
162
|
-
'{2aeb4ada-6623-4087-9fc5-f09aeaafd81e}',
|
163
|
-
'{68f7e154-6755-46f6-ad1f-a79c5f488f35}'])
|
137
|
+
Backup.stub(:all).and_return([])
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'should query list of backups for given UUID once' do
|
141
|
+
Backup.should_receive(:all).with(@vm.uuid).once
|
142
|
+
2.times { @vm.instance_eval { full_backups } }
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'should return only full backups' do
|
146
|
+
full_backup = double('full backup')
|
147
|
+
full_backup.stub(:full?).and_return(true)
|
148
|
+
incremental_backup = double('incremental backup')
|
149
|
+
incremental_backup.stub(:full?).and_return(false)
|
150
|
+
Backup.stub(:all).and_return([full_backup, incremental_backup])
|
151
|
+
@vm.instance_eval { full_backups }.should eql([full_backup])
|
164
152
|
end
|
165
153
|
end
|
166
154
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prlbackup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2012-05-05 00:00:00.000000000Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mixlib-cli
|
16
|
-
requirement: &
|
16
|
+
requirement: &70297487607280 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 1.2.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70297487607280
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: gem-man
|
27
|
-
requirement: &
|
27
|
+
requirement: &70297487605600 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 0.3.0
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70297487605600
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: cucumber
|
38
|
-
requirement: &
|
38
|
+
requirement: &70297487603540 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 1.1.4
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70297487603540
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: aruba
|
49
|
-
requirement: &
|
49
|
+
requirement: &70297487584840 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 0.4.11
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70297487584840
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: aruba-doubles
|
60
|
-
requirement: &
|
60
|
+
requirement: &70297487583560 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: 1.2.1
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70297487583560
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: guard-cucumber
|
71
|
-
requirement: &
|
71
|
+
requirement: &70297487581460 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: 0.7.5
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70297487581460
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: guard-rspec
|
82
|
-
requirement: &
|
82
|
+
requirement: &70297487579380 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: 0.5.1
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70297487579380
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: ronn
|
93
|
-
requirement: &
|
93
|
+
requirement: &70297487578400 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: 0.7.3
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70297487578400
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: rake
|
104
|
-
requirement: &
|
104
|
+
requirement: &70297487576720 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ! '>='
|
@@ -109,10 +109,10 @@ dependencies:
|
|
109
109
|
version: '0'
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *70297487576720
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: rb-fsevent
|
115
|
-
requirement: &
|
115
|
+
requirement: &70297487574660 !ruby/object:Gem::Requirement
|
116
116
|
none: false
|
117
117
|
requirements:
|
118
118
|
- - ! '>='
|
@@ -120,7 +120,7 @@ dependencies:
|
|
120
120
|
version: 0.9.0
|
121
121
|
type: :development
|
122
122
|
prerelease: false
|
123
|
-
version_requirements: *
|
123
|
+
version_requirements: *70297487574660
|
124
124
|
description: an awesome backup tool for Parallels Server Virtual Machines
|
125
125
|
email:
|
126
126
|
- bjoernalbers@googlemail.com
|
@@ -142,12 +142,14 @@ files:
|
|
142
142
|
- features/steps/dev_steps.rb
|
143
143
|
- features/support/env.rb
|
144
144
|
- lib/prlbackup.rb
|
145
|
+
- lib/prlbackup/backup.rb
|
145
146
|
- lib/prlbackup/cli.rb
|
146
147
|
- lib/prlbackup/version.rb
|
147
148
|
- lib/prlbackup/virtual_machine.rb
|
148
149
|
- man/prlbackup.1
|
149
150
|
- man/prlbackup.1.ronn
|
150
151
|
- prlbackup.gemspec
|
152
|
+
- spec/prlbackup/backup_spec.rb
|
151
153
|
- spec/prlbackup/cli_spec.rb
|
152
154
|
- spec/prlbackup/virtual_machine_spec.rb
|
153
155
|
- spec/prlbackup_spec.rb
|
@@ -166,7 +168,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
166
168
|
version: '0'
|
167
169
|
segments:
|
168
170
|
- 0
|
169
|
-
hash:
|
171
|
+
hash: -855199531079728294
|
170
172
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
171
173
|
none: false
|
172
174
|
requirements:
|
@@ -175,13 +177,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
175
177
|
version: '0'
|
176
178
|
segments:
|
177
179
|
- 0
|
178
|
-
hash:
|
180
|
+
hash: -855199531079728294
|
179
181
|
requirements: []
|
180
182
|
rubyforge_project:
|
181
183
|
rubygems_version: 1.8.10
|
182
184
|
signing_key:
|
183
185
|
specification_version: 3
|
184
|
-
summary: prlbackup-1.
|
186
|
+
summary: prlbackup-1.2.0
|
185
187
|
test_files:
|
186
188
|
- features/cleanup.feature
|
187
189
|
- features/create_backups.feature
|
@@ -189,6 +191,7 @@ test_files:
|
|
189
191
|
- features/logging.feature
|
190
192
|
- features/steps/dev_steps.rb
|
191
193
|
- features/support/env.rb
|
194
|
+
- spec/prlbackup/backup_spec.rb
|
192
195
|
- spec/prlbackup/cli_spec.rb
|
193
196
|
- spec/prlbackup/virtual_machine_spec.rb
|
194
197
|
- spec/prlbackup_spec.rb
|