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.
- Part of the vlutils package
- """
- import glob
- import os
- import sys
- import commands
- from subprocess import call
- import ConfigParser
- import datetime
- __version__ = '0.1.1'
- configpath = '/etc/vlupdater.conf'
- #tmpdir = ""
- if os.path.exists(configpath):
- cfg = ConfigParser.ConfigParser()
- cfg.read(configpath)
- tmpdir = cfg.get("general","cachedir")
- pkg_ext = cfg.get("general", "compression")
- compression = pkg_ext
- else:
- tmpdir = "/tmp/vlupdater"
- compression = "tgz"
- pkg_ext = compression
- #today = commands.getoutput('date +\%Y-\%m-\%d')
- today = datetime.date.today().isoformat()
- pkgdir = "/var/log/packages"
- scriptdir = "/var/log/scripts"
- tmp_pkg = os.path.join(tmpdir, today,"tmp")
- def load_config_settings():
- if os.path.exists(configpath) == False: return
- cfg = ConfigParser.ConfigParser()
- cfg.read(configpath)
- tmpdir = cfg.get('general','cachedir')
- pkg_ext = cfg.get('general','compression')
- if os.path.exists(tmpdir) == False:
- os.makedirs(tmpdir)
- def upgrade_summary():
- """
- Returns a summary of a possible upgrade"""
- print "Generating summary"
- commands.getoutput('slapt-get -u')
- pre = commands.getoutput('slapt-get --upgrade -s')
- ret = pre.split('\n')
- new = []
- upg = []
- for l in ret:
- if "is to be upgraded to" in l:
- upg.append(l.strip())
- elif "is to be installed" in l:
- new.append(l.strip())
- if len(upg) == 0 and len(new) == 0:
- print "System is up to date"
- sys.exit()
- print "%s packages will be upgraded \n%s" % (len(upg),"\n".join(upg))
- print "%s new packages will be installed \n%s" % (len(new),"\n".join(new))
- return ret
- 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 installed" in l:
- pk = l.strip().split(" ")[0]
- new.append(pk)
- if len(new) <= 0:
- return
- f = open(os.path.join(tmpdir,today,"manifest"),"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)
- """
- print "Refreshing software sources... Please wait"
- commands.getoutput("slapt-get -u")
- pre = commands.getoutput("slapt-get --upgrade -s")
- ret = pre.split("\n")
- m = 0
- new = []
- rem = []
- if "After unpacking" not in pre:
- print "System is up to date"
- sys.exit()
- for l in ret:
- if "After unpacking" in l:
- m = ret.index(l) + 1
- while m < (len(ret) - 1):
- str = ret[m].split(" ")[0]
- if "is to be upgraded to" in ret[m]:
- new.append(str)
- elif "is to be installed" in ret[m]:
- rem.append(str)
- m = m + 1
- if len(rem) > 0:
- f = open(os.path.join(tmpdir,today,"manifest"),'w')
- f.write("\n".join(rem) + "\n")
- f.close()
- 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
- sys.exit()
- 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
- if os.path.exists(os.path.join(tmpdir, datecode, "manifest")):
- f = open(os.path.join(tmpdir, datecode, "manifest"), 'r')
- rem = f.readlines()
- f.close()
- for i in rem:
- print "Removing %s" % (i)
- commands.getoutput("/sbin/removepkg %s" % (i.strip()))
- 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):
- 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:
- if os.path.exists(src) == False:
- if os.path.splitext(src)[-1] == ".new":
- print "searching for .new file"
- src = os.path.splitext(src)[0]
- print "saving %s to %s" % (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()
- 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) + "." + pkg_ext)
- os.chdir(tmp_pkg + "/")
- commands.getoutput("/usr/bin/makepkg -l y -c n %s" % (os.path.join(tmpdir,today,self.pkgname) + "." + pkg_ext))
- 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."""
- print "Performing pre-upgrade backup"
- perform_backup()
- try:
- ret = call("/usr/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
- def main():
- if check_root() > 0:
- print "You must be root to use this"
- sys.exit()
- if __name__ == '__main__':
- main()
- load_config_settings()
Add Comment
Please, Sign In to add comment