示例#1
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))
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)
示例#3
0
class Credentials(Config, ReprMixin):

    cloud_files = ListField(CloudFilesCredential)
    ssh_keys = ListField(SSHKey)
    s3 = ListField(S3Credential)
    ambari = ListField(AmbariCredential)

    def display(self):
        data = chain([('SSH Key', key.name) for key in self.ssh_keys],
                     [('Cloud Files', cred.username)
                      for cred in self.cloud_files],
                     [('Amazon S3', cred.access_key_id) for cred in self.s3],
                     [('Ambari', cred.username) for cred in self.ambari])
        print_table(data, ('Type', 'Name'), title='Credentials')
示例#4
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 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)
示例#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={})
class Service(Config):

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

    @classmethod
    def _describe(cls):
        return cls.describe().replace('\n', ', ')
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', ', ')
示例#9
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)
示例#10
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))
示例#11
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))
示例#12
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)
示例#13
0
class DistroDetail(Config, ReprMixin):

    table_columns = ('id', 'name', 'version')
    table_header = ('ID', 'Name', 'Version')

    __inherits__ = [Distro]

    services = ListField(DistroService,
                         required=True,
                         help='See: :class:`DistroService`')

    def display(self):
        display_result(self, DistroDetail, title='Distro')
        six.print_()
        display_result(self.services, DistroService, 'Services')
示例#14
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)))
示例#15
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)
示例#16
0
class CredentialType(Config, ReprMixin):

    type = Field(six.text_type, required=True)
    schema = Field(dict, required=True)
    links = ListField(Link)
示例#17
0
class Addresses(Config, ReprMixin):

    public = ListField(Address, required=True, help='See: :class:`Address`')
    private = ListField(Address, required=True, help='See: :class:`Address`')
示例#18
0
class StacksResponse(Config):

    stacks = ListField(Stack, required=True)
class ClusterCredentialsRequest(Config):

    credentials = ListField(ClusterUpdateCredential)
示例#20
0
class RecommendationsResponse(Config):

    recommendations = ListField(Recommendations)
示例#21
0
class WorkloadsResponse(Config):
    """Response from /workloads"""

    workloads = ListField(Workload, required=True)
 class Conf(Config):
     one = Field(SubConf)
     two = ListField(SubConf)
     three = Field(int)
 class SubConf(Config):
     foo = Field(SubSubConf)
     bar = ListField(SubSubConf)
     baz = Field(int)
class ClustersResponse(Config, ReprMixin):
    """Response from /clusters"""

    clusters = ListField(Cluster, required=True)
class ClusterResizeRequest(Config):
    """PUT data to resize cluster"""

    node_groups = ListField(ClusterCreateNodeGroups)
示例#26
0
class Node(Config, ReprMixin):
    table_columns = ('id', 'name', 'node_group', 'status', 'public_ip',
                     'private_ip')
    table_header = ('ID', 'Name', 'Role', 'Status', 'Public IP', 'Private IP')

    id = Field(six.text_type, required=True)
    name = 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')
    status = Field(six.text_type, required=True)
    flavor_id = Field(six.text_type, required=True)
    addresses = Field(Addresses,
                      required=True,
                      help='Public and private IP addresses; See: '
                      ':class:`Addresses`')
    node_group = Field(six.text_type, required=True, help='Node group ID')
    components = ListField(dict,
                           required=True,
                           help='Components installed on this node, e.g. '
                           '`HiveClient`')

    @classmethod
    def display_nodes(cls, nodes):
        sorted_nodes = sorted(nodes, key=lambda node: node.name)
        display_result(sorted_nodes, Node, title='Nodes')

        six.print_()
        rows = []
        for node in sorted_nodes:
            node_column = chain([node.name], repeat(''))

            rows.extend(
                no_nulls(
                    [name, comp['name'], comp['nice_name'],
                     comp.get('uri')])
                for name, comp in six.moves.zip(node_column, node.components))

        print_table(rows, ('Node', 'ID', 'Name', 'URI'), title='Components')

    @property
    def private_ip(self):
        """Private IP address on service network"""
        try:
            return self.addresses.private[0].address
        except IndexError:
            return None

    @property
    def public_ip(self):
        """Public IP address"""
        try:
            return self.addresses.public[0].address
        except IndexError:
            return None

    def _ssh(self, username, command=None, ssh_command=None):
        """
        SSH to this node, optionally running a command and returning the
        output.

        :param username: Login user
        :param command: Command to execute remotely
        :param ssh_command: ssh command string or `list`, e.g.
                            `ssh -F configfile`
        :returns: Output from running command, if a command was specified
        """
        try:
            return ssh_to_host(username,
                               self.public_ip,
                               command=command,
                               ssh_command=ssh_command)
        except subprocess.CalledProcessError as exc:
            msg = 'Command failed with code %d', exc.returncode
            LOG.error(msg)
            LOG.debug('Command output:\n%s', exc.output)
            raise error.FailedError(msg)

    def execute(self, username, command, ssh_command=None):
        """
        Execute a command remotely on this node, returning the output.

        :param username: Login user
        :param command: Command to execute remotely
        :param ssh_command: ssh command string or `list`, e.g.
                            `ssh -F configfile`
        :returns: Output from running command
        """
        return self._ssh(username, command=command, ssh_command=ssh_command)
class ClusterCredentialsRemovalRequest(Config):

    remove_credentials = ListField(ClusterUpdateCredential)
示例#28
0
class FlavorsResponse(Config):

    flavors = ListField(Flavor, required=True)
示例#29
0
class NodesResponse(Config):
    """Response from /clusters/<cluster_id>/nodes"""

    nodes = ListField(Node, required=True)
示例#30
0
class ScriptsResponse(Config):

    """Response from /scripts"""

    scripts = ListField(Script, required=True)