Beispiel #1
0
class GeneralConfig(FiggisConfig):

    conf_dir = Field(expand, default='$HOME/.suggestive')
    database = Field(expand, default='{conf_dir}/music.db')
    highcolor = Field(bool, default=True)
    default_buffers = Field(CSV,
                            valid_buffers,
                            default=['library', 'playlist'])
    orientation = Field(default='horizontal', choices=VALID_ORIENTATIONS)
    log = Field(expand, default='{conf_dir}/log.txt')
    verbose = Field(bool, default=False)
    log_sql_queries = Field(bool, default=False)
    session_file = Field(expand, default='{conf_dir}/session')
    update_on_startup = Field(bool, default=False)

    @property
    def colormode(self):
        return 256 if self.highcolor else 88

    @property
    def log_level(self):
        return logging.DEBUG if self.verbose else logging.INFO

    @property
    def sqlalchemy_url(self):
        return 'sqlite:///{}'.format(self.database)
class ClusterCreateNodeGroups(Config):

    __allow_extra__ = False

    id = Field(six.text_type, required=True, validator=Length(min=1, max=255))
    count = Field(int, validator=Range(min=1, max=100))
    flavor_id = Field(six.text_type)
Beispiel #3
0
class AbsoluteLimit(Config, ReprMixin):

    limit = Field(int, required=True)
    remaining = Field(int, required=True)

    @property
    def used(self):
        return self.limit - self.remaining
Beispiel #4
0
class PlaylistConfig(FiggisConfig):

    __nointerpolate__ = {'status_format'}

    status_format = Field(
        default='{status}: {artist} - {title} [{time_elapsed}/{time_total}]')
    save_playlist_on_close = Field(bool, default=False)
    playlist_save_name = Field(default='suggestive.state')
Beispiel #5
0
class Size(Config, ReprMixin):

    table_columns = ('flavor', 'minutes', 'nodecount', 'recommended')
    table_header = ('Flavor', 'Minutes', 'Nodes', 'Recommended')

    flavor_id = Field(six.text_type, required=True, key='flavor')
    minutes = Field(float, required=True)
    nodecount = Field(int, required=True)
    recommended = Field(bool, default=False)
Beispiel #6
0
class NodeGroup(Config, ReprMixin):
    """Group of nodes that share the same flavor and installed services"""

    table_columns = ('id', 'flavor_id', 'count', '_components')
    table_header = ('ID', 'Flavor', 'Count', 'Components')

    id = Field(six.text_type, required=True, validator=Length(min=1, max=255))
    count = Field(int, validator=Range(min=1, max=100))
    flavor_id = Field(six.text_type)
    components = ListField(dict, default={})
Beispiel #7
0
class CreateS3Request(Config):

    access_key_id = Field(six.text_type,
                          required=True,
                          nullable=False,
                          validator=Length(min=20, max=20))
    access_secret_key = Field(six.text_type,
                              nullable=False,
                              required=True,
                              validator=Length(min=40, max=40))
Beispiel #8
0
class CreateCloudFilesRequest(Config):

    username = Field(six.text_type,
                     required=True,
                     nullable=False,
                     validator=Length(min=3, max=255))
    api_key = Field(six.text_type,
                    nullable=False,
                    required=True,
                    validator=Length(min=20, max=40))
Beispiel #9
0
class CreateAmbariRequest(Config):

    username = Field(six.text_type,
                     required=True,
                     nullable=False,
                     validator=Length(min=3, max=255))
    password = Field(six.text_type,
                     nullable=False,
                     required=True,
                     validator=Length(min=8, max=255))
Beispiel #10
0
class CreateSSHKeyRequest(Config):

    key_name = Field(six.text_type,
                     required=True,
                     nullable=False,
                     validator=Length(min=3, max=255))
    public_key = Field(six.text_type,
                       nullable=False,
                       required=True,
                       validator=Length(min=50, max=1024))
class NodeGroup(Config):

    id = Field(six.text_type, required=True, validator=Length(min=1, max=36))
    flavor_id = Field(six.text_type)
    count = Field(int, validator=Range(min=0, max=100))
    components = ListField(Component)

    @classmethod
    def _describe(cls):
        return cls.describe().replace('\n', ', ')
class CreateStackRequest(Config):

    name = Field(six.text_type,
                 required=True,
                 validator=Length(min=1, max=255))
    description = Field(six.text_type, validator=Length(min=1, max=1024))
    distro = Field(six.text_type,
                   required=True,
                   validator=Length(min=1, max=255))
    services = ListField(Service, required=True)
    node_groups = ListField(NodeGroup)
Beispiel #13
0
class Recommendations(Config, ReprMixin):
    """Recommendations on how to use the Lava API for a given workload"""

    name = Field(six.text_type, required=True)
    description = Field(six.text_type, required=True)
    requires = ListField(six.text_type, required=True)
    sizes = ListField(Size, required=True, help='See: :class:`Size`')

    @property
    def _description(self):
        return '\n'.join(textwrap.wrap(self.description, 30))
Beispiel #14
0
class Flavor(Config, ReprMixin):

    table_columns = ('id', 'name', 'ram', 'vcpus', 'disk')
    table_header = ('ID', 'Name', 'RAM', 'VCPUs', 'Disk')

    id = Field(six.text_type, required=True)
    name = Field(six.text_type, required=True)
    disk = Field(int, required=True, help='Disk space in MB')
    vcpus = Field(int, required=True)
    ram = Field(int, required=True, help='Memory in MB')
    links = ListField(Link)
Beispiel #15
0
class DistroService(Config, ReprMixin):

    table_columns = ('name', 'version', '_components', '_description')
    table_header = ('Name', 'Version', 'Components', 'Description')

    name = Field(six.text_type, required=True)
    version = Field(six.text_type, required=True)
    description = Field(six.text_type, required=True)
    components = ListField(dict, required=True)

    @property
    def _description(self):
        return '\n'.join(textwrap.wrap(self.description, 30))
Beispiel #16
0
class StackNodeGroup(Config, ReprMixin):

    table_columns = ('id', 'flavor_id', 'count', 'resource_limits.min_ram',
                     'resource_limits.min_count', 'resource_limits.max_count')
    table_header = ('ID', 'Flavor', 'Count', 'Min RAM', 'Min count',
                    'Max Count')

    id = Field(six.text_type, required=True)
    flavor_id = Field(six.text_type, required=True)
    resource_limits = Field(ResourceLimits,
                            required=True,
                            help='See: :class:`ResourceLimits`')
    count = Field(int, required=True)
    components = ListField(dict, required=True)
class ClusterCreateRequest(Config):
    """POST data to create cluster"""

    name = Field(six.text_type,
                 required=True,
                 validator=Length(min=1, max=255))
    username = Field(six.text_type,
                     required=True,
                     validator=[Length(min=2, max=255), valid_username])
    ssh_keys = ListField(six.text_type,
                         required=True,
                         validator=List(Length(min=1, max=255)))
    stack_id = Field(six.text_type, required=True)
    node_groups = ListField(ClusterCreateNodeGroups)
    scripts = ListField(ClusterCreateScript)
    connectors = ListField(ClusterCreateCredential)
    credentials = ListField(ClusterCreateCredential)
Beispiel #18
0
class Script(Config, ReprMixin):

    table_columns = ('id', 'name', 'type', 'is_public', 'created', 'url')
    table_header = ('ID', 'Name', 'Type', 'Public', 'Created', 'URL')

    id = Field(six.text_type, required=True)
    name = Field(six.text_type, required=True)
    type = Field(six.text_type, required=True)
    url = Field(six.text_type, required=True)
    is_public = Field(bool, required=True)
    created = Field(DateTime,
                    required=True,
                    help=':py:class:`~datetime.datetime` corresponding to '
                    'creation date')
    updated = Field(DateTime,
                    required=True,
                    help=':py:class:`~datetime.datetime` corresponding to '
                    'date last updated')
    links = ListField(Link)

    def update(self, **kwargs):
        """
        Update this script. See
        :meth:`~lavaclient.api.scripts.Resource.update`.
        """
        return self._client.scripts.update(self.id, **kwargs)

    def delete(self):
        """
        Delete this script. See
        :meth:`~lavaclient.api.scripts.Resource.delete`.
        """
        return self._client.scripts.delete(self.id)
class Component(Config):

    name = Field(six.text_type,
                 required=True,
                 validator=Length(min=1, max=255))

    @classmethod
    def _describe(cls):
        return cls.describe().replace('\n', ', ')
Beispiel #20
0
class Config(FiggisConfig):

    general = Field(GeneralConfig)
    mpd = Field(MpdConfig)
    lastfm = Field(LastfmConfig)
    appearance = Field(AppearanceConfig)
    playlist = Field(PlaylistConfig)
    library = Field(LibraryConfig)
    scrobbles = Field(ScrobblesConfig)
    custom_orderers = Field(parse_custom_orders, default={})

    def __init__(self, args=None, configuration=None):
        if configuration:
            super().__init__(configuration)
            return

        parser = ConfigParser()
        paths = CONFIG_PATHS
        if args and args.config:
            paths = [args.config] + CONFIG_PATHS

        # Make sure all sections are present
        parser.read([expand(path) for path in paths])
        for section in self._fields:
            if not parser.has_section(section):
                parser.add_section(section)

        # Override from CLI
        data = self._override_config(parser, args)

        # Parse config without interpolation first, then do interpolation afterward.  This prevents
        # fields with defaults from not being interpolated properly
        first_pass_conf = Config(configuration=data)
        first_pass = first_pass_conf.to_dict()

        # Do string interpolation
        for section, settings in first_pass.items():
            nointerpolate = getattr(getattr(first_pass_conf, section),
                                    '__nointerpolate__', [])
            for key, value in settings.items():
                settings[key] = value if key in nointerpolate else interpolate(
                    value, settings)

        super().__init__(first_pass)

    def _override_config(self, parser, args):
        if args:
            if args.log:
                parser['general']['log'] = args.log

        return parser._sections
Beispiel #21
0
class Stack(Config, ReprMixin, BaseStack):

    table_columns = ('id', '_name', 'distro', '_description')
    table_header = ('ID', 'Name', 'Distro', 'Description')

    id = Field(six.text_type, required=True)
    name = Field(six.text_type, required=True)
    description = Field(six.text_type)
    links = ListField(Link)
    distro = Field(six.text_type, required=True, help='Distribution ID')
    services = ListField(StackService,
                         required=True,
                         help='See: :class:`StackService`')

    @property
    def _name(self):
        return '\n'.join(textwrap.wrap(self.name, 25))

    @property
    def _description(self):
        return '\n'.join(textwrap.wrap(self.description, 30))
Beispiel #22
0
class Workload(Config, ReprMixin):

    table_columns = ('id', 'name', 'caption', '_description')
    table_header = ('ID', 'Name', 'Caption', 'Description')

    id = Field(six.text_type, required=True)
    name = Field(six.text_type, required=True)
    caption = Field(six.text_type, required=True)
    description = Field(six.text_type, required=True)

    @property
    def _description(self):
        return '\n'.join(textwrap.wrap(self.description, 30))

    def recommendations(self, *args):
        """
        recommendations(storage_size, persistence)

        Get recommendations for this workload. See
        :meth:`~lavaclient.api.workloads.Resource.recommendations`.
        """
        return self._client.workloads.recommendations(self.id, *args)
Beispiel #23
0
class LastfmConfig(FiggisConfig):

    scrobble_days = Field(int, non_negative, default=180)
    user = Field(default='')
    api_key = Field(default='')
    api_secret = Field(default='')
    log_responses = Field(bool, default=False)
    url = Field(default='http://ws.audioscrobbler.com/2.0')
Beispiel #24
0
class AmbariCredential(Config, ReprMixin):

    table_columns = ('type', 'username')

    type = 'Ambari'
    username = Field(six.text_type, required=True)

    @property
    def id(self):
        """Equivalent to :attr:`username`"""
        return self.username

    def delete(self):
        """Delete s3 credential"""
        self.__client.credentials.delete_ambari(self.username)
Beispiel #25
0
class AbsoluteLimits(Config, ReprMixin):

    node_count = Field(AbsoluteLimit,
                       required=True,
                       help='See: :class:`AbsoluteLimit`')
    ram = Field(AbsoluteLimit,
                required=True,
                help='See: :class:`AbsoluteLimit`')
    disk = Field(AbsoluteLimit,
                 required=True,
                 help='See: :class:`AbsoluteLimit`')
    vcpus = Field(AbsoluteLimit,
                  required=True,
                  help='See: :class:`AbsoluteLimit`')

    def display(self):
        properties = [
            ('Nodes', self.node_count.limit, self.node_count.remaining),
            ('RAM', self.ram.limit, self.ram.remaining),
            ('Disk', self.disk.limit, self.disk.remaining),
            ('VCPUs', self.vcpus.limit, self.vcpus.remaining),
        ]
        header = ('Property', 'Limit', 'Remaining')
        print_table(properties, header, title='Quotas')
Beispiel #26
0
class SSHKey(Config, ReprMixin):

    table_columns = ('type', 'name')
    table_header = ('Type', 'Name')

    type = 'SSH Key'
    name = Field(six.text_type, key='key_name', required=True)

    @property
    def id(self):
        """Equivalent to :attr:`name`"""
        return self.name

    def delete(self):
        """Delete this key"""
        self._client.credentials.delete_ssh_key(self.name)
Beispiel #27
0
class CloudFilesCredential(Config, ReprMixin):

    table_columns = ('type', 'username')
    table_header = ('Type', 'Username')

    type = 'Cloud Files'
    username = Field(six.text_type, required=True)

    @property
    def id(self):
        """Equivalent to :attr:`username`"""
        return self.username

    def delete(self):
        """Delete this credential"""
        self._client.credentials.delete_cloud_files(self.username)
Beispiel #28
0
class S3Credential(Config, ReprMixin):

    table_columns = ('type', 'access_key_id')
    table_header = ('Type', 'Access Key ID')

    type = 'Amazon S3'
    access_key_id = Field(six.text_type, required=True)

    @property
    def id(self):
        """Equivalent to :attr:`access_key_id`"""
        return self.access_key_id

    def delete(self):
        """Delete s3 credential"""
        self.__client.credentials.delete_s3(self.access_key_id)
Beispiel #29
0
class StackDetail(Stack, ReprMixin, BaseStack):

    __inherits__ = [Stack]

    table_columns = ('id', 'name', 'distro', 'created', '_description',
                     '_services', '_node_group_ids')
    table_header = ('ID', 'Name', 'Distro', 'Created', 'Description',
                    'Services', 'Node Groups')

    created = Field(DateTime,
                    required=True,
                    help=':py:class:`~datetime.datetime` corresponding to '
                    'creation date')
    node_groups = ListField(StackNodeGroup,
                            required=True,
                            help='See: :class:`StackNodeGroup`')

    def display(self):
        display_result(self, StackDetail, title='Stack')

        if self.node_groups:
            display_result(self.node_groups,
                           StackNodeGroup,
                           title='Node Groups')

            self._display_components()

    def _display_components(self):
        rows = []
        for group in self.node_groups:
            group_column = chain([group.id], repeat(''))
            rows.extend(
                no_nulls((grp, comp['name']))
                for grp, comp in six.moves.zip(group_column, group.components))

        print_table(rows, ('Node Group', 'Name'), title='Components')

    @property
    def _description(self):
        return '\n'.join(textwrap.wrap(self.description, 60))

    @property
    def _node_group_ids(self):
        return '\n'.join(
            textwrap.wrap(', '.join(group.id for group in self.node_groups)))
Beispiel #30
0
class Cluster(Config, ReprMixin, BaseCluster):
    """Basic cluster information"""

    table_columns = ('id', 'name', 'status', 'stack_id', 'created')
    table_header = ('ID', 'Name', 'Status', 'Stack', 'Created')

    id = Field(six.text_type, required=True)
    created = Field(DateTime,
                    required=True,
                    help=':py:class:`~datetime.datetime` corresponding to '
                    'creation date')
    updated = Field(DateTime,
                    required=True,
                    help=':py:class:`~datetime.datetime` corresponding to '
                    'date last updated')
    name = Field(six.text_type, required=True)
    status = Field(six.text_type, required=True)
    stack_id = Field(six.text_type, required=True)
    cbd_version = Field(int,
                        required=True,
                        help='API version at which cluster was created')
    links = ListField(Link)