ekko/tools/backup.py

95 lines
2.7 KiB
Python

#!/usr/bin/python
# Copyright 2016 Sam Yaple
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Copied and licensed from https://github.com/SamYaple/osdk
from hashlib import sha1
from osdk import osdk
from uuid import uuid4 as uuid
def get_disk_size(device):
with open(device, 'rb') as f:
return f.seek(0, 2)
def read_segments(f, lst, size, o):
zero_hash = sha1(bytes([0] * size)).hexdigest()
for segment in lst:
f.seek(segment * size, 0)
data = f.read(size)
if not data:
raise Exception('Failed to read data')
sha1_hash = sha1(data)
if sha1_hash.hexdigest() != zero_hash:
meta = dict()
meta['incremental'] = o.metadata['incremental']
meta['base'] = len(o.metadata['bases']) - 1
meta['encryption'] = 0
meta['compression'] = 0
meta['sha1_hash'] = sha1_hash.digest()
o.segments[segment] = meta
else:
try:
del o.segments[segment]
except KeyError:
pass
def main():
device = '/dev/loop0'
old_manifest = 'manifest0.osdk'
manifest = 'manifest0.osdk'
manifest = 'manifest1.osdk'
segment_size = 4 * 1024**2 # 4MiB
size_of_disk = get_disk_size(device)
num_of_sectors = int(size_of_disk / 512)
num_of_segments = int(size_of_disk / segment_size)
o = osdk(manifest)
o.metadata['sectors'] = num_of_sectors
new = True
new = False
existing = True
existing_full = True
existing_full = False
if new:
o.metadata['incremental'] = 0
o.metadata['segment_size'] = segment_size
o.metadata['bases'] = [uuid().bytes]
segments_to_read = range(0, num_of_segments - 1)
elif existing:
o.read_manifest(old_manifest)
o.metadata['incremental'] += 1
segments_to_read = range(1, num_of_segments - 1)
elif existing_full:
o.read_manifest(old_manifest)
o.metadata['incremental'] += 1
segments_to_read = range(0, num_of_segments - 1)
with open(device, 'rb+') as f:
read_segments(f, segments_to_read, segment_size, o)
o.write_manifest()
if __name__ == '__main__':
main()