1
/*******************************************************************************
2
*Copyright (c) 2009 Eucalyptus Systems, Inc.
4
* This program is free software: you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation, only version 3 of the License.
9
* This file is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* You should have received a copy of the GNU General Public License along
15
* with this program. If not, see <http://www.gnu.org/licenses/>.
17
* Please contact Eucalyptus Systems, Inc., 130 Castilian
18
* Dr., Goleta, CA 93101 USA or visit <http://www.eucalyptus.com/licenses/>
19
* if you need additional information or have any questions.
21
* This file may incorporate work covered under the following copyright and
24
* Software License Agreement (BSD License)
26
* Copyright (c) 2008, Regents of the University of California
27
* All rights reserved.
29
* Redistribution and use of this software in source and binary forms, with
30
* or without modification, are permitted provided that the following
33
* Redistributions of source code must retain the above copyright notice,
34
* this list of conditions and the following disclaimer.
36
* Redistributions in binary form must reproduce the above copyright
37
* notice, this list of conditions and the following disclaimer in the
38
* documentation and/or other materials provided with the distribution.
40
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
41
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
42
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
43
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
44
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
46
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
47
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
48
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
49
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
50
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF
51
* THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE
52
* LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS
53
* SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
54
* IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA
55
* BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN
56
* THE REGENTS’ DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT
57
* OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR
58
* WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH
59
* ANY SUCH LICENSES OR RIGHTS.
60
*******************************************************************************
61
* @author chris grzegorczyk <grze@eucalyptus.com>
63
package com.eucalyptus.component;
66
import java.util.List;
68
import java.util.NavigableSet;
69
import java.util.NoSuchElementException;
70
import org.apache.log4j.Logger;
71
import org.mule.config.ConfigResource;
72
import com.eucalyptus.bootstrap.BootstrapException;
73
import com.eucalyptus.bootstrap.Bootstrapper;
74
import com.eucalyptus.records.EventRecord;
75
import com.eucalyptus.records.EventType;
76
import com.eucalyptus.records.Record;
77
import com.eucalyptus.util.Exceptions;
78
import com.eucalyptus.util.HasName;
79
import com.eucalyptus.util.NetworkUtil;
80
import com.google.common.collect.Maps;
81
import com.google.common.collect.Sets;
87
public class Component implements ComponentInformation, HasName<Component> {
88
private static Logger LOG = Logger.getLogger( Component.class );
89
public static String DISABLE_PATTERN = "euca.disable.%s";
90
public static String REMOTE_PATTERN = "euca.remote.%s";
91
private final String name;
92
private final com.eucalyptus.bootstrap.Component component;
93
private final Configuration configuration;
94
private ServiceBuilder<ServiceConfiguration> builder;
95
private Lifecycle lifecycle;
96
private Boolean enabled;
97
private Boolean local;
98
private Map<String, Service> services = Maps.newConcurrentHashMap( );
100
Component( String name, URI configFile ) throws ServiceRegistrationException {
102
boolean enabled = false, local = false;
103
if ( System.getProperty( String.format( DISABLE_PATTERN, this.name ) ) == null ) {
105
if ( System.getProperty( String.format( REMOTE_PATTERN, this.name ) ) == null ) {
109
this.enabled = enabled;
111
this.component = initComponent( );
112
if ( configFile != null ) {
113
this.configuration = new Configuration( this, configFile );
114
Components.register( this.configuration );
116
this.configuration = new Configuration( this );
118
this.lifecycle = new Lifecycle( this );
119
Components.register( this.lifecycle );
120
this.builder = new DefaultServiceBuilder( this );
123
public void removeService( final ServiceConfiguration config ) throws ServiceRegistrationException {
124
Service service = this.lookupServiceByHost( config.getHostName( ) );
125
this.builder.fireStop( config );
126
DispatcherFactory.remove( service );
127
Components.deregister( service );
128
EventRecord.caller( Component.class, config.isLocal( ) ? EventType.COMPONENT_SERVICE_STOP : EventType.COMPONENT_SERVICE_STOP, this.getName( ),
129
service.getName( ), service.getUri( ).toString( ) ).info( );
130
this.services.remove( service.getName( ) );
134
* Builds a Service instance for this component using a service configuration created with the specified URI.
136
* @throws ServiceRegistrationException
138
public Service buildService( URI uri ) throws ServiceRegistrationException {
140
ServiceConfiguration config = this.builder.toConfiguration( uri );
141
Service service = new Service( this, config );
142
return this.setupService( config, service );
146
* Builds a Service instance for this component using the provided service configuration.
148
* @throws ServiceRegistrationException
150
public Service buildService( ServiceConfiguration config ) throws ServiceRegistrationException {
152
Service service = new Service( this, config );
153
return this.setupService( config, service );
158
* Builds a Service instance for this component using the local default values.
160
* @throws ServiceRegistrationException
162
public Service buildService( ) throws ServiceRegistrationException {
164
ServiceConfiguration conf = this.builder.toConfiguration( this.getConfiguration( ).getLocalUri( ) );
165
Service service = new Service( this, conf );
166
return this.setupService( conf, service );
169
private Service setupService( ServiceConfiguration config, Service service ) throws ServiceRegistrationException {
170
this.services.put( service.getName( ), service );
171
Components.register( service );
172
EventRecord.caller( Component.class, config.isLocal( ) ? EventType.COMPONENT_SERVICE_INIT : EventType.COMPONENT_SERVICE_INIT, this.getName( ),
173
service.getName( ), service.getUri( ).toString( ) ).info( );
177
public void startService( ServiceConfiguration service ) throws ServiceRegistrationException {
178
EventRecord.caller( Component.class, EventType.COMPONENT_SERVICE_START, this.getName( ), service.getName( ), service.getUri( ).toString( ) ).info( );
179
this.builder.fireStart( service );
180
this.lifecycle.setState( Lifecycles.State.STARTED );
183
private com.eucalyptus.bootstrap.Component initComponent( ) {
185
com.eucalyptus.bootstrap.Component component = com.eucalyptus.bootstrap.Component.valueOf( name );
186
if ( component == null ) {
187
throw BootstrapException.throwError( "Error loading component. Failed to find component named '" + name );
190
} catch ( Exception e ) {
191
throw BootstrapException.throwError( "Error loading component. Failed to find component named '" + name, e );
195
public com.eucalyptus.bootstrap.Component getPeer( ) {
196
return this.component;
199
public String getName( ) {
203
public String toString( ) {
204
Record rec = EventRecord.caller( Component.class, EventType.COMPONENT_INFO, this.getName( ), "enabled", this.isEnabled( ), "local", this.isLocal( ),
205
"state", this.getLifecycle( ).getState( ) );
206
if( this.getConfiguration( ).getResource( ) != null ) {
207
for ( ConfigResource cfg : this.getConfiguration( ).getResource( ).getConfigurations( ) ) {
208
rec.next( ).append( ConfigResource.class, EventType.COMPONENT_INFO, this.getName( ), "->" + cfg.getUrl( ) );
211
for ( Bootstrapper b : this.configuration.getBootstrappers( ) ) {
212
rec.next( ).append( Bootstrapper.class, EventType.COMPONENT_INFO, this.getName( ), "->" + b.getClass( ).getSimpleName( ) );
214
return rec.toString( );
217
public Configuration getConfiguration( ) {
218
return this.configuration;
221
public ServiceBuilder<ServiceConfiguration> getBuilder( ) {
225
public void markRemote( ) {
229
public void markDisabled( ) {
231
this.enabled = false;
234
public Boolean isEnabled( ) {
238
public Boolean isLocal( ) {
243
public int compareTo( Component that ) {
244
return this.getName( ).compareTo( that.getName( ) );
247
public List<ServiceConfiguration> list( ) throws ServiceRegistrationException {
248
return this.builder.list( );
251
public URI getUri( String hostName, Integer port ) {
252
return this.getConfiguration( ).makeUri( hostName, port );
255
public void setBuilder( ServiceBuilder<ServiceConfiguration> builder ) {
256
this.builder = builder;
259
Lifecycle getLifecycle( ) {
260
return this.lifecycle;
263
public Boolean isInitialized( ) {
264
return Lifecycles.State.INITIALIZED.equals( this.getLifecycle( ).getState( ) );
267
public Boolean isRunning( ) {
268
return Lifecycles.State.STARTED.equals( this.getLifecycle( ).getState( ) );
271
public NavigableSet<Service> getServices( ) {
272
return Sets.newTreeSet( this.services.values( ) );
275
public String getState( ) {
276
return this.lifecycle.getState( ).name( );
279
public Service lookupServiceByName( String name ) {
280
Exceptions.ifNullArgument( name );
281
for ( Service s : this.services.values( ) ) {
283
if ( name.equals( s.getServiceConfiguration( ).getName( ) ) ) {
287
throw new NoSuchElementException( "No service found matching name: " + name + " for component: " + this.getName( ) );
290
public Service lookupServiceByHost( String hostName ) {
291
Exceptions.ifNullArgument( hostName );
292
for ( Service s : this.services.values( ) ) {
293
if ( hostName.equals( s.getServiceConfiguration( ).getHostName( ) ) ) {
297
for ( Service s : this.services.values( ) ) {
298
if ( hostName.equals( s.getEndpoint( ).getHost( ) ) ) {
302
if ( NetworkUtil.testLocal( hostName ) ) {
303
hostName = "localhost";
304
for ( Service s : this.services.values( ) ) {
305
if ( hostName.equals( s.getEndpoint( ).getHost( ) ) ) {
310
LOG.error( this.services.values( ) );
311
throw new NoSuchElementException( "No service found matching hostname: " + hostName + " for component: " + this.getName( ) );
314
public Boolean isRunningLocally( ) {
316
for( Service s : this.services.values( ) ) {
322
} catch ( NoSuchElementException ex ) {