Exemple #1
0
    def configure(count, name, policy):
        """Configure application monitor"""

        restapi = context.GLOBAL.cell_api()
        url = _REST_PATH + name

        options = {}
        if count is not None:
            options['count'] = count
        if policy is not None:
            options['policy'] = policy

        # reconfigure if any of the parameters is specified
        if options:
            existing = None
            try:
                existing = restclient.get(restapi, url).json()
            except restclient.NotFoundError:
                _LOGGER.debug('App monitor not found: %s', name)

            if existing is None:
                _check_configure_usage(count)

                _LOGGER.debug('Creating app monitor: %s', name)
                restclient.post(restapi, url, payload=options)

            else:
                existing.update(options)
                _LOGGER.debug('Updating app monitor: %s', name)
                restclient.put(restapi, url, payload=existing)

        _LOGGER.debug('Retrieving app monitor: %s', name)
        monitor_entry = restclient.get(restapi, url)
        cli.out(formatter(monitor_entry.json()))
Exemple #2
0
    def configure(job_id, event, resource, expression, count):
        """Create or modify an existing app start schedule"""
        restapi = context.GLOBAL.cell_api(ctx['api'])
        url = _REST_PATH + job_id

        data = {}

        if event:
            data['event'] = event
        if resource:
            data['resource'] = resource
        if expression:
            data['expression'] = expression
        if count is not None:
            data['count'] = count

        if data:
            try:
                _LOGGER.debug('Creating cron job: %s', job_id)
                restclient.post(restapi, url, payload=data)
            except restclient.AlreadyExistsError:
                _LOGGER.debug('Updating cron job: %s', job_id)
                restclient.put(restapi, url, payload=data)

        _LOGGER.debug('Retrieving cron job: %s', job_id)
        job = restclient.get(restapi, url).json()
        _LOGGER.debug('job: %r', job)

        cli.out(_FORMATTER(job))
Exemple #3
0
    def configure(tenant, systems, name, env):
        """Configure allocation tenant."""
        restapi = context.GLOBAL.admin_api(ctx.get('api'))
        tenant_url = '/tenant/%s' % tenant

        if systems:
            try:
                existing = restclient.get(restapi, tenant_url).json()
                all_systems = set(existing['systems'])
                all_systems.update(map(int, systems))
                restclient.put(restapi,
                               tenant_url,
                               payload={'systems': list(all_systems)})
            except restclient.NotFoundError:
                restclient.post(restapi,
                                tenant_url,
                                payload={'systems': map(int, systems)})

        if env:
            if name is None:
                name = env

            alloc_url = '/allocation/%s/%s' % (tenant, name)
            try:
                restclient.post(restapi,
                                alloc_url,
                                payload={'environment': env})
            except restclient.AlreadyExistsError:
                pass

        _display_tenant(restapi, tenant)
    def configure(name, cell, pattern, endpoints, alias, scope):
        """Create, modify or get Treadmill App DNS entry"""
        restapi = context.GLOBAL.admin_api()
        url = _REST_PATH + name
        data = {}

        if cell:
            data['cells'] = cell
        if pattern is not None:
            data['pattern'] = pattern
        if endpoints is not None:
            data['endpoints'] = endpoints
        if alias is not None:
            data['alias'] = alias
        if scope is not None:
            data['scope'] = scope

        if data:
            try:
                _LOGGER.debug('Trying to create app-dns entry %s', name)
                restclient.post(restapi, url, data)
            except restclient.AlreadyExistsError:
                _LOGGER.debug('Updating app-dns entry %s', name)
                restclient.put(restapi, url, data)

        _LOGGER.debug('Retrieving App DNS entry %s', name)
        app_dns_entry = restclient.get(restapi, url).json()

        cli.out(formatter(app_dns_entry))
Exemple #5
0
def _make_allocation(restapi, allocation, env):
    """Ensure allocation exists for given environment."""
    # Make sure allocation exists for given environment.
    alloc_url = '/allocation/{}/{}'.format(allocation, env)
    try:
        restclient.post(restapi, alloc_url, payload={'environment': env})
    except restclient.AlreadyExistsError:
        pass
Exemple #6
0
 def test_default_timeout_post(self, resp_mock):
     """Tests that default timeout for post request is set correctly."""
     resp_mock.return_value.status_code = http.client.OK
     resp_mock.return_value.text = 'foo'
     restclient.post('http://foo.com', '/', '')
     resp_mock.assert_called_with(
         'http://foo.com/', stream=None, auth=mock.ANY,
         headers=None, json='', timeout=(0.5, None), proxies=None
     )
Exemple #7
0
    def reserve(allocation, env, cell, partition, rank, rank_adjustment,
                max_utilization, empty, memory, cpu, disk, traits):
        """Reserve capacity on the cell for given environment."""
        _check_reserve_usage(empty, memory, cpu, disk)

        restapi = context.GLOBAL.admin_api(ctx.get('api'))

        _check_tenant_exists(restapi, allocation)
        _make_allocation(restapi, allocation, env)

        data = {}
        if empty:
            data['memory'] = '0M'
            data['disk'] = '0M'
            data['cpu'] = '0%'

        if memory:
            data['memory'] = memory
        if cpu:
            data['cpu'] = cpu
        if disk:
            data['disk'] = disk

        if rank is not None:
            data['rank'] = rank
        if rank_adjustment is not None:
            data['rank_adjustment'] = rank_adjustment
        if max_utilization is not None:
            data['max_utilization'] = max_utilization
        if partition:
            data['partition'] = partition
        if traits:
            data['traits'] = cli.combine(traits)

        if data:
            reservation_url = '/allocation/{}/{}/reservation/{}'.format(
                allocation, env, cell)

            try:
                existing = restclient.get(restapi, reservation_url).json()
                # TODO: need cleaner way of deleting attributes that are not
                #       valid for update. It is a hack.
                for attr in list(existing):
                    if (attr not in ['memory', 'cpu', 'disk', 'partition']):
                        del existing[attr]

                existing.update(data)
                restclient.put(restapi, reservation_url, payload=existing)

            except restclient.NotFoundError:
                # some attributes need default values when creating
                if not partition:
                    data['partition'] = admin.DEFAULT_PARTITION

                restclient.post(restapi, reservation_url, payload=data)

        _display_tenant(restapi, allocation)
Exemple #8
0
    def reserve(allocation, env, cell, partition, rank, rank_adjustment,
                max_utilization, empty, memory, cpu, disk, traits):
        """Reserve capacity on the cell for given environment."""
        _check_reserve_usage(empty, memory, cpu, disk)

        restapi = context.GLOBAL.admin_api(ctx.get('api'))

        _check_tenant_exists(restapi, allocation)
        _make_allocation(restapi, allocation, env)

        data = {}
        if empty:
            data['memory'] = '0M'
            data['disk'] = '0M'
            data['cpu'] = '0%'

        if memory:
            data['memory'] = memory
        if cpu:
            data['cpu'] = cpu
        if disk:
            data['disk'] = disk
        if partition:
            data['partition'] = partition

        reservation_url = '/allocation/{}/{}/reservation/{}'.format(
            allocation, env, cell)

        try:
            existing = restclient.get(restapi, reservation_url).json()
            if data:
                # To meet the json schema required in create
                if 'memory' not in data:
                    data['memory'] = existing['memory']
                if 'cpu' not in data:
                    data['cpu'] = existing['cpu']
                if 'disk' not in data:
                    data['disk'] = existing['disk']
                if 'partition' not in data:
                    data['partition'] = existing['partition']
                restclient.put(restapi, reservation_url, payload=data)
        except restclient.NotFoundError:
            if rank is not None:
                data['rank'] = rank
            if rank_adjustment is not None:
                data['rank_adjustment'] = rank_adjustment
            if max_utilization is not None:
                data['max_utilization'] = max_utilization
            if traits:
                data['traits'] = cli.combine(traits)

            restclient.post(restapi, reservation_url, payload=data)

        _display_tenant(restapi, allocation)
Exemple #9
0
    def assign(allocation, env, cell, pattern, priority, delete):
        """Assign application pattern:priority to the allocation.

        Application pattern must start with <PROID>. and is a glob expression.

        Environments of the proid and one specified in command line using
        --env option must match.

        Once scheduled, Treadmill scheduler will match application against all
        available patterns and assign application to a reserved capacity.

        All application assigned to a capacity are ordered by priority from
        high to low.
        """
        restapi = context.GLOBAL.admin_api(ctx.get('api'))

        _check_tenant_exists(restapi, allocation)
        _make_allocation(restapi, allocation, env)

        reservation_url = '/allocation/{}/{}/reservation/{}'.format(
            allocation, env, cell)

        try:
            restclient.get(restapi, reservation_url)
        except restclient.NotFoundError:
            # TODO: default partition should be resolved in API, not in CLI.
            restclient.post(restapi,
                            reservation_url,
                            payload={
                                'memory': '0M',
                                'disk': '0M',
                                'cpu': '0%',
                                'partition': admin.DEFAULT_PARTITION
                            })

        url = '/allocation/{}/{}/assignment/{}/{}'.format(
            allocation, env, cell, pattern)

        if delete:
            restclient.delete(restapi, url)
        else:
            default_prio = None
            existing = restclient.get(restapi, url).json()
            for assignment in existing:
                if assignment['pattern'] == pattern:
                    default_prio = assignment['priority']
            if default_prio is None:
                default_prio = _DEFAULT_PRIORITY

            data = {'priority': priority if priority else default_prio}
            restclient.put(restapi, url, payload=data)

        _display_tenant(restapi, allocation)
 def test_verify_post(self, resp_mock):
     """Tests that 'verify' for post request is set correctly."""
     resp_mock.return_value.status_code = http_client.OK
     resp_mock.return_value.text = 'foo'
     restclient.post('http://foo.com', '/', '', verify='/path/to/ca/certs')
     resp_mock.assert_called_with('http://foo.com/',
                                  stream=None,
                                  auth=mock.ANY,
                                  headers=None,
                                  json='',
                                  timeout=(0.5, None),
                                  proxies=None,
                                  verify='/path/to/ca/certs')
def _configure_monitor(name, count):
    """Configure target count for the current cell."""
    _LOGGER.info('configuring monitor: %s, count: %s', name, count)
    url = '/app-monitor/%s' % name

    restapi = context.GLOBAL.cell_api()
    data = {'count': count}
    try:
        _LOGGER.debug('Creating app monitor: %s', name)
        restclient.post(restapi, url, payload=data)
    except restclient.AlreadyExistsError:
        _LOGGER.debug('Updating app monitor: %s', name)
        restclient.put(restapi, url, payload=data)
Exemple #12
0
    def assign(allocation, cell, pattern, priority, delete):
        """Assign application pattern:priority to the allocation."""
        restapi = context.GLOBAL.admin_api(ctx.get('api'))
        url = '/allocation/%s/assignment/%s/%s' % (allocation, cell, pattern)
        if delete:
            restclient.delete(restapi, url)
        else:
            try:
                restclient.post(restapi, url, payload={'priority': priority})
            except restclient.AlreadyExistsError:
                restclient.put(restapi, url, payload={'priority': priority})

        _display_alloc(restapi, allocation)
Exemple #13
0
    def assign(allocation, env, cell, pattern, priority, delete):
        """Assign application pattern:priority to the allocation.

        Application pattern must start with <PROID>. and is a glob expression.

        Environments of the proid and one specified in command line using
        --env option must match.

        Once scheduled, Treadmill scheduler will match application against all
        available patterns and assign application to a reserved capacity.

        All application assigned to a capacity are ordered by priority from
        high to low.
        """
        restapi = context.GLOBAL.admin_api()

        _check_tenant_exists(restapi, allocation)
        _make_allocation(restapi, allocation, env)

        reservation_url = '/allocation/{}/{}/reservation/{}'.format(
            allocation, env, cell)

        try:
            restclient.get(restapi, reservation_url)
        except restclient.NotFoundError:
            restclient.post(restapi,
                            reservation_url,
                            payload={
                                'memory': '0M',
                                'disk': '0M',
                                'cpu': '0%'
                            })

        url = '/allocation/{}/{}/assignment/{}/{}'.format(
            allocation, env, cell, pattern)

        if delete:
            restclient.delete(restapi, url)
        else:
            data = {}
            if priority:
                data['priority'] = priority
            existing = restclient.get(restapi, url).json()
            rest_func = restclient.post
            for assignment in existing:
                if assignment['pattern'] == pattern:
                    rest_func = restclient.put
                    break
            rest_func(restapi, url, payload=data)

            _display_tenant(restapi, allocation)
Exemple #14
0
def set_count(monitor_name=None, count=None):
    """Set the count on the supplied monitor"""
    _LOGGER.debug('monitor: %s, count: %s', monitor_name, count)

    if not monitor_name:
        _LOGGER.error('No monitor name supplied, cannot continue')
        return

    restclient.post(
        [_API_URL],
        '/app-monitor/{}'.format(monitor_name),
        payload={'count': count},
        headers={'X-Treadmill-Trusted-Agent': 'cron'}
    )
Exemple #15
0
    def reserve(allocation, cell, partition, rank, memory, cpu, disk):
        """Reserve capacity on the cell."""
        restapi = context.GLOBAL.admin_api(ctx.get('api'))

        if (cell is None
                and any([memory, cpu, disk, rank is not None, partition])):
            raise click.UsageError(
                'Must specify cell with modifying reservation.')

        if cell:
            # Create reservation for the given cell.
            reservation_url = '/allocation/%s/reservation/%s' % (allocation,
                                                                 cell)
            try:
                existing = restclient.get(restapi, reservation_url).json()
                # TODO: need cleaner way of deleting attributes that are not
                #       valid for update. It is a hack.
                for attr in existing.keys():
                    if (attr not in [
                            'memory', 'cpu', 'disk', 'rank', 'partition'
                    ]):
                        del existing[attr]

                if memory:
                    existing['memory'] = memory
                if cpu:
                    existing['cpu'] = cpu
                if disk:
                    existing['disk'] = disk
                if rank is not None:
                    existing['rank'] = rank
                if partition:
                    existing['partition'] = partition
                restclient.put(restapi, reservation_url, payload=existing)
            except restclient.NotFoundError:
                payload = {
                    'memory': memory,
                    'disk': disk,
                    'cpu': cpu,
                    'rank': rank if rank is not None else 100
                }

                if partition:
                    payload['partition'] = partition
                else:
                    payload['partition'] = admin.DEFAULT_PARTITION

                restclient.post(restapi, reservation_url, payload=payload)

        _display_alloc(restapi, allocation)
Exemple #16
0
    def configure_node(ctx, vpc_name, region, name, key, image, subnet_name,
                       instance_type, tm_release, app_root,
                       ipa_admin_password, with_api, manifest):
        """Configure new Node in Cell"""

        domain = ctx.obj['DOMAIN']
        _url = '/cloud/vpc/' + vpc_name + '/domain/' + domain \
               + '/server/' + name
        cli.out(
            restclient.post(
                api=ctx.obj.get('API'),
                url=_url,
                payload={
                    "role": "node",
                    "key": key,
                    "tm_release": tm_release,
                    "region": region,
                    "app_root": app_root,
                    "instance_type": instance_type,
                    "image": image,
                    "ipa_admin_password": ipa_admin_password,
                    "subnet_name": subnet_name,
                    "with_api": with_api,
                },
                headers={'Content-Type': 'application/json'}
            ).content
        )
Exemple #17
0
 def configure_cell(ctx, vpc_name, region, name, key, image,
                    subnet_name, instance_type, tm_release,
                    app_root, cidr_block, ipa_admin_password,
                    manifest):
     """Configure Treadmill Cell"""
     domain = ctx.obj['DOMAIN']
     _url = '/cloud/vpc/' + vpc_name + '/domain/' + domain + '/cell'
     cli.out(
         restclient.post(
             api=ctx.obj.get('API'),
             url=_url,
             payload={
                 "role": "cell",
                 "key": key,
                 "tm_release": tm_release,
                 "region": region,
                 "app_root": app_root,
                 "cidr_block": cidr_block,
                 "instance_type": instance_type,
                 "image": image,
                 "ipa_admin_password": ipa_admin_password,
                 "subnet_name": subnet_name
             },
             headers={'Content-Type': 'application/json'}
         ).content
     )
Exemple #18
0
def start(job_id=None, app_name=None, count=1):
    """Start an application in the given cell"""
    _LOGGER.debug('job_id: %s, app_name: %s, count: %s', job_id, app_name,
                  count)

    if not app_name:
        _LOGGER.error('No app name provided, cannot continue')
        return

    try:
        restclient.post([_API_URL],
                        '/instance/{}?count={}'.format(app_name, count),
                        payload={},
                        headers={'X-Treadmill-Trusted-Agent': 'cron'})
    except Exception:  # pylint: disable=W0703
        _LOGGER.exception('Error starting app: %s', app_name)
Exemple #19
0
    def post(path, payload):
        """REST POST request."""
        request = yaml.load(payload.read())
        response = restclient.post(ctx['api'], path, payload=request)

        formatter = cli.make_formatter(None)
        cli.out(formatter(response.json()))
 def test_raw_payload_post(self, resp_mock):
     """Tests that post can send payload not in json."""
     resp_mock.return_value.status_code = http_client.OK
     resp_mock.return_value.text = 'foo'
     restclient.post('http://foo.com',
                     '/',
                     'payload',
                     payload_to_json=False)
     resp_mock.assert_called_with('http://foo.com/',
                                  stream=None,
                                  auth=mock.ANY,
                                  headers=None,
                                  timeout=(0.5, None),
                                  proxies=None,
                                  data='payload',
                                  verify=True)
Exemple #21
0
    def authorize(self, resource, action, args, _kwargs):
        """Delegate authorization to the plugin."""
        resource = resource.split('.').pop()

        user = self.user_clbk()
        # PGE API can't handle None.
        if user is None:
            user = ''

        # Defaults for primary key and payload.
        url = '/%s/%s/%s' % (user, action, resource)
        data = {}

        if len(args) > 0:
            data['pk'] = str(args[0])
        if len(args) > 1:
            data['payload'] = args[1]

        # POST http://auth_server/user/action/resource
        # {"pk": "foo", "payload": { ... }}
        response = restclient.post(api=self.remote,
                                   url=url,
                                   payload=data,
                                   auth=None)
        authd = response.json()
        _LOGGER.debug('client authorize ressult %r', authd)

        if not authd['auth']:
            raise AuthorizationError(authd['annotations'])

        return authd
Exemple #22
0
    def authorize(self, resource, action, args, _kwargs):
        """Delegate authorization to the plugin."""
        resource = resource.split('.').pop()

        user = self.user_clbk()
        # PGE API can't handle None.
        if user is None:
            user = ''

        # Defaults for primary key and payload.
        url = '/%s/%s/%s' % (user, action, resource)
        data = {}

        nargs = len(args)
        if nargs > 0:
            data['pk'] = args[0]

        if nargs > 1:
            data['payload'] = args[1]

        response = restclient.post(
            [self.remote],
            url,
            payload=data,
        )
        authd = response.json()
        _LOGGER.debug('client authorize ressult %r', authd)

        if not authd['auth']:
            raise AuthorizationError(authd['annotations'])

        return authd
Exemple #23
0
def _reap(bad):
    """Delete instances that did not path health check."""
    if not bad:
        return []

    cellapi = context.GLOBAL.cell_api()
    try:
        for instance in bad:
            _LOGGER.info('Delete: %s', instance)

        restclient.post(cellapi,
                        '/instance/_bulk/delete',
                        payload=dict(instances=bad))
        return bad
    except Exception:  # pylint: disable=W0703
        _LOGGER.exception('Error reaping: %r', bad)
        return []
Exemple #24
0
    def configure(count, name):
        """Configure application monitor"""
        restapi = context.GLOBAL.cell_api()
        url = _REST_PATH + name

        if count is not None:
            data = {'count': count}
            try:
                _LOGGER.debug('Creating app monitor: %s', name)
                restclient.post(restapi, url, payload=data)
            except restclient.AlreadyExistsError:
                _LOGGER.debug('Updating app monitor: %s', name)
                restclient.put(restapi, url, payload=data)

        _LOGGER.debug('Retrieving app monitor: %s', name)
        monitor_entry = restclient.get(restapi, url)
        cli.out(formatter(monitor_entry.json()))
Exemple #25
0
    def post(path, payload):
        """REST POST request."""
        with io.open(payload, 'rb') as fd:
            request = yaml.load(stream=fd)
        response = restclient.post(ctx['api'], path, payload=request)

        formatter = cli.make_formatter(None)
        cli.out(formatter(response.json()))
Exemple #26
0
 def create_user(ctx, username):
     """Creates an IPA User"""
     cli.out(
         restclient.post(
             api=ctx.obj.get('API'),
             url='/ipa/user/' + username,
             headers={'Content-Type': 'application/json'}
         ).content
     )
Exemple #27
0
 def create_host(ctx, hostname):
     """Creates an IPA Host"""
     cli.out(
         restclient.post(
             api=ctx.obj.get('API'),
             url='/ipa/host/' + hostname,
             headers={'Content-Type': 'application/json'}
         ).content
     )
Exemple #28
0
def _run(apis, count, manifest, memory, cpu, disk, tickets, service,
         restart_limit, restart_interval, endpoint, appname, command):
    """Run Treadmill app."""
    # too many branches
    #
    # pylint: disable=R0912
    app = {}
    if manifest:
        app = yaml.load(manifest.read())

    if endpoint:
        app['endpoints'] = [{
            'name': name,
            'port': port
        } for name, port in endpoint]
    if tickets:
        app['tickets'] = tickets

    if command:
        if not service:
            # Take the basename of the command, always assume / on all
            # platforms.
            service = command[0].split('/')[-1]

    services_dict = {svc['name']: svc for svc in app.get('services', [])}
    if service:
        if service not in services_dict:
            services_dict[service] = {
                'name': service,
                'restart': {
                    'limit': restart_limit,
                    'interval': restart_interval,
                }
            }

        if command:
            services_dict[service]['command'] = ' '.join(list(command))

    if services_dict:
        app['services'] = services_dict.values()

    if app:
        if memory:
            app['memory'] = memory
        if disk:
            app['disk'] = disk
        if cpu:
            app['cpu'] = cpu

    url = '/instance/' + appname
    if count:
        url += '?count=%d' % count

    response = restclient.post(apis, url, payload=app)
    for instance_id in response.json()['instances']:
        cli.out(instance_id)
Exemple #29
0
    def configure(allocation, systems, set_):
        """Configure allocation.

        Allocation name is global, and is associated with list of systems.
        """
        restapi = context.GLOBAL.admin_api()
        url = '/tenant/{}'.format(allocation)

        if systems:

            # If tenant exists, update or replace it with new systems.
            # If update fails with resource does not exist error, try creating
            # tenants from parent to child, those that do not exist will be
            # created with provided systems.
            try:
                existing = restclient.get(restapi, url).json()
                all_systems = set(six.moves.map(int, systems))
                # if the system ids have to be extended instead of replaced
                if not set_:
                    all_systems.update(existing['systems'])
                restclient.put(restapi,
                               url,
                               payload={'systems': list(all_systems)})
            except restclient.NotFoundError:
                # Create parent tenants recursively.
                #
                # If parent does not exist, it will be created with the systems
                # specified.
                parts = allocation.split(':')
                for idx in range(1, len(parts) + 1):
                    url = '/tenant/{}'.format(':'.join(parts[:idx]))

                    try:
                        existing = restclient.get(restapi, url).json()
                    except restclient.NotFoundError:
                        restclient.post(restapi,
                                        url,
                                        payload={
                                            'systems':
                                            list(six.moves.map(int, systems))
                                        })

        _display_tenant(restapi, allocation)
Exemple #30
0
def stop(job_id=None, app_name=None):
    """Stop an application"""
    _LOGGER.debug('job_id: %s, app_name: %r', job_id, app_name)

    try:
        response = restclient.get([_API_URL],
                                  '/instance/?match={}'.format(app_name))
        instances = response.json().get('instances', [])
        _LOGGER.info('Stopping: %r', instances)

        if not instances:
            _LOGGER.warning('No instances running for %s', app_name)
            return

        restclient.post([_API_URL],
                        '/instance/_bulk/delete',
                        payload=dict(instances=instances),
                        headers={'X-Treadmill-Trusted-Agent': 'cron'})
    except Exception:  # pylint: disable=W0703
        _LOGGER.exception('Error stopping app: %s', app_name)