summaryrefslogtreecommitdiffstats
path: root/funcweb/funcweb/controllers.py
blob: 2b2c98844c7a8e841d91677746b5bb90086127c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
import logging
log = logging.getLogger(__name__)

from turbogears import controllers, expose, flash, identity, redirect, error_handler,validate
from func.overlord.client import Overlord, Minions
from funcweb.widget_automation import WidgetListFactory,RemoteFormAutomation,RemoteFormFactory
from funcweb.widget_validation import WidgetSchemaFactory

# it is assigned into method_display on every request 
global_form = None 

def validate_decorator_updater(validator_value=None):
    """
    When we pass the global_form directly to 
    turbogears.validate it is not updated on 
    every request we should pass a callable
    to trigger it ;)

    @param :validator_value : Does nothing in the code
    of validate it is passed but is irrelevant in our case
    because we compute the global_form in the method_display

    @return : the current form and schema to validate the
    current input in cherrypy's request 
    """
    global global_form
    return global_form

class Root(controllers.RootController):
    
    
    #will be reused for widget validation

    @expose(template="funcweb.templates.minions")
    #@identity.require(identity.not_anonymous())
    def minions(self, glob='*'):
        """ Return a list of our minions that match a given glob """
        return dict(minions=Minions(glob).get_all_hosts())

    index = minions # start with our minion view, for now

    @expose(template="funcweb.templates.minion")
    #@identity.require(identity.not_anonymous())
    def minion(self, name="*", module=None, method=None):
        """ Display module or method details for a specific minion.

        If only the minion name is given, it will display a list of modules
        for that minion.  If a module is supplied, it will display a list of
        methods.  If a method is supplied, it will display a method execution
        form.
        """
        fc = Overlord(name)
        if not module: # list all modules
            #just list those who have get_method_args
            modules = fc.system.list_modules()
            display_modules = []
            #FIXME slow really i know !
            for module in modules.itervalues():
                for mod in module:
                    #if it is not empty
                    if getattr(fc,mod).get_method_args()[name]:
                        display_modules.append(mod)
            modules = {}
            modules[name]=display_modules
            
            return dict(modules=modules)
        else: # a module is specified
            if method: # minion.module.method specified; bring up execution form
                return dict(minion=name, module=module, method=method,
                            tg_template="funcweb.templates.method")
            else: # return a list of methods for specified module
                modules = getattr(fc, module).list_methods()
                return dict(modules=modules, module=module,
                            tg_template="funcweb.templates.module")


    @expose(template="funcweb.templates.method_args")
    #@identity.require(identity.not_anonymous())
    def method_display(self,minion=None,module=None,method=None):
        
        global global_form
        fc = Overlord(minion)
        method_args = getattr(fc,module).get_method_args()
        
        if not method_args.values():
            print "Not registered method here"
            return dict(minion_form = None,minion=minion,module=module,method=method)

        minion_arguments = method_args[minion][method]['args']
        if minion_arguments:
            wlist_object = WidgetListFactory(minion_arguments,minion=minion,module=module,method=method)
            wlist_object = wlist_object.get_widgetlist_object()
            #create the validation parts for the remote form
            wf = WidgetSchemaFactory(minion_arguments)
            schema_man=wf.get_ready_schema()

            #create the final form
            minion_form = RemoteFormAutomation(wlist_object,schema_man)
            global_form = minion_form.for_widget
            #print global_form
            #i use that when something goes wrong to check the problem better to stay here ;)
            #self.minion_form =RemoteFormFactory(wlist_object,schema_man).get_remote_form()
            
            del wlist_object
            del minion_arguments

            return dict(minion_form =minion_form,minion=minion,module=module,method=method)
        else:
            return dict(minion_form = None,minion=minion,module=module,method=method)



    @expose(template="funcweb.templates.login")
    def login(self, forward_url=None, previous_url=None, *args, **kw):
        from cherrypy import request, response
        if not identity.current.anonymous \
            and identity.was_login_attempted() \
            and not identity.get_identity_errors():
            raise redirect(forward_url)

        forward_url=None
        previous_url= request.path

        if identity.was_login_attempted():
            msg=_("The credentials you supplied were not correct or "
                   "did not grant access to this resource.")
        elif identity.get_identity_errors():
            msg=_("You must provide your credentials before accessing "
                   "this resource.")
        else:
            msg=_("Please log in.")
            forward_url= request.headers.get("Referer", "/")

        response.status=403
        return dict(message=msg, previous_url=previous_url, logging_in=True,
                    original_parameters=request.params,
                    forward_url=forward_url)
        
    
    @expose() 
    def handle_minion_error(self,tg_errors=None):
        """
        The method checks the result from turbogears.validate
        decorator so if it has the tg_errors we know that the
        form validation is failed. That prevents the extra traffic
        to be sent to the minions!
        """
        if tg_errors:
            #print tg_errors
            return str(tg_errors)
        

    @expose(allow_json=True)
    @error_handler(handle_minion_error)
    @validate(form=validate_decorator_updater)
    def post_form(self,**kw):
        """
        Data processing part
        """
        if kw.has_key('minion') and kw.has_key('module') and kw.has_key('method'):
            #assign them because we need the rest so dont control everytime
            #and dont make lookup everytime ...
            minion = kw['minion']
            del kw['minion']
            module = kw['module']
            del kw['module']
            method = kw['method']
            del kw['method']
            
            #everytime we do that should be a clever way for that ???
            fc = Overlord(minion)
            #get again the method args to get their order :
            arguments=getattr(fc,module).get_method_args()
            #so we know the order just allocate and put them there 
            cmd_args=['']*(len(kw.keys()))
            
            for arg in kw.keys():
                #wow what a lookup :)
                index_of_arg = arguments[minion][method]['args'][arg]['order']
                cmd_args[index_of_arg]=kw[arg]
           
            #now execute the stuff
            result = getattr(getattr(fc,module),method)(*cmd_args)
            return str(result)

        else:
            return "Missing arguments sorry can not proceess the form"
    
    @expose(template="funcweb.templates.method_args")
    def execute_link(self,minion=None,module=None,method=None):
        """
        Method is fot those minion methods that dont accept any 
        arguments so they provide only some information,executed
        by pressing only the link !
        """
        fc = Overlord(minion)
        result = getattr(getattr(fc,module),method)()
        return str(result)



    @expose()
    def logout(self):
        identity.current.logout()
        raise redirect("/")