Home | History | Annotate | Download | only in module
      1 #    Copyright 2014-2015 ARM Limited
      2 #
      3 # Licensed under the Apache License, Version 2.0 (the "License");
      4 # you may not use this file except in compliance with the License.
      5 # You may obtain a copy of the License at
      6 #
      7 #     http://www.apache.org/licenses/LICENSE-2.0
      8 #
      9 # Unless required by applicable law or agreed to in writing, software
     10 # distributed under the License is distributed on an "AS IS" BASIS,
     11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 # See the License for the specific language governing permissions and
     13 # limitations under the License.
     14 #
     15 import logging
     16 from inspect import isclass
     17 
     18 from devlib.utils.misc import walk_modules
     19 from devlib.utils.types import identifier
     20 
     21 
     22 __module_cache = {}
     23 
     24 
     25 class Module(object):
     26 
     27     name = None
     28     kind = None
     29     # This is the stage at which the module will be installed. Current valid
     30     # stages are:
     31     #  'early' -- installed when the Target is first created. This should be
     32     #             used for modules that do not rely on the main connection
     33     #             being established (usually because the commumnitcate with the
     34     #             target through some sorto of secondary connection, e.g. via
     35     #             serial).
     36     #  'connected' -- installed when a connection to to the target has been
     37     #                 established. This is the default.
     38     stage = 'connected'
     39 
     40     @staticmethod
     41     def probe(target):
     42         raise NotImplementedError()
     43 
     44     @classmethod
     45     def install(cls, target, **params):
     46         if cls.kind is not None:
     47             attr_name = identifier(cls.kind)
     48         else:
     49             attr_name = identifier(cls.name)
     50         if hasattr(target, attr_name):
     51             existing_module = getattr(target, attr_name)
     52             existing_name = getattr(existing_module, 'name', str(existing_module))
     53             message = 'Attempting to install module "{}" which already exists (new: {}, existing: {})'
     54             raise ValueError(message.format(attr_name, cls.name, existing_name))
     55         setattr(target, attr_name, cls(target, **params))
     56 
     57     def __init__(self, target):
     58         self.target = target
     59         self.logger = logging.getLogger(self.name)
     60 
     61 
     62 class HardRestModule(Module):  # pylint: disable=R0921
     63 
     64     kind = 'hard_reset'
     65 
     66     def __call__(self):
     67         raise NotImplementedError()
     68 
     69 
     70 class BootModule(Module):  # pylint: disable=R0921
     71 
     72     kind = 'boot'
     73 
     74     def __call__(self):
     75         raise NotImplementedError()
     76 
     77     def update(self, **kwargs):
     78         for name, value in kwargs.iteritems():
     79             if not hasattr(self, name):
     80                 raise ValueError('Unknown parameter "{}" for {}'.format(name, self.name))
     81             self.logger.debug('Updating "{}" to "{}"'.format(name, value))
     82             setattr(self, name, value)
     83 
     84 
     85 class FlashModule(Module):
     86 
     87     kind = 'flash'
     88 
     89     def __call__(self, image_bundle=None, images=None, boot_config=None):
     90         raise NotImplementedError()
     91 
     92 
     93 def get_module(mod):
     94     if not __module_cache:
     95         __load_cache()
     96 
     97     if isinstance(mod, basestring):
     98         try:
     99             return __module_cache[mod]
    100         except KeyError:
    101             raise ValueError('Module "{}" does not exist'.format(mod))
    102     elif issubclass(mod, Module):
    103         return mod
    104     else:
    105         raise ValueError('Not a valid module: {}'.format(mod))
    106 
    107 
    108 def register_module(mod):
    109     if not issubclass(mod, Module):
    110         raise ValueError('A module must subclass devlib.Module')
    111     if mod.name is None:
    112         raise ValueError('A module must define a name')
    113     if mod.name in __module_cache:
    114         raise ValueError('Module {} already exists'.format(mod.name))
    115     __module_cache[mod.name] = mod
    116 
    117 
    118 def __load_cache():
    119     for module in walk_modules('devlib.module'):
    120         for obj in vars(module).itervalues():
    121             if isclass(obj) and issubclass(obj, Module) and obj.name:
    122                 register_module(obj)
    123