def generate_reservation(self, *, sliver: BaseSliver, slice_id: str, end_time: datetime, pred_list: List[str] = None) -> TicketReservationAvro: """ Responsible to generate reservation from the sliver :param sliver Network Service or Network Node Sliver :param slice_id Slice Id :param end_time End Time :param pred_list Predecessor Reservation Id List :returns list of tickets """ ticket = None if pred_list is not None: ticket = LeaseReservationAvro() ticket.redeem_processors = [] for rid in pred_list: pred = ReservationPredecessorAvro() pred.set_reservation_id(value=rid) ticket.redeem_processors.append(pred) else: ticket = TicketReservationAvro() ticket.set_slice_id(slice_id) ticket.set_broker(str(self.broker)) ticket.set_units(1) ticket.set_resource_type(str(sliver.get_type())) start = datetime.utcnow() end = start + timedelta(hours=Constants.DEFAULT_LEASE_IN_HOURS) if end_time is not None: end = end_time ticket.set_start(ActorClock.to_milliseconds(when=start)) ticket.set_end(ActorClock.to_milliseconds(when=end)) ticket.set_state(ReservationStates.Unknown.value) ticket.set_pending_state(ReservationPendingStates.None_.value) ticket.set_sliver(sliver) ticket.set_reservation_id(value=str(ID())) return ticket
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 delta(d1: datetime, d2: datetime) -> int: """ Computes the difference in microseconds between two dates. @params d1 : date 1 @params d2: date 2 @returns the difference in microseconds between two dates. """ d2_ms = ActorClock.to_milliseconds(when=d2) d1_ms = ActorClock.to_milliseconds(when=d1) return d2_ms - d1_ms
def get_length(self) -> int: """ Returns the length of a term in milliseconds. The length of a term is the number of milliseconds in the closed interval [new_start, end] @returns term length """ if self.new_start_time is None or self.end_time is None: raise TimeException(Constants.INVALID_STATE) new_start_ms = ActorClock.to_milliseconds(when=self.new_start_time) end_ms = ActorClock.to_milliseconds(when=self.end_time) return end_ms - new_start_ms + 1
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 translate_term(*, term: Term) -> TermAvro: avro_term = TermAvro() if term.get_start_time() is not None: avro_term.start_time = ActorClock.to_milliseconds(when=term.get_start_time()) else: term.start_time = 0 if term.get_end_time() is not None: avro_term.end_time = ActorClock.to_milliseconds(when=term.get_end_time()) else: term.end_time = 0 if term.get_new_start_time() is not None: avro_term.new_start_time = ActorClock.to_milliseconds(when=term.get_new_start_time()) else: avro_term.new_start_time = 0 return avro_term
def add_outlay(self, *, reservation: ABCReservationMixin, start: datetime, end: datetime): """ Adds an allocated client reservation. @params reservation: reservation to add @params start: start time @params end: end time """ try: self.lock.acquire() self.outlays.add_reservation( reservation=reservation, start=ActorClock.to_milliseconds(when=start), end=ActorClock.to_milliseconds(when=end)) finally: self.lock.release()
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_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 add_holdings(self, *, reservation: ABCReservationMixin, start: datetime, end: datetime): """ Adds a reservation to the holdings list. @params reservation : reservation to add @params start : start time @params end : end time """ try: self.lock.acquire() self.holdings.add_reservation( reservation=reservation, start=ActorClock.to_milliseconds(when=start), end=ActorClock.to_milliseconds(when=end)) finally: self.lock.release()
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 check(self, *, term: Term, start: int = None, new_start: int = None, end: int = None): if start is not None and new_start is not None and end is not None: self.assertIsNotNone(term.start_time) self.assertIsNotNone(term.new_start_time) self.assertIsNotNone(term.end_time) self.assertIsNotNone(term.get_start_time()) self.assertIsNotNone(term.get_new_start_time()) self.assertIsNotNone(term.get_end_time()) self.assertEqual(start, ActorClock.to_milliseconds(when=term.get_start_time())) self.assertEqual(new_start, ActorClock.to_milliseconds(when=term.get_new_start_time())) self.assertEqual(end, ActorClock.to_milliseconds(when=term.get_end_time())) else: self.assertIsNone(term.start_time) self.assertIsNone(term.new_start_time) self.assertIsNone(term.end_time) self.assertIsNone(term.get_start_time()) self.assertIsNone(term.get_new_start_time()) self.assertIsNone(term.get_end_time())
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 add_outlay(self, *, source: ABCDelegation, client: ABCReservationMixin, start: datetime, end: datetime): """ Adds an outlay reservation. @params source: source reservation @params client: reservation to add @params start: start time @params end: start time """ try: self.lock.acquire() calendar = self.get_source_calendar(source=source) calendar.outlays.add_reservation( reservation=client, start=ActorClock.to_milliseconds(when=start), end=ActorClock.to_milliseconds(when=end)) finally: self.lock.release()
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 initialize(self): try: self.lock.acquire() if not self.initialized: self.clock = ActorClock( beginning_of_time=self.beginning_of_time, cycle_millis=self.cycle_millis) if self.current_cycle == -1: self.calculate_cycle() self.initialized = True finally: self.lock.release()
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 __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_outlays(self, *, d: datetime = None) -> ReservationSet: """ Returns the active client reservations. @returns set of all active client reservations """ try: self.lock.acquire() if d is None: return self.outlays.get_reservations() else: return self.outlays.get_reservations( time=ActorClock.to_milliseconds(when=d)) finally: self.lock.release()
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_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 set_time(self): """ Set the Actor clock and time """ start_time = int(self.config.get_global_config().get_time().get(Constants.PROPERTY_CONF_TIME_START_TIME, None)) if start_time == -1: start_time = ActorClock.get_current_milliseconds() cycle_millis = int(self.config.get_global_config().get_time().get(Constants.PROPERTY_CONF_TIME_CYCLE_MILLIS, None)) manual = False if self.config.get_global_config().get_time().get(Constants.PROPERTY_CONF_TIME_MANUAL, None): manual = True self.create_and_start_tick(start_time=start_time, cycle_millis=cycle_millis, manual=manual)
def get_holdings(self, *, d: datetime = None, type: ResourceType = None) -> ReservationSet: """ Returns the resources of the specified type held by the client that are active at the specified time instance. @params d : datetime instance. @params type : resource type @returns st of reservations of the specified type that are active at the specified time """ try: self.lock.acquire() when = None if d is not None: when = ActorClock.to_milliseconds(when=d) return self.holdings.get_reservations(time=when, rtype=type) finally: self.lock.release()
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 get_outlays(self, *, source: ABCDelegation, time: datetime = None) -> ReservationSet: """ Returns the client reservations satisfied from the given source reservation at the specified time. @params source : source reservation @params time: time instance @returns set of client reservations satisfied from the given source at the specified time. """ try: self.lock.acquire() calendar = self.get_source_calendar(source=source) if time is None: return calendar.outlays.get_reservations() else: return calendar.outlays.get_reservations( time=ActorClock.to_milliseconds(when=time)) finally: self.lock.release()
def get_actor_clock(self) -> ActorClock: if self.ticker is None: raise ContainerException("No tick") return ActorClock(beginning_of_time=self.ticker.get_beginning_of_time(), cycle_millis=self.ticker.get_cycle_millis())