Guest User

Untitled

a guest
Jul 16th, 2018
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.91 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # backuputils.py
  5. #
  6. # Copyright 2009 Moises Henriquez <M0E.lnx [at] gmail [dot] com>
  7. #
  8. # This program is free software; you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License as published by
  10. # the Free Software Foundation; either version 3 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU General Public License
  19. # along with this program; if not, write to the Free Software
  20. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  21. # MA 02110-1301, USA.
  22.  
  23. """
  24. Backup utilities for vectorlinux.
  25.  
  26. Provides a way to safely perform a system upgrade.
  27. Part of the vlutils package
  28. """
  29.  
  30.  
  31. import glob
  32. import os
  33. import sys
  34. import commands
  35. from subprocess import call
  36. import ConfigParser
  37. import datetime
  38.  
  39.  
  40. __version__ = '0.1.1'
  41. configpath = '/etc/vlupdater.conf'
  42. #tmpdir = ""
  43. if os.path.exists(configpath):
  44. cfg = ConfigParser.ConfigParser()
  45. cfg.read(configpath)
  46. tmpdir = cfg.get("general","cachedir")
  47. pkg_ext = cfg.get("general", "compression")
  48. compression = pkg_ext
  49. else:
  50. tmpdir = "/tmp/vlupdater"
  51. compression = "tgz"
  52. pkg_ext = compression
  53.  
  54.  
  55. #today = commands.getoutput('date +\%Y-\%m-\%d')
  56. today = datetime.date.today().isoformat()
  57. pkgdir = "/var/log/packages"
  58. scriptdir = "/var/log/scripts"
  59. tmp_pkg = os.path.join(tmpdir, today,"tmp")
  60.  
  61.  
  62.  
  63. def load_config_settings():
  64.  
  65. if os.path.exists(configpath) == False: return
  66. cfg = ConfigParser.ConfigParser()
  67. cfg.read(configpath)
  68. tmpdir = cfg.get('general','cachedir')
  69. pkg_ext = cfg.get('general','compression')
  70.  
  71. if os.path.exists(tmpdir) == False:
  72. os.makedirs(tmpdir)
  73.  
  74. def upgrade_summary():
  75. """
  76. Returns a summary of a possible upgrade"""
  77. print "Generating summary"
  78. commands.getoutput('slapt-get -u')
  79. pre = commands.getoutput('slapt-get --upgrade -s')
  80. ret = pre.split('\n')
  81. new = []
  82. upg = []
  83. for l in ret:
  84. if "is to be upgraded to" in l:
  85. upg.append(l.strip())
  86. elif "is to be installed" in l:
  87. new.append(l.strip())
  88.  
  89. if len(upg) == 0 and len(new) == 0:
  90. print "System is up to date"
  91. sys.exit()
  92.  
  93. print "%s packages will be upgraded \n%s" % (len(upg),"\n".join(upg))
  94. print "%s new packages will be installed \n%s" % (len(new),"\n".join(new))
  95. return ret
  96.  
  97.  
  98. def save_new_packages_list():
  99. """
  100. Create a record of new packages that will get installed as a result of
  101. a system upgrade
  102.  
  103. This list contains packages that must be removed in case of a roll back
  104. file list is called 'rollback'
  105. """
  106. pre = commands.getoutput("slapt-get --upgrade -s")
  107. ret = pre.split("\n")
  108. new = []
  109. for l in ret:
  110. if "is to be installed" in l:
  111. pk = l.strip().split(" ")[0]
  112. new.append(pk)
  113. if len(new) <= 0:
  114. return
  115. f = open(os.path.join(tmpdir,today,"manifest"),"w")
  116. f.write("\n".join(new) + "\n")
  117. f.close()
  118.  
  119. def read_preupgrade_report():
  120. """
  121. Reads a short (internal) report of packages to be upgrade
  122. and installed.
  123.  
  124. Takes no arguments and returns a list of package names (upgrades only)
  125. """
  126. print "Refreshing software sources... Please wait"
  127. commands.getoutput("slapt-get -u")
  128. pre = commands.getoutput("slapt-get --upgrade -s")
  129. ret = pre.split("\n")
  130. m = 0
  131. new = []
  132. rem = []
  133.  
  134. if "After unpacking" not in pre:
  135. print "System is up to date"
  136. sys.exit()
  137.  
  138. for l in ret:
  139. if "After unpacking" in l:
  140. m = ret.index(l) + 1
  141. while m < (len(ret) - 1):
  142. str = ret[m].split(" ")[0]
  143. if "is to be upgraded to" in ret[m]:
  144. new.append(str)
  145. elif "is to be installed" in ret[m]:
  146. rem.append(str)
  147. m = m + 1
  148. if len(rem) > 0:
  149. f = open(os.path.join(tmpdir,today,"manifest"),'w')
  150. f.write("\n".join(rem) + "\n")
  151. f.close()
  152.  
  153. return new
  154.  
  155. def perform_backup():
  156. """
  157. Performs a backup of existing packages to be upgraded by slapt-get
  158. Also creates a list of new packages to be removed in case the
  159. backup is rolled over.
  160.  
  161. Takes no arguments (yet)
  162. """
  163.  
  164. if os.path.exists(tmpdir) == False:
  165. os.makedirs(tmpdir)
  166. if os.path.exists(os.path.join(tmpdir,today)) == False:
  167. os.makedirs(os.path.join(tmpdir, today))
  168.  
  169.  
  170. for i in read_preupgrade_report():
  171.  
  172. pkg = Package(os.path.join(pkgdir,i))
  173. pkg.backup()
  174.  
  175. def restore_backup(datecode):
  176. """Restores a previously performed backup
  177. Takes one argument ie,
  178.  
  179. restore_backup(2009-11-01)
  180. """
  181. if os.path.exists(os.path.join(tmpdir, datecode)) == False:
  182. print """
  183.  
  184. No records of a backup for %s
  185.  
  186. """ % datecode
  187. sys.exit()
  188. list = os.listdir(os.path.join(tmpdir, datecode))
  189. for i in list:
  190. pkg = Package(i)
  191. print "Restore %s" % i
  192. try:
  193. res = call('/sbin/removepkg ' + pkg.appname, shell=True)
  194. if res < 0:
  195. print "Finished with",-res
  196. except OSError, e:
  197. print "Error", e
  198. try:
  199. res = call('/sbin/installpkg ' + os.path.join( \
  200. tmpdir, datecode, i), shell=True)
  201. if res < 0:
  202. print "Ended with", -res
  203. except OSError, e:
  204. print "Error",e
  205. if os.path.exists(os.path.join(tmpdir, datecode, "manifest")):
  206. f = open(os.path.join(tmpdir, datecode, "manifest"), 'r')
  207. rem = f.readlines()
  208. f.close()
  209.  
  210. for i in rem:
  211. print "Removing %s" % (i)
  212. commands.getoutput("/sbin/removepkg %s" % (i.strip()))
  213.  
  214.  
  215. class Package():
  216. """
  217. Returns a package object
  218. Takes one argument, a file path to a package in /var/log/packages/
  219.  
  220. ie:
  221. pkg = Package('/var/log/packages/foo-bar-1.2.3-i586-1vl60')
  222. Use the following methods with it
  223. pkg.backup - Re-creates the original package
  224. OTHER INTERNAL USE METHODS
  225. pkg.generate_desc - Returns the package description (as a list)
  226. pkg.generate_doinst - Returns the package's install script (as a list)
  227. pkg.backup_files - creates backup copies of files in the package. """
  228.  
  229. def __init__(self, name):
  230. self.pkgname = os.path.split(name)[-1]
  231. self.pkgdir = '/var/log/packages/'
  232. self.scriptdir = '/var/log/scripts/'
  233. sp = self.pkgname.rsplit("-",3)
  234. self.appname = os.path.split(sp[0])[-1]
  235. file = open(os.path.join(self.pkgdir,name),'r')
  236. self.data = file.readlines()
  237. file.close()
  238. self.desc = "\n".join(self.generate_desc()) + "\n"
  239.  
  240.  
  241. def generate_desc(self):
  242. """
  243. Returns a package's description as a list"""
  244.  
  245. ret = []
  246.  
  247. for i in self.data:
  248. if i[:len(self.appname)] == self.appname:
  249. ret.append(i.strip())
  250. return ret
  251. def generate_doinst(self):
  252. """
  253. Returns a packages install script (if exists) as a list"""
  254.  
  255. if os.path.exists(os.path.join(self.scriptdir,self.pkgname)) == False:
  256. return
  257. data = open(os.path.join(self.scriptdir,self.pkgname),'r')
  258. file = data.readlines()
  259. ret = []
  260. for i in file:
  261. ret.append(i.strip())
  262. return ret
  263. def backup_files(self):
  264. """
  265. Create backup copies of the files in the package object
  266. """
  267. l = self.data.index("./\n") + 1
  268. n = 0
  269. tmp_pkg = os.path.join(tmpdir, today, "tmp")
  270. if os.path.exists(os.path.join(pkgdir, self.pkgname)) == False:
  271. print "%s is not installed" % self.pkgname
  272. return
  273. commands.getoutput("rm -r " + tmp_pkg)
  274. commands.getoutput("mkdir -p " + tmp_pkg)
  275. n = l
  276. while l < len(self.data):
  277. # print "making dir %s/%s" % (l,len(self.data))
  278. if os.path.isdir(os.path.join("/",self.data[l].strip())) == True:
  279. commands.getoutput("mkdir -p " + os.path.join(tmp_pkg,self.data[l].strip()))
  280. else:
  281. commands.getoutput("mkdir -p " + os.path.dirname(os.path.join(tmp_pkg,self.data[l].strip())))
  282.  
  283. l = l + 1
  284.  
  285. while n < len(self.data):
  286. src = os.path.join("/",self.data[n].strip())
  287. trgt = os.path.join(tmpdir,today,"tmp") + src
  288. if os.path.isdir(os.path.join("/",self.data[n].strip())) == True:
  289. pass
  290. else:
  291. if os.path.exists(src) == False:
  292. if os.path.splitext(src)[-1] == ".new":
  293. print "searching for .new file"
  294. src = os.path.splitext(src)[0]
  295. print "saving %s to %s" % (src, trgt)
  296.  
  297. commands.getoutput("cp -arp " + src + " " + trgt)
  298. n = n + 1
  299.  
  300.  
  301. if os.path.isdir(os.path.join(tmp_pkg,"install")) == False:
  302. os.makedirs(os.path.join(tmp_pkg,"install"))
  303. if self.generate_desc() != None:
  304.  
  305. desc = open(os.path.join(tmp_pkg,"install/slack-desc"),'w')
  306. desc.write("\n".join(self.generate_desc()) + "\n")
  307. desc.close()
  308. # Backup the doinst.sh script
  309. if self.generate_doinst() != None:
  310. script = open(os.path.join(tmp_pkg,'install/doinst.sh'),'w')
  311. script.write("\n".join(self.generate_doinst()) + "\n")
  312. script.close()
  313.  
  314.  
  315.  
  316.  
  317. def repack(self):
  318. """
  319. Re-create the package using the backed up files
  320. *** For internal use only ***"""
  321. print "Re-packaging %s to %s" % (self.pkgname, os.path.join(tmpdir,today, self.pkgname) + "." + pkg_ext)
  322. os.chdir(tmp_pkg + "/")
  323.  
  324. commands.getoutput("/usr/bin/makepkg -l y -c n %s" % (os.path.join(tmpdir,today,self.pkgname) + "." + pkg_ext))
  325. commands.getoutput("rm -rf " + tmp_pkg)
  326.  
  327. os.chdir(tmpdir)
  328.  
  329. def backup(self):
  330. """
  331. Create a complete backup of the package object using the backed up
  332. files. """
  333. self.backup_files()
  334. self.repack()
  335.  
  336. def check_root():
  337. return os.getuid()
  338.  
  339. def safe_upgrade():
  340. """
  341. Performs a safe system upgrade by creating backup copies of packages to be
  342. upgrade before the upgrade."""
  343. print "Performing pre-upgrade backup"
  344. perform_backup()
  345. try:
  346. ret = call("/usr/sbin/slapt-get -y --upgrade",shell=True)
  347. if ret < 0:
  348. print "Error while upgrading packages", -ret
  349. except OSError, e:
  350. print "safe upgrade failed with error",e
  351.  
  352. def main():
  353.  
  354. if check_root() > 0:
  355. print "You must be root to use this"
  356. sys.exit()
  357.  
  358. if __name__ == '__main__':
  359. main()
  360. load_config_settings()
Add Comment
Please, Sign In to add comment