def cabinet(self): if self.cabinet_id is not None: if self.cabinet_id == self.event_id: return self else: from uw_r25.events import get_event_by_id return get_event_by_id(self.cabinet_id)
def parent(self): if not hasattr(self, "_parent"): self._parent = None if self.parent_id is not None: from uw_r25.events import get_event_by_id self._parent = get_event_by_id(self.parent_id) return self._parent
def test_cabinet_event(self): event = get_event_by_id("100002") cabinet = event.cabinet() self.assertEquals(cabinet.event_id, event.cabinet_id, "cabinet_id") # cabinet is self cabinet2 = cabinet.cabinet() self.assertEquals(cabinet2.event_id, cabinet.event_id, "cabinet_id")
def test_parent_event(self): event = get_event_by_id("100002") parent = event.parent() self.assertEquals(parent.event_id, event.parent_id, "parent_id") # No parent event parent2 = parent.parent() self.assertEquals(parent2, None, "parent_id")
def test_child_events(self): event = get_event_by_id("100000") children = event.children() self.assertEquals(len(children), 1, "child event count") # No child events child = children[0] children = child.children() self.assertEquals(len(children), 0, "child event count")
def test_event_by_id(self): event = get_event_by_id("100000") self.assertEquals(event.event_id, "100000", "event_id") self.assertEquals(event.name, "BOTHELL WINTER 2013 CABINET", "name") self.assertEquals(event.title, "BOTHELL WINTER 2013 CABINET", "title") self.assertEquals(event.alien_uid, None, "alien_uid") self.assertEquals(event.start_date, "2013-01-01", "start_date") self.assertEquals(event.end_date, "2013-03-28", "end_date") self.assertEquals(event.state, "1", "state") self.assertEquals(event.parent_id, None, "parent_id") self.assertEquals(event.cabinet_id, event.event_id, "cabinet_id") self.assertEquals(event.cabinet_name, event.name, "cabinet_name") self.assertEquals(event.state_name(), "Tentative", "state_name") self.assertEquals(len(event.reservations), 1, "reservations") self.assertEquals(len(event.binding_reservations), 1, "binding_reservations")
def handle(self, *args, **options): messages = [] self.set_logger(options.get("verbosity")) if options["changed"]: if options["start"]: start_date = parse(options["start"]).date() else: start_date = datetime.date.today() if options["end"]: end_date = parse(options["end"]).date() else: end_date = datetime.date.today() else: if options["start"]: start_date = parse(options["start"]).date() else: start_date = datetime.date.today() if options["end"] == "max": end_date = datetime.date.max elif options["end"]: end_date = parse(options["end"]).date() else: end_date = start_date + datetime.timedelta(days=7) logger.info("Considering bookings from %s to %s" % (start_date, end_date)) _ems = Service() if settings.DEBUG: requests.urllib3.disable_warnings(InsecureRequestWarning) space_ids = update_get_space_ids(_ems.get_all_rooms()) logger.info("Found %d R25 spaces linked to EMS rooms" % len(space_ids)) status_list = _ems.get_statuses() statuses = {} search_statuses = [] for status in status_list: statuses[status.id] = status if status.description not in settings.EMS_R25_IGNORE_STATUSES: search_statuses.append(status.id) logger.info("Considering statuses %s" % ", ".join(statuses[status].description for status in search_statuses)) # Get all bookings in range, regardless of room, status, or event type. # We do this because a now-unwanted booking might already have been # Created in R25, and we need to cancel it there. if options["booking"]: logger.info("Looking for single booking %s" % options["booking"]) try: bookings = [_ems.get_booking(options["booking"])] except IndexError: bookings = [] elif options["reservation"]: logger.info("Looking for reservation %s" % options["reservation"]) bookings = _ems.get_bookings2( reservation_id=options["reservation"], start_date=start_date.isoformat(), end_date=end_date.isoformat(), ) elif options["changed"]: logger.info("Looking for changed bookings") bookings = _ems.get_changed_bookings( start_date=start_date.isoformat(), end_date=end_date.isoformat(), statuses=search_statuses, ) else: logger.info("Looking for all bookings") bookings = _ems.get_bookings( start_date=start_date.isoformat(), end_date=end_date.isoformat(), statuses=search_statuses, ) logger.info("Found %d bookings" % len(bookings)) ems_reservations = {} current_num = 0 for booking in bookings: current_num += 1 if booking.date_changed is None: # get_booking doesn't return date_changed... booking.date_changed = datetime.date.min if options["changed"]: # Booking hasn't changed, EMS Reservation has... if (booking.date_changed.date() < start_date or booking.date_changed.date() > end_date): continue booking.status = statuses[booking.status_id] if booking.reservation_id not in ems_reservations: # Use data from first booking as reservation data. # FIXME: we need a way to grab actual EMS Reservation data # FIXME: instead of just Bookings ems_reservations[booking.reservation_id] = booking ems_reservations[booking.reservation_id].bookings = {} ems_reservations[booking.reservation_id].bookings[ booking.id] = booking logger.debug( "Processing EMS Booking %d/%d %d: '%s'" % (current_num, len(bookings), booking.id, booking.event_name)) logger.debug("\tStatus: %s, space_id: %s" % (( booking.status.description, space_ids.get(booking.room_id), ))) logger.debug("\tStart: %s, End: %s, Changed: %s" % ( booking.time_booking_start.isoformat(), booking.time_booking_end.isoformat(), booking.date_changed.isoformat(), )) r25_event = None try: events = get_events( starts_with="%d_" % booking.id, scope="extended", include="reservations", ) r25_event = events[0] if len(events) > 1: logger.warning("\tFound multiple R25 events") messages.append("\tFound multiple R25 events") for event in events: if event.reservations[0].space_reservation is None: logger.warning("\tFound R25 event with no space " "reservation %s: %s" % (event.event_id, event.name)) messages.append("\tFound R25 event with no space " "reservation %s: %s" % (event.event_id, event.name)) if options["update"]: logger.debug("\tDeleting!") delete_event(event.event_id) else: r25_event = event logger.debug("\tFound R25 event %s: '%s'" % (r25_event.event_id, r25_event.name)) except IndexError: # No R25 event matching this EMS Booking logger.debug("\tNo R25 event found") pass except HTTPError as ex: # Server timeout, etc self.stdout.write("HTTP Error retrieving R25 Event, skipping " "Booking %s: %s" % (booking.id, ex)) messages.append("HTTP Error retrieving R25 Event, skipping " "Booking %s: %s" % (booking.id, ex)) continue except XMLSyntaxError as ex: # Bad response from R25 server - usually means outage self.stdout.write("XML Error retrieving R25 Event, skipping " "Booking %s: %s" % (booking.id, ex)) messages.append("XML Error retrieving R25 Event, skipping " "Booking %s: %s" % (booking.id, ex)) continue if options["delete"]: if r25_event: logger.debug("\tDeleting!") delete_event(r25_event.event_id) else: logger.debug("\tNothing to delete.") continue wanted_booking = True if booking.status_type_id != Status.STATUS_TYPE_BOOKED_SPACE: wanted_booking = False elif booking.room_id not in space_ids: wanted_booking = False elif (booking.status.description in settings.EMS_R25_REMOVE_STATUSES): wanted_booking = False elif (booking.status.description in settings.EMS_R25_IGNORE_STATUSES): wanted_booking = False if r25_event is None: # Do we even want in r25? if not wanted_booking: logger.debug("\t\tGood") continue # Need to create r25 event logger.debug("\t\tWill create") r25_event = Event() r25_event.reservations = [] r25_res = Reservation() r25_res.space_reservation = None r25_event.reservations.append(r25_res) event_name = booking.event_name if isinstance(event_name, six.text_type): event_name = unicodedata.normalize("NFKD", event_name).encode( "ascii", "ignore") event_name = six.ensure_text(event_name) r25_event.name = "%d_%s" % ( booking.id, event_name[:30].strip().upper(), ) r25_event.title = event_name.strip() r25_event.state = r25_event.CONFIRMED_STATE r25_event.event_type_id = settings.EMS_R25_EVENTTYPE_MAP.get( booking.status.description, settings.EMS_R25_EVENTTYPE_DEFAULT) r25_res = r25_event.reservations[0] if wanted_booking: r25_res.start_datetime = booking.time_booking_start.isoformat() r25_res.end_datetime = booking.time_booking_end.isoformat() r25_res.state = r25_res.STANDARD_STATE if r25_res.space_reservation is None: r25_res.space_reservation = Space() r25_res.space_reservation.space_id = space_ids[booking.room_id] else: # Cancel this unwanted r25 event logger.debug("\t\tSetting event state to cancelled") r25_event.state = r25_event.CANCELLED_STATE r25_res.state = r25_res.CANCELLED_STATE # r25_res.space_reservation = None # by default, don't actually make changes if not options["update"]: continue try: logger.debug("\tUpdating event") updated = update_event(r25_event) logger.debug("\t\tUpdated event %s" % updated.event_id) except R25MessageException as ex: while ex: if ex.msg_id == "EV_I_SPACECON": logger.warning( "Conflict while syncing EMS Booking %s: %s" % (booking.id, ex.text)) messages.append( "Conflict while syncing EMS Booking %s: %s" % (booking.id, ex.text)) match = re.search(r"\[(?P<event_id>\d+)\]", ex.text) if match: old_event = get_event_by_id( match.group("event_id")) logger.warning("Existing event: %s" % old_event.live_url()) messages.append("Existing event: %s" % old_event.live_url()) logger.warning("Is blocking event: %s" % r25_event.live_url()) messages.append("Is blocking event: %s" % r25_event.live_url()) else: logger.warning( "R25 message while syncing EMS Booking %s to " "R25 Event %s: %s" % (booking.id, r25_event.event_id, ex)) messages.append( "R25 message while syncing EMS Booking %s to " "R25 Event %s: %s" % (booking.id, r25_event.event_id, ex)) ex = ex.next_msg except R25ErrorException as ex: logger.warning( "R25 error while syncing EMS Booking %s to R25 Event " " %s: %s" % (booking.id, r25_event.event_id, ex)) messages.append( "R25 error while syncing EMS Booking %s to R25 Event " " %s: %s" % (booking.id, r25_event.event_id, ex)) except HTTPError as ex: logger.warning( "HTTP error while syncing EMS Booking %s to R25 Event " " %s: %s" % (booking.id, r25_event.event_id, ex)) messages.append( "HTTP error while syncing EMS Booking %s to R25 Event " " %s: %s" % (booking.id, r25_event.event_id, ex)) except TooManyRequestsException: self.stdout.write( "Too Many Requests while syncing EMS Booking %s to " "R25 Event %s" % (booking.id, r25_event.event_id)) messages.append( "Too Many Requests while syncing EMS Booking %s to " "R25 Event %s" % (booking.id, r25_event.event_id)) # send email if len(messages) > 0: send_mail( 'EMS2R25 report', '\n'.join(messages), settings.EMS2R25_EMAIL_HOST_USER, settings.EMS2R25_EMAIL_RECIPIENTS, fail_silently=False, auth_user=settings.EMS2R25_EMAIL_HOST_USER, auth_password=settings.EMS2R25_EMAIL_HOST_PASSWORD, )