예제 #1
0
    def find_device(self):
        self.logger.info('Finding device.')
        device_name = None
        count = self.machine.increment_counter(self.state_name)
        request = data.request_config(self.machine.request_id)
        image_is_reusable = data.image_is_reusable(request['image'])

        free_devices = data.get_free_devices(
                environment=request['environment'],
                device_name=request['requested_device'])

        if free_devices:
            if image_is_reusable:
                devices_with_image = [x for x in free_devices
                                      if x['image'] == request['image'] and
                                         data.from_json(x['boot_config']) ==
                                         data.from_json(request['boot_config'])]
                if devices_with_image:
                    free_devices = devices_with_image

            # pick a device at random from the returned list
            device_name = random.choice(free_devices)['name']
            self.logger.info('Assigning device %s.' % device_name)
            if data.reserve_device(self.machine.request_id,
                                                device_name):
                self.logger.info('Request succeeded.')
                self.machine.goto_state(contacting_lifeguard)
        else:
            self.logger.warn('Request failed!')
            if request['requested_device'] == 'any':
                if count >= self.MAX_ANY_REQUESTS:
                    self.logger.warn('Hit maximum number of attempts to find '
                                     'a free device; giving up.')
                    self.machine.goto_state(device_not_found)
            else:
                if count >= self.MAX_SPECIFIC_REQUESTS:
                    self.logger.warn('Requested device %s is busy.' %
                                     device_name)
                    self.machine.goto_state(device_busy)
예제 #2
0
    def contact_lifeguard(self, request_config):
        # If the requested image is reusable and we got a device with that
        # image and the requested bootconfig, just power cycle it.
        # Otherwise, image it.  Note that there will be a failure if the
        # image is not installed and the device is not imageable.
        event = ''
        device_request_data = {}
        assigned_device_name = request_config['assigned_device']

        if data.image_is_reusable(request_config['image']):
            device_config = data.device_config(request_config['assigned_device'])
            if (device_config['image'] == request_config['image'] and
                data.from_json(device_config['boot_config']) ==
                data.from_json(request_config['boot_config'])):
                event = 'please_power_cycle'

        if not event:
            # Use the device's hardware type and requested image to find the
            # pxe config, if any.
            event = 'please_image'
            device_request_data['boot_config'] = request_config['boot_config']
            device_request_data['image'] = request_config['image']

        device_url = 'http://%s/api/device/%s/event/%s/' % (
            data.get_server_for_device(assigned_device_name),
            assigned_device_name, event)

        # FIXME: make this asynchronous so slow/missing servers don't halt
        # the state machine.
        try:
            urllib.urlopen(device_url, json.dumps(device_request_data))
        except IOError:
            self.logger.warn('Could not contact lifeguard server at %s' %
                             device_url)
            return False
        return True