def on_entry(self): req = self.db.requests.get_info(self.machine.request_id) device_name = req['assigned_device'] device_state = self.db.devices.get_machine_state(device_name) if device_state != 'ready': self.logger.error('Assigned device %s is in unexpected state %s ' 'when about to contact lifeguard.' % (device_name, device_state)) self.machine.goto_state(finding_device) # note that there's still a small chance of a race here between # mozpool and lifeguard: lifeguard begins self-testing the device # after this check and before it receives the event below; the # device eventually returns to the 'ready' state, but has not sent # the request. The timeout for 'pending' will catch this rare # situation. return # 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 = req['assigned_device'] if self.db.images.is_reusable(req['image']): dev = self.db.devices.get_image(req['assigned_device']) if (dev['image'] == req['image'] and util.from_json( dev['boot_config']) == util.from_json(req['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'] = req['boot_config'] device_request_data['image'] = req['image'] # try to ask lifeguard to start imaging or power cycling device_url = 'http://%s/api/device/%s/event/%s/' % ( self.db.devices.get_imaging_server(assigned_device_name), assigned_device_name, event) def posted(result): if result.status_code != 200: self.logger.warn("got %d from Lifeguard" % result.status_code) return mozpool.driver.handle_event(self.machine.request_id, 'lifeguard_contacted', {}) async .requests.post.start(posted, device_url, data=json.dumps(device_request_data))
def on_entry(self): req = self.db.requests.get_info(self.machine.request_id) device_name = req['assigned_device'] device_state = self.db.devices.get_machine_state(device_name) if device_state != 'ready': self.logger.error('Assigned device %s is in unexpected state %s ' 'when about to contact lifeguard.' % (device_name, device_state)) self.machine.goto_state(finding_device) # note that there's still a small chance of a race here between # mozpool and lifeguard: lifeguard begins self-testing the device # after this check and before it receives the event below; the # device eventually returns to the 'ready' state, but has not sent # the request. The timeout for 'pending' will catch this rare # situation. return # 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 = req['assigned_device'] if self.db.images.is_reusable(req['image']): dev = self.db.devices.get_image(req['assigned_device']) if (dev['image'] == req['image'] and util.from_json(dev['boot_config']) == util.from_json(req['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'] = req['boot_config'] device_request_data['image'] = req['image'] # try to ask lifeguard to start imaging or power cycling device_url = 'http://%s/api/device/%s/event/%s/' % ( self.db.devices.get_imaging_server(assigned_device_name), assigned_device_name, event) def posted(result): if result.status_code != 200: self.logger.warn("got %d from Lifeguard" % result.status_code) return mozpool.driver.handle_event(self.machine.request_id, 'lifeguard_contacted', {}) async.requests.post.start(posted, device_url, data=json.dumps(device_request_data))
def find_device(self): self.logger.info('Finding device.') device_name = None count = self.machine.increment_counter(self.state_name) self.db.device_requests.clear(self.machine.request_id) request = self.db.requests.get_info(self.machine.request_id) image_is_reusable = self.db.images.is_reusable(request['image']) avail_devices = self.db.devices.list_available( environment=request['environment'], device_name=request['requested_device']) if avail_devices: if image_is_reusable: devices_with_image = [ x for x in avail_devices if x['image'] == request['image'] and util.from_json(x['boot_config']) == util.from_json( request['boot_config']) ] if devices_with_image: avail_devices = devices_with_image # pick a device at random from the returned list device_name = random.choice(avail_devices)['name'] self.logger.info('Assigning device %s.' % device_name) if self.db.device_requests.add(self.machine.request_id, device_name): self.logger.info('Request succeeded.') self.machine.goto_state(contact_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(failed_device_not_found) else: if count >= self.MAX_SPECIFIC_REQUESTS: self.logger.warn('Requested device %s is busy.' % request['requested_device']) self.machine.goto_state(failed_device_busy) return # check the device status - if it's failed, then short-circuit # to failed_bad_device state = self.db.devices.get_machine_state( request['requested_device']) if state.startswith('failed_'): self.machine.goto_state(failed_bad_device)
def find_device(self): self.logger.info('Finding device.') device_name = None count = self.machine.increment_counter(self.state_name) self.db.device_requests.clear(self.machine.request_id) request = self.db.requests.get_info(self.machine.request_id) image_is_reusable = self.db.images.is_reusable(request['image']) avail_devices = self.db.devices.list_available( environment=request['environment'], device_name=request['requested_device']) if avail_devices: if image_is_reusable: devices_with_image = [x for x in avail_devices if x['image'] == request['image'] and util.from_json(x['boot_config']) == util.from_json(request['boot_config'])] if devices_with_image: avail_devices = devices_with_image # pick a device at random from the returned list device_name = random.choice(avail_devices)['name'] self.logger.info('Assigning device %s.' % device_name) if self.db.device_requests.add(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(failed_device_not_found) else: if count >= self.MAX_SPECIFIC_REQUESTS: self.logger.warn('Requested device %s is busy.' % request['requested_device']) self.machine.goto_state(failed_device_busy) return # check the device status - if it's failed, then short-circuit # to failed_bad_device state = self.db.devices.get_machine_state(request['requested_device']) if state.startswith('failed_'): self.machine.goto_state(failed_bad_device)
def test_from_json(self): self.assertEqual(util.from_json('{"a": "b"}'), {'a': 'b'}) self.assertEqual(util.from_json('{"a"'), {})