예제 #1
0
    def __init__(self):

        self._recipe_actions = {}
        self._recipe_resources = {}
        self._recipes = {}

        reg = ComponentRegistry()
        for name, action in reg.load_extensions('iotile.recipe_action',
                                                product_name='build_step'):
            self._recipe_actions[name] = action

        for name, resource in reg.load_extensions('iotile.recipe_resource'):
            self._recipe_resources[name] = resource
예제 #2
0
    def FindByName(cls, name):
        """Find a specific installed auth provider by name."""

        reg = ComponentRegistry()
        for _, entry in reg.load_extensions('iotile.auth_provider',
                                            name_filter=name):
            return entry
예제 #3
0
def require(builder_name):
    """Find an advertised autobuilder and return it

    This function searches through all installed distributions to find
    if any advertise an entry point with group 'iotile.autobuild' and
    name equal to builder_name.  The first one that is found is returned.

    This function raises a BuildError if it cannot find the required
    autobuild function

    Args:
        builder_name (string): The name of the builder to find

    Returns:
        callable: the autobuilder function found in the search
    """

    reg = ComponentRegistry()
    for _name, autobuild_func in reg.load_extensions('iotile.autobuild',
                                                     name_filter=builder_name):
        return autobuild_func

    raise BuildError(
        'Cannot find required autobuilder, make sure the distribution providing it is installed',
        name=builder_name)
예제 #4
0
    def FindByName(cls, name):
        """Find an installed VirtualTile by name.

        This function searches for installed virtual tiles
        using the pkg_resources entry_point `iotile.virtual_tile`.

        If name is a path ending in .py, it is assumed to point to
        a module on disk and loaded directly rather than using
        pkg_resources.

        Args:
            name (str): The name of the tile to search
                for.

        Returns:
            VirtualTile class: A virtual tile subclass that can be
                instantiated to create a virtual tile.
        """

        if name.endswith('.py'):
            return cls.LoadFromFile(name)

        reg = ComponentRegistry()
        for _name, tile in reg.load_extensions('iotile.virtual_tile',
                                               name_filter=name,
                                               class_filter=BaseVirtualTile):
            return tile

        raise ArgumentError("VirtualTile could not be found by name",
                            name=name)
예제 #5
0
    def LoadPlugins(cls):
        """Load all registered iotile.update_record plugins."""

        if cls.PLUGINS_LOADED:
            return

        reg = ComponentRegistry()
        for _, record in reg.load_extensions('iotile.update_record'):
            cls.RegisterRecordType(record)

        cls.PLUGINS_LOADED = True
예제 #6
0
    def _load_device(self, name, config):
        """Load a device either from a script or from an installed module"""

        if config is None:
            config_dict = {}
        elif isinstance(config, dict):
            config_dict = config
        elif config[0] == '#':
            # Allow passing base64 encoded json directly in the port string to ease testing.
            import base64
            config_str = str(base64.b64decode(config[1:]), 'utf-8')
            config_dict = json.loads(config_str)
        else:
            try:
                with open(config, "r") as conf:
                    data = json.load(conf)
            except IOError as exc:
                raise ArgumentError("Could not open config file",
                                    error=str(exc),
                                    path=config)

            if 'device' not in data:
                raise ArgumentError(
                    "Invalid configuration file passed to VirtualDeviceAdapter",
                    device_name=name,
                    config_path=config,
                    missing_key='device')

            config_dict = data['device']

        reg = ComponentRegistry()

        if name.endswith('.py'):
            _name, device_factory = reg.load_extension(
                name, class_filter=BaseVirtualDevice, unique=True)
            return _instantiate_virtual_device(device_factory, config_dict,
                                               self._loop)

        seen_names = []
        for device_name, device_factory in reg.load_extensions(
                'iotile.virtual_device',
                class_filter=BaseVirtualDevice,
                product_name="virtual_device"):
            if device_name == name:
                return _instantiate_virtual_device(device_factory, config_dict,
                                                   self._loop)

            seen_names.append(device_name)

        raise ArgumentError("Could not find virtual_device by name",
                            name=name,
                            known_names=seen_names)
예제 #7
0
    def __init__(self, settings_file=None):
        self.rules = []

        logger = logging.getLogger('iotile.build.warnings')
        logger.addHandler(logging.NullHandler)

        #FIXME: Load settings_file

        #Find all registered default builders and load them in priority order
        #Each default resolver should be a 4-tuple with (priority, matching_regex, factory, default args)
        reg = ComponentRegistry()

        for name, resolver_entry in reg.load_extensions(
                'iotile.build.default_depresolver'):
            try:
                priority, regex, factory, settings = resolver_entry
            except TypeError:
                logger.warn(
                    'Invalid default resolver entry %s that was not a 4-tuple: %s',
                    name, str(resolver_entry))
                continue

            self.rules.append((priority, (regex, factory, settings)))

        self.rules.sort(key=lambda x: x[0])

        self._known_resolvers = {}
        for _, factory in reg.load_extensions('iotile.build.depresolver'):
            name = factory.__name__

            if name in self._known_resolvers:
                raise ExternalError(
                    "The same dependency resolver class name is provided by more than one entry point",
                    name=name)

            self._known_resolvers[name] = factory
예제 #8
0
    def __init__(self, args=None):
        super(ChainedAuthProvider, self).__init__(args)

        # FIXME: Allow overwriting default providers via args
        self._load_installed_providers()

        reg = ComponentRegistry()

        sub_providers = []
        for _, (priority, provider, provider_args
                ) in reg.load_extensions('iotile.default_auth_providers'):
            if provider not in self._auth_factories:
                raise ExternalError(
                    "Default authentication provider list references unknown auth provider",
                    provider_name=provider,
                    known_providers=self._auth_factories.keys())
            configured = self._auth_factories[provider](provider_args)
            sub_providers.append((priority, configured))

        sub_providers.sort(key=lambda x: x[0])
        self.providers = sub_providers
예제 #9
0
def instantiate_interface(virtual_iface, config):
    """Find a virtual interface by name and instantiate it

    Args:
        virtual_iface (string): The name of the pkg_resources entry point corresponding to
            the interface.  It should be in group iotile.virtual_interface
        config (dict): A dictionary with a 'interface' key with the config info for configuring
            this virtual interface.  This is optional.

    Returns:
        VirtualInterface: The instantiated subclass of VirtualInterface
    """

    # Allow the null virtual interface for testing
    if virtual_iface == 'null':
        return VirtualIOTileInterface()

    conf = {}
    if 'interface' in config:
        conf = config['interface']

    try:
        reg = ComponentRegistry()
        if virtual_iface.endswith('.py'):
            _name, iface = reg.load_extension(
                virtual_iface,
                class_filter=VirtualIOTileInterface,
                unique=True)
        else:
            _name, iface = reg.load_extensions(
                'iotile.virtual_interface',
                name_filter=virtual_iface,
                class_filter=VirtualIOTileInterface,
                unique=True)

        return iface(conf)
    except ArgumentError as err:
        print("ERROR: Could not load virtual interface (%s): %s" %
              (virtual_iface, err.msg))
        sys.exit(1)
예제 #10
0
def instantiate_device(virtual_dev, config, loop):
    """Find a virtual device by name and instantiate it

    Args:
        virtual_dev (string): The name of the pkg_resources entry point corresponding to
            the device.  It should be in group iotile.virtual_device.  If virtual_dev ends
            in .py, it is interpreted as a python script and loaded directly from the script.
        config (dict): A dictionary with a 'device' key with the config info for configuring
            this virtual device.  This is optional.

    Returns:
        BaseVirtualDevice: The instantiated subclass of BaseVirtualDevice
    """
    conf = {}
    if 'device' in config:
        conf = config['device']

    # If we're given a path to a script, try to load and use that rather than search for an installed module
    try:
        reg = ComponentRegistry()

        if virtual_dev.endswith('.py'):
            _name, dev = reg.load_extension(virtual_dev,
                                            class_filter=BaseVirtualDevice,
                                            unique=True)
        else:
            _name, dev = reg.load_extensions('iotile.virtual_device',
                                             name_filter=virtual_dev,
                                             class_filter=BaseVirtualDevice,
                                             product_name="virtual_device",
                                             unique=True)

        return dev(conf)
    except ArgumentError as err:
        print("ERROR: Could not load virtual device (%s): %s" %
              (virtual_dev, err.msg))
        sys.exit(1)
예제 #11
0
    def _load_installed_providers(self):
        self._auth_factories = {}
        reg = ComponentRegistry()

        for name, entry in reg.load_extensions('iotile.auth_provider'):
            self._auth_factories[name] = entry
예제 #12
0
def main(argv=None, loop=SharedLoop):
    """Serve access to a virtual IOTile device using a virtual iotile interface."""

    if argv is None:
        argv = sys.argv[1:]

    list_parser = argparse.ArgumentParser(add_help=False)
    list_parser.add_argument(
        '-l',
        '--list',
        action='store_true',
        help="List all known installed interfaces and devices and then exit")
    list_parser.add_argument(
        '-v',
        '--verbose',
        action="count",
        default=0,
        help="Increase logging level (goes error, warn, info, debug)")

    parser = argparse.ArgumentParser(
        description=
        "Serve acess to a virtual IOTile device using a virtual IOTile interface"
    )

    parser.add_argument('interface',
                        help="The name of the virtual device interface to use")
    parser.add_argument('device',
                        help="The name of the virtual device to create")
    parser.add_argument(
        '-c',
        '--config',
        help=
        "An optional JSON config file with arguments for the interface and device"
    )
    parser.add_argument(
        '-l',
        '--list',
        action='store_true',
        help="List all known installed interfaces and devices and then exit")
    parser.add_argument('-n',
                        '--scenario',
                        help="Load a test scenario from the given file")
    parser.add_argument(
        '-s',
        '--state',
        help=
        "Load a given state into the device before starting to serve it.  Only works with emulated devices."
    )
    parser.add_argument(
        '-d',
        '--dump',
        help=
        "Dump the device's state when we exit the program.  Only works with emulated devices."
    )
    parser.add_argument(
        '-t',
        '--track',
        help=
        "Track all changes to the device's state.  Only works with emulated devices."
    )
    parser.add_argument(
        '-v',
        '--verbose',
        action="count",
        default=0,
        help="Increase logging level (goes error, warn, info, debug)")

    args, _rest = list_parser.parse_known_args(argv)

    if args.list:
        configure_logging(args.verbose)

        reg = ComponentRegistry()
        print("Installed Device Servers:")
        for name, _iface in reg.load_extensions(
                'iotile.device_server', class_filter=AbstractDeviceServer):
            print('- {}'.format(name))

        print("\nInstalled Virtual Devices:")
        for name, dev in reg.load_extensions('iotile.virtual_device',
                                             class_filter=BaseVirtualDevice,
                                             product_name="virtual_device"):
            print('- {}: {}'.format(name, one_line_desc(dev)))

        return 0

    args = parser.parse_args(argv)

    configure_logging(args.verbose)

    config = {}
    if args.config is not None:
        with open(args.config, "r") as conf_file:
            config = json.load(conf_file)

    started = False
    device = None
    stop_immediately = args.interface == 'null'
    try:
        server = instantiate_interface(args.interface, config, loop)
        device = instantiate_device(args.device, config, loop)

        if args.state is not None:
            print("Loading device state from file %s" % args.state)
            device.load_state(args.state)

        if args.scenario is not None:
            print("Loading scenario from file %s" % args.scenario)

            with open(args.scenario, "r") as infile:
                scenario = json.load(infile)

            # load_metascenario expects a list of scenarios even when there is only one
            if isinstance(scenario, dict):
                scenario = [scenario]

            device.load_metascenario(scenario)

        if args.track is not None:
            print("Tracking all state changes to device")
            device.state_history.enable()

        adapter = VirtualDeviceAdapter(devices=[device], loop=loop)
        server.adapter = adapter

        loop.run_coroutine(adapter.start())

        try:
            loop.run_coroutine(server.start())
        except:
            loop.run_coroutine(adapter.stop())
            adapter = None
            raise

        started = True

        print("Starting to serve virtual IOTile device")

        if stop_immediately:
            return 0

        # We need to periodically process events that are queued up in the interface
        while True:
            time.sleep(0.5)

    except KeyboardInterrupt:
        print("Break received, cleanly exiting...")
    finally:
        if args.dump is not None and device is not None:
            print("Dumping final device state to %s" % args.dump)
            device.save_state(args.dump)

        if started:
            loop.run_coroutine(server.stop())
            loop.run_coroutine(adapter.stop())

        if args.track is not None and device is not None:
            print("Saving state history to file %s" % args.track)
            device.state_history.dump(args.track)

    return 0
예제 #13
0
def _find_release_providers():
    reg = ComponentRegistry()
    return {
        name: entry
        for name, entry in reg.load_extensions('iotile.build.release_provider')
    }