Example #1
0
    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()))
Example #2
0
    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,
        )