async def get_schedules(request): """ Returns: a list of all the defined schedules from schedules table :Example: curl -X GET http://localhost:8081/foglamp/schedule """ schedule_list = await server.Server.scheduler.get_schedules() schedules = [] for sch in schedule_list: schedules.append({ 'id': str(sch.schedule_id), 'name': sch.name, 'processName': sch.process_name, 'type': Schedule.Type(int(sch.schedule_type)).name, 'repeat': sch.repeat.total_seconds() if sch.repeat else 0, 'time': (sch.time.hour * 60 * 60 + sch.time.minute * 60 + sch.time.second) if sch.time else 0, 'day': sch.day, 'exclusive': sch.exclusive, 'enabled': sch.enabled }) return web.json_response({'schedules': schedules})
async def get_schedule(request): """ Returns: the information for the given schedule from schedules table :Example: curl -X GET http://localhost:8081/foglamp/schedule/2176eb68-7303-11e7-8cf7-a6006ad3dba0 """ try: schedule_id = request.match_info.get('schedule_id', None) try: assert uuid.UUID(schedule_id) except ValueError as ex: raise web.HTTPNotFound(reason="Invalid Schedule ID {}".format(schedule_id)) sch = await server.Server.scheduler.get_schedule(uuid.UUID(schedule_id)) schedule = { 'id': str(sch.schedule_id), 'name': sch.name, "processName": sch.process_name, 'type': Schedule.Type(int(sch.schedule_type)).name, 'repeat': sch.repeat.total_seconds() if sch.repeat else 0, 'time': (sch.time.hour * 60 * 60 + sch.time.minute * 60 + sch.time.second) if sch.time else 0, 'day': sch.day, 'exclusive': sch.exclusive, 'enabled': sch.enabled } return web.json_response(schedule) except (ValueError, ScheduleNotFoundError) as ex: raise web.HTTPNotFound(reason=str(ex))
async def update_schedule(request): """ Update a schedule in schedules table :Example: curl -d '{"type": 4, "name": "sleep30 updated", "process_name": "sleep30", "repeat": "15"}' -X PUT http://localhost:8081/foglamp/schedule/84fe4ea1-df9c-4c87-bb78-cab2e7d5d2cc """ try: data = await request.json() schedule_id = request.match_info.get('schedule_id', None) try: assert uuid.UUID(schedule_id) except ValueError as ex: raise web.HTTPNotFound(reason="Invalid Schedule ID {}".format(schedule_id)) sch = await server.Server.scheduler.get_schedule(uuid.UUID(schedule_id)) if not sch: raise ScheduleNotFoundError(schedule_id) curr_value = dict() curr_value['schedule_id'] = sch.schedule_id curr_value['schedule_process_name'] = sch.process_name curr_value['schedule_name'] = sch.name curr_value['schedule_type'] = sch.schedule_type curr_value['schedule_repeat'] = sch.repeat.total_seconds() if sch.repeat else 0 curr_value['schedule_time'] = (sch.time.hour * 60 * 60 + sch.time.minute * 60 + sch.time.second) if sch.time else 0 curr_value['schedule_day'] = sch.day curr_value['schedule_exclusive'] = sch.exclusive curr_value['schedule_enabled'] = sch.enabled go_no_go = await _check_schedule_post_parameters(data, curr_value) if len(go_no_go) != 0: raise ValueError("Errors in request: {}".format(','.join(go_no_go))) updated_schedule_id = await _execute_add_update_schedule(data, curr_value) sch = await server.Server.scheduler.get_schedule(updated_schedule_id) schedule = { 'id': str(sch.schedule_id), 'name': sch.name, "processName": sch.process_name, 'type': Schedule.Type(int(sch.schedule_type)).name, 'repeat': sch.repeat.total_seconds() if sch.repeat else 0, 'time': (sch.time.hour * 60 * 60 + sch.time.minute * 60 + sch.time.second) if sch.time else 0, 'day': sch.day, 'exclusive': sch.exclusive, 'enabled': sch.enabled } return web.json_response({'schedule': schedule}) except (ScheduleNotFoundError, ScheduleProcessNameNotFoundError) as ex: raise web.HTTPNotFound(reason=str(ex)) except ValueError as ex: raise web.HTTPBadRequest(reason=str(ex))
async def post_schedule(request): """ Create a new schedule in schedules table :Example: curl -d '{"type": 3, "name": "sleep30test", "process_name": "sleep30", "repeat": "45"}' -X POST http://localhost:8081/foglamp/schedule """ try: data = await request.json() schedule_id = data.get('schedule_id', None) if schedule_id: raise web.HTTPBadRequest( reason='Schedule ID not needed for new Schedule.') go_no_go = await _check_schedule_post_parameters(data) if len(go_no_go) != 0: raise ValueError("Errors in request: {} {}".format( ','.join(go_no_go), len(go_no_go))) updated_schedule_id = await _execute_add_update_schedule(data) sch = await server.Server.scheduler.get_schedule(updated_schedule_id) schedule = { 'id': str(sch.schedule_id), 'name': sch.name, "processName": sch.process_name, 'type': Schedule.Type(int(sch.schedule_type)).name, 'repeat': sch.repeat.total_seconds() if sch.repeat else 0, 'time': (sch.time.hour * 60 * 60 + sch.time.minute * 60 + sch.time.second) if sch.time else 0, 'day': sch.day, 'exclusive': sch.exclusive, 'enabled': sch.enabled } return web.json_response({'schedule': schedule}) except (ScheduleNotFoundError, ScheduleProcessNameNotFoundError) as ex: raise web.HTTPNotFound(reason=str(ex)) except ValueError as ex: raise web.HTTPBadRequest(reason=str(ex))
async def get_schedule(request): """ Return the information for the given schedule from schedules table :Example: curl -X GET http://localhost:8082/foglamp/schedule/ac6dd55d-f55d-44f7-8741-984604bf2384 """ try: schedule_id = request.match_info.get('schedule_id', None) if not schedule_id: raise web.HTTPBadRequest(reason='Schedule ID is required.') try: assert uuid.UUID(schedule_id) except ValueError as ex: raise web.HTTPNotFound( reason="Invalid Schedule ID {}".format(schedule_id)) sch = await server.Server.scheduler.get_schedule(uuid.UUID(schedule_id) ) schedule = { 'id': str(sch.schedule_id), 'name': sch.name, 'process_name': sch.process_name, 'type': Schedule.Type(int(sch.schedule_type)).name, 'repeat': sch.repeat.total_seconds() if sch.repeat else 0, 'time': (sch.time.hour * 60 * 60 + sch.time.minute * 60 + sch.time.second) if sch.time else 0, 'day': sch.day, 'exclusive': sch.exclusive } return web.json_response(schedule) except (ValueError, ScheduleNotFoundError) as ex: raise web.HTTPNotFound(reason=str(ex))
async def save_schedule(self, schedule: Schedule): """Creates or update a schedule Args: schedule: The id can be None, in which case a new id will be generated Raises: NotReadyError: The scheduler is not ready for requests """ if self._paused or not self._ready: raise NotReadyError() # TODO should these checks be moved to the storage layer? if schedule.name is None or len(schedule.name) == 0: raise ValueError("name can not be empty") if schedule.repeat is not None and not isinstance( schedule.repeat, datetime.timedelta): raise ValueError('repeat must be of type datetime.timedelta') if schedule.exclusive is None or not (schedule.exclusive == True or schedule.exclusive == False): raise ValueError('exclusive can not be None') if isinstance(schedule, TimedSchedule): schedule_time = schedule.time if schedule_time is not None and not isinstance( schedule_time, datetime.time): raise ValueError('time must be of type datetime.time') day = schedule.day # TODO Remove this check when the database has constraint if day is not None and (day < 1 or day > 7): raise ValueError('day must be between 1 and 7') else: day = None schedule_time = None prev_schedule_row = None if schedule.schedule_id is None: is_new_schedule = True schedule.schedule_id = uuid.uuid4() else: try: prev_schedule_row = self._schedules[schedule.schedule_id] is_new_schedule = False except KeyError: is_new_schedule = True if not is_new_schedule: update_payload = PayloadBuilder() \ .SET(schedule_name=schedule.name, schedule_type=int(schedule.schedule_type), schedule_interval=str(schedule.repeat), schedule_day=day if day else 0, schedule_time=str(schedule_time) if schedule_time else '00:00:00', exclusive='t' if schedule.exclusive else 'f', process_name=schedule.process_name) \ .WHERE(['id', '=', str(schedule.schedule_id)]) \ .payload() try: self._logger.debug('Database command: %s', update_payload) res = self._storage.update_tbl("schedules", update_payload) if res.get('count') == 0: is_new_schedule = True except Exception: self._logger.exception('Update failed: %s', update_payload) raise if is_new_schedule: insert_payload = PayloadBuilder() \ .INSERT(id=str(schedule.schedule_id), schedule_type=int(schedule.schedule_type), schedule_name=schedule.name, schedule_interval=str(schedule.repeat), schedule_day=day if day else 0, schedule_time=str(schedule_time) if schedule_time else '00:00:00', exclusive='t' if schedule.exclusive else 'f', process_name=schedule.process_name) \ .payload() try: self._logger.debug('Database command: %s', insert_payload) res = self._storage.insert_into_tbl("schedules", insert_payload) except Exception: self._logger.exception('Insert failed: %s', insert_payload) raise repeat_seconds = None if schedule.repeat is not None: repeat_seconds = schedule.repeat.total_seconds() schedule_row = self._ScheduleRow(id=schedule.schedule_id, name=schedule.name, type=schedule.schedule_type, time=schedule_time, day=day, repeat=schedule.repeat, repeat_seconds=repeat_seconds, exclusive=schedule.exclusive, process_name=schedule.process_name) self._schedules[schedule.schedule_id] = schedule_row # Did the schedule change in a way that will affect task scheduling? if schedule.schedule_type in [ Schedule.Type.INTERVAL, Schedule.Type.TIMED ] and (is_new_schedule or prev_schedule_row.time != schedule_row.time or prev_schedule_row.day != schedule_row.day or prev_schedule_row.repeat_seconds != schedule_row.repeat_seconds or prev_schedule_row.exclusive != schedule_row.exclusive): now = self.current_time if self.current_time else time.time() self._schedule_first_task(schedule_row, now) self._resume_check_schedules()