Skip to content
This repository was archived by the owner on Sep 23, 2024. It is now read-only.

Commit 05042f9

Browse files
majorveruu
authored andcommitted
Move KernelBuilder into its own file
Signed-off-by: Major Hayden <[email protected]>
1 parent b4de71a commit 05042f9

File tree

5 files changed

+357
-307
lines changed

5 files changed

+357
-307
lines changed

skt/__init__.py

Lines changed: 0 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,10 @@
1616
import email.header
1717
import email.parser
1818
import logging
19-
import multiprocessing
2019
import os
2120
import re
22-
import shlex
2321
import shutil
2422
import subprocess
25-
import sys
26-
import io
27-
import time
28-
from threading import Timer
2923
import requests
3024

3125

@@ -436,193 +430,3 @@ def bisect_iter(self, bad):
436430
logging.info(line)
437431

438432
return (ret, binfo)
439-
440-
441-
class KernelBuilder(object):
442-
def __init__(self, source_dir, basecfg, cfgtype=None,
443-
extra_make_args=None, enable_debuginfo=False):
444-
self.source_dir = source_dir
445-
self.basecfg = basecfg
446-
self.cfgtype = cfgtype if cfgtype is not None else "olddefconfig"
447-
self._ready = 0
448-
self.buildlog = "%s/build.log" % self.source_dir
449-
self.make_argv_base = ["make", "-C", self.source_dir]
450-
self.enable_debuginfo = enable_debuginfo
451-
452-
# Split the extra make arguments provided by the user
453-
if extra_make_args:
454-
self.extra_make_args = shlex.split(extra_make_args)
455-
else:
456-
self.extra_make_args = []
457-
458-
try:
459-
os.unlink(self.buildlog)
460-
except OSError:
461-
pass
462-
463-
logging.info("basecfg: %s", self.basecfg)
464-
logging.info("cfgtype: %s", self.cfgtype)
465-
466-
def prepare(self, clean=True):
467-
if (clean):
468-
args = self.make_argv_base + ["mrproper"]
469-
logging.info("cleaning up tree: %s", args)
470-
subprocess.check_call(args)
471-
472-
shutil.copyfile(self.basecfg, "%s/.config" % self.source_dir)
473-
474-
# NOTE(mhayden): Building kernels with debuginfo can increase the
475-
# final kernel tarball size by 3-4x and can increase build time
476-
# slightly. Debug symbols are really only needed for deep diagnosis
477-
# of kernel issues on a specific system. This is why debuginfo is
478-
# disabled by default.
479-
if not self.enable_debuginfo:
480-
args = ["%s/scripts/config" % self.source_dir,
481-
"--file", self.get_cfgpath(),
482-
"--disable", "debug_info"]
483-
logging.info("disabling debuginfo: %s", args)
484-
subprocess.check_call(args)
485-
486-
args = self.make_argv_base + [self.cfgtype]
487-
logging.info("prepare config: %s", args)
488-
subprocess.check_call(args)
489-
self._ready = 1
490-
491-
def get_cfgpath(self):
492-
return "%s/.config" % self.source_dir
493-
494-
def getrelease(self):
495-
krelease = None
496-
if not self._ready:
497-
self.prepare(False)
498-
499-
args = self.make_argv_base + ["kernelrelease"]
500-
mk = subprocess.Popen(args, stdout=subprocess.PIPE)
501-
(stdout, _) = mk.communicate()
502-
for line in stdout.split("\n"):
503-
m = re.match(r'^\d+\.\d+\.\d+.*$', line)
504-
if m:
505-
krelease = m.group()
506-
break
507-
508-
if krelease is None:
509-
raise Exception("Failed to find kernel release in stdout")
510-
511-
return krelease
512-
513-
def mktgz(self, clean=True, timeout=60 * 60 * 12):
514-
"""
515-
Build kernel and modules, after that, pack everything into a tarball.
516-
517-
Args:
518-
clean: If it is True, run the `mrproper` target before build.
519-
timeout: Max time in seconds will wait for build.
520-
Returns:
521-
The full path of the tarball generated.
522-
Raises:
523-
CommandTimeoutError: When building kernel takes longer than the
524-
specified timeout.
525-
CalledProcessError: When a command returns an exit code different
526-
than zero.
527-
ParsingError: When can not find the tarball path in stdout.
528-
IOError: When tarball file doesn't exist.
529-
"""
530-
fpath = None
531-
stdout_list = []
532-
self.prepare(clean)
533-
534-
# Set up the arguments and options for the kernel build
535-
targz_pkg_argv = [
536-
"INSTALL_MOD_STRIP=1",
537-
"-j%d" % multiprocessing.cpu_count(),
538-
"targz-pkg"
539-
]
540-
kernel_build_argv = (
541-
self.make_argv_base
542-
+ targz_pkg_argv
543-
+ self.extra_make_args
544-
)
545-
546-
logging.info("building kernel: %s", kernel_build_argv)
547-
548-
with io.open(self.buildlog, 'wb') as writer, \
549-
io.open(self.buildlog, 'rb') as reader:
550-
make = subprocess.Popen(kernel_build_argv,
551-
stdout=writer,
552-
stderr=subprocess.STDOUT)
553-
make_timedout = []
554-
555-
def stop_process(proc):
556-
"""
557-
Terminate the process with SIGTERM and flag it as timed out.
558-
"""
559-
if proc.poll() is None:
560-
proc.terminate()
561-
make_timedout.append(True)
562-
timer = Timer(timeout, stop_process, [make])
563-
timer.setDaemon(True)
564-
timer.start()
565-
try:
566-
while make.poll() is None:
567-
self.append_and_log2stdout(reader.readlines(), stdout_list)
568-
time.sleep(1)
569-
self.append_and_log2stdout(reader.readlines(), stdout_list)
570-
finally:
571-
timer.cancel()
572-
if make_timedout:
573-
raise CommandTimeoutError(
574-
"'{}' was taking too long".format(
575-
' '.join(kernel_build_argv)
576-
)
577-
)
578-
if make.returncode != 0:
579-
raise subprocess.CalledProcessError(
580-
make.returncode,
581-
' '.join(kernel_build_argv)
582-
)
583-
584-
match = re.search("^Tarball successfully created in (.*)$",
585-
''.join(stdout_list), re.MULTILINE)
586-
if match:
587-
fpath = os.path.realpath(
588-
os.path.join(
589-
self.source_dir,
590-
match.group(1)
591-
)
592-
)
593-
else:
594-
raise ParsingError('Failed to find tgz path in stdout')
595-
596-
if not os.path.isfile(fpath):
597-
raise IOError("Built kernel tarball {} not found".format(fpath))
598-
599-
return fpath
600-
601-
@staticmethod
602-
def append_and_log2stdout(lines, full_log):
603-
"""
604-
Append `lines` into `full_log` and show `lines` on stdout.
605-
606-
Args:
607-
lines: list of strings.
608-
full_log: list where `lines` members are appended.
609-
"""
610-
full_log.extend(lines)
611-
sys.stdout.write(''.join(lines))
612-
sys.stdout.flush()
613-
614-
615-
class CommandTimeoutError(Exception):
616-
"""
617-
Exception raised when a timeout occurs on a process which has had timeouts
618-
enabled. The accompanying value is a string whose value is the command
619-
launched plus a small explanation.
620-
"""
621-
622-
623-
class ParsingError(Exception):
624-
"""
625-
Exception raised when a regex does not match and it is impossible to
626-
continue. The accompanying value is a string which explains what it can not
627-
find.
628-
"""

skt/executable.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import skt.publisher
3434
import skt.reporter
3535
import skt.runner
36+
from skt.kernelbuilder import KernelBuilder
3637

3738
DEFAULTRC = "~/.sktrc"
3839
LOGGER = logging.getLogger()
@@ -200,7 +201,7 @@ def cmd_build(cfg):
200201
tstamp = datetime.datetime.strftime(datetime.datetime.now(),
201202
"%Y%m%d%H%M%S")
202203

203-
builder = skt.KernelBuilder(
204+
builder = KernelBuilder(
204205
source_dir=cfg.get('workdir'),
205206
basecfg=cfg.get('baseconfig'),
206207
cfgtype=cfg.get('cfgtype'),

0 commit comments

Comments
 (0)