KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > clif > deploy > Deployer


1 /*
2 * CLIF is a Load Injection Framework
3 * Copyright (C) 2004 France Telecom R&D
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * CLIF $Name: $
20 *
21 * Contact: clif@objectweb.org
22 */

23
24 package org.objectweb.clif.deploy;
25
26 import org.objectweb.clif.supervisor.api.ClifException;
27 import org.objectweb.clif.supervisor.api.BladeState;
28 import org.objectweb.clif.supervisor.api.SupervisorInfo;
29 import org.objectweb.clif.supervisor.api.TestControl;
30 import org.objectweb.clif.supervisor.lib.BladeObservation;
31 import org.objectweb.clif.storage.api.StorageProxyAdmin;
32 import org.objectweb.clif.server.api.ClifServerControl;
33 import org.objectweb.clif.server.api.BladeControl;
34 import org.objectweb.clif.datacollector.api.DataCollectorAdmin;
35 import org.objectweb.clif.util.ItfName;
36 import org.objectweb.fractal.api.control.BindingController;
37 import org.objectweb.fractal.api.control.LifeCycleController;
38 import org.objectweb.fractal.api.control.IllegalLifeCycleException;
39 import org.objectweb.fractal.api.control.ContentController;
40 import org.objectweb.fractal.api.Component;
41 import org.objectweb.fractal.api.NoSuchInterfaceException;
42 import org.objectweb.fractal.api.type.ComponentType;
43 import org.objectweb.fractal.util.Fractal;
44 import org.objectweb.fractal.adl.FactoryFactory;
45 import org.objectweb.fractal.rmi.registry.NamingService;
46 import org.objectweb.fractal.rmi.registry.Registry;
47 import org.objectweb.util.monolog.api.BasicLevel;
48 import org.objectweb.util.monolog.api.Logger;
49 import org.objectweb.util.monolog.Monolog;
50 import java.util.Map JavaDoc;
51 import java.util.Iterator JavaDoc;
52 import java.util.HashMap JavaDoc;
53 import java.util.Observable JavaDoc;
54 import java.util.Stack JavaDoc;
55
56
57 /**
58  *
59  * @author Bruno Dillenseger
60  */

61 public class Deployer extends Observable JavaDoc
62 {
63     static protected Logger log = Monolog.getDefaultMonologFactory().getLogger(Deployer.class.getName());
64
65
66     protected NamingService registry;
67     protected Component clifApp;
68     protected Component storage;
69     protected Component supervisor;
70     /** clif application static components indexed by their name (storage, supervisor, analyser) */
71     protected Map JavaDoc components = new HashMap JavaDoc();
72     protected BindingController storageBc;
73     protected BindingController supervisorBc;
74     protected LifeCycleController clifAppLfc;
75     protected ContentController clifAppCc;
76     protected ComponentType bladeType;
77     /** contains bound clif servers components, indexed by their names */
78     private Map JavaDoc serversComp = new HashMap JavaDoc();
79
80
81     /**
82      * Creates a new test plan deployer, creating a RMI registry with default parameters
83      * (as specified by system properties fractal.registry.host and fractal.registry.port)
84      */

85     public Deployer()
86     {
87         this(null, true);
88     }
89
90
91     /**
92      * Creates a new test plan deployer, using the default RMI registry (as specified by
93      * system properties fractal.registry.host and fractal.registry.port)
94      * @param createRegistry if true, a FractalRMI registry is created on localhost using
95      * default port; if false, the registry is supposed to be running already on the default host
96      * and port.
97      */

98     public Deployer(boolean createRegistry)
99     {
100         this(null, createRegistry);
101     }
102
103
104     /**
105      * Creates a new test plan deployer, using the given registry or creating a new one.
106      * @param registry the RMI registry to be used. If null, a registry is created on localhost
107      * using default port (see system properties fractal.registry.port and fractal.registry.host).
108      */

109     public Deployer(NamingService registry)
110     {
111         this(registry, true);
112     }
113
114
115     /**
116      * Main constructor for test plan deployers.
117      * @param registry Fractal RMI registry to be used if not null
118      * @param createRegistry if parameter registry is null, indicates whether a new registry
119      * should be created or not (if not, a registry is supposed to be running). In both cases,
120      * default settings apply for registry host and port number according to system properties
121      * fractal.registry.host and fractal.registry.port.
122      */

123     private Deployer(NamingService registry, boolean createRegistry)
124     {
125         // 1st step: get a FractalRMI registry
126
try
127         {
128             new org.objectweb.clif.supervisor.lib.CodeServer(Integer.parseInt(System.getProperty("clif.codeserver.port", "1357")));
129         }
130         catch (Exception JavaDoc ex)
131         {
132             log.log(BasicLevel.WARN, "could not start the code server - deployment may fail", ex);
133         }
134         if (registry == null)
135         {
136             int port = Registry.DEFAULT_PORT;
137             String JavaDoc portStr = System.getProperty("fractal.registry.port");
138             if (portStr != null)
139             {
140                 try
141                 {
142                     port = Integer.parseInt(portStr);
143                     log.log(BasicLevel.INFO, "using port number " + port + " for FractalRMI registry");
144                 }
145                 catch (Exception JavaDoc ex)
146                 {
147                     log.log(
148                         BasicLevel.WARN,
149                         "invalid port number " + portStr
150                         + " for RMI registry; using default port number " + port);
151                 }
152             }
153             if (createRegistry)
154             {
155                 try
156                 {
157                     Registry.createRegistry(port);
158                     registry = Registry.getRegistry("localhost", port);
159                 }
160                 catch (Exception JavaDoc ex)
161                 {
162                     throw new Error JavaDoc("Cannot create a Fractal registry", ex);
163                 }
164             }
165             else
166             {
167                 try
168                 {
169                     registry = Registry.getRegistry(
170                         System.getProperty("fractal.registry.host", "localhost"),
171                         port);
172                 }
173                 catch (Exception JavaDoc ex)
174                 {
175                     throw new Error JavaDoc("Cannot get a Fractal registry", ex);
176                 }
177             }
178         }
179         this.registry = registry;
180         // 2nd step: create a Clif Application and gets useful component and controllers
181
try
182         {
183             clifApp = (Component)FactoryFactory.getFactory(FactoryFactory.FRACTAL_BACKEND
184                 ).newComponent("org.objectweb.clif.console.lib.ClifApp", null);
185             bladeType = (ComponentType)FactoryFactory.getFactory(FactoryFactory.FRACTAL_BACKEND
186                 ).newComponentType("org.objectweb.clif.server.api.BladeType", null);
187             Component[] subComp = Fractal.getContentController(clifApp).getFcSubComponents();
188             for (int i=0 ; i<subComp.length ; ++i)
189             {
190                 components.put(Fractal.getNameController(subComp[i]).getFcName(), subComp[i]);
191                 if (Fractal.getNameController(subComp[i]).getFcName().equals("storage"))
192                 {
193                     storage = subComp[i];
194                 }
195                 else if (Fractal.getNameController(subComp[i]).getFcName().equals("supervisor"))
196                 {
197                     supervisor = subComp[i];
198                 }
199             }
200             storageBc = Fractal.getBindingController(storage);
201             supervisorBc = Fractal.getBindingController(supervisor);
202             clifAppLfc = Fractal.getLifeCycleController(clifApp);
203             clifAppCc = Fractal.getContentController(clifApp);
204             clifAppLfc.startFc();
205         }
206         catch (Exception JavaDoc ex)
207         {
208             throw new Error JavaDoc("Could not create CLIF deployer: bad component configuration", ex);
209         }
210     }
211
212
213     /**
214      * Asynchronously deploys blades according to the given definitions, deploying Clif servers
215      * when necessary (i.e. when not already deployed in a previous test plan),
216      * and creates a Supervisor component to control the new test plan. The TestControl interface
217      * of this supervisor, or a ClifException, will be sent to the deployer observers in a
218      * DeployObservation object.
219      * Deployment is aborted as soon as one Clif server or blade deployment fails.
220      * Old blades that may have been previously deployed by this supervisor are removed.
221      * @param definitions a Map containing test plan definitions, indexed by a String blade identifier
222      * The reply may also be a ClifException if a Clif server or a blade could not be deployed.
223      * @see org.objectweb.clif.deploy.DeployDefinition
224      * @see org.objectweb.clif.deploy.DeployObservation
225      * @see org.objectweb.clif.supervisor.api.ClifException
226      */

227     public void deploy(Map JavaDoc definitions)
228     {
229         DeployThread deployerThr = new DeployThread(definitions);
230         deployerThr.start();
231     }
232
233
234     /**
235      * @return an array of the names of all available servers (i.e. Fractal seeds registered in the
236      * FractalRMI Registry)
237      */

238     public String JavaDoc[] getServers()
239     {
240         return registry.list();
241     }
242
243
244     /**
245      * @return the FractalRMI naming service used by this deployer
246      */

247     public NamingService getRegistry()
248     {
249         return registry;
250     }
251
252
253     /**
254      * @param name the name of the component to find
255      * @return the reference of a component contained by the Clif Application whose name equals the
256      * String passed as parameter, or null if there is no such component.
257      */

258     public Component getComponentByName(String JavaDoc name)
259     {
260         return (Component)components.get(name);
261     }
262
263
264
265     //////////////////////////////////////////////////////////
266
// inner class for asynchronously deploying a test plan //
267
//////////////////////////////////////////////////////////
268

269
270     class DeployThread extends Thread JavaDoc
271     {
272         Map JavaDoc definitions;
273
274
275         DeployThread(Map JavaDoc testPlan)
276         {
277             super("Deployer thread");
278             this.definitions = testPlan;
279         }
280
281
282         public void run()
283         {
284             Iterator JavaDoc list;
285             DeployObservation result = null;
286             // step 1: remove existing blades
287
try
288             {
289                 Deployer.this.clifAppLfc.stopFc();
290                 String JavaDoc[] itfNames;
291                 itfNames = Deployer.this.storageBc.listFc();
292                 for (int i=0 ; i<itfNames.length ; ++i)
293                 {
294                     if (itfNames[i].startsWith(StorageProxyAdmin.STORAGEPROXY_ADMIN))
295                     {
296                         Deployer.this.storageBc.unbindFc(itfNames[i]);
297                     }
298                 }
299                 itfNames = Deployer.this.supervisorBc.listFc();
300                 for (int i=0 ; i<itfNames.length ; ++i)
301                 {
302                     if (itfNames[i].startsWith(DataCollectorAdmin.DATA_COLLECTOR_ADMIN)
303                         || itfNames[i].startsWith(BladeControl.BLADE_CONTROL))
304                     {
305                         Deployer.this.supervisorBc.unbindFc(itfNames[i]);
306                     }
307                 }
308                 Stack JavaDoc pendingRemoval = new Stack JavaDoc();
309                 Iterator JavaDoc iter = serversComp.values().iterator();
310                 while (iter.hasNext())
311                 {
312                     BladeRemove removeThr = new BladeRemove(
313                         clifApp,
314                         (ClifServerControl)((Component)iter.next()).getFcInterface(
315                             ClifServerControl.CLIF_SERVER_CONTROL));
316                     removeThr.start();
317                     pendingRemoval.push(removeThr);
318                 }
319                 while (! pendingRemoval.empty())
320                 {
321                     ((BladeRemove)pendingRemoval.pop()).join();
322                 }
323             }
324             catch (Exception JavaDoc ex)
325             {
326                 result = new DeployObservation(
327                     false,
328                     new Error JavaDoc("Aborted deployment: cannot remove existing blades", ex));
329             }
330             if (result == null && definitions != null)
331             {
332                 // step 2: enforce deployment of (i.e. create missing) CLIF servers
333
Map JavaDoc bladesById = new HashMap JavaDoc();
334                 Map JavaDoc pendingServers = new HashMap JavaDoc();
335                 list = definitions.values().iterator();
336                 while (list.hasNext())
337                 {
338                     String JavaDoc serverName = ((DeployDefinition)list.next()).getServerName();
339                     if (! Deployer.this.serversComp.containsKey(serverName)
340                         && ! pendingServers.containsKey(serverName))
341                     {
342                         ServerDeploy deployThr = new ServerDeploy(Deployer.this.registry.lookup(serverName));
343                         pendingServers.put(serverName, deployThr);
344                         deployThr.start();
345                     }
346                 }
347                 list = pendingServers.keySet().iterator();
348                 while (list.hasNext() && result == null)
349                 {
350                     String JavaDoc name = (String JavaDoc)list.next();
351                     Component server = ((ServerDeploy)pendingServers.get(name)).get();
352                     if (server != null)
353                     {
354                         try
355                         {
356                             Fractal.getLifeCycleController(server).startFc();
357                             Deployer.this.serversComp.put(name, server);
358                         }
359                         catch (NoSuchInterfaceException ex)
360                         {
361                             setChanged();
362                             result = new DeployObservation(
363                                 false,
364                                 new Error JavaDoc(
365                                     "Configuration error: can't get Clif Server LifeCycleController interface",
366                                     ex));
367                         }
368                         catch (IllegalLifeCycleException ex)
369                         {
370                             result = new DeployObservation(
371                                 false,
372                                 new ClifException(
373                                     "deployment aborted: unable to start CLIF server on " + name,
374                                     ex));
375                         }
376                     }
377                     else
378                     {
379                         String JavaDoc message = "Deployment aborted (can't deploy a Clif server in Fractal seed " + name + ")";
380                         Deployer.this.log.log(BasicLevel.ERROR, message);
381                         result = new DeployObservation(false, new ClifException(message));
382                     }
383                 }
384                 // step 3: deploy blades
385
if (result == null)
386                 {
387                     Map JavaDoc pendingBlades = new HashMap JavaDoc();
388                     list = definitions.entrySet().iterator();
389                     while (list.hasNext() && result == null)
390                     {
391                         try
392                         {
393                             Map.Entry JavaDoc entry = (Map.Entry JavaDoc)list.next();
394                             DeployDefinition def = (DeployDefinition)entry.getValue();
395                             String JavaDoc key = (String JavaDoc)entry.getKey();
396                             BladeDeploy deployThr = new BladeDeploy(
397                                 Deployer.this.clifApp,
398                                 def.getAdlDefinition(),
399                                 def.getContext(),
400                                 (ClifServerControl)((Component)Deployer.this.serversComp.get(def.getServerName()))
401                                     .getFcInterface(ClifServerControl.CLIF_SERVER_CONTROL),
402                                 key);
403                             pendingBlades.put(key, deployThr);
404                             deployThr.start();
405                             Deployer.this.setChanged();
406                             Deployer.this.notifyObservers(new BladeObservation(key, BladeState.DEPLOYING));
407                         }
408                         catch (NoSuchInterfaceException ex)
409                         {
410                             String JavaDoc message = "Fatal error in blade deployment: the Clif server type mismatch";
411                             Deployer.this.log.log(BasicLevel.FATAL, message, ex);
412                             result = new DeployObservation(
413                                 false,
414                                 new Error JavaDoc(message, ex));
415                         }
416                     }
417                     try
418                     {
419                         list = pendingBlades.entrySet().iterator();
420                         while (list.hasNext() && result == null)
421                         {
422                             Map.Entry JavaDoc entry = (Map.Entry JavaDoc)list.next();
423                             String JavaDoc key = (String JavaDoc)entry.getKey();
424                             Component blade = ((BladeDeploy)entry.getValue()).get();
425                             if (blade != null)
426                             {
427                                 BladeControl bladeCtl = (BladeControl) blade.getFcInterface(
428                                     BladeControl.BLADE_CONTROL);
429                                 Fractal.getBindingController(blade).bindFc(
430                                     SupervisorInfo.SUPERVISOR_INFO,
431                                     Deployer.this.supervisor.getFcInterface(SupervisorInfo.SUPERVISOR_INFO));
432                                 Fractal.getLifeCycleController(blade).startFc();
433                                 bladeCtl.setId(key);
434                                 bladeCtl.setArgument(((DeployDefinition)definitions.get(key)).getArgument());
435                                 Deployer.this.storageBc.bindFc(
436                                     ItfName.gen(StorageProxyAdmin.STORAGEPROXY_ADMIN),
437                                     blade.getFcInterface(StorageProxyAdmin.STORAGEPROXY_ADMIN));
438                                 Deployer.this.supervisorBc.bindFc(
439                                     ItfName.gen(DataCollectorAdmin.DATA_COLLECTOR_ADMIN),
440                                     blade.getFcInterface(DataCollectorAdmin.DATA_COLLECTOR_ADMIN));
441                                 Deployer.this.supervisorBc.bindFc(
442                                     ItfName.gen(BladeControl.BLADE_CONTROL),
443                                     blade.getFcInterface(BladeControl.BLADE_CONTROL));
444                                 bladesById.put(key, blade);
445                                 Deployer.this.setChanged();
446                                 Deployer.this.notifyObservers(new BladeObservation(key, BladeState.DEPLOYED));
447                             }
448                             else
449                             {
450                                 setChanged();
451                                 notifyObservers(new BladeObservation(key, BladeState.UNDEPLOYED));
452                                 String JavaDoc message = "Deployment aborted (blade deployment error)";
453                                 Deployer.this.log.log(BasicLevel.ERROR, message);
454                                 result = new DeployObservation(
455                                     false,
456                                     new ClifException(message));
457                             }
458                         }
459                         if (result == null)
460                         {
461                             Deployer.this.clifAppLfc.startFc();
462                             TestControl supervisorCtl =
463                                 (TestControl)Deployer.this.supervisor.getFcInterface(TestControl.TEST_CONTROL);
464                             supervisorCtl.deleteObservers();
465                             result = new DeployObservation(supervisorCtl);
466                         }
467                     }
468                     catch (Exception JavaDoc ex)
469                     {
470                         result = new DeployObservation(
471                             false,
472                             new ClifException("Deployment failure", ex));
473                     }
474                 }
475             }
476             Deployer.this.setChanged();
477             Deployer.this.notifyObservers(result);
478         }
479     }
480 }
481
Popular Tags