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()))
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))
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))
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)
def test_default_timeout_put(self, resp_mock): """Tests that default timeout for put request is set correctly.""" resp_mock.return_value.status_code = http.client.OK resp_mock.return_value.text = 'foo' restclient.put('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 )
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)
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_raw_payload_put(self, resp_mock): """Tests that put can send payload not in json.""" resp_mock.return_value.status_code = http_client.OK resp_mock.return_value.text = 'foo' restclient.put('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)
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)
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)
def test_verify_put(self, resp_mock): """Tests that 'verify' for put request is set correctly.""" resp_mock.return_value.status_code = http_client.OK resp_mock.return_value.text = 'foo' restclient.put('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 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)
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 not delete and priority is None: raise click.UsageError( 'Must specify priority when creating/modifying assignments.') if delete: restclient.delete(restapi, url) else: restclient.put(restapi, url, payload={'priority': priority}) _display_alloc(restapi, allocation)
def put(path, payload): """REST PUT request.""" request = yaml.load(payload.read()) response = restclient.put(ctx['api'], path, payload=request) formatter = cli.make_formatter(None) cli.out(formatter(response.json()))
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 # assign is always put # because assign and reserve belong to the same ldap obj restclient.put(restapi, url, payload=data) _display_tenant(restapi, allocation)
def pause(job_id): """Pause a cron job""" restapi = context.GLOBAL.cell_api() url = _REST_PATH + job_id + '?pause=true' job = restclient.put(restapi, url, {}).json() _LOGGER.debug('job: %r', job) cli.out(_FORMATTER(job))
def resume(job_id): """Resume a cron job""" restapi = context.GLOBAL.cell_api(ctx['api']) url = _REST_PATH + job_id + '?resume=true' job = restclient.put(restapi, url, {}).json() _LOGGER.debug('job: %r', job) cli.out(_FORMATTER(job))
def cells(add, remove, name): """Add or remove cells from the app-dns.""" url = _REST_PATH + name restapi = context.GLOBAL.admin_api() existing = restclient.get(restapi, url).json() cells = set(existing['cells']) if add: cells.update(add) if remove: cells = cells - set(remove) if '_id' in existing: del existing['_id'] existing['cells'] = list(cells) restclient.put(restapi, url, existing)
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()))
def put(path, payload): """REST PUT request.""" with io.open(payload, 'rb') as fd: request = yaml.load(stream=fd) response = restclient.put(ctx['api'], path, payload=request) formatter = cli.make_formatter(None) cli.out(formatter(response.json()))
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)
def _configure(apis, manifest, appname): """Configure a Treadmill app""" try: existing = restclient.get(apis, _APP_REST_PATH + appname).json() except restclient.NotFoundError: if not manifest: raise else: existing = None if manifest: app = yaml.load(manifest.read()) if existing: restclient.put(apis, _APP_REST_PATH + appname, payload=app) else: restclient.post(apis, _APP_REST_PATH + appname, payload=app) # Get new value after update. existing = restclient.get(apis, _APP_REST_PATH + appname).json() cli.out(_FORMATTER(existing))
def _configure(apis, manifest, appname): """Configure a Treadmill app""" try: existing = restclient.get(apis, _APP_REST_PATH + appname).json() except restclient.NotFoundError: if not manifest: raise existing = None if manifest: app = yaml.load(stream=manifest) if existing: response = restclient.put(apis, _APP_REST_PATH + appname, payload=app) else: response = restclient.post(apis, _APP_REST_PATH + appname, payload=app) existing = response.json() cli.out(_FORMATTER(existing))