Home | History | Annotate | Download | only in virt
      1 import os, re, sys, pwd, time, socket, getpass
      2 import inspect, new, logging, string, tempfile
      3 
      4 from autotest_lib.cli import topic_common, action_common
      5 from autotest_lib.cli import job
      6 from autotest_lib.client.common_lib import logging_config
      7 from autotest_lib.client.virt import virt_utils
      8 
      9 logging_config.LoggingConfig().configure_logging(verbose=True)
     10 
     11 
     12 class site_job(job.job):
     13     pass
     14 
     15 
     16 class site_job_create(job.job_create):
     17     """
     18     Adds job manipulation including installing packages from brew
     19     """
     20 
     21     op_action = 'create'
     22 
     23     def __init__(self):
     24         super(site_job_create, self).__init__()
     25         self.parser.add_option('-T', '--template', action='store_true',
     26                                help='Control file is actually a template')
     27         self.parser.add_option('-x', '--extra-cartesian-config',
     28                                action='append',
     29                                help='Add extra configuration to the cartesian '
     30                                'config file')
     31         self.parser.add_option('--timestamp', action='store_true',
     32                                help='Add a timestamp to the name of the job')
     33         self.parser.add_option('--koji-arch', default='x86_64',
     34                                help='Default architecture for packages '
     35                                'that will be fetched from koji build. '
     36                                'This will be combined with "noarch".'
     37                                'This option is used to help to validate '
     38                                'packages from the job submitting machine.')
     39         self.parser.add_option('--koji-tag', help='Sets a default koji tag '
     40                                'for koji packages specified with --koji-pkg')
     41         self.parser.add_option('--koji-pkg', action='append',
     42                                help='Packages to add to host installation '
     43                                'based on koji build. This options may be '
     44                                'specified multiple times.')
     45         self.koji_client = None
     46 
     47 
     48     def parse(self):
     49         '''
     50         Parse options.
     51 
     52         If any brew options is specified, instantiate KojiDownloader
     53         '''
     54         (self.command_line_options,
     55          self.command_line_leftover) = super(site_job_create, self).parse()
     56 
     57         #
     58         # creating the new control file
     59         #
     60         if (self.command_line_options.template and
     61             self.command_line_options.control_file):
     62             generated_control_file = self._generate_control_file()
     63             self.data['control_file'] = open(generated_control_file).read()
     64 
     65         if self.command_line_options.koji_pkg:
     66             if self.koji_client is None:
     67                 self.koji_client = virt_utils.KojiClient()
     68 
     69         return (self.command_line_options, self.command_line_leftover)
     70 
     71 
     72     def _process_options(self):
     73         '''
     74         Process all options given on command line
     75         '''
     76         all_options_valid = True
     77 
     78         self._set_koji_tag()
     79         if not self._check_koji_packages():
     80             all_options_valid = False
     81 
     82         return all_options_valid
     83 
     84 
     85     def _set_koji_tag(self):
     86         '''
     87         Sets the default koji tag.
     88 
     89         Configuration item on file is: koji_tag
     90         '''
     91         if self.command_line_options.koji_tag is not None:
     92             virt_utils.set_default_koji_tag(self.command_line_options.koji_tag)
     93 
     94 
     95     def _check_koji_packages(self):
     96         '''
     97         Check if packages specification are valid and exist on koji/brew
     98 
     99         Configuration item on file is: koji_pkgs
    100         '''
    101         all_packages_found = True
    102         if self.command_line_options.koji_pkg is not None:
    103             logging.debug('Checking koji packages specification')
    104             for pkg_spec_text in self.command_line_options.koji_pkg:
    105                 pkg_spec = virt_utils.KojiPkgSpec(pkg_spec_text)
    106 
    107                 if not (pkg_spec.is_valid() and
    108                         self.koji_client.is_pkg_valid(pkg_spec)):
    109                     logging.error('Koji package spec is not valid, skipping: '
    110                                   '%s' % pkg_spec)
    111                     all_packages_found = False
    112                 else:
    113                     rpms = self.koji_client.get_pkg_rpm_info(
    114                         pkg_spec,
    115                         self.command_line_options.koji_arch)
    116                     for subpackage in pkg_spec.subpackages:
    117                         if subpackage not in [rpm['name'] for rpm in rpms]:
    118                             logging.error('Package specified but not found in '
    119                                           'koji: %s' % subpackage)
    120                             all_packages_found = False
    121 
    122                     rpms = ", ".join(rpm['nvr'] for rpm in rpms)
    123                     logging.debug('Koji package spec is valid')
    124                     logging.debug('Koji packages to be fetched and installed: '
    125                                   '%s' % rpms)
    126 
    127         return all_packages_found
    128 
    129     def _generate_job_config(self):
    130         '''
    131         Converts all options given on the command line to config file syntax
    132         '''
    133         extra = []
    134         if self.command_line_options.extra_cartesian_config:
    135             extra += self.command_line_options.extra_cartesian_config
    136 
    137         if self.command_line_options.koji_tag:
    138             extra.append("koji_tag = %s" % self.command_line_options.koji_tag)
    139 
    140         if self.command_line_options.koji_pkg:
    141             koji_pkgs = []
    142             for koji_pkg in self.command_line_options.koji_pkg:
    143                 koji_pkgs.append('"%s"' % koji_pkg)
    144             extra.append("koji_pkgs = [%s]" % ', '.join(koji_pkgs))
    145 
    146         # add quotes...
    147         extra = ["'%s'" % e for e in extra]
    148         # ... and return as string that will be eval'd as a Python list
    149         return "[%s]" % ', '.join(extra)
    150 
    151 
    152     def _generate_control_file(self):
    153         '''
    154         Generates a controle file from a template
    155         '''
    156         custom_job_cfg = self._generate_job_config()
    157         input_file = self.command_line_options.control_file
    158         logging.debug('Generating control file from template: %s' % input_file)
    159         template = string.Template(open(input_file).read())
    160         output_fd, path = tempfile.mkstemp(prefix='atest_control_', dir='/tmp')
    161         logging.debug('Generated control file to be saved at: %s' % path)
    162         parameters_dict = {"custom_job_cfg": custom_job_cfg}
    163         control_file_text = template.substitute(parameters_dict)
    164         os.write(output_fd, control_file_text)
    165         os.close(output_fd)
    166         return path
    167 
    168 
    169     def execute(self):
    170         if not self._process_options():
    171             self.generic_error('Some command line options validation failed. '
    172                                'Aborting job creation.')
    173             return
    174 
    175         #
    176         # add timestamp to the jobname
    177         #
    178         if self.command_line_options.timestamp:
    179             logging.debug("Adding timestamp to jobname")
    180             timestamp = time.strftime(" %m-%d-%Y %H:%M:%S", time.localtime())
    181             self.jobname += timestamp
    182             self.data['name'] = self.jobname
    183 
    184         execute_results = super(site_job_create, self).execute()
    185         self.output(execute_results)
    186 
    187 
    188 for cls in [getattr(job, n) for n in dir(job) if not n.startswith("_")]:
    189     if not inspect.isclass(cls):
    190         continue
    191     cls_name = cls.__name__
    192     site_cls_name = 'site_' + cls_name
    193     if hasattr(sys.modules[__name__], site_cls_name):
    194         continue
    195     bases = (site_job, cls)
    196     members = {'__doc__': cls.__doc__}
    197     site_cls = new.classobj(site_cls_name, bases, members)
    198     setattr(sys.modules[__name__], site_cls_name, site_cls)
    199