def register_result_file(self, server, result_id, path, filename, basepath): """ register file and return path to store """ try: result = RecipeTaskResult.by_id(result_id, lockmode='update') except NoResultFound: raise BX(_('Invalid result ID: %s' % result_id)) RecipeTask.by_id(result.recipe_task_id, lockmode='update') Recipe.by_id(result.recipetask.recipe_id, lockmode='update') if result.recipetask.is_finished(): raise BX('Cannot register file for finished task %s' % result.recipetask.t_id) self._check_log_limit(result.recipetask) log_recipe = LogRecipeTaskResult.lazy_create( recipe_task_result_id=result.id, path=path, filename=filename, ) log_recipe.server = server log_recipe.basepath = basepath result.recipetask.recipe.log_server = urlparse.urlparse(server)[1] return '%s' % result.filepath
def provision_virt_recipe(recipe_id): log.debug('Attempting to provision dynamic virt guest for recipe %s', recipe_id) session.begin() try: recipe = Recipe.by_id(recipe_id) manager = dynamic_virt.VirtManager(recipe.recipeset.job.owner) available_flavors = manager.available_flavors() # We want them in order of smallest to largest, so that we can pick the # smallest flavor that satisfies the recipe's requirements. Sorting by RAM # is a decent approximation. possible_flavors = XmlHost.from_string(recipe.host_requires)\ .filter_openstack_flavors(available_flavors, manager.lab_controller) if not possible_flavors: log.debug('No OpenStack flavors matched recipe %s, marking precluded', recipe.id) recipe.virt_status = RecipeVirtStatus.precluded return possible_flavors = sorted(possible_flavors, key=lambda flavor: flavor.ram) flavor = possible_flavors[0] vm_name = '%srecipe-%s' % ( ConfigItem.by_name(u'guest_name_prefix').current_value(u'beaker-'), recipe.id) # FIXME can we control use of virtio? #virtio_possible = True #if self.recipe.distro_tree.distro.osversion.osmajor.osmajor == "RedHatEnterpriseLinux3": # virtio_possible = False vm = manager.create_vm(vm_name, flavor) vm.instance_created = datetime.utcnow() try: recipe.createRepo() recipe.clear_candidate_systems() recipe.watchdog = Watchdog() recipe.resource = vm recipe.recipeset.lab_controller = manager.lab_controller recipe.virt_status = RecipeVirtStatus.succeeded recipe.schedule() log.info("recipe ID %s moved from Queued to Scheduled by provision_virt_recipe" % recipe.id) recipe.waiting() recipe.provision() log.info("recipe ID %s moved from Scheduled to Waiting by provision_virt_recipe" % recipe.id) except: exc_type, exc_value, exc_tb = sys.exc_info() try: manager.destroy_vm(vm) except Exception: log.exception('Failed to clean up vm %s ' 'during provision_virt_recipe, leaked!', vm.instance_id) # suppress this exception so the original one is not masked raise exc_type, exc_value, exc_tb session.commit() except Exception, e: log.exception('Error in provision_virt_recipe(%s)', recipe_id) session.rollback() # As an added precaution, let's try and avoid this recipe in future with session.begin(): recipe = Recipe.by_id(recipe_id) recipe.virt_status = RecipeVirtStatus.failed
def provision_virt_recipe(recipe_id): log.debug('Attempting to provision dynamic virt guest for recipe %s', recipe_id) session.begin() try: recipe = Recipe.by_id(recipe_id) manager = dynamic_virt.VirtManager(recipe.recipeset.job.owner) available_flavors = manager.available_flavors() # We want them in order of smallest to largest, so that we can pick the # smallest flavor that satisfies the recipe's requirements. Sorting by RAM # is a decent approximation. possible_flavors = XmlHost.from_string(recipe.host_requires)\ .filter_openstack_flavors(available_flavors, manager.lab_controller) if not possible_flavors: log.debug('No OpenStack flavors matched recipe %s, marking precluded', recipe.id) recipe.virt_status = RecipeVirtStatus.precluded return possible_flavors = sorted(possible_flavors, key=lambda flavor: flavor.ram) flavor = possible_flavors[0] vm_name = '%srecipe-%s' % ( ConfigItem.by_name(u'guest_name_prefix').current_value(u'beaker-'), recipe.id) # FIXME can we control use of virtio? #virtio_possible = True #if self.recipe.distro_tree.distro.osversion.osmajor.osmajor == "RedHatEnterpriseLinux3": # virtio_possible = False vm = manager.create_vm(vm_name, flavor) vm.instance_created = datetime.utcnow() try: recipe.createRepo() recipe.systems = [] recipe.watchdog = Watchdog() recipe.resource = vm recipe.recipeset.lab_controller = manager.lab_controller recipe.virt_status = RecipeVirtStatus.succeeded recipe.schedule() log.info("recipe ID %s moved from Queued to Scheduled by provision_virt_recipe" % recipe.id) recipe.waiting() recipe.provision() log.info("recipe ID %s moved from Scheduled to Waiting by provision_virt_recipe" % recipe.id) except: exc_type, exc_value, exc_tb = sys.exc_info() try: manager.destroy_vm(vm) except Exception: log.exception('Failed to clean up vm %s ' 'during provision_virt_recipe, leaked!', vm.instance_id) # suppress this exception so the original one is not masked raise exc_type, exc_value, exc_tb session.commit() except Exception, e: log.exception('Error in provision_virt_recipe(%s)', recipe_id) session.rollback() # As an added precaution, let's try and avoid this recipe in future with session.begin(): recipe = Recipe.by_id(recipe_id) recipe.virt_status = RecipeVirtStatus.failed
def provision_virt_recipes(*args): # We limit to labs where the tree is available by NFS because RHEV needs to # use autofs to grab the images. See VirtManager.start_install. recipes = MachineRecipe.query\ .join(Recipe.recipeset).join(RecipeSet.job)\ .filter(Job.dirty_version == Job.clean_version)\ .join(Recipe.distro_tree, DistroTree.lab_controller_assocs, LabController)\ .filter(Recipe.status == TaskStatus.queued)\ .filter(Recipe.virt_status == RecipeVirtStatus.possible)\ .filter(LabController.disabled == False)\ .filter(or_(RecipeSet.lab_controller == None, RecipeSet.lab_controller_id == LabController.id))\ .filter(LabControllerDistroTree.url.like(u'nfs://%'))\ .order_by(RecipeSet.priority.desc(), Recipe.id.asc()) if not recipes.count(): return False log.debug("Entering provision_virt_recipes") for recipe_id, in recipes.values(Recipe.id.distinct()): system_name = None session.begin() try: system_name = u'%srecipe_%s' % ( ConfigItem.by_name(u'guest_name_prefix').current_value(u'beaker_'), recipe_id) provision_virt_recipe(system_name, recipe_id) session.commit() except needpropertyxml.NotVirtualisable: session.rollback() session.begin() recipe = Recipe.by_id(recipe_id) recipe.virt_status = RecipeVirtStatus.precluded session.commit() except VMCreationFailedException: session.rollback() session.begin() recipe = Recipe.by_id(recipe_id) recipe.virt_status = RecipeVirtStatus.skipped session.commit() except Exception, e: # This will get ovirt RequestErrors from recipe.provision() log.exception('Error in provision_virt_recipe(%s)', recipe_id) session.rollback() try: # Don't leak the vm if it was created if system_name: with dynamic_virt.VirtManager() as manager: manager.destroy_vm(system_name) # As an added precaution, let's try and avoid this recipe in future session.begin() recipe = Recipe.by_id(recipe_id) recipe.virt_status = RecipeVirtStatus.failed session.commit() except Exception: log.exception('Exception in exception handler :-(') finally:
def provision_virt_recipes(*args): recipes = MachineRecipe.query\ .join(Recipe.recipeset).join(RecipeSet.job)\ .filter(Job.dirty_version == Job.clean_version)\ .join(Recipe.distro_tree, DistroTree.lab_controller_assocs, LabController)\ .filter(Recipe.status == TaskStatus.queued)\ .filter(Recipe.virt_status == RecipeVirtStatus.possible)\ .filter(LabController.disabled == False)\ .filter(or_(RecipeSet.lab_controller == None, RecipeSet.lab_controller_id == LabController.id))\ .order_by(RecipeSet.priority.desc(), Recipe.id.asc()) if not recipes.count(): return False log.debug("Entering provision_virt_recipes") for recipe_id, in recipes.values(Recipe.id.distinct()): session.begin() try: provision_virt_recipe(recipe_id) session.commit() except Exception, e: log.exception('Error in provision_virt_recipe(%s)', recipe_id) session.rollback() # As an added precaution, let's try and avoid this recipe in future with session.begin(): recipe = Recipe.by_id(recipe_id) recipe.virt_status = RecipeVirtStatus.failed finally:
def tearDown(self): admin_user = User.by_user_name(data_setup.ADMIN_USER) if getattr(self,'recipe_id', None): with session.begin(): recipe = Recipe.by_id(self.recipe_id) if recipe.resource.system.open_reservation: recipe.resource.release()
def install_start(self, recipe_id=None): """ Report comencement of provisioning of a recipe's resource, extend first task's watchdog, and report 'Install Started' against it. """ try: recipe = Recipe.by_id(recipe_id) except InvalidRequestError: raise BX(_("Invalid Recipe ID %s" % recipe_id)) first_task = recipe.first_task if not recipe.resource.install_started: recipe.resource.install_started = datetime.utcnow() # extend watchdog by 3 hours 60 * 60 * 3 kill_time = 10800 # XXX In future releases where 'Provisioning' # is a valid recipe state, we will no longer # need the following block. log.debug('Extending watchdog for %s', first_task.t_id) first_task.extend(kill_time) log.debug('Recording /start for %s', first_task.t_id) first_task.pass_(path=u'/start', score=0, summary=u'Install Started') return True else: log.debug('Already recorded /start for %s', first_task.t_id) return False
def tearDown(self): admin_user = User.by_user_name(data_setup.ADMIN_USER) if getattr(self, 'recipe_id', None): with session.begin(): recipe = Recipe.by_id(self.recipe_id) if recipe.resource.system.open_reservation: recipe.resource.release()
def files(self, recipe_id): """ Return an array of logs for the given recipe. :param recipe_id: id of recipe :type recipe_id: integer .. deprecated:: 0.9.4 Use :meth:`taskactions.files() <bkr.server.task_actions.taskactions.files>` instead. """ try: recipe = Recipe.by_id(recipe_id) except InvalidRequestError: raise BX(_('Invalid recipe ID: %s' % recipe_id)) # Build a list of logs excluding duplicate paths, to mitigate: # https://bugzilla.redhat.com/show_bug.cgi?id=963492 logdicts = [] seen_paths = set() for log in recipe.all_logs(): logdict = log.dict # The path we care about here is the path which beaker-transfer # will move the file to. # Don't be tempted to use os.path.join() here since log['path'] # is often '/' which does not give the result you would expect. path = os.path.normpath( '%s/%s/%s' % (logdict['filepath'], logdict['path'], logdict['filename'])) if path in seen_paths: logger.warn('%s contains duplicate log %s', log.parent.t_id, path) else: seen_paths.add(path) logdicts.append(logdict) return logdicts
def install_done(self, recipe_id=None, fqdn=None): """ Report completion of installation with current FQDN """ if not recipe_id: raise BX(_("No recipe id provided!")) try: recipe = Recipe.by_id(recipe_id) except InvalidRequestError: raise BX(_("Invalid Recipe ID %s" % recipe_id)) if not recipe.installation: raise BX(_('Recipe %s not provisioned yet') % recipe_id) recipe.installation.install_finished = datetime.utcnow() # We don't want to change an existing FQDN, just set it # if it hasn't been set already (see BZ#879146) configured = recipe.resource.fqdn if configured is None and fqdn: recipe.resource.fqdn = configured = fqdn elif configured != fqdn: # We use eager formatting here to make this easier to test logger.info("Configured FQDN (%s) != reported FQDN (%s) in R:%s" % (configured, fqdn, recipe_id)) return configured
def provision_virt_recipe(system_name, recipe_id): recipe = Recipe.by_id(recipe_id) recipe.createRepo() # Figure out the "data centers" where we can run the recipe if recipe.recipeset.lab_controller: # First recipe of a recipeSet determines the lab_controller lab_controllers = [recipe.recipeset.lab_controller] else: # NB the same criteria are also expressed above lab_controllers = LabController.query.filter_by(disabled=False, removed=None) lab_controllers = needpropertyxml.apply_lab_controller_filter( recipe.host_requires, lab_controllers) lab_controllers = [lc for lc in lab_controllers.all() if recipe.distro_tree.url_in_lab(lc, 'nfs')] recipe.systems = [] recipe.watchdog = Watchdog() recipe.resource = VirtResource(system_name=system_name) with dynamic_virt.VirtManager() as manager: recipe.resource.allocate(manager, lab_controllers) recipe.recipeset.lab_controller = recipe.resource.lab_controller recipe.schedule() log.info("recipe ID %s moved from Queued to Scheduled by provision_virt_recipe" % recipe.id) recipe.waiting() recipe.provision() log.info("recipe ID %s moved from Scheduled to Waiting by provision_virt_recipe" % recipe.id)
def install_done(self, recipe_id=None, fqdn=None): """ Report completion of installation with current FQDN """ if not recipe_id: raise BX(_("No recipe id provided!")) if not fqdn: raise BX(_("No fqdn provided!")) try: recipe = Recipe.by_id(recipe_id) except InvalidRequestError: raise BX(_("Invalid Recipe ID %s" % recipe_id)) recipe.resource.install_finished = datetime.utcnow() # We don't want to change an existing FQDN, just set it # if it hasn't been set already (see BZ#879146) configured = recipe.resource.fqdn if configured is None: recipe.resource.fqdn = configured = fqdn elif configured != fqdn: # We use eager formatting here to make this easier to test log.info("Configured FQDN (%s) != reported FQDN (%s) in R:%s" % (configured, fqdn, recipe_id)) return configured
def run(self): session.begin() recipe = Recipe.by_id(self.recipe_id) self.ready_evt.set() self.continue_evt.wait() recipe.tasks[-1].stop() session.commit()
def files(self, recipe_id): """ Return an array of logs for the given recipe. :param recipe_id: id of recipe :type recipe_id: integer .. deprecated:: 0.9.4 Use :meth:`taskactions.files() <bkr.server.task_actions.taskactions.files>` instead. """ try: recipe = Recipe.by_id(recipe_id) except InvalidRequestError: raise BX(_('Invalid recipe ID: %s' % recipe_id)) # Build a list of logs excluding duplicate paths, to mitigate: # https://bugzilla.redhat.com/show_bug.cgi?id=963492 logdicts = [] seen_paths = set() for log in recipe.all_logs(): logdict = log.dict # The path we care about here is the path which beaker-transfer # will move the file to. # Don't be tempted to use os.path.join() here since log['path'] # is often '/' which does not give the result you would expect. path = os.path.normpath('%s/%s/%s' % (logdict['filepath'], logdict['path'], logdict['filename'])) if path in seen_paths: logger.warn('%s contains duplicate log %s', log.parent.t_id, path) else: seen_paths.add(path) logdicts.append(logdict) return logdicts
def really_return_reservation(self, id, msg=None): try: recipe = Recipe.by_id(id) except InvalidRequestError: raise BX(_("Invalid Recipe ID %s" % id)) recipe.return_reservation() flash(_(u"Successfully released reserved system for %s" % recipe.t_id)) redirect('/jobs/mine')
def extend(self, recipe_id, kill_time): """ Extend recipe watchdog by kill_time seconds """ try: recipe = Recipe.by_id(recipe_id) except InvalidRequestError: raise BX(_('Invalid recipe ID: %s' % recipe_id)) return recipe.extend(kill_time)
def postinstall_done(self, recipe_id=None): """ Report completion of postinstallation """ try: recipe = Recipe.by_id(recipe_id) except InvalidRequestError: raise BX(_(u'Invalid Recipe ID %s' % recipe_id)) recipe.resource.postinstall_finished = datetime.utcnow() return True
def console_output(self, recipe_id, output_length=None, offset=None): """ Get text console log output from OpenStack """ try: recipe = Recipe.by_id(recipe_id) except InvalidRequestError: raise BX(_('Invalid recipe ID: %s' % recipe_id)) manager = dynamic_virt.VirtManager(recipe.recipeset.job.owner) return manager.get_console_output(recipe.resource.instance_id, output_length)
def test_rendered_kickstart_is_deleted(self): with session.begin(): self.job_to_delete.to_delete = datetime.datetime.utcnow() recipe = self.job_to_delete.recipesets[0].recipes[0] ks = RenderedKickstart(kickstart=u'This is not a real kickstart.') recipe.rendered_kickstart = ks log_delete.log_delete() with session.begin(): self.assertEqual(Recipe.by_id(recipe.id).rendered_kickstart, None) self.assertRaises(NoResultFound, RenderedKickstart.by_id, ks.id)
def to_xml(self, recipe_id=None): """ Pass in recipe id and you'll get that recipe's xml """ if not recipe_id: raise BX(_("No recipe id provided!")) try: recipexml = Recipe.by_id(recipe_id).to_xml().toprettyxml() except InvalidRequestError: raise BX(_("Invalid Recipe ID %s" % recipe_id)) return recipexml
def install_fail(self, recipe_id=None): """ Records the fail of a recipe's installation. """ try: recipe = Recipe.by_id(recipe_id) except InvalidRequestError: raise BX(_("Invalid Recipe ID {}".format(recipe_id))) # noqa: F821 if not recipe.installation: raise BX(_("Recipe {} not provisioned yet".format(recipe_id))) # noqa: F821 return recipe.abort('Installation failed')
def postinstall_done(self, recipe_id=None): """ Report completion of postinstallation """ try: recipe = Recipe.by_id(recipe_id) except InvalidRequestError: raise BX(_(u'Invalid Recipe ID %s' % recipe_id)) if not recipe.installation: raise BX(_('Recipe %s not provisioned yet') % recipe_id) recipe.installation.postinstall_finished = datetime.utcnow() return True
def default(self, id): try: recipe = Recipe.by_id(id) except InvalidRequestError: flash(_(u"Invalid recipe id %s" % id)) redirect(".") if recipe.is_deleted(): flash(_(u"Invalid %s, has been deleted" % recipe.t_id)) redirect(".") return dict(title='Recipe', recipe_widget=self.recipe_widget, recipe=recipe)
def to_xml(self, recipe_id=None): """ Pass in recipe id and you'll get that recipe's xml """ if not recipe_id: raise BX(_("No recipe id provided!")) try: recipexml = etree.tostring(Recipe.by_id(recipe_id).to_xml(), pretty_print=True, encoding='utf8') except InvalidRequestError: raise BX(_("Invalid Recipe ID %s" % recipe_id)) return recipexml
def systems(self, recipe_id=None, *args, **kw): try: recipe = Recipe.by_id(recipe_id) except NoResultFound: flash(_(u"Invalid recipe id %s" % recipe_id)) redirect(url("/recipes")) PDC = widgets.PaginateDataGrid.Column fields = [PDC(name='fqdn', getter=lambda x: x.link, title='Name'), PDC(name='user', getter=lambda x: x.user.email_link if x.user else None, title='User'),] grid = myPaginateDataGrid(fields=fields) return dict(title='Recipe Systems', grid=grid, list=recipe.systems, search_bar=None)
def default(self, id): try: recipe = Recipe.by_id(id) except InvalidRequestError: flash(_(u"Invalid recipe id %s" % id)) redirect(".") if recipe.is_deleted(): flash(_(u"Invalid %s, has been deleted" % recipe.t_id)) redirect(".") return dict(title = 'Recipe', recipe_widget = self.recipe_widget, recipe = recipe)
def stop(self, recipe_id, stop_type, msg=None): """ Set recipe status to Completed """ try: recipe = Recipe.by_id(recipe_id) except InvalidRequestError: raise BX(_('Invalid recipe ID: %s' % recipe_id)) if stop_type not in recipe.stop_types: raise BX(_('Invalid stop_type: %s, must be one of %s' % (stop_type, recipe.stop_types))) kwargs = dict(msg = msg) return getattr(recipe,stop_type)(**kwargs)
def change_files(self, recipe_id, server, basepath): """ Change the server and basepath where the log files lives, Usually used to move from lab controller cache to archive storage. """ try: recipe = Recipe.by_id(recipe_id) except InvalidRequestError: raise BX(_('Invalid recipe ID: %s' % recipe_id)) for mylog in recipe.all_logs(): mylog.server = '%s/%s/' % (server, mylog.parent.filepath) mylog.basepath = '%s/%s/' % (basepath, mylog.parent.filepath) recipe.log_server = urlparse.urlparse(server)[1] return True
def register_file(self, server, task_id, path, filename, basepath): """ register file and return path to store """ try: recipetask = RecipeTask.by_id(task_id, lockmode='update') except NoResultFound: raise BX(_('Invalid task ID: %s' % task_id)) Recipe.by_id(recipetask.recipe_id, lockmode='update') if recipetask.is_finished(): raise BX('Cannot register file for finished task %s' % recipetask.t_id) self._check_log_limit(recipetask) # Add the log to the DB if it hasn't been recorded yet. log_recipe = LogRecipeTask.lazy_create(recipe_task_id=recipetask.id, path=path, filename=filename, ) log_recipe.server = server log_recipe.basepath = basepath recipetask.recipe.log_server = urlparse.urlparse(server)[1] return '%s' % recipetask.filepath
def files(self, recipe_id): """ Return an array of logs for the given recipe. :param recipe_id: id of recipe :type recipe_id: integer .. deprecated:: 0.9.4 Use :meth:`taskactions.files` instead. """ try: recipe = Recipe.by_id(recipe_id) except InvalidRequestError: raise BX(_('Invalid recipe ID: %s' % recipe_id)) return [log for log in recipe.all_logs]
def default(self, id, *args, **kwargs): # When flask returns a 404, it falls back to here so we need to # raise a cherrypy 404. if cherrypy.request.method == 'POST': raise cherrypy.HTTPError(404) try: recipe = Recipe.by_id(id) except InvalidRequestError: flash(_(u"Invalid recipe id %s" % id)) redirect(".") if recipe.is_deleted(): flash(_(u"Invalid %s, has been deleted" % recipe.t_id)) redirect(".") return dict(title = 'Recipe', recipe_widget = self.recipe_widget, recipe = recipe)
def default(self, id, *args, **kwargs): # When flask returns a 404, it falls back to here so we need to # raise a cherrypy 404. if cherrypy.request.method == 'POST': raise cherrypy.HTTPError(404) try: recipe = Recipe.by_id(id) except InvalidRequestError: flash(_(u"Invalid recipe id %s" % id)) redirect(".") if recipe.is_deleted(): flash(_(u"Invalid %s, has been deleted" % recipe.t_id)) redirect(".") return dict(title='Recipe', recipe_widget=self.recipe_widget, recipe=recipe)
def postreboot(self, recipe_id=None): # Backwards compat only, delete this after 0.10: # the recipe_id arg used to be hostname try: int(recipe_id) except ValueError: system = System.by_fqdn(recipe_id, identity.current.user) system.action_power('reboot', service=u'XMLRPC', delay=30) return system.fqdn try: recipe = Recipe.by_id(int(recipe_id)) except (InvalidRequestError, NoResultFound, ValueError): raise BX(_('Invalid recipe ID %s') % recipe_id) if isinstance(recipe.resource, SystemResource): recipe.resource.system.action_power('reboot', service=u'XMLRPC', delay=30) return True
def default(self, id, *args, **kwargs): # When flask returns a 404, it falls back to here so we need to # raise a cherrypy 404. if cherrypy.request.method == 'POST': raise cherrypy.HTTPError(404) if args: raise cherrypy.HTTPError(404) if cherrypy.request.path.endswith('/'): raise cherrypy.HTTPError(404) try: recipe = Recipe.by_id(id) except InvalidRequestError: flash(_(u"Invalid recipe id %s" % id)) redirect(".") if recipe.is_deleted: flash(_(u"Invalid %s, has been deleted" % recipe.t_id)) redirect(".") recipe.set_reviewed_state(identity.current.user, True) return dict(title = 'Recipe', recipe_widget = self.recipe_widget, recipe = recipe)
def register_file(self, server, recipe_id, path, filename, basepath): """ register file and return path to store """ try: recipe = Recipe.by_id(recipe_id) except InvalidRequestError: raise BX(_('Invalid recipe ID: %s' % recipe_id)) if recipe.is_finished(): raise BX('Cannot register file for finished recipe %s' % recipe.t_id) # Add the log to the DB if it hasn't been recorded yet. log_recipe = LogRecipe.lazy_create(recipe_id=recipe.id, path=path, filename=filename, ) log_recipe.server = server log_recipe.basepath = basepath # Pull log_server out of server_url. recipe.log_server = urlparse.urlparse(server)[1] return '%s' % recipe.filepath
def default(self, id, *args, **kwargs): # When flask returns a 404, it falls back to here so we need to # raise a cherrypy 404. if cherrypy.request.method == 'POST': raise cherrypy.HTTPError(404) if args: raise cherrypy.HTTPError(404) if cherrypy.request.path.endswith('/'): raise cherrypy.HTTPError(404) try: recipe = Recipe.by_id(id) except InvalidRequestError: flash(_(u"Invalid recipe id %s" % id)) redirect(".") if recipe.is_deleted: flash(_(u"Invalid %s, has been deleted" % recipe.t_id)) redirect(".") if recipe.is_finished() or recipe.status == TaskStatus.reserved: recipe.set_reviewed_state(identity.current.user, True) return dict(title = 'Recipe', recipe_widget = self.recipe_widget, recipe = recipe)
def register_file(self, server, recipe_id, path, filename, basepath): """ register file and return path to store """ try: recipe = Recipe.by_id(recipe_id, lockmode='update') except NoResultFound: raise BX(_('Invalid recipe ID: %s' % recipe_id)) if recipe.is_finished(): raise BX('Cannot register file for finished recipe %s' % recipe.t_id) # Add the log to the DB if it hasn't been recorded yet. log_recipe = LogRecipe.lazy_create(recipe_id=recipe.id, path=path, filename=filename, ) log_recipe.server = server log_recipe.basepath = basepath # Pull log_server out of server_url. recipe.log_server = urlparse.urlparse(server)[1] return '%s' % recipe.filepath
def test_reserve_with_recipe(self): with session.begin(): recipe = data_setup.create_recipe() job = data_setup.create_job_for_recipes([recipe]) data_setup.mark_job_running(job) recipe = Recipe.by_id(recipe.id) fqdn = recipe.resource.system.fqdn user = recipe.resource.system.user recipe.resource.system.loaned = user recipe.resource.system.loan_comment = 'Amy, must I jujitsu my ma?' system = recipe.resource.system # JSON output json_out = run_client( ['bkr', 'system-status', fqdn, '--format', 'json']) json_out = loads(json_out) current_reservation = json_out.get('current_reservation') self.assertEqual(current_reservation.get('user_name'), unicode(system.user)) self.assertEqual(current_reservation.get('recipe_id'), '%s' % \ system.open_reservation.recipe.id) self.assertEqual(json_out.get('condition'), '%s' % system.status) # Human friendly output human_out = run_client(['bkr', 'system-status', fqdn]) expected_out = textwrap.dedent('''\ Condition: %s Current reservation: User: %s Recipe ID: %s Start time: %s UTC Current loan: User: %s Comment: Amy, must I jujitsu my ma?''' % \ (system.status, system.user, system.open_reservation.recipe.id, system.open_reservation.recipe.start_time.strftime('%Y-%m-%d %H:%M:%S'), system.loaned)) human_out = human_out.rstrip('\n') self.assertEqual(human_out, expected_out, human_out)
def test_reserve_with_recipe(self): with session.begin(): recipe = data_setup.create_recipe() job = data_setup.create_job_for_recipes([recipe]) data_setup.mark_job_running(job) recipe = Recipe.by_id(recipe.id) fqdn = recipe.resource.system.fqdn user = recipe.resource.system.user recipe.resource.system.loaned = user recipe.resource.system.loan_comment = u'Amy, must I jujitsu my ma?' system = recipe.resource.system # JSON output json_out = run_client(['bkr', 'system-status', fqdn, '--format', 'json']) json_out = loads(json_out) current_reservation = json_out.get('current_reservation') self.assertEqual(current_reservation.get('user_name'), unicode(system.user)) self.assertEqual(current_reservation.get('recipe_id'), '%s' % \ system.open_reservation.recipe.id) self.assertEqual(json_out.get('condition'), '%s' % system.status) # Human friendly output human_out = run_client(['bkr', 'system-status', fqdn]) expected_out = textwrap.dedent('''\ Condition: %s Current reservation: User: %s Recipe ID: %s Start time: %s UTC Current loan: User: %s Comment: Amy, must I jujitsu my ma?''' % \ (system.status, system.user, system.open_reservation.recipe.id, system.open_reservation.recipe.start_time.strftime('%Y-%m-%d %H:%M:%S'), system.loaned)) human_out = human_out.rstrip('\n') self.assertEqual(human_out, expected_out, human_out)
def install_start(self, recipe_id=None): """ Records the start of a recipe's installation. The watchdog is extended by 3 hours to allow the installation to complete. """ try: recipe = Recipe.by_id(recipe_id) except InvalidRequestError: raise BX(_("Invalid Recipe ID %s" % recipe_id)) if not recipe.installation: raise BX(_('Recipe %s not provisioned yet') % recipe_id) installation = recipe.installation if not installation.install_started: installation.install_started = datetime.utcnow() # extend watchdog by 3 hours 60 * 60 * 3 kill_time = 10800 logger.debug('Extending watchdog for %s', recipe.t_id) recipe.extend(kill_time) return True else: logger.debug('Already recorded install_started for %s', recipe.t_id) return False
def install_start(self, recipe_id=None): """ Records the start of a recipe's installation. The watchdog is extended by 3 hours to allow the installation to complete. """ try: recipe = Recipe.by_id(recipe_id) except InvalidRequestError: raise BX(_("Invalid Recipe ID %s" % recipe_id)) if not recipe.installation: raise BX(_('Recipe %s not provisioned yet') % recipe_id) installation = recipe.installation if not installation.install_started: installation.install_started = datetime.utcnow() # extend watchdog by 3 hours 60 * 60 * 3 kill_time = 10800 log.debug('Extending watchdog for %s', recipe.t_id) recipe.extend(kill_time) return True else: log.debug('Already recorded install_started for %s', recipe.t_id) return False
def postreboot(self, recipe_id=None): # Backwards compat only, delete this after 0.10: # the recipe_id arg used to be hostname try: int(recipe_id) except ValueError: system = System.by_fqdn(recipe_id, identity.current.user) system.action_power('reboot', service=u'XMLRPC', delay=30) return system.fqdn try: recipe = Recipe.by_id(int(recipe_id)) except (InvalidRequestError, NoResultFound, ValueError): raise BX(_('Invalid recipe ID %s') % recipe_id) if isinstance(recipe.resource, SystemResource): recipe.resource.system.action_power('reboot', service=u'XMLRPC', delay=30) elif isinstance(recipe.resource, VirtResource): # XXX this should also be delayed 30 seconds but there is no way with dynamic_virt.VirtManager() as manager: vm = manager.api.vms.get(recipe.resource.system_name) vm.stop() vm.start() return True
def _get_recipe_by_id(id): """Get recipe by id, reporting HTTP 404 if the recipe is not found""" try: return Recipe.by_id(id) except NoResultFound: raise NotFound404('Recipe not found')
def watchdog(self, recipe_id): try: recipe = Recipe.by_id(recipe_id) except InvalidRequestError: raise BX(_('Invalid recipe ID: %s' % recipe_id)) return recipe.status_watchdog()