source: sage/dsage/dsage.py @ 5818:960d6fda768c

Revision 5818:960d6fda768c, 7.9 KB checked in by William Stein <wstein@…>, 6 years ago (diff)

Give user the option to set the hostname used for the notebook server certificate.

Line 
1"""nodoctests
2Distributed SAGE
3
4AUTHORS:
5    Yi Qiang (yqiang@gmail.com)
6"""
7
8import os
9import subprocess
10from getpass import getuser
11
12import sage.interfaces.cleaner
13from sage.misc.all import SAGE_ROOT
14from sage.dsage.misc.constants import DSAGE_DIR
15
16def spawn(cmd, verbose=True):
17    """
18    Spawns a process and registers it with the SAGE cleaner.
19    """
20   
21    null = open('/dev/null', 'a')
22    proc = '%s/%s' % (SAGE_ROOT + '/local/bin', cmd)
23    process = subprocess.Popen(proc, shell=True, stdout=null, stderr=null)
24    sage.interfaces.cleaner.cleaner(process.pid, cmd)
25    if verbose:             
26        print 'Spawned %s (pid = %s)\n' % (cmd, process.pid)
27
28class DistributedSage(object):
29    r"""
30    Distributed SAGE allows you to do distributed computing in SAGE.
31
32    To get up and running quickly, run dsage.setup() to run the
33    configuration utility.
34
35    Note that configuration files will be stored in the
36    directory \code{\$DOT\_SAGE/dsage}.
37
38    There are three distinct parts of Distributed SAGE:
39        Server
40            Launch the server with dsage.server()
41           
42        Worker
43            Launch the worker with dsage.worker()
44           
45        Client
46            Create the DSage object like this:
47                d = DSage()
48   
49    EXAMPLES:
50    This starts a server instance on localhost:
51   
52        sage: dsage.server()
53
54    The dsage server is currently blocking by default.
55
56    Open another sage instance and type:
57
58        sage: dsage.worker()
59
60    This starts a worker connecting the localhost. By default the worker will
61    connect to localhost and the port the last server started is listening on.
62    All of these settings are configurable via changing
63    \code{\$DOT\_SAGE/dsage/worker.conf}
64
65    Open yet another terminal and type:
66        sage: D = DSage()
67
68    This creates a connection to the remote server.  To do a simple
69    evaluation, type:
70        sage: job1 = D('2+2')
71
72    This sends the job '2+2' to a worker and you can view the
73    result by typing:
74
75        sage: print job1
76
77    This is the most basic way of interacting with dsage. To do more
78    complicated tasks, you should look at the DistributedFunction
79    class.  For example, to do distributed integer factorization with
80    ECM, type this:
81
82        sage: f = DistributedFactor(P, number, name='my_factor')
83        sage: f.start()
84
85    To check the result, do
86
87        sage: print f.result
88
89    To check if it is done, do
90
91        sage: print f.done
92
93    Customization:
94   
95        See the DOT\_SAGE/dsage directory.
96       
97    """
98   
99    def __init__(self):
100        pass
101   
102    def start_all(self, port=8081, workers=2, log_level=0, poll=1.0,
103                  anonymous_workers=False, verbose=True):
104        """
105        Start the server and worker and returns a connection to the server.
106       
107        """
108       
109        from sage.dsage.interface.dsage_interface import BlockingDSage
110       
111        self.server(port=port, log_level=log_level, blocking=False,
112                    verbose=verbose)
113        self.worker(port=port, workers=workers, log_level=log_level,
114                    blocking=False, poll=poll, anonymous=anonymous_workers,
115                    verbose=verbose)
116       
117        import time
118        time.sleep(1)  # Allow the server to start completely before trying
119                       # to connect
120        d = BlockingDSage(server='localhost', port=port)
121       
122        return d
123       
124    def server(self, blocking=True, port=8081, log_level=0, ssl=True,
125               db_file=os.path.join(DSAGE_DIR, 'db', 'dsage.db'),
126               log_file=os.path.join(DSAGE_DIR, 'server.log'),
127               privkey=os.path.join(DSAGE_DIR, 'cacert.pem'),
128               cert=os.path.join(DSAGE_DIR, 'pubcert.pem'),
129               stats_file=os.path.join(DSAGE_DIR, 'dsage.xml'),
130               anonymous_logins=False,
131               verbose=True):
132        r"""
133        Run the Distributed SAGE server.
134       
135        Doing \code{dsage.server()} will spawn a server process which
136        listens by default on port 8081.
137
138        INPUT:
139            blocking -- boolean (default: True) -- if False the dsage
140                        server will run and you'll still be able to
141                        enter commands at the command prompt (though
142                        logging will make this hard).
143            logfile  -- only used if blocking=True; the default is
144                        to log to $DOT_SAGE/dsage/server.log
145                       
146        """
147       
148        cmd = 'dsage_server.py -d %s -p %s -l %s -f %s ' + \
149                              '-c %s -k %s --statsfile=%s' 
150        cmd = cmd % (db_file, port, log_level, log_file, cert, privkey,
151                     stats_file)
152        if ssl:
153            cmd += ' --ssl'
154        if not blocking:
155            cmd += ' --noblock'
156            spawn(cmd, verbose=verbose)
157        else:
158            os.system(cmd)
159
160    def worker(self, server='localhost', port=8081, workers=2, poll=1.0,
161               username=getuser(), blocking=True, ssl=True, log_level=0,
162               anonymous=False, priority=20,
163               privkey=os.path.join(DSAGE_DIR, 'dsage_key'),
164               pubkey=os.path.join(DSAGE_DIR, 'dsage_key.pub'),
165               log_file=os.path.join(DSAGE_DIR, 'worker.log'),
166               verbose=True):
167        r"""
168        Run the Distributed SAGE worker.
169
170        Typing \code{sage.worker()} will launch a worker which by
171        default connects to localhost on port 8081 to fetch jobs.
172       
173        INPUT:
174            server -- (string, default: None) the server you want to
175                      connect to if None, connects to the server
176                      specified in .sage/dsage/worker.conf
177            port -- (integer, default: None) the port that the server
178                      listens on for workers.
179            blocking -- (bool, default: True) whether or not to make a
180                        blocking connection.
181            logfile -- only used if blocking=True; the default is
182                       to log to $DOT_SAGE/dsage/worker.log
183            poll -- rate at which the worker pings the server to check for new
184                    jobs, this value will increase if the server has no jobs
185        """
186       
187        cmd = 'dsage_worker.py -s %s -p %s -u %s -w %s --poll %s -l %s -f %s ' + \
188                               '--privkey=%s --pubkey=%s --priority=%s '
189        cmd = cmd % (server, port, username, workers, poll, log_level,
190                     log_file, privkey, pubkey, priority)
191       
192        if ssl:
193            cmd += ' --ssl'
194        if anonymous:
195            cmd += ' -a'
196        if not blocking:
197            cmd += ' --noblock'
198            spawn(cmd, verbose=verbose)
199        else:
200            os.system(cmd)
201           
202    def setup(self, template=None):
203        r"""
204        This is the setup utility which helps you configure dsage.
205
206        Type \code{dsage.setup()} to run the configuration for the server,
207        worker and client.  Alternatively, if you want to run the
208        configuration for just one parts, you can launch
209        \code{dsage.setup_server()}, \code{dsage.setup\_worker()}
210        or \code{dsage.setup()}.
211       
212        """
213       
214        from sage.dsage.scripts.dsage_setup import setup       
215        setup(template=template)
216   
217    def setup_server(self, *args):
218        """
219        This method runs the configuration utility for the server.
220       
221        """
222       
223        from sage.dsage.scripts.dsage_setup import setup_server
224        setup_server(*args)
225
226    def setup_worker(self):
227        """
228        This method runs the configuration utility for the worker.
229       
230        """
231       
232        from sage.dsage.scripts.dsage_setup import setup_worker
233        setup_worker()
234
235    def setup_client(self):
236        """
237        This method runs the configuration utility for the client.
238       
239        """
240       
241        from sage.dsage.scripts.dsage_setup import setup_client
242        setup_client()
243
244dsage = DistributedSage()
Note: See TracBrowser for help on using the repository browser.