Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
- #
- # backuputils.py
- #
- # Copyright 2009 Moises Henriquez <M0E.lnx [at] gmail [dot] com>
- #
- # This program is free software; you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation; either version 3 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- # MA 02110-1301, USA.
- """
- Backup utilities for vectorlinux.
- Provides a way to safely perform a system upgrade.
- """
- import glob
- import os
- import sys
- import commands
- from subprocess import call
- tmpdir = "/tmp/vl-backup"
- today = commands.getoutput('date +\%Y-\%m-\%d')
- pkgdir = "/var/log/packages"
- scriptdir = "/var/log/scripts"
- tmp_pkg = os.path.join(tmpdir, today,"tmp")
- def save_new_packages_list():
- """
- Create a record of new packages that will get installed as a result of
- a system upgrade
- This list contains packages that must be removed in case of a roll back
- file list is called 'rollback'
- """
- pre = commands.getoutput("slapt-get --upgrade -s")
- ret = pre.split("\n")
- new = []
- for l in ret:
- if "is to be upgraded" in l:
- pass
- else:
- pk = l.strip().split(" ")[0]
- new.append(pk)
- if len(new) <= 0:
- return
- f = open(os.path.join(tmpdir,today,"rollback"),"w")
- f.write("\n".join(new) + "\n")
- f.close()
- def read_preupgrade_report():
- """
- Reads a short (internal) report of packages to be upgrade
- and installed.
- Takes no arguments and returns a list of package names (upgrades only)
- """
- pre = commands.getoutput("slapt-get --upgrade -s")
- ret = pre.split("\n")
- m = 0
- new = []
- for l in ret:
- if "After unpacking" in l:
- m = ret.index(l) + 1
- while m < (len(ret) - 1):
- str = ret[m].split(" ")[0]
- new.append(str)
- m = m + 1
- return new
- def perform_backup():
- """
- Performs a backup of existing packages to be upgraded by slapt-get
- Also creates a list of new packages to be removed in case the
- backup is rolled over.
- Takes no arguments (yet)
- """
- if os.path.exists(tmpdir) == False:
- os.makedirs(tmpdir)
- if os.path.exists(os.path.join(tmpdir,today)) == False:
- os.makedirs(os.path.join(tmpdir, today))
- for i in read_preupgrade_report():
- pkg = Package(os.path.join(pkgdir,i))
- pkg.backup()
- def restore_backup(datecode):
- """Restores a previously performed backup
- Takes one argument ie,
- restore_backup(2009-11-01)
- """
- if os.path.exists(os.path.join(tmpdir, datecode)) == False:
- print "No records of a backup for %s" % datecode
- list = os.listdir(os.path.join(tmpdir, datecode))
- for i in list:
- pkg = Package(i)
- print "Restore %s" % i
- try:
- res = call('/sbin/removepkg ' + pkg.appname, shell=True)
- if res < 0:
- print "Finished with",-res
- except OSError, e:
- print "Error", e
- try:
- res = call('/sbin/installpkg ' + os.path.join( \
- tmpdir, datecode, i), shell=True)
- if res < 0:
- print "Ended with", -res
- except OSError, e:
- print "Error",e
- class Package():
- """
- Returns a package object
- Takes one argument, a file path to a package in /var/log/packages/
- ie:
- pkg = Package('/var/log/packages/foo-bar-1.2.3-i586-1vl60')
- Use the following methods with it
- pkg.backup - Re-creates the original package
- OTHER INTERNAL USE METHODS
- pkg.generate_desc - Returns the package description (as a list)
- pkg.generate_doinst - Returns the package's install script (as a list)
- pkg.backup_files - creates backup copies of files in the package. """
- def __init__(self, name):
- self.pkgname = os.path.split(name)[-1]
- self.pkgdir = '/var/log/packages/'
- self.scriptdir = '/var/log/scripts/'
- sp = self.pkgname.rsplit("-",3)
- self.appname = os.path.split(sp[0])[-1]
- file = open(os.path.join(self.pkgdir,name),'r')
- self.data = file.readlines()
- file.close()
- self.desc = "\n".join(self.generate_desc()) + "\n"
- def generate_desc(self):
- """
- Returns a package's description as a list"""
- ret = []
- for i in self.data:
- if i[:len(self.appname)] == self.appname:
- ret.append(i.strip())
- return ret
- def generate_doinst(self):
- """
- Returns a packages install script (if exists) as a list"""
- if os.path.exists(os.path.join(self.scriptdir,self.pkgname)) == False:
- return
- data = open(os.path.join(self.scriptdir,self.pkgname),'r')
- file = data.readlines()
- ret = []
- for i in file:
- ret.append(i.strip())
- return ret
- def backup_files(self):
- """
- Create backup copies of the files in the package object
- """
- l = self.data.index("./\n") + 1
- n = 0
- tmp_pkg = os.path.join(tmpdir, today, "tmp")
- if os.path.exists(os.path.join(pkgdir, self.pkgname)) == False:
- print "%s is not installed" % self.pkgname
- return
- commands.getoutput("rm -r " + tmp_pkg)
- commands.getoutput("mkdir -p " + tmp_pkg)
- n = l
- while l < len(self.data):
- # print "making dir %s/%s" % (l,len(self.data))
- if os.path.isdir(os.path.join("/",self.data[l].strip())) == True:
- commands.getoutput("mkdir -p " + os.path.join(tmp_pkg,self.data[l].strip()))
- else:
- commands.getoutput("mkdir -p " + os.path.dirname(os.path.join(tmp_pkg,self.data[l].strip())))
- l = l + 1
- while n < len(self.data):
- # print "copying files %s/%s" % (n,len(self.data))
- src = os.path.join("/",self.data[n].strip())
- trgt = os.path.join(tmpdir,today,"tmp") + src
- if os.path.isdir(os.path.join("/",self.data[n].strip())) == True:
- pass
- else:
- # print src + " -> " + trgt
- commands.getoutput("cp -arp " + src + " " + trgt)
- n = n + 1
- if os.path.isdir(os.path.join(tmp_pkg,"install")) == False:
- os.makedirs(os.path.join(tmp_pkg,"install"))
- if self.generate_desc() != None:
- desc = open(os.path.join(tmp_pkg,"install/slack-desc"),'w')
- desc.write("\n".join(self.generate_desc()) + "\n")
- desc.close()
- # Backup the doinst.sh script
- if self.generate_doinst() != None:
- script = open(os.path.join(tmp_pkg,'install/doinst.sh'),'w')
- script.write("\n".join(self.generate_doinst()) + "\n")
- script.close()
- # cleanup the temp dir
- #commands.getoutput("rm -rf " + tmp_pkg + "/*")
- def repack(self):
- """
- Re-create the package using the backed up files
- *** For internal use only ***"""
- print "Re-packaging %s to %s" % (self.pkgname, os.path.join(tmpdir,today, self.pkgname) + ".txz")
- os.chdir(tmp_pkg + "/")
- commands.getoutput("/sbin/makepkg -l y -c n %s" % (self.pkgname + ".txz"))
- commands.getoutput("rm -rf " + tmp_pkg + "/*")
- os.chdir(tmpdir)
- def backup(self):
- """
- Create a complete backup of the package object using the backed up
- files. """
- self.backup_files()
- self.repack()
- def check_root():
- return os.getuid()
- def safe_upgrade():
- """
- Performs a safe system upgrade by creating backup copies of packages to be
- upgrade before the upgrade."""
- if len(read_preupgrade_report()) > 0:
- print "Performing backup safety net"
- perform_backup()
- try:
- ret = call("/sbin/slapt-get -y --upgrade",shell=True)
- if ret < 0:
- print "Error while upgrading packages", -ret
- except OSError, e:
- print "safe upgrade failed with error",e
- else:
- print "No upgrades available"
- sys.exit()
- def main():
- if check_root() > 0:
- print "You must be root to use this"
- sys.exit()
- if __name__ == '__main__':
- main()
Add Comment
Please, Sign In to add comment