65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
# File 'lib/zfs_mgmt/restic.rb', line 65
def self.backup(backup_level: 2,
options: {})
ZfsMgmt.zfs_managed_list(filter: options['filter'],
properties: ['name',
'zfsmgmt:restic_backup',
'zfsmgmt:restic_repository',
'userrefs',
],
property_match: { 'zfsmgmt:restic_backup' => ['on','true'] }).each do |blob|
zfs,props,zfs_snapshots = blob
last_zfs_snapshot = zfs_snapshots.keys.sort { |a,b| zfs_snapshots[a]['creation'] <=> zfs_snapshots[b]['creation'] }.last
zfs_snap_time = Time.at(zfs_snapshots[last_zfs_snapshot]['creation'])
level = 0
chain = []
zfs_snap_parent = ''
restic_snap_parent = ''
(restic_snapshots,restic_snapshot_zfs_snapshot_index) = restic_snapshots(zfs,options,props)
if restic_snapshot_zfs_snapshot_index.has_key?(last_zfs_snapshot)
$logger.warn("backup of this snapshot #{last_zfs_snapshot} already exists in restic, cannot continue with backup of #{zfs}")
next
end
if backup_level > 0 and restic_snapshots.count > 0
restic_snap_parent = restic_snapshots.filter { |rsnap|
rsnap.has_key?('zfsmgmt:zfs') and rsnap['zfsmgmt:zfs'] == zfs and
rsnap.has_key?('zfsmgmt:level') and rsnap['zfsmgmt:level'] < backup_level }.sort {
|a,b| a['date_time'] <=> b['date_time'] }.last
if restic_snap_parent and
zfs_snapshots.has_key?(restic_snap_parent['zfsmgmt:snapshot']) and
chain = valid_chain(restic_snap_parent,restic_snapshots,restic_snapshot_zfs_snapshot_index,[]) and
chain.length > 0
level = restic_snap_parent['zfsmgmt:level'] + 1
zfs_snap_parent = restic_snap_parent['zfsmgmt:snapshot']
$logger.debug("restic_snap_parent: level: #{restic_snap_parent['zfsmgmt:level']} snapshot: #{zfs_snap_parent}")
else
$logger.error("restic_snap_parent rejected: level: #{restic_snap_parent['zfsmgmt:level']} snapshot: #{restic_snap_parent['zfsmgmt:snapshot']}")
end
$logger.debug("chain of snapshots: #{chain}")
end
tags = [ 'zfsmgmt',
"zfsmgmt:snapshot=#{last_zfs_snapshot}",
"zfsmgmt:zfs=#{zfs}",
"zfsmgmt:level=#{level}" ]
com = [ ZfsMgmt.global_options['zfs_binary'], 'send', '-w', '-h', '-p' ]
if level > 0
if options[:intermediary]
com.push('-I')
else
com.push('-i')
end
com.push(zfs_snap_parent)
tags.push("zfsmgmt:parent=#{zfs_snap_parent}")
end
com.push( last_zfs_snapshot )
com.push( '|', 'mbuffer', '-m', options[:buffer], '-q' )
com.push( '|', options[:restic_binary], 'backup', '--stdin',
'--stdin-filename', zfs, '--time', "\"#{zfs_snap_time.strftime('%F %T')}\"" )
tags.each do |tag|
com.push( '--tag', "\"#{tag}\"" )
end
if options.has_key?('limit_upload')
com.push('--limit-upload', options['limit_upload'])
end
if options.has_key?('password_file')
com.push('-p',options['password_file'])
end
if options.has_key?('repo')
com.push('--repo', options['repo'])
elsif props.has_key?('zfsmgmt:restic_repository')
com.push( '--repo', props['zfsmgmt:restic_repository'] )
end
if options[:verbose]
com.push('--verbose',options[:verbose])
elsif $stdout.isatty
com.push('-v')
end
unless ZfsMgmt.zfs_holds(last_zfs_snapshot).include?('zfsmgmt_restic')
ZfsMgmt.zfs_hold('zfsmgmt_restic',last_zfs_snapshot)
end
ZfsMgmt.system_com(com)
chain_snaps = chain.map do |rsnap|
rsnap['zfsmgmt:snapshot']
end
zfs_snapshots.each do |s,d|
d['userrefs'] == 0 and next
chain_snaps.include?(s) and next
s == last_zfs_snapshot and next
if ZfsMgmt.zfs_holds(s).include?('zfsmgmt_restic')
ZfsMgmt.zfs_release('zfsmgmt_restic',s)
end
end
end
end
|