Exemplo n.º 1
0
    def title(self, id, searchvalues=None):
        thetitle = Title.get(id)
        searchform = widgets.TableForm(fields=PrivateSearchFields(),
                                       submit_text="Search!")
        titleform = widgets.TableForm(
            name="titleform",
            fields=PrivateTitleFields(),
            submit_text="modify this title's sections and distributor")
        titlepersistenceform = widgets.TableForm(
            fields=PrivateTitlePersistenceFields(), submit_text="")
        persisting_sections = []
        #       try:
        #           persisting_sections=session['persisting_sections']
        #       except:
        #           session['persisting_sections']=[]
        #       print persisting_sections
        #        sections=list(set(thetitle.get_tag_collection(category='inventory',key='section')))
        #        sections=thetitle.sections
        #      sections.extend(persisting_sections)
        print[s.id for s in list(thetitle.sections)]

        return dict(thetitle=thetitle,
                    authorswidget=PrivateAuthorsWidget(),
                    searchform=searchform,
                    searchvalues=searchvalues,
                    titleform=titleform,
                    today=strftime("%Y-%m-%d", gmtime()),
                    titlepersistenceform=titlepersistenceform,
                    titlesections=[s.id for s in list(thetitle.sections)],
                    persisting_sections=persisting_sections)
def test_required_fields():
    """
    Required field are automatically discovered from the form validator and marked
    with the "requiredfield" css class.
    """
    class MyFields(widgets.WidgetsList):
        name = widgets.TextField(validator=validators.String())
        comment = widgets.TextArea(validator=validators.String(not_empty=True))

    form = widgets.TableForm(fields=MyFields())

    class MyRoot(turbogears.controllers.RootController):
        def test(self):
            return dict(form=form)

        test = turbogears.expose(template=".form")(test)

    cherrypy.root = MyRoot()
    testutil.create_request("/test")
    output = cherrypy.response.body[0].lower()

    print output
    name_p = 'name="comment"'
    class_p = 'class="textarea requiredfield"'
    assert (re.compile('.*'.join([class_p, name_p])).search(output)
            or re.compile('.*'.join([name_p, class_p])).search(output))
    name_p = 'name="name"'
    class_p = 'class="textfield"'
    assert (re.compile('.*'.join([class_p, name_p])).search(output)
            or re.compile('.*'.join([name_p, class_p])).search(output))
Exemplo n.º 3
0
    def storefront(self):
        searchform = widgets.TableForm(fields=SearchFields(),
                                       submit_text="Search!")
        conn = db.connect()
        cursor = conn.cursor()
        cursor.execute("""
        select booktitle,count(book.id) as blah,title_id   from book,title where book.title_id=title.id and book.status='SOLD' and title.kind_id=1 group by title_id order by blah desc limit 30
        """)
        results = cursor.fetchall()
        cursor.close()

        best_sellers = [
            Title.get(x[2]) for x in results
            if Title.get(x[2]).copies_in_status("STOCK") > 0
        ]

        new_titles = Title.select("""
            book.title_id=title.id AND
            book.status ='STOCK'
            """,
                                  orderBy="-title.id",
                                  clauseTables=['book'],
                                  distinct=True)
        return dict(authorswidget=AuthorsWidget(),
                    titlelistwidget=TitleListWidget(),
                    searchform=searchform,
                    new_titles=new_titles[:10],
                    best_sellers=best_sellers)
Exemplo n.º 4
0
    def reinventory(self, isbn="", author="", title=""):
        searchform = widgets.TableForm(fields=PrivateSearchFields(),
                                       submit_text="Search!")
        if author == "" and title == "" and isbn == "":
            the_titles = False
        else:
            the_titles = Title.select("""
            title.isbn LIKE '%%%s%%' AND
            author.id=author_title.author_id AND
            author_title.title_id=title.id AND author.author_name LIKE '%%%s%%' AND title.booktitle LIKE '%%%s%%'
            """ % (escape_string(isbn), escape_string(author),
                   escape_string(title)),
                                      orderBy="booktitle",
                                      clauseTables=['author', 'author_title'],
                                      distinct=True)

        title_count = 0
        try:
            title_count = the_titles.count()
        except:
            pass
        if title_count > 0:
            if the_titles.count() == 1:
                return self.title(the_titles[0].id,
                                  searchvalues=dict(author=author,
                                                    title=title,
                                                    isbn=isbn))

        return dict(the_titles=the_titles,
                    authorswidget=PrivateAuthorsWidget(),
                    titlelistwidget=PrivateTitleListWidget(),
                    searchform=searchform,
                    values=dict(author=author, title=title, isbn=isbn))
Exemplo n.º 5
0
class TestNestedWidgetsWMixedValidation:

    form = widgets.TableForm(
        name="myform",
        validator=s_validator,
        fields=[
            widgets.TextField("name"),
            widgets.TextField("age"),
            widgets.TextField("number", validator=int_validator),
            widgets.FieldSet(
                name="sub",
                validator=s_validator,
                fields=[
                    widgets.TextField("name"),
                    widgets.TextField("age"),
                    widgets.TextField("number", validator=int_validator),
                    widgets.FieldSet(
                        name="sub2",
                        fields=[
                            widgets.TextField("name"),
                            widgets.TextField("age", validator=int_validator),
                            widgets.TextField("number",
                                              validator=int_validator),
                        ]),
                ]),
        ])

    def test_mixed_validators(self):
        """
        Tests that schema validators and single validators can be mixed
        safely.
        """
        values = dict(age="bad",
                      number="22",
                      sub=dict(age="bad",
                               number="bad",
                               sub2=dict(
                                   age="bad",
                                   number="bad",
                               )))

        values, errors = catch_validation_errors(self.form, values)
        print values, errors

        assert errors.pop('age', False)
        #assert values['number'] == 22

        # assert errors are not getting poluted errors from other levels of
        # the tree
        assert errors.keys() == ['sub']
        errors = errors['sub']
        assert errors.pop('age', False)
        assert errors.pop('number', False)

        assert errors.keys() == ['sub2']
        errors = errors['sub2']
        assert errors.pop('age', False)
        assert errors.pop('number', False)
        assert not errors
Exemplo n.º 6
0
def test_disabled_widget():
    form = widgets.TableForm(fields=[
        widgets.TextField("name"),
        widgets.TextField("age", validator=validators.Int())
    ],
                             submit_text="Submit")
    output = form.render(disabled_fields=["age"])
    assert "age" not in output
Exemplo n.º 7
0
def test_creation_overriding():
    class TestFormFields(widgets.WidgetsList):
        foo = widgets.TextField()
        bar = widgets.CheckBox()

    fields = TestFormFields()
    fields[1] = widgets.TextField('bar')
    t = widgets.TableForm(fields=fields)
    assert len(t.fields) == 2, '%s' % [x.name for x in t.fields]
Exemplo n.º 8
0
def test_input_errors():
    """Data is stored in the request object if there are errors"""
    form = widgets.TableForm(fields=[
        widgets.TextField("name"),
        widgets.TextField("age", validator=validators.Int())
    ])
    values = dict(name="ed", age="ed")
    values, errors = catch_validation_errors(form, values)
    assert "enter an integer" in str(errors["age"])
Exemplo n.º 9
0
def test_creation():
    class TestFormFields(widgets.WidgetsList):
        foo = widgets.TextField()
        bar = widgets.CheckBox()

    t = widgets.TableForm(fields=TestFormFields() + [widgets.TextField('a')])
    wlist = t.fields
    assert len(wlist) == 3, '%s' % [x.name for x in wlist]
    assert wlist[0].name == 'foo'
    assert wlist[1].name == 'bar'
    assert wlist[2].name == 'a'
Exemplo n.º 10
0
def test_input_conversion():
    """Input for the whole form can be validated and converted"""
    form = widgets.TableForm(fields=[
        widgets.TextField("name"),
        widgets.TextField("age", validator=validators.Int())
    ],
                             submit_text="Submit")
    values = dict(name="ed", age="15")
    values = form.validate(values)
    assert values["name"] == "ed"
    assert values["age"] == 15
    assert not values.has_key("submit")
Exemplo n.º 11
0
def test_passing_instance():
    """You can pass an instance to a form for the value"""
    form = widgets.TableForm(fields=[
        widgets.TextField("name"),
        widgets.TextField("age", validator=validators.Int())
    ],
                             submit_text="Submit")

    class Person(object):
        name = "ed"
        age = 892

    output = form.render(Person(), format="xhtml")
    assert 'value="ed"' in output
    assert 'value="892"' in output
Exemplo n.º 12
0
class TestSchemaValidationWithChildWidgetsValidators:
    """Tests the validation of a CompoundWidget is done correctly with a
    Schema validator and independent validators on the each of the child
    widgets."""
    class Fields(widgets.WidgetsList):
        name = widgets.TextField(validator=validators.UnicodeString())
        age = widgets.TextField(validator=validators.Int())
        passwd = widgets.PasswordField(validator=validators.NotEmpty())
        passwd2 = widgets.PasswordField(validator=validators.UnicodeString())

    class FieldsSchema(validators.Schema):
        chained_validators = [validators.FieldsMatch('passwd', 'passwd2')]

    form = widgets.TableForm(fields=Fields(), validator=FieldsSchema())

    def test_goodvalues(self):
        values = dict(name=u'Jos\xc3\xa9',
                      age="99",
                      passwd="fado",
                      passwd2="fado")

        values, errors = catch_validation_errors(self.form, values)
        assert values['age'] == 99
        assert not errors.keys()

    def test_widget_validator_failure(self):
        values = dict(name=u'Jos\xc3\xa9',
                      age="ninetynine",
                      passwd="fado",
                      passwd2="fado")
        values, errors = catch_validation_errors(self.form, values)
        assert "age" in errors.keys()

    def test_widget_validator_and_schema_failure(self):
        values = dict(name=u'Jos\xc3\xa9',
                      age="ninetynine",
                      passwd="fado",
                      passwd2="fadO")
        values, errors = catch_validation_errors(self.form, values)
        assert "age" in errors.keys()
        assert "passwd2" in errors.keys()
Exemplo n.º 13
0
    def search(self, author="", title=""):
        searchform = widgets.TableForm(fields=SearchFields(),
                                       submit_text="Search!")
        if author == "" and title == "":
            the_titles = False
        else:
            the_titles = Title.select(
                """
	    book.title_id=title.id AND
            book.status ='STOCK' AND
            author.id=author_title.author_id AND
            author_title.title_id=title.id AND author.author_name LIKE '%%%s%%' AND title.booktitle LIKE '%%%s%%'
            """ % (escape_string(author), escape_string(title)),
                orderBy="booktitle",
                clauseTables=['book', 'author', 'author_title'],
                distinct=True)
        return dict(the_titles=the_titles,
                    authorswidget=AuthorsWidget(),
                    titlelistwidget=TitleListWidget(),
                    searchform=searchform,
                    values=dict(author=author, title=title))
Exemplo n.º 14
0
class TestSchemaValidation:
    """Tests the validation of a CompoundWidget is done correctly with a
    Schema validator and no validators on the child widgets."""
    class Fields(widgets.WidgetsList):
        name = widgets.TextField()
        age = widgets.TextField()
        passwd = widgets.PasswordField()
        passwd2 = widgets.PasswordField()

    class FieldsSchema(validators.Schema):
        chained_validators = [validators.FieldsMatch('passwd', 'passwd2')]

        name = validators.UnicodeString()
        age = validators.Int()
        passwd = validators.NotEmpty()
        passwd2 = validators.UnicodeString()

    form = widgets.TableForm(fields=Fields(), validator=FieldsSchema())

    def test_goodvalues(self):
        values = dict(name=u'Jos\xc3\xa9',
                      age="99",
                      passwd="fado",
                      passwd2="fado")

        values, errors = catch_validation_errors(self.form, values)
        assert values['age'] == 99
        assert not errors

    def test_badvalues(self):
        values = dict(name=u'Jos\xc3\xa9',
                      age="99",
                      passwd="fado",
                      passwd2="fadO")

        values, errors = catch_validation_errors(self.form, values)
        assert "passwd2" in errors.keys()
Exemplo n.º 15
0
class TestNestedSchemaValidators:

    #XXX: Age is always validated by the nested schemas, number is
    #     validated with widget validator.
    form = widgets.TableForm(
        name="myform",
        validator=OuterSchema(),
        fields=[
            widgets.TextField("age"),
            widgets.TextField("number", validator=int_validator),
            widgets.FieldSet(
                name="sub",
                fields=[
                    widgets.TextField("age"),
                    widgets.TextField("number", validator=int_validator),
                    widgets.FieldSet(
                        name="sub2",
                        fields=[
                            widgets.TextField("age"),
                            widgets.TextField("number",
                                              validator=int_validator),
                        ]),
                ]),
        ])

    def test_nested_schemas(self):
        """
        Tests that we can nest schema validators safely.
        """
        values = dict(age="bad",
                      number="22",
                      sub=dict(age="27",
                               number="bad",
                               sub2=dict(
                                   age="bad",
                                   number="bad",
                               )))

        values, errors = catch_validation_errors(self.form, values)
        print values, errors

        assert errors.pop('age', False)
        #assert values['number'] == 22

        # assert errors are not getting poluted errors from other levels of
        # the tree
        assert errors.keys() == ['sub']
        errors = errors['sub']
        values = values['sub']
        #XXX This assertion fails :(
        #XXX But it's normal as the Schema doesn't convert good values in
        #    invalid Schemas, ATM
        #assert values['age'] == 27
        assert errors.pop('number', False)

        assert errors.keys() == ['sub2']
        errors = errors['sub2']
        assert errors.pop('age', False)
        assert errors.pop('number', False)
        assert not errors

    def test_nested_schemas_good_values(self):
        values = dict(age="21",
                      number="22",
                      sub=dict(age="27",
                               number="28",
                               sub2=dict(
                                   age="33",
                                   number="34",
                               )))

        values, errors = catch_validation_errors(self.form, values)
        print values, errors

        assert not errors
        assert (values["age"], values['number']) == (21, 22)

        values = values['sub']
        assert (values["age"], values['number']) == (27, 28)

        values = values['sub2']
        assert (values["age"], values['number']) == (33, 34)
Exemplo n.º 16
0
class TestNestedWidgets:

    form = widgets.TableForm(
        name="myform",
        fields=[
            widgets.TextField("name"),
            widgets.TextField("age", validator=int_validator),
            widgets.FieldSet("sub",
                             fields=[
                                 widgets.TextField("name"),
                                 widgets.TextField("age",
                                                   validator=int_validator),
                                 widgets.FieldSet(
                                     "sub2",
                                     fields=[
                                         widgets.TextField("name"),
                                         widgets.TextField(
                                             "age", validator=int_validator),
                                     ],
                                     validator=TestSchema()),
                             ],
                             validator=TestSchema()),
        ],
        validator=TestSchema())

    def test_display(self):
        """
        Checks if names fo the widgets are set correctly depending on their
        path.
        """
        output = self.form.render(dict(sub=dict(sub2=dict(age=22))),
                                  format='xhtml')
        value_p = 'value="22"'
        name_p = 'name="sub.sub2.age"'
        assert (re.compile('.*'.join([value_p, name_p])).search(output)
                or re.compile('.*'.join([name_p, value_p])).search(output))

        output = self.form.render(dict(sub=dict(age=22)), format='xhtml')
        value_p = 'value="22"'
        name_p = 'name="sub.age"'
        assert (re.compile('.*'.join([value_p, name_p])).search(output)
                or re.compile('.*'.join([name_p, value_p])).search(output))

        output = self.form.render(dict(sub=dict(age=22)), format='xhtml')
        id_p = 'id="myform_sub_age"'
        name_p = 'name="sub.age"'
        assert (re.compile('.*'.join([value_p, id_p])).search(output)
                or re.compile('.*'.join([id_p, value_p])).search(output))

        output = self.form.render(dict(age=22), format='xhtml')
        value_p = 'value="22"'
        name_p = 'name="age"'
        assert (re.compile('.*'.join([value_p, name_p])).search(output)
                or re.compile('.*'.join([name_p, value_p])).search(output))

    def test_validate_outermost(self):
        values = dict(age="twenty")
        values, errors = catch_validation_errors(self.form, values)

        print values, errors

        assert errors.pop('age', False)
        assert not errors

    def test_validate_sub(self):
        values = dict(sub=dict(age="twenty"))

        values, errors = catch_validation_errors(self.form, values)

        print values, errors
        # check the outermost dict is not poluted with errors from the inner
        # dicts
        assert not errors.has_key('age')

        errors = errors['sub']
        assert errors.pop('age', False)
        assert not errors

    def test_validate_sub2(self):
        values = dict(sub=dict(sub2=dict(age="twenty")))

        values, errors = catch_validation_errors(self.form, values)

        print values, errors
        assert not errors.has_key('age')

        errors = errors['sub']
        print values, errors
        assert not errors.has_key('age')

        errors = errors['sub2']
        print values, errors
        assert errors.pop('age', False)
        assert not errors

    def test_validate_sub_and_sub2(self):
        values = dict(sub=dict(age="fhg", sub2=dict(age="twenty")))

        values, errors = catch_validation_errors(self.form, values)

        print values, errors
        assert not errors.has_key('age')

        errors = errors['sub']
        print values, errors
        assert errors.pop('age', False)

        errors = errors['sub2']
        print values, errors
        assert errors.pop('age', False)
        assert not errors

    def test_good_values(self):
        values = dict(age=22, sub=dict(sub2=dict(age=20)))

        values, errors = catch_validation_errors(self.form, values)

        print values, errors

        assert errors == {}
        assert values['age'] == 22

    def test_good_and_bad_values(self):
        values = dict(age="ddd", sub=dict(age="20", sub2=dict()))

        values, errors = catch_validation_errors(self.form, values)
        print values, errors

        assert errors.pop('age', False)
        assert not errors
Exemplo n.º 17
0
class TestNestedWidgetsWSchemaValidation:

    form = widgets.TableForm(name="myform",
                             validator=s_validator,
                             fields=[
                                 widgets.TextField("name"),
                                 widgets.TextField("age"),
                                 widgets.FieldSet(
                                     name="sub",
                                     validator=s_validator,
                                     fields=[
                                         widgets.TextField("name"),
                                         widgets.TextField("age"),
                                         widgets.FieldSet(
                                             name="sub2",
                                             validator=s_validator,
                                             fields=[
                                                 widgets.TextField("name"),
                                                 widgets.TextField("age"),
                                             ]),
                                     ]),
                             ])

    def test_validate_sub_schema(self):
        values = dict(sub=dict(age="twenty"))

        values, errors = catch_validation_errors(self.form, values)
        print values, errors

        # check the outermost dict is not poluted with errors from the inner
        # dicts
        assert not errors.has_key('age')

        errors = errors['sub']
        assert errors.pop('age', False)
        assert not errors

    def test_good_and_bad_values_schema(self):
        values = dict(age="ddd", sub=dict(age="20", sub2=dict()))

        values, errors = catch_validation_errors(self.form, values)
        print values, errors

        assert errors.pop('age', False)
        assert not errors
        #assert values['sub']['age'] == 20

    def test_good_values_schema(self):
        values = dict(age=22, sub=dict(sub2=dict(age=20)))

        values, errors = catch_validation_errors(self.form, values)
        print values, errors

        assert errors == {}
        assert values['age'] == 22

    def test_validate_sub_and_sub2_schema(self):
        values = dict(sub=dict(age="fhg", sub2=dict(age="twenty")))

        values, errors = catch_validation_errors(self.form, values)
        print values, errors

        assert not errors.has_key('age')

        errors = errors['sub']
        print values, errors
        assert errors.pop('age', False)

        errors = errors['sub2']
        print values, errors
        assert errors.pop('age', False)
        assert not errors

    def test_validate_sub2_schema(self):
        values = dict(sub=dict(sub2=dict(age="twenty")))

        values, errors = catch_validation_errors(self.form, values)
        print values, errors

        assert not errors.has_key('age')

        errors = errors['sub']
        print values, errors
        assert not errors.has_key('age')

        errors = errors['sub2']
        print values, errors
        assert errors.pop('age', False)

    def test_validate_outermost_schema(self):
        values = dict(age="twenty")

        values, errors = catch_validation_errors(self.form, values)
        print values, errors

        assert errors.pop('age', False)
        assert not errors
        assert not errors
Exemplo n.º 18
0
class Recipes(RPCRoot):
    # For XMLRPC methods in this class.
    exposed = True

    hidden_id = widgets.HiddenField(name='id')
    confirm = widgets.Label(
        name='confirm', default="Are you sure you want to release the system?")
    return_reservation_form = widgets.TableForm(
        'end_recipe_reservation',
        fields=[hidden_id, confirm],
        action='./really_return_reservation',
        submit_text=_(u'Yes'))

    tasks = RecipeTasks()

    recipe_widget = RecipeWidget()

    log_types = dict(
        R=LogRecipe,
        T=LogRecipeTask,
        E=LogRecipeTaskResult,
    )

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    def by_log_server(self, server, limit=50):
        """
        Returns a list of recipe IDs which have logs stored on the given 
        server. By default, returns at most 50 at a time.

        Only returns recipes where the whole recipe set has completed. Also 
        excludes recently completed recipe sets, since the system may continue 
        uploading logs for a short while until beaker-provision powers it off.
        """
        finish_threshold = datetime.utcnow() - timedelta(minutes=2)
        recipes = Recipe.query.join(Recipe.recipeset)\
                .filter(RecipeSet.status.in_([s for s in TaskStatus if s.finished]))\
                .filter(not_(RecipeSet.recipes.any(Recipe.finish_time >= finish_threshold)))\
                .filter(Recipe.log_server == server)\
                .limit(limit)
        return [recipe_id for recipe_id, in recipes.values(Recipe.id)]

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    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

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    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]

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    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:
            myserver = '%s/%s/' % (server, mylog['filepath'])
            mybasepath = '%s/%s/' % (basepath, mylog['filepath'])
            self.change_file(mylog['tid'], myserver, mybasepath)
        recipe.log_server = urlparse.urlparse(server)[1]
        return True

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    def change_file(self, tid, server, basepath):
        """
        Change the server and basepath where the log file lives, Usually
         used to move from lab controller cache to archive storage.
        """
        log_type, log_id = tid.split(":")
        if log_type.upper() in self.log_types.keys():
            try:
                mylog = self.log_types[log_type.upper()].by_id(log_id)
            except InvalidRequestError:
                raise BX(_("Invalid %s" % tid))
        mylog.server = server
        mylog.basepath = basepath
        return True

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    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)

    @cherrypy.expose
    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)

    @cherrypy.expose
    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()

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    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)

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    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

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    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

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    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

    @identity.require(identity.not_anonymous())
    @expose()
    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')

    @expose(template="bkr.server.templates.form")
    @identity.require(identity.not_anonymous())
    def return_reservation(self, recipe_id=None):
        """
        End recipe reservation
        """
        if not recipe_id:
            raise BX(_("No recipe id provided!"))

        return dict(
            title='Release reserved system for Recipe %s' % recipe_id,
            form=self.return_reservation_form,
            action='./really_return_reservation',
            options={},
            value=dict(id=recipe_id),
        )

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    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

    @cherrypy.expose
    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 _recipe_search(self, recipe, **kw):
        recipe_search = search_utility.Recipe.search(recipe)
        for search in kw['recipesearch']:
            col = search['table']
            try:
                recipe_search.append_results(search['value'], col,
                                             search['operation'], **kw)
            except KeyError, e:
                log.error(e)
                return recipe_search.return_results()

        return recipe_search.return_results()
Exemplo n.º 19
0
def test_callable_options_for_selection_field():
    cc = CallableCounter()
    w = widgets.CheckBoxList('collections', label='Collections', options=cc)
    assert cc.counter == 1  # called once to guess validator
    cc = CallableCounter()
    w = widgets.CheckBoxList('collections',
                             label='Collections',
                             validator=validators.Int(),
                             options=cc)
    assert cc.counter == 0  # cc shouldn't be called if validator is provided


nestedform = widgets.TableForm(fields=[
    widgets.FieldSet(
        "foo", fields=[widgets.TextField("name"),
                       widgets.TextField("age")])
])


class NestedController(controllers.Controller):

    [expose()]
    [validate(form=nestedform)]

    def checkform(self, foo):
        self.foo = foo


def test_nested_variables():
    cherrypy.request = oldrequest
def test_two_form_in_the_same_page():
    """
    Two different forms containing some fields with the same name can be
    validated and re-displayed on the same page with right values and errors.
    """
    class MyFields(widgets.WidgetsList):
        age = widgets.TextField(validator=validators.Int())
        email = widgets.TextArea(validator=validators.Email())

    form1 = widgets.TableForm(name="form1", fields=MyFields())
    form2 = widgets.TableForm(name="form2", fields=MyFields())

    class MyRoot(turbogears.controllers.RootController):
        def test(self):
            return dict(form1=form1, form2=form2)

        test = turbogears.expose(template=".two_forms")(test)
        test = turbogears.validate(form=form1)(test)
        test = turbogears.error_handler(test)(test)

        def test2(self):
            return dict(form=form2)

        test2 = turbogears.expose(template=".form")(test2)
        test2 = turbogears.validate(form=form2)(test2)
        test2 = turbogears.error_handler(test2)(test2)

        def test3(self):
            return dict(form=form1)

        test3 = turbogears.expose(template=".form")(test3)
        test3 = turbogears.validate(form=form2)(test3)
        test3 = turbogears.error_handler(test3)(test3)

    cherrypy.root = MyRoot()
    testutil.create_request("/test?age=foo&email=bar")
    output = cherrypy.response.body[0].lower()
    iv = cherrypy.request.input_values
    validation_errors = cherrypy.request.validation_errors
    validated_form = cherrypy.request.validated_form

    print output
    print iv
    print validation_errors
    print validated_form
    assert form1 is validated_form
    assert form1.is_validated
    assert form2 is not validated_form
    assert not form2.is_validated
    value_p = 'value="foo"'
    id_p = 'id="form1_age"'
    assert (re.compile('.*'.join([value_p, id_p])).search(output)
            or re.compile('.*'.join([id_p, value_p])).search(output))
    value_p = 'value="foo"'
    id_p = 'id="form2_age"'
    assert not (re.compile('.*'.join([value_p, id_p])).search(output)
                or re.compile('.*'.join([id_p, value_p])).search(output))

    cherrypy.root = MyRoot()
    testutil.create_request("/test2?age=foo&email=bar")
    output = cherrypy.response.body[0].lower()
    iv = cherrypy.request.input_values
    validation_errors = cherrypy.request.validation_errors
    validated_form = cherrypy.request.validated_form

    print output
    print iv
    print validation_errors
    print validated_form
    assert form1 is not validated_form
    assert not form1.is_validated
    assert form2 is validated_form
    assert form2.is_validated
    assert 'value="foo"' in output
    assert '>bar<' in output
    assert 'class="fielderror"' in output

    cherrypy.root = MyRoot()
    testutil.create_request("/test3?age=foo&email=bar")
    output = cherrypy.response.body[0].lower()
    iv = cherrypy.request.input_values
    validation_errors = cherrypy.request.validation_errors
    validated_form = cherrypy.request.validated_form

    print output
    print iv
    print validation_errors
    print validated_form
    assert form1 is not validated_form
    assert not form1.is_validated
    assert form2 is validated_form
    assert form2.is_validated
    assert 'value="foo"' not in output
    assert '>bar<' not in output
    assert 'class="fielderror"' not in output
def test_repeating_fields():
    repetitions = 5

    class MyFields(widgets.WidgetsList):
        name = widgets.TextField(validator=validators.String(not_empty=True))
        comment = widgets.TextField(validator=validators.String())

    form = widgets.TableForm(name="form",
                             fields=[
                                 widgets.RepeatingFieldSet(
                                     name="repeat",
                                     fields=MyFields(),
                                     repetitions=repetitions)
                             ])

    class MyRoot(turbogears.controllers.RootController):
        def test(self):
            return dict(form=form)

        test = turbogears.expose(template=".form")(test)

        def test_value(self):
            value = dict(repeat=[{
                'name': 'foo',
                'comment': 'hello'
            }, None, None, {
                'name': 'bar',
                'comment': 'byebye'
            }])
            return dict(form=form, value=value)

        test_value = turbogears.expose(template=".form")(test_value)

        def test_validation(self):
            return dict(form=form)

        test_validation = turbogears.expose(template=".form")(test_validation)
        test_validation = turbogears.validate(form=form)(test_validation)
        test_validation = turbogears.error_handler(test_validation)(
            test_validation)

    cherrypy.root = MyRoot()
    testutil.create_request("/test")
    output = cherrypy.response.body[0].lower()
    for i in range(repetitions):
        assert 'id="form_repeat_%i"' % i in output
        assert 'name="repeat-%i.name"' % i in output
        assert 'id="form_repeat_%i_name"' % i in output
        assert 'name="repeat-%i.comment"' % i in output
        assert 'id="form_repeat_%i_comment"' % i in output

    cherrypy.root = MyRoot()
    testutil.create_request("/test_value")
    output = cherrypy.response.body[0].lower()
    name_p = 'name="repeat-0.name"'
    value_p = 'value="foo"'
    assert (re.compile('.*'.join([value_p, name_p])).search(output)
            or re.compile('.*'.join([name_p, value_p])).search(output))
    name_p = 'name="repeat-0.comment"'
    value_p = 'value="hello"'
    assert (re.compile('.*'.join([value_p, name_p])).search(output)
            or re.compile('.*'.join([name_p, value_p])).search(output))
    name_p = 'name="repeat-3.name"'
    value_p = 'value="bar"'
    assert (re.compile('.*'.join([value_p, name_p])).search(output)
            or re.compile('.*'.join([name_p, value_p])).search(output))
    name_p = 'name="repeat-3.comment"'
    value_p = 'value="byebye"'
    assert (re.compile('.*'.join([value_p, name_p])).search(output)
            or re.compile('.*'.join([name_p, value_p])).search(output))
    name_p = 'name="repeat-1.name"'
    value_p = 'value=""'
    assert (re.compile('.*'.join([value_p, name_p])).search(output)
            or re.compile('.*'.join([name_p, value_p])).search(output))
    name_p = 'name="repeat-1.comment"'
    value_p = 'value=""'
    assert (re.compile('.*'.join([value_p, name_p])).search(output)
            or re.compile('.*'.join([name_p, value_p])).search(output))

    cherrypy.root = MyRoot()
    testutil.create_request("/test_validation?repeat-0.name=foo&repeat-1.name="
                            "&repeat-2.name=bar&repeat-3.name=&repeat-4.name=")
    output = cherrypy.response.body[0].lower()
    validation_errors = cherrypy.request.validation_errors
    assert validation_errors.has_key("repeat")
    assert isinstance(validation_errors["repeat"], list)
    assert validation_errors["repeat"][0] is None
    assert validation_errors["repeat"][1].has_key("name")
    assert validation_errors["repeat"][2] is None
    assert validation_errors["repeat"][3].has_key("name")
    assert validation_errors["repeat"][4].has_key("name")
import turbogears
import cherrypy
from turbogears import widgets
from turbogears import controllers
from turbogears import validators
from turbogears import testutil

myform = widgets.TableForm(fields = [
    widgets.FieldSet(
        name = "p_data",
        fields = [
            widgets.TextField(name="name"),
            widgets.TextField(name="age",
                validator=validators.Int()),
        ]),
])

class MyRoot(controllers.RootController):
    def testform(self, p_data, tg_errors=None):
        if tg_errors:
            self.has_errors = True
        self.name = p_data['name']
        self.age = p_data['age']
    testform = turbogears.validate(form=myform)(testform)
    testform = turbogears.expose(template="turbogears.tests.othertemplate")(
                                 testform)

    def set_errors(self):
        self.has_errors = True

    def testform_new_style(self, p_data):
Exemplo n.º 23
0
class Jobs(RPCRoot):
    # For XMLRPC methods in this class.
    exposed = True
    job_list_action_widget = JobActionWidget()
    job_page_action_widget = JobPageActionWidget()
    recipeset_widget = RecipeSetWidget()
    recipe_widget = RecipeWidget()
    priority_widget = PriorityWidget(
    )  #FIXME I have a feeling we don't need this as the RecipeSet widget declares an instance of it
    product_widget = ProductWidget()
    retention_tag_widget = RetentionTagWidget()
    job_type = {'RS': RecipeSet, 'J': Job}
    whiteboard_widget = JobWhiteboard()

    hidden_id = widgets.HiddenField(name='id')
    confirm = widgets.Label(name='confirm',
                            default="Are you sure you want to cancel?")
    message = widgets.TextArea(name='msg',
                               label=_(u'Reason?'),
                               help_text=_(u'Optional'))

    _upload = widgets.FileField(name='filexml', label='Job XML')
    form = HorizontalForm('jobs',
                          fields=[_upload],
                          action='save_data',
                          submit_text=_(u'Submit Data'))
    del _upload

    cancel_form = widgets.TableForm('cancel_job',
                                    fields=[hidden_id, message, confirm],
                                    action='really_cancel',
                                    submit_text=_(u'Yes'))

    job_form = JobForm()

    job_schema_doc = lxml.etree.parse(
        pkg_resources.resource_stream('bkr.common', 'schema/beaker-job.rng'))

    @classmethod
    def success_redirect(cls, id, url='/jobs/mine', *args, **kw):
        flash(_(u'Success! job id: %s' % id))
        redirect('%s' % url)

    @expose(template='bkr.server.templates.form-post')
    @identity.require(identity.not_anonymous())
    def new(self, **kw):
        return dict(
            title='New Job',
            form=self.form,
            action='./clone',
            options={},
            value=kw,
        )

    def _check_job_deletability(self, t_id, job):
        if not isinstance(job, Job):
            raise TypeError('%s is not of type %s' % (t_id, Job.__name__))
        if not job.can_delete(identity.current.user):
            raise BeakerException(
                _(u'You do not have permission to delete %s' % t_id))

    def _delete_job(self, t_id):
        job = TaskBase.get_by_t_id(t_id)
        self._check_job_deletability(t_id, job)
        Job.delete_jobs([job])
        return [t_id]

    @expose()
    @identity.require(identity.not_anonymous())
    @restrict_http_method('post')
    def delete_job_page(self, t_id):
        try:
            self._delete_job(t_id)
            flash(_(u'Succesfully deleted %s' % t_id))
        except (BeakerException, TypeError):
            flash(_(u'Unable to delete %s' % t_id))
            redirect('.')
        redirect('./mine')

    @expose()
    @identity.require(identity.not_anonymous())
    @restrict_http_method('post')
    def delete_job_row(self, t_id):
        try:
            self._delete_job(t_id)
            return [t_id]
        except (BeakerException, TypeError), e:
            log.debug(str(e))
            response.status = 400
            return ['Unable to delete %s' % t_id]
Exemplo n.º 24
0
import cherrypy
from turbogears import widgets, config, controllers, expose, mochikit, \
    validate, validators, testutil


class MyFormFields(widgets.WidgetsList):
    #XXX: Since allow_extra_fields should be removed from validators.Schema,
    #     we need a validator for every input-expecting widget
    name = widgets.TextField(validator=validators.String())
    age = widgets.TextField(validator=validators.Int(), default=0)
    date = widgets.CalendarDatePicker(validator=validators.DateConverter(
        if_empty=datetime.now()))


myfields = MyFormFields()
myform = widgets.TableForm(fields=myfields)


class MyRoot(controllers.RootController):

    [expose(template="turbogears.tests.form")]

    def index(self):
        return dict(form=myform)

    [expose(template="turbogears.tests.form")]

    def fields(self):
        myfields.display = lambda **kw: kw.values()
        return dict(form=myfields)
Exemplo n.º 25
0
def test_javascriptsets():
    """JavaScripts are only added once"""
    form = widgets.TableForm(fields=[w1("foo"), w2("bar")])
    assert len(form.retrieve_javascript()) == 3
Exemplo n.º 26
0
def test_csssets():
    """CSS references are added once"""
    form = widgets.TableForm(fields=[w1("foo"), w2("bar")])
    assert len(form.retrieve_css()) == 1
Exemplo n.º 27
0
class RecipeSets(RPCRoot):
    # For XMLRPC methods in this class.
    exposed = True

    hidden_id = widgets.HiddenField(name='id')
    confirm = widgets.Label(name='confirm',
                            default="Are you sure you want to cancel?")
    message = widgets.TextArea(name='msg',
                               label=_(u'Reason?'),
                               help_text=_(u'Optional'))
    cancel_form = widgets.TableForm('cancel_recipeset',
                                    fields=[hidden_id, message, confirm],
                                    action='really_cancel',
                                    submit_text=_(u'Yes'))

    @identity.require(identity.not_anonymous())
    @expose(template="bkr.server.templates.form")
    def cancel(self, id):
        """
        Confirm cancel recipeset
        """
        try:
            recipeset = RecipeSet.by_id(id)
        except InvalidRequestError:
            flash(_(u"Invalid recipeset id %s" % id))
            redirect("/jobs/%s" % recipeset.job.id)
        if not recipeset.can_cancel(identity.current.user):
            flash(
                _(u"You don't have permission to cancel recipeset id %s" % id))
            redirect("/jobs/%s" % recipeset.job.id)
        return dict(
            title='Cancel RecipeSet %s' % id,
            form=self.cancel_form,
            action='./really_cancel',
            options={},
            value=dict(id=recipeset.id,
                       confirm='really cancel recipeset %s?' % id),
        )

    @identity.require(identity.not_anonymous())
    @expose()
    def really_cancel(self, id, msg=None):
        """
        Confirm cancel recipeset
        """
        try:
            recipeset = RecipeSet.by_id(id)
        except InvalidRequestError:
            flash(_(u"Invalid recipeset id %s" % id))
            redirect("/jobs/%s" % recipeset.job.id)
        if not recipeset.can_cancel(identity.current.user):
            flash(
                _(u"You don't have permission to cancel recipeset id %s" % id))
            redirect("/jobs/%s" % recipeset.job.id)
        recipeset.cancel(msg)
        recipeset.record_activity(user=identity.current.user,
                                  service=u'WEBUI',
                                  field=u'Status',
                                  action=u'Cancelled',
                                  old='',
                                  new='')
        flash(_(u"Successfully cancelled recipeset %s" % id))
        redirect("/jobs/%s" % recipeset.job.id)

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    def stop(self, recipeset_id, stop_type, msg=None):
        """
        Set recipeset status to Completed
        """
        try:
            recipeset = RecipeSet.by_id(recipeset_id)
        except InvalidRequestError:
            raise BX(_('Invalid recipeset ID: %s' % recipeset_id))
        if stop_type not in recipeset.stop_types:
            raise BX(
                _('Invalid stop_type: %s, must be one of %s' %
                  (stop_type, recipeset.stop_types)))
        kwargs = dict(msg=msg)
        return getattr(recipeset, stop_type)(**kwargs)
Exemplo n.º 28
0
def test_ticket272():
    """TextFields with a "name" attribute = "title" should be OK."""
    w = widgets.TableForm(fields=[widgets.TextField(name='title')])
    output = w.render(format='xhtml')
    assert 'value' not in output
Exemplo n.º 29
0
class Recipes(RPCRoot):
    # For XMLRPC methods in this class.
    exposed = True

    hidden_id = widgets.HiddenField(name='id')
    confirm = widgets.Label(
        name='confirm', default="Are you sure you want to release the system?")
    return_reservation_form = widgets.TableForm(
        'end_recipe_reservation',
        fields=[hidden_id, confirm],
        action='./really_return_reservation',
        submit_text=_(u'Yes'))

    tasks = RecipeTasks()

    recipe_widget = RecipeWidget()

    log_types = dict(
        R=LogRecipe,
        T=LogRecipeTask,
        E=LogRecipeTaskResult,
    )

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    def by_log_server(self, server, limit=50):
        """
        Returns a list of recipe IDs which have logs stored on the given 
        server. By default, returns at most 50 at a time.

        Only returns recipes where the whole recipe set has completed. Also 
        excludes recently completed recipe sets, since the system may continue 
        uploading logs for a short while until beaker-provision powers it off.
        """
        finish_threshold = datetime.utcnow() - timedelta(minutes=2)
        recipes = Recipe.query.join(Recipe.recipeset)\
                .join(RecipeSet.job)\
                .filter(not_(Job.is_deleted))\
                .filter(RecipeSet.status.in_([s for s in TaskStatus if s.finished]))\
                .filter(not_(RecipeSet.recipes.any(Recipe.finish_time >= finish_threshold)))\
                .filter(Recipe.log_server == server)\
                .limit(limit)
        return [recipe_id for recipe_id, in recipes.values(Recipe.id)]

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    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

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    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

    @cherrypy.expose
    @identity.require(identity.in_group('lab_controller'))
    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

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    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)

    @cherrypy.expose
    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)

    @cherrypy.expose
    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()

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    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)

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    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

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    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

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    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

    @identity.require(identity.not_anonymous())
    @expose()
    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')

    @expose(template="bkr.server.templates.form")
    @identity.require(identity.not_anonymous())
    def return_reservation(self, recipe_id=None):
        """
        End recipe reservation
        """
        if not recipe_id:
            raise BX(_("No recipe id provided!"))

        return dict(
            title='Release reserved system for Recipe %s' % recipe_id,
            form=self.return_reservation_form,
            action='./really_return_reservation',
            options={},
            value=dict(id=recipe_id),
        )

    @cherrypy.expose
    @identity.require(identity.not_anonymous())
    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

    @cherrypy.expose
    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 _recipe_search(self, recipe, **kw):
        recipe_search = search_utility.Recipe.search(recipe)
        for search in kw['recipesearch']:
            col = search['table']
            try:
                recipe_search.append_results(search['value'], col,
                                             search['operation'], **kw)
            except KeyError, e:
                logger.error(e)
                return recipe_search.return_results()

        return recipe_search.return_results()
Exemplo n.º 30
0
            r'^[^\x00-\x09\x0B-\x0C\x0E-\x1F\x21-\x2F\x3A-\x3C\x3F-\x40\x5B-\x5E\x60\x7B\x7D-\x7F]*$'
        ))
    enzyme = validators.OneOf([
        "Chymotrypsin", "Chymotrypsin Low Specificity", "Trypsin",
        "Pepsin (ph = 1.3)", "Pepsin (ph >= 2.0)"
    ])
    misses = validators.Int(if_empty=0, min=0, max=50)
    minlen = validators.Int(if_empty=0, min=0)
    maxlen = validators.Int(if_empty=1000000000, min=0)
    minweight = validators.Int(if_empty=500, min=0)
    maxweight = validators.Int(if_empty=1000000000, min=0)


# Turbogears form creation using input fields and validation schema
input_form = widgets.TableForm(fields=InputFields(),
                               action="digest_submit",
                               submit_text="Digest",
                               validator=InputFieldsSchema())


class Root(controllers.RootController):
    """The root controller of the application."""
    @expose(template="proteindigest.templates.welcome")
    def index(self):
        """"Show the welcome page."""
        # log.debug("Happy TurboGears Controller Responding For Duty")
        return dict(form=input_form)

    @expose(template="proteindigest.templates.digest_submit")
    @expose(template="proteindigest.templates.digest_submitxml",
            as_format='xml',
            format='xml')