def extend_reservation(self, extend_reservation_time, force_username=False): """Extend reservation for additional time. Raises: NodeReservationError: If there was error while making attempt to extend reservation. Args: extend_reservation_time (:obj:`int`): Requested reservation time in Hours force_username (:obj:`bool`): Extend even if not owner of reservation """ reservation_owner = self.get_reservation_owner() if not self.node_data.get('temporarilyOffline') or \ reservation_owner == "": raise NodeReservationError( "Node %s is currently not reserved nor " "queued to be reserved. Reservation " "can not be extended. Node state: %s" % (self.get_name(), self.get_node_status_str())) if not force_username: jenkins_user = self.jenkins.requester.username if reservation_owner != jenkins_user: raise NodeReservationError( "Node %s is currently reserved by " "%s. Use --force flag to extend " "reservation for different user." % (self.get_name(), reservation_owner)) LOG.info('Extending node reservation: %s by %s Hours' % (self.get_name(), extend_reservation_time)) res = self.reservation_info # If reservation is pending reprovisioning, but it's not yet # being reprovisioned, extend time from now, because # reservation was already expired. if self.get_node_status() == NodeStatus.REPROVISION: start_time = time.time() offset_time = timedelta( hours=extend_reservation_time).total_seconds() new_end_time = start_time + offset_time else: offset_time = timedelta( hours=extend_reservation_time).total_seconds() new_end_time = res.reservation_endtime + offset_time new_reservation = NodeReservation(res.reservation_starttime, new_end_time, res.reservation_owner, False) self._set_offline_cause(str(new_reservation)) LOG.info('Node %s is reserved until: %s' % (self.get_name(), new_reservation.get_reservation_endtime()))
def reserve(self, reservation_time, owner=None, reprovision_pending=False, force_reserve=False): """Marks node as reserved for requested time. Reserved node is put temporarily offline, is it can finish currently running task and metadata is stored in the offline reason section containing information about reservation. See NodeReservation class. Raises: NodeReservationError: If there was error while making attempt to reserve node. Args: reservation_time (:obj:`int`): Requested reservation time in Hours owner (:obj:`int`): Override automatically discovered username reprovision_pending (:obj:`bool`): If reprovision pending state force_reserve (:obj:`bool`): Reserve even if node is running CI job """ LOG.info('Attempting to reserve node: %s for %s Hours' % (self.get_name(), reservation_time)) if self.node_status != NodeStatus.ONLINE and not force_reserve: raise NodeReservationError("Node %s is not Online and " "can't be reserved." % self.get_name()) if (self.node_status != NodeStatus.JOB_RUNNING and self.node_status != NodeStatus.ONLINE) and force_reserve: raise NodeReservationError("--force can be used only when node %s" " is running CI job." % self.get_name()) if self.reservation_info is not None: raise NodeReservationError("Node %s is not released properly and " "can't be reserved. Use -l option to " "get more info." % self.get_name()) if not owner: owner = self.jenkins.requester.username start_time = time.time() offset_time = timedelta(hours=reservation_time).total_seconds() end_time = start_time + offset_time self.reservation_info = NodeReservation(start_time, end_time, owner, reprovision_pending) jenkins_node = self.jenkins.get_node(self.get_name()) slave_xml = ElementTree.fromstring(jenkins_node.get_config()) ip_address = None for slave_element in slave_xml.findall('launcher'): ip_address = slave_element.find('host').text jenkins_node.toggle_temporarily_offline(str(self.reservation_info)) LOG.info('Node: %s reserved for %s Hours by %s' % (self.get_name(), reservation_time, owner)) username = self.node_details.get_capability('username') password = self.node_details.get_capability('password') if username and len(username) > 0 and password and len(password) > 0: LOG.info('Node access (pass: "******"): $ ssh %s@%s' % (password, username, ip_address)) else: LOG.info('Node ssh: %s' % (ip_address)) LOG.info('Cancel reservation with "devnest release' ' %s"' % (self.get_name())) return dict( username=username, password=password, ip_address=ip_address, )