#!/usr/bin/env python import copy import os import re import shutil import signal import sys import urllib.request from getopt import getopt, GetoptError from html.parser import HTMLParser from grs import CONST from grs import Execute from grs import Log from grs import Synchronize from grs import WorldConf from _emerge.main import emerge_main, parse_opts from portage.exception import IsADirectory, ParseError, PermissionDenied from portage import settings def install_kernel(version = 'latest', logfile = CONST.LOGFILE): """ doc here more doc """ class MyHTMLParser(HTMLParser): def __init__(self, **kwargs): HTMLParser.__init__(self, **kwargs) self.kernels = [] def handle_starttag(self, tag, attrs): if tag != 'a': return for attr in attrs: if attr[0] == 'href' and re.match('linux-image-', attr[1]): self.kernels.append(attr[1]) def get_kernels(self): return self.kernels baseurl = settings['PORTAGE_BINHOST'] if baseurl == '': print('PORTAGE_BINHOST is not set. Install kernel manually.') return try: request = urllib.request.urlopen('%s/%s' % (baseurl,'linux-images')) dload = request.read().decode('utf-8') except urllib.error.HTTPError: print('Cannot open %s' % baseurl) return parser = MyHTMLParser() parser.feed(dload) kernels = parser.get_kernels() kernels.sort() if version == 'latest': try: kernel = kernels[-1] except IndexError: print('No linux-image available') return else: for k in kernels: m = re.search('linux-image-(.+).tar.xz', k) if m.group(1) == version: kernel = k break else: print('No linux-image %s available' % version) return # Download the linux-image tarball to packages/linux-image request = urllib.request.urlopen('%s/%s/%s' % (baseurl, 'linux-images', kernel)) package = '/usr/portage/packages/linux-images' os.makedirs(package, mode=0o755, exist_ok=True) kpath = os.path.join(package, kernel) with open(kpath, 'wb') as f: shutil.copyfileobj(request, f) # Try to mount /boot. Fail silently since it may not be mountable. if not os.path.ismount('/boot'): cmd = 'mount /boot' Execute(cmd, timeout=60, failok=True, logfile=logfile) # Untar it at '/'. tar will not clobber files. cwd = os.getcwd() os.chdir('/') cmd = 'tar --overwrite -Jxf %s' % kpath Execute(cmd, timeout=600, logfile=logfile) os.chdir(cwd) def usage(rc=1): usage = """ usage: grsup [pkg(s)] : update @world or pkg(s) if given grsup [-r|-d] pkg(s) : re-install or delete pkg(s) grsup -D : download all @world pkgs, don't install grsup -k kernel : install 'kernel' version, or 'latest' grsup -h : print this help """ print(usage) sys.exit(rc) def main(): myaction, myopts, myfiles = parse_opts(sys.argv[1:]) try: opts, x = getopt(sys.argv[1:], 'Ck:rdh') except GetoptError: usage() do_install_kernel = False if len(opts) == 0: args = ['-1', '-g', '-K', '-u', '-D', '-q'] if len(myfiles) == 0: myfiles = ['@world'] args.extend(myfiles) else: exclude = 0 for o, a in opts: if o == '-h': usage(rc=0) elif o == '-r': if len(myfiles) == 0 or exclude > 1: usage() args = ['-1', '-g', '-K', '-D', '-q'] args.extend(myfiles) exclude += 1 elif o == '-d': if len(myfiles) == 0 or exclude > 1: usage() args = ['-C', '-q'] args.extend(myfiles) exclude += 1 elif o == '-D': if len(myfiles) > 0: usage() args = ['-g', '-e', '-f', '-q', '@world'] elif o == '-k': if len(sys.argv[1:]) != 2: usage() version = a do_install_kernel = True if len(CONST.names) > 1: sys.stderr.write('More than one GRS specified in systems.conf. Using the first one.\n') name = CONST.names[0] repo_uri = CONST.repo_uris[0] stage_uri = CONST.stage_uris[0] libdir = CONST.libdirs[0] logfile = CONST.logfiles[0] # Change the log name for the client. basename = os.path.basename(logfile) dirname = os.path.dirname(logfile) logfile = os.path.join(dirname, 'grsup-%s' % basename) Log(logfile).rotate_logs() Synchronize(repo_uri, name, libdir, logfile).sync() # Copy the new world.conf to CONST.WORLD_CONFIG newconf = '%s/core%s' % (libdir, CONST.WORLD_CONFIG) shutil.copy(newconf, CONST.WORLD_CONFIG) if os.path.isfile(CONST.PORTAGE_DIRTYFILE): WorldConf.clean() open(CONST.PORTAGE_DIRTYFILE, 'a').close() WorldConf.install() if do_install_kernel: install_kernel(version=version) else: try: emerge_main(args) except PermissionDenied as e: sys.stderr.write("Permission denied: '%s'\n" % str(e)) sys.stderr.flush() sys.exit(e.errno) except IsADirectory as e: sys.stderr.write("'%s' is a directory, but should be a file!\n" % sys.exit(e.errno)) sys.stderr.flush() except ParseError as e: sys.stderr.write("%s\n" % str(e)) sys.stderr.flush() sys.exit(1) WorldConf.clean() if os.path.exists(CONST.PORTAGE_DIRTYFILE): os.remove(CONST.PORTAGE_DIRTYFILE) if __name__ == "__main__": try: main() except KeyboardInterrupt: sys.stderr.write("Cleaning up /etc/portage. This make take some time.\n") WorldConf.clean() if os.path.exists(CONST.PORTAGE_DIRTYFILE): os.remove(CONST.PORTAGE_DIRTYFILE)