def assert_am_broker_reservations(self, slice_id: str, res_id: str, am_res_state: int, broker_res_state: int, new_time: str = None): KafkaProcessorSingleton.get().start() manage_helper = ManageHelper(logger=self.logger) am_reservation, status = manage_helper.do_get_reservations(actor_name=self.am_name, callback_topic=KafkaProcessorSingleton.get().kafka_topic, rid=res_id) if am_res_state == -1: self.assertEqual(8, status.status.code) else: self.assertEqual(0, status.status.code) self.assertEqual(1, len(am_reservation)) self.assertEqual(slice_id, am_reservation[0].slice_id) self.assertEqual(res_id, am_reservation[0].reservation_id) self.assertEqual(am_res_state, am_reservation[0].state) if new_time is not None: lease_end = ActorClock.from_milliseconds(milli_seconds=am_reservation[0].requested_end) lease_end_str = lease_end.strftime(self.TIME_FORMAT_IN_SECONDS) self.assertEqual(new_time, lease_end_str) broker_reservation, status = manage_helper.do_get_reservations(actor_name=self.broker_name, callback_topic=KafkaProcessorSingleton.get().kafka_topic, rid=res_id) self.assertEqual(0, status.status.code) self.assertEqual(1, len(broker_reservation)) self.assertEqual(slice_id, broker_reservation[0].slice_id) self.assertEqual(res_id, broker_reservation[0].reservation_id) self.assertEqual(broker_res_state, broker_reservation[0].state) if new_time is not None: lease_end = ActorClock.from_milliseconds(milli_seconds=broker_reservation[0].requested_end) lease_end_str = lease_end.strftime(self.TIME_FORMAT_IN_SECONDS) self.assertEqual(new_time, lease_end_str) KafkaProcessorSingleton.get().stop()
def add_reservation_private(self, *, reservation: TicketReservationAvro): result = ResultAvro() slice_id = ID(uid=reservation.get_slice_id()) rset = Converter.get_resource_set(res_mng=reservation) term = Term(start=ActorClock.from_milliseconds( milli_seconds=reservation.get_start()), end=ActorClock.from_milliseconds( milli_seconds=reservation.get_end())) broker = None if reservation.get_broker() is not None: broker = ID(uid=reservation.get_broker()) rid = None if reservation.get_reservation_id() is not None: rid = ID(uid=reservation.get_reservation_id()) else: rid = ID() rc = ClientReservationFactory.create(rid=rid, resources=rset, term=term) rc.set_renewable(renewable=reservation.is_renewable()) if rc.get_state() != ReservationStates.Nascent or rc.get_pending_state( ) != ReservationPendingStates.None_: result.set_code(ErrorCodes.ErrorInvalidReservation.value) result.set_message( "Only reservations in Nascent.None can be added") return None, result slice_obj = self.client.get_slice(slice_id=slice_id) if slice_obj is None: result.set_code(ErrorCodes.ErrorNoSuchSlice.value) result.set_message(ErrorCodes.ErrorNoSuchSlice.interpret()) return None, result rc.set_slice(slice_object=slice_obj) proxy = None if broker is None: proxy = self.client.get_default_broker() else: proxy = self.client.get_broker(guid=broker) if proxy is None: result.set_code(ErrorCodes.ErrorNoSuchBroker.value) result.set_message(ErrorCodes.ErrorNoSuchBroker.interpret()) return None, result rc.set_broker(broker=proxy) self.client.register(reservation=rc) return rc.get_reservation_id(), result
def translate_term_from_avro(*, term: TermAvro) -> Term: start_time = None end_time = None new_start_time = None if term.start_time > 0: start_time = ActorClock.from_milliseconds(milli_seconds=term.start_time) if term.end_time > 0: end_time = ActorClock.from_milliseconds(milli_seconds=term.end_time) if term.new_start_time > 0: new_start_time = ActorClock.from_milliseconds(milli_seconds=term.new_start_time) return Term(start=start_time, end=end_time, new_start=new_start_time)
def test_change(self): start = 1000 end = 1499 length = 500 t = Term(start=ActorClock.from_milliseconds(milli_seconds=start), end=ActorClock.from_milliseconds(milli_seconds=end)) self.check(term=t, start=start, new_start=start, end=end) self.assertEqual(length, t.get_length()) t1 = t.change_length(length=2 * length) self.check(term=t1, start=start, new_start=start, end=end+length) self.assertEqual(length * 2, t1.get_length()) t1 = t.change_length(length=int(length/2)) self.check(term=t1, start=start, new_start=start, end=int(end - length/2)) self.assertEqual(length / 2, t1.get_length())
def extend_reservation(self, *, request: ExtendReservationAvro) -> ResultStringAvro: result = ResultStringAvro() result.message_id = request.message_id try: if request.guid is None or request.reservation_id is None: result.status.set_code(ErrorCodes.ErrorInvalidArguments.value) result.status.set_message(ErrorCodes.ErrorInvalidArguments.interpret()) return result auth = Translate.translate_auth_from_avro(auth_avro=request.auth) mo = self.get_actor_mo(guid=ID(uid=request.guid)) end_time = ActorClock.from_milliseconds(milli_seconds=request.end_time) rtype = None if request.new_resource_type is not None: rtype = ResourceType(resource_type=request.new_resource_type) result.status = mo.extend_reservation(rid=ID(uid=request.reservation_id), new_end_time=end_time, new_units=request.new_units, new_resource_type=rtype, request_properties=request.request_properties, config_properties=request.config_properties, caller=auth) except Exception as e: result.status.set_code(ErrorCodes.ErrorInternalError.value) result.status.set_message(ErrorCodes.ErrorInternalError.interpret(exception=e)) result.status = ManagementObject.set_exception_details(result=result.status, e=e) result.message_id = request.message_id return result
def test_extend(self): start_ms = 1000 end_ms = 1499 length_ms = 500 t = Term(start=ActorClock.from_milliseconds(milli_seconds=start_ms), end=ActorClock.from_milliseconds(milli_seconds=end_ms)) self.assertEqual(length_ms, t.get_length()) self.check(term=t, start=start_ms, new_start=start_ms, end=end_ms) # extend with same length t1 = t.extend() self.check(term=t1, start=start_ms, new_start=end_ms + 1, end=end_ms + length_ms) self.assertEqual(length_ms, t1.get_length()) self.assertEqual(2 * length_ms, t1.get_full_length()) self.assertTrue(t1.extends_term(old_term=t)) # extend multiple times for i in range(10): t2 = t1.extend() self.check(start=ActorClock.to_milliseconds(when=t1.get_start_time()), new_start=ActorClock.to_milliseconds(when=t1.get_end_time()) + 1, end=ActorClock.to_milliseconds(when=t1.get_end_time()) + length_ms, term=t2) self.assertEqual(length_ms, t2.get_length()) self.assertEqual(t1.get_full_length() + length_ms, t2.get_full_length()) self.assertTrue(t2.extends_term(old_term=t1)) t1 = t2 # extend with 1000 l = 1000 t1 = t.extend(length=l) self.check(start=start_ms, new_start=end_ms+1, end=end_ms+l, term=t1) self.assertEqual(l, t1.get_length()) self.assertEqual(l + length_ms, t1.get_full_length()) # extend multiple times for i in range(10): t2 = t1.extend() self.check(start=ActorClock.to_milliseconds(when=t1.get_start_time()), new_start=ActorClock.to_milliseconds(when=t1.get_end_time()) + 1, end=ActorClock.to_milliseconds(when=t1.get_end_time()) + l, term=t2) self.assertEqual(l, t2.get_length()) self.assertEqual(t1.get_full_length() + l, t2.get_full_length()) self.assertTrue(t2.extends_term(old_term=t2)) t1 = t2
def test_cycle_start_end_date(self): offset = 1000 length = 10 clock = self._get_clock(1000, 10) start = offset end = offset + length - 1 for i in range(100): self.assertEqual(ActorClock.from_milliseconds(milli_seconds=start), clock.cycle_start_date(cycle=i)) self.assertEqual(ActorClock.from_milliseconds(milli_seconds=end), clock.cycle_end_date(cycle=i)) self.assertEqual(start, clock.cycle_start_in_millis(cycle=i)) self.assertEqual(end, clock.cycle_end_in_millis(cycle=i)) start += length end += length
def test_create(self): length = 500 start = 1000 new_start = 1500 end = 1999 old_end = 1499 with self.assertRaises(Exception): Term() with self.assertRaises(Exception): t2 = Term(start=ActorClock.from_milliseconds(milli_seconds=start)) # Term(start, length) t3 = Term(start=ActorClock.from_milliseconds(milli_seconds=start), length=length) self.check(term=t3, start=start, new_start=start, end=old_end) self.assertEqual(length, t3.get_length()) # Term(start, end) t4 = Term(start=ActorClock.from_milliseconds(milli_seconds=start), end=ActorClock.from_milliseconds(milli_seconds=old_end)) self.check(term=t4, start=start, new_start=start, end=old_end) self.assertEqual(length, t4.get_length()) # Term(start, end, new_start) t5 = Term(start=ActorClock.from_milliseconds(milli_seconds=start), new_start=ActorClock.from_milliseconds(milli_seconds=new_start), end=ActorClock.from_milliseconds(milli_seconds=end)) self.check(term=t5, start=start, new_start=new_start, end=end) # NOTE: length is measured only relative to newStartTime!!! self.assertEqual(length, t5.get_length())
def extend(self, *, length: int = 0): """ Creates a new term as an extension of the specified term. The term is extended with the current term length. @params length new term length in milliseconds @returns term extended with the current term length """ if self.start_time is None or self.end_time is None: raise TimeException(Constants.INVALID_STATE) length_to_use = self.get_length() if length != 0: length_to_use = length new_start_ms = ActorClock.to_milliseconds(when=self.end_time) + 1 new_start = ActorClock.from_milliseconds(milli_seconds=new_start_ms) end = ActorClock.from_milliseconds(milli_seconds=new_start_ms + length_to_use - 1) return Term(start=self.start_time, end=end, new_start=new_start)
def test_date(self): offset = 1000 length = 10 clock = self._get_clock(1000, 10) ms = offset for i in range(100): self.assertEqual(ActorClock.from_milliseconds(milli_seconds=ms), clock.date(cycle=i)) ms += length
def align_start(self, *, when: datetime) -> datetime: """ Aligns the specified date with the start of the closest cycle. @param when when to align @return date aligned with the start of the closes cycle """ cycle = self.clock.cycle(when=when) time = self.clock.cycle_start_in_millis(cycle=cycle) return ActorClock.from_milliseconds(milli_seconds=time)
def test_shift(self): start = 1000 end = 1499 length = 500 t = Term(start=ActorClock.from_milliseconds(milli_seconds=start), end=ActorClock.from_milliseconds(milli_seconds=end)) self.check(term=t, start=start, new_start=start, end=end) self.assertEqual(length, t.get_length()) t1 = t.shift(date=ActorClock.from_milliseconds(milli_seconds=start-500)) self.check(term=t1, start=start-500, new_start=start-500, end=end-500) self.assertEqual(length, t1.get_length()) t1 = t.shift(date=ActorClock.from_milliseconds(milli_seconds=start)) self.check(term=t1, start=start, new_start=start, end=end) self.assertEqual(length, t1.get_length()) t1 = t.shift(date=ActorClock.from_milliseconds(milli_seconds=start+500)) self.check(term=t1, start=start + 500, new_start=start + 500, end=end + 500) self.assertEqual(length, t1.get_length())
def test_equals(self): start = 1000 end = 1499 length = 500 t = Term(start=ActorClock.from_milliseconds(milli_seconds=start), end=ActorClock.from_milliseconds(milli_seconds=end)) self.check(term=t, start=start, new_start=start, end=end) self.assertEqual(length, t.get_length()) self.assertTrue(t == t) t1 = Term(start=ActorClock.from_milliseconds(milli_seconds=start), end=ActorClock.from_milliseconds(milli_seconds=end)) self.check(term=t1, start=start, new_start=start, end=end) self.assertEqual(length, t1.get_length()) t2 = Term(start=ActorClock.from_milliseconds(milli_seconds=start + 100), end=ActorClock.from_milliseconds(milli_seconds=end)) self.check(term=t2, start=start + 100, new_start=start + 100, end=end) self.assertEqual(length - 100, t2.get_length()) self.assertTrue(t == t1) self.assertFalse(t == t2) self.assertFalse(t == 11) class Abc: def __init__(self): self.num = 1 self.assertFalse(t == Abc())
def test_cycle(self): offset = 1000 length = 10 clock = self._get_clock(1000, 10) ms = offset for i in range(100): exp = i self.assertEqual( exp, clock.cycle(when=ActorClock.from_milliseconds( milli_seconds=ms))) ms += length ms = offset for i in range(100): exp = i for j in range(length): self.assertEqual( exp, clock.cycle(when=ActorClock.from_milliseconds( milli_seconds=ms))) ms += 1
def test_ends(self): start = 1000 end = 1499 length = 500 t = Term(start=ActorClock.from_milliseconds(milli_seconds=start), end=ActorClock.from_milliseconds(milli_seconds=end)) self.check(term=t, start=start, new_start=start, end=end) self.assertEqual(length, t.get_length()) # term cannot end before it started self.assertFalse(t.ends_before(date=t.get_start_time())) self.assertFalse(t.expired(date=t.get_start_time())) self.assertTrue(t.ends_after(date=t.get_start_time())) self.assertFalse(t.ends_before(date=t.get_end_time())) self.assertFalse(t.ends_after(date=t.get_end_time())) self.assertFalse(t.expired(date=t.get_end_time())) self.assertFalse(t.ends_before(date=ActorClock.from_milliseconds(milli_seconds=start - 100))) self.assertTrue(t.ends_after(date=ActorClock.from_milliseconds(milli_seconds=start - 100))) self.assertFalse(t.expired(date=ActorClock.from_milliseconds(milli_seconds=start - 100))) self.assertTrue(t.ends_before(date=ActorClock.from_milliseconds(milli_seconds=end + 1))) self.assertTrue(t.expired(date=ActorClock.from_milliseconds(milli_seconds=end + 1))) self.assertFalse(t.ends_after(date=ActorClock.from_milliseconds(milli_seconds=end + 1)))
def __init__(self, *, start: datetime = None, end: datetime = None, new_start: datetime = None, length: int = None): """ Creates a new term. @params start: start time @params end: end time @params new_start: new start time @params length: length in ms """ # Start time: first valid millisecond. if start is not None: self.start_time = start else: self.start_time = datetime.utcnow() # End time: last valid millisecond. if end is not None: self.end_time = end else: if start is not None and length is not None and length > 1: start_ms = ActorClock.to_milliseconds(when=start) + length - 1 self.end_time = ActorClock.from_milliseconds(milli_seconds=start_ms) else: raise TimeException("Invalid arguments, length and end both not specified") # Start time for this section of the lease if new_start is not None: self.new_start_time = new_start else: if start is not None: self.new_start_time = start else: self.new_start_time = datetime.utcnow() # Start cycle. Used only for debugging. self.cycle_start = 0 # End cycle. Used only for debugging. self.cycle_end = 0 # New start cycle. Used only for debugging. self.cycle_new_start = 0 self._set_cycles()
def get_reservation_summary(*, res_list: List[ReservationMng], include_notices: bool = True, include_sliver: bool = False) -> dict: """ Get Reservation summary :param res_list: :param include_notices: :param include_sliver: :return: """ reservations = [] status = ResponseBuilder.STATUS_OK message = "" if res_list is not None: for reservation in res_list: res_dict = { ResponseBuilder.PROP_SLICE_ID: reservation.get_slice_id(), ResponseBuilder.PROP_RESERVATION_ID: reservation.get_reservation_id(), ResponseBuilder.PROP_RESERVATION_STATE: ReservationStates(reservation.get_state()).name } if reservation.get_pending_state() is not None: res_dict[ResponseBuilder.PROP_RESERVATION_PENDING_STATE] = \ ReservationPendingStates(reservation.get_pending_state()).name if isinstance(reservation, LeaseReservationAvro ) and reservation.get_join_state() is not None: res_dict[ResponseBuilder. PROP_RESERVATION_JOIN_STATE] = JoinState( reservation.get_join_state()).name sliver = reservation.get_sliver() if sliver is not None: res_dict[ ResponseBuilder.PROP_GRAPH_NODE_ID] = sliver.node_id if include_sliver: res_dict[ResponseBuilder.PROP_SLIVER_TYPE] = type( sliver).__name__ res_dict[ResponseBuilder. PROP_SLIVER] = JSONSliver.sliver_to_json( sliver=sliver) if include_notices: res_dict[ResponseBuilder. PROP_NOTICES] = reservation.get_notices() if reservation.get_start() is not None: start_time = ActorClock.from_milliseconds( milli_seconds=reservation.get_start()) res_dict[ResponseBuilder. PROP_LEASE_START_TIME] = start_time.strftime( Constants.LEASE_TIME_FORMAT) if reservation.get_end() is not None: end_time = ActorClock.from_milliseconds( milli_seconds=reservation.get_end()) res_dict[ResponseBuilder. PROP_LEASE_END_TIME] = end_time.strftime( Constants.LEASE_TIME_FORMAT) reservations.append(res_dict) else: status = ResponseBuilder.STATUS_FAILURE message = "No reservations were found/computed" response = { ResponseBuilder.RESPONSE_STATUS: status, ResponseBuilder.RESPONSE_MESSAGE: message, ResponseBuilder.RESPONSE_RESERVATIONS: reservations } return response
def renew_slice(self, *, token: str, slice_id: str, new_lease_end_time: str): """ Renew a slice :param token Fabric Identity Token :param slice_id Slice Id :param new_lease_end_time: New Lease End Time in UTC in '%Y-%m-%d %H:%M:%S' format :raises Raises an exception in case of failure :return: """ if self.globals.is_maintenance_mode_on(): raise OrchestratorException(Constants.MAINTENANCE_MODE_ERROR) failed_to_extend_rid_list = [] try: controller = self.controller_state.get_management_actor() self.logger.debug(f"renew_slice invoked for Controller: {controller}") slice_guid = None if slice_id is not None: slice_guid = ID(uid=slice_id) slice_list = controller.get_slices(id_token=token, slice_id=slice_guid) if slice_list is None or len(slice_list) == 0: raise OrchestratorException(f"Slice# {slice_id} not found", http_error_code=NOT_FOUND) slice_object = next(iter(slice_list)) slice_state = SliceState(slice_object.get_state()) if slice_state == SliceState.Dead or slice_state == SliceState.Closing: raise OrchestratorException(f"Slice# {slice_id} already closed", http_error_code=BAD_REQUEST) if slice_state != SliceState.StableOK and slice_state != SliceState.StableError: self.logger.info(f"Unable to renew Slice# {slice_guid} that is not yet stable, try again later") raise OrchestratorException(f"Unable to renew Slice# {slice_guid} that is not yet stable, " f"try again later") new_end_time = self.__validate_lease_end_time(lease_end_time=new_lease_end_time) reservations = controller.get_reservations(id_token=token, slice_id=slice_id) if reservations is None or len(reservations) < 1: if controller.get_last_error() is not None: self.logger.error(controller.get_last_error()) raise OrchestratorException(f"Slice# {slice_id} has no reservations") self.logger.debug(f"There are {len(reservations)} reservations in the slice# {slice_id}") for r in reservations: res_state = ReservationStates(r.get_state()) if res_state == ReservationStates.Closed or res_state == ReservationStates.Failed or \ res_state == ReservationStates.CloseWait: continue current_end_time = ActorClock.from_milliseconds(milli_seconds=r.get_end()) if new_end_time < current_end_time: raise OrchestratorException(f"Attempted new term end time is shorter than current slice end time") self.logger.debug(f"Extending reservation with reservation# {r.get_reservation_id()}") result = controller.extend_reservation(reservation=ID(uid=r.get_reservation_id()), new_end_time=new_end_time) if not result: failed_to_extend_rid_list.append(r.get_reservation_id()) else: slice_object.set_lease_end(lease_end=new_end_time) if not controller.update_slice(slice_obj=slice_object): self.logger.error(f"Failed to update lease end time: {new_end_time} in Slice: {slice_object}") return ResponseBuilder.get_response_summary(rid_list=failed_to_extend_rid_list) except Exception as e: self.logger.error(traceback.format_exc()) self.logger.error(f"Exception occurred processing renew e: {e}") raise e
def test_contains(self): start = 1000 end = 1499 length = 500 t = Term(start=ActorClock.from_milliseconds(milli_seconds=start), end=ActorClock.from_milliseconds(milli_seconds=end)) self.check(term=t, start=start, new_start=start, end=end) self.assertEqual(length, t.get_length()) # self -> true self.assertTrue(t.contains(term=t)) # self - 1 from the right self.assertTrue(t.contains(term=Term(start=ActorClock.from_milliseconds(milli_seconds=start), length=length-1))) # self + 1 from the left self.assertTrue(t.contains(term=Term(start=ActorClock.from_milliseconds(milli_seconds=start), end=ActorClock.from_milliseconds(milli_seconds=end)))) # self +1 from the left, -1 from the right self.assertTrue(t.contains(term=Term(start=ActorClock.from_milliseconds(milli_seconds=start), end=ActorClock.from_milliseconds(milli_seconds=end - 1)))) self.assertFalse(t.contains(term=Term(start=ActorClock.from_milliseconds(milli_seconds=start -1), end=ActorClock.from_milliseconds(milli_seconds=end)))) self.assertFalse(t.contains(term=Term(start=ActorClock.from_milliseconds(milli_seconds=start -100), end=ActorClock.from_milliseconds(milli_seconds=start)))) self.assertFalse(t.contains(term=Term(start=ActorClock.from_milliseconds(milli_seconds=start), end=ActorClock.from_milliseconds(milli_seconds=end + 1)))) self.assertFalse(t.contains(term=Term(start=ActorClock.from_milliseconds(milli_seconds=start), end=ActorClock.from_milliseconds(milli_seconds=end + 100)))) self.assertFalse(t.contains(term=Term(start=ActorClock.from_milliseconds(milli_seconds=start - 100), end=ActorClock.from_milliseconds(milli_seconds=end + 100)))) self.assertTrue(t.contains(date=ActorClock.from_milliseconds(milli_seconds=start))) self.assertTrue(t.contains(date=ActorClock.from_milliseconds(milli_seconds=end))) self.assertTrue(t.contains(date=ActorClock.from_milliseconds(milli_seconds=int((start + end)/2)))) self.assertFalse(t.contains(date=ActorClock.from_milliseconds(milli_seconds=start -1))) self.assertFalse(t.contains(date=ActorClock.from_milliseconds(milli_seconds=end + 1)))
def test_d_extend_ticket(self): """ Requests a ticket for all resources. Checks if the ticket is allocated for what was asked. Checks the term. Checks whether the reservation is closed when it expires. Repeat one more time. """ broker = self.get_broker() controller = self.get_controller() clock = broker.get_actor_clock() proxy = ClientCallbackHelper(name=controller.get_name(), guid=controller.get_guid()) broker_callback = ClientCallbackHelper(name=broker.get_name(), guid=broker.get_guid()) ActorRegistrySingleton.get().register_callback(callback=proxy) ActorRegistrySingleton.get().register_callback( callback=broker_callback) last_called = proxy.get_called() inv_slice = SliceFactory.create(slice_id=ID(), name="inventory-slice") inv_slice.set_inventory(value=True) source = self.get_source_delegation(self.broker, inv_slice) self.broker.register_slice(slice_object=inv_slice) self.broker.register_delegation(delegation=source) self.broker.donate_delegation(delegation=source) cycle = 1 broker.external_tick(cycle=cycle) cycle += 1 units = 1 start = clock.cycle_start_date(cycle=self.DonateStartCycle) cycle_end = self.DonateEndCycle - 50 end = clock.cycle_end_date(cycle=cycle_end) sliver = self.build_sliver() request = self.get_reservation_for_network_node(start, end, sliver) reservation = request broker.ticket(reservation=request, callback=proxy, caller=proxy.get_identity()) for c in range(cycle, self.DonateEndCycle): broker.external_tick(cycle=c) while broker.get_current_cycle() != c: time.sleep(0.001) if last_called < proxy.get_called(): self.assert_ticketed(proxy.get_reservation(), units, request.get_type(), start, end) last_called = proxy.get_called() if c == cycle_end - 10: self.assertEqual(1, proxy.get_called()) start = ActorClock.from_milliseconds( milli_seconds=ActorClock.to_milliseconds(when=end) + 1) end = clock.cycle_end_date(cycle=self.DonateEndCycle - 1) request = self.get_request_from_request( request, units, request.get_type(), start, end) broker.extend_ticket(reservation=request, caller=proxy.get_identity()) print("Extend done") broker.await_no_pending_reservations() self.assertEqual(2, proxy.get_called()) self.assertTrue(reservation.is_closed())
def test_validate(self): with self.assertRaises(Exception): self.check_valid(term=Term(start=ActorClock.from_milliseconds(milli_seconds=10), new_start=ActorClock.from_milliseconds(milli_seconds=100), end=ActorClock.from_milliseconds(milli_seconds=10))) self.check_valid(term=Term(start=ActorClock.from_milliseconds(milli_seconds=10), new_start=ActorClock.from_milliseconds(milli_seconds=100), end=ActorClock.from_milliseconds(milli_seconds=99))) self.check_valid(term=Term(start=ActorClock.from_milliseconds(milli_seconds=10), new_start=ActorClock.from_milliseconds(milli_seconds=1000), end=ActorClock.from_milliseconds(milli_seconds=1000))) self.check_not_valid(term=Term(start=ActorClock.from_milliseconds(milli_seconds=100), end=ActorClock.from_milliseconds(milli_seconds=10))) self.check_not_valid(term=Term(start=ActorClock.from_milliseconds(milli_seconds=100), end=ActorClock.from_milliseconds(milli_seconds=100))) self.check_not_valid(term=Term(start=ActorClock.from_milliseconds(milli_seconds=100), end=ActorClock.from_milliseconds(milli_seconds=1000), new_start=ActorClock.from_milliseconds(milli_seconds=10))) self.check_not_valid(term=Term(start=ActorClock.from_milliseconds(milli_seconds=100), end=ActorClock.from_milliseconds(milli_seconds=10), new_start=ActorClock.from_milliseconds(milli_seconds=10000)))