~ubuntu-branches/ubuntu/raring/eucalyptus/raring

« back to all changes in this revision

Viewing changes to clc/modules/cluster-manager/src/main/java/com/eucalyptus/cluster/ClusterBuilder.java

  • Committer: Package Import Robot
  • Author(s): Brian Thomason
  • Date: 2011-11-29 13:17:52 UTC
  • mfrom: (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 185.
  • Revision ID: package-import@ubuntu.com-20111129131752-rq31al3ntutv2vvl
Tags: upstream-3.0.999beta1
ImportĀ upstreamĀ versionĀ 3.0.999beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
package com.eucalyptus.cluster;
2
2
 
3
 
import java.io.File;
4
 
import java.io.FileWriter;
5
 
import java.io.IOException;
6
 
import java.net.URI;
7
 
import java.security.KeyPair;
8
 
import java.security.cert.X509Certificate;
9
 
import java.util.List;
10
3
import java.util.NoSuchElementException;
11
4
import org.apache.log4j.Logger;
12
 
import com.eucalyptus.auth.Authentication;
13
 
import com.eucalyptus.auth.ClusterCredentials;
14
 
import com.eucalyptus.auth.Groups;
15
 
import com.eucalyptus.auth.SystemCredentialProvider;
16
 
import com.eucalyptus.auth.X509Cert;
17
 
import com.eucalyptus.auth.crypto.Certs;
18
 
import com.eucalyptus.auth.crypto.Hmacs;
19
 
import com.eucalyptus.auth.principal.Authorization;
20
 
import com.eucalyptus.auth.principal.AvailabilityZonePermission;
21
 
import com.eucalyptus.auth.principal.Group;
22
 
import com.eucalyptus.auth.util.PEMFiles;
23
 
import com.eucalyptus.bootstrap.Component;
24
 
import com.eucalyptus.component.Components;
25
 
import com.eucalyptus.component.DatabaseServiceBuilder;
26
 
import com.eucalyptus.component.DiscoverableServiceBuilder;
 
5
import com.eucalyptus.bootstrap.Handles;
 
6
import com.eucalyptus.component.AbstractServiceBuilder;
 
7
import com.eucalyptus.component.ComponentId;
 
8
import com.eucalyptus.component.ComponentId.ComponentPart;
 
9
import com.eucalyptus.component.ComponentIds;
 
10
import com.eucalyptus.component.Faults;
 
11
import com.eucalyptus.component.Partition;
 
12
import com.eucalyptus.component.Partitions;
27
13
import com.eucalyptus.component.ServiceConfiguration;
28
 
import com.eucalyptus.component.ServiceConfigurations;
29
14
import com.eucalyptus.component.ServiceRegistrationException;
30
 
import com.eucalyptus.config.ClusterConfiguration;
31
 
import com.eucalyptus.config.Configuration;
32
 
import com.eucalyptus.config.Handles;
33
 
import com.eucalyptus.config.RemoteConfiguration;
34
 
import com.eucalyptus.entities.EntityWrapper;
 
15
import com.eucalyptus.component.ServiceUris;
 
16
import com.eucalyptus.component.id.ClusterController;
 
17
import com.eucalyptus.config.DeregisterClusterType;
 
18
import com.eucalyptus.config.DescribeClustersType;
 
19
import com.eucalyptus.config.ModifyClusterAttributeType;
 
20
import com.eucalyptus.config.RegisterClusterType;
35
21
import com.eucalyptus.records.EventRecord;
36
22
import com.eucalyptus.records.EventType;
37
 
import com.eucalyptus.system.SubDirectory;
38
 
import com.eucalyptus.util.EucalyptusCloudException;
39
 
import edu.ucsb.eucalyptus.msgs.DeregisterClusterType;
40
 
import edu.ucsb.eucalyptus.msgs.DescribeClustersType;
41
 
import edu.ucsb.eucalyptus.msgs.RegisterClusterType;
 
23
import com.eucalyptus.records.Logs;
42
24
 
43
 
@DiscoverableServiceBuilder( com.eucalyptus.bootstrap.Component.cluster )
44
 
@Handles( { RegisterClusterType.class, DeregisterClusterType.class, DescribeClustersType.class } )
45
 
public class ClusterBuilder extends DatabaseServiceBuilder<ClusterConfiguration> {
46
 
  private static Logger LOG = Logger.getLogger( ClusterBuilder.class );
 
25
@ComponentPart( ClusterController.class )
 
26
@Handles( { RegisterClusterType.class,
 
27
           DeregisterClusterType.class,
 
28
           DescribeClustersType.class,
 
29
           ModifyClusterAttributeType.class } )
 
30
public class ClusterBuilder extends AbstractServiceBuilder<ClusterConfiguration> {
 
31
  static Logger LOG = Logger.getLogger( ClusterBuilder.class );
 
32
  
 
33
  @Override
 
34
  public Boolean checkAdd( final String partition, final String name, final String host, final Integer port ) throws ServiceRegistrationException {
 
35
    try {
 
36
      final Partition part = Partitions.lookup( this.newInstance( partition, name, host, port ) );
 
37
      part.syncKeysToDisk( );
 
38
    } catch ( final Exception ex ) {
 
39
      Logs.extreme( ).error( ex, ex );
 
40
      throw new ServiceRegistrationException( String.format( "Unexpected error caused cluster registration to fail for: partition=%s name=%s host=%s port=%d",
 
41
                                                             partition, name, host, port ), ex );
 
42
    }
 
43
    return super.checkAdd( partition, name, host, port );
 
44
  }
47
45
  
48
46
  @Override
49
47
  public ClusterConfiguration newInstance( ) {
51
49
  }
52
50
  
53
51
  @Override
54
 
  public ClusterConfiguration newInstance( String name, String host, Integer port ) {
55
 
    return new ClusterConfiguration( name, host, port );
56
 
  }
57
 
  
58
 
  @Override
59
 
  public com.eucalyptus.component.Component getComponent( ) {
60
 
    return Components.lookup( Component.cluster );
61
 
  }
62
 
  
63
 
  @Override
64
 
  public Boolean checkAdd( String name, String host, Integer port ) throws ServiceRegistrationException {
65
 
    if ( !testClusterCredentialsDirectory( name ) ) {
66
 
      throw new ServiceRegistrationException( "Cluster registration failed because the key directory cannot be created." );
67
 
    } else {
68
 
      return super.checkAdd( name, host, port );
69
 
    }
70
 
  }
71
 
  
72
 
  @Override
73
 
  public ClusterConfiguration add( String name, String host, Integer port ) throws ServiceRegistrationException {
74
 
    ClusterConfiguration config = this.newInstance( name, host, port );
75
 
    removeCredentials( config );
76
 
    try {
77
 
      /** generate the Component keys **/
78
 
      addCredentials( config );
79
 
      addAuthorizations( config );
80
 
      ServiceConfigurations.getInstance( ).store( config );
81
 
    } catch ( EucalyptusCloudException e ) {
82
 
      throw new ServiceRegistrationException( e.getMessage( ), e );
83
 
    }
84
 
    return config;
85
 
  }
86
 
 
87
 
  @Override
88
 
  public void fireStart( ServiceConfiguration config ) throws ServiceRegistrationException {
89
 
    EventRecord.here( ClusterBuilder.class, EventType.COMPONENT_SERVICE_START, config.getComponent( ).name( ), config.getName( ), config.getUri( ) ).info( );
90
 
    try {
91
 
      if ( Components.lookup( Components.delegate.eucalyptus ).isLocal( ) ) {
 
52
  public ClusterConfiguration newInstance( final String partition, final String name, final String host, final Integer port ) {
 
53
    return new ClusterConfiguration( partition, name, host, port );
 
54
  }
 
55
  
 
56
  @Override
 
57
  public ComponentId getComponentId( ) {
 
58
    return ComponentIds.lookup( ClusterController.class );
 
59
  }
 
60
  
 
61
  @Override
 
62
  public void fireStart( final ServiceConfiguration config ) throws ServiceRegistrationException {
 
63
    LOG.info( "Starting cluster: " + config );
 
64
    EventRecord.here( ClusterBuilder.class, EventType.COMPONENT_SERVICE_START, config.getComponentId( ).name( ), config.getName( ),
 
65
                      ServiceUris.remote( config ).toASCIIString( ) ).info( );
 
66
    try {
 
67
      if ( !Clusters.getInstance( ).contains( config.getName( ) ) ) {
 
68
        final Cluster newCluster = new Cluster( ( ClusterConfiguration ) config );//TODO:GRZE:fix the type issue here.
 
69
        newCluster.start( );
 
70
      } else {
92
71
        try {
93
 
          Clusters.start( ( ClusterConfiguration ) config );
94
 
        } catch ( EucalyptusCloudException ex ) {
95
 
          LOG.error( ex, ex );
96
 
          throw new ServiceRegistrationException( "Registration failed: " + ex.getMessage( ), ex );
 
72
          final Cluster newCluster = Clusters.getInstance( ).lookupDisabled( config.getName( ) );
 
73
          Clusters.getInstance( ).deregister( config.getName( ) );
 
74
          newCluster.start( );
 
75
        } catch ( final NoSuchElementException ex ) {
 
76
          final Cluster newCluster = Clusters.getInstance( ).lookup( config.getName( ) );
 
77
          Clusters.getInstance( ).deregister( config.getName( ) );
 
78
          newCluster.start( );
97
79
        }
98
 
        super.fireStart( config );
99
80
      }
100
 
    } catch ( NoSuchElementException ex ) {
 
81
    } catch ( final NoSuchElementException ex ) {
101
82
      LOG.error( ex, ex );
102
83
    }
103
84
  }
104
85
  
105
86
  @Override
106
 
  public Boolean checkRemove( String name ) throws ServiceRegistrationException {
 
87
  public void fireEnable( final ServiceConfiguration config ) throws ServiceRegistrationException {
 
88
    LOG.info( "Enabling cluster: " + config );
 
89
    EventRecord.here( ClusterBuilder.class, EventType.COMPONENT_SERVICE_ENABLED, config.getComponentId( ).name( ), config.getName( ),
 
90
                      ServiceUris.remote( config ).toASCIIString( ) ).info( );
107
91
    try {
108
 
      Configuration.getStorageControllerConfiguration( name );
109
 
      throw new ServiceRegistrationException( "Cannot deregister a cluster controller when there is a storage controller registered." );
110
 
    } catch ( EucalyptusCloudException e ) {
111
 
      return true;
112
 
    }
113
 
  }
114
 
  
115
 
  
116
 
  @Override
117
 
  public ClusterConfiguration remove( ServiceConfiguration removeConfig ) throws ServiceRegistrationException {
118
 
    ClusterConfiguration config = ( ClusterConfiguration ) removeConfig;
119
 
    removeAuthorizations( config );
120
 
    removeKeys( config );
121
 
    removeCredentials( config );
122
 
    ServiceConfigurations.getInstance( ).remove( config );
123
 
    return ( ClusterConfiguration ) config;
124
 
  }
125
 
 
126
 
  @Override
127
 
  public void fireStop( ServiceConfiguration config ) throws ServiceRegistrationException {
128
 
    Clusters.stop( config.getName( ) );
129
 
    super.fireStop( config );
130
 
  }
131
 
  
132
 
  @Override
133
 
  public ServiceConfiguration toConfiguration( URI uri ) throws ServiceRegistrationException {
134
 
    return new RemoteConfiguration( this.getComponent( ).getPeer( ), uri );
135
 
  }
136
 
 
137
 
  private static void addAuthorizations( ClusterConfiguration config ) {
138
 
    Groups.DEFAULT.addAuthorization( new AvailabilityZonePermission( config.getName( ) ) );
139
 
  }
140
 
  
141
 
  private static void addCredentials( ClusterConfiguration config ) throws ServiceRegistrationException {
142
 
    String directory = SubDirectory.KEYS.toString( ) + File.separator + config.getName( );
143
 
    File keyDir = new File( directory );
144
 
    LOG.info( "creating keys in " + directory );
145
 
    if ( !keyDir.mkdir( ) && !keyDir.exists( ) ) {
146
 
      throw new ServiceRegistrationException( "Failed to create cluster key directory: " + keyDir.getAbsolutePath( ) );
147
 
    } else if ( !keyDir.canWrite( ) ) {
148
 
      throw new ServiceRegistrationException( "Cluster key directory is not writeable: " + keyDir.getAbsolutePath( ) );
 
92
      try {
 
93
        final Cluster newCluster = Clusters.getInstance( ).lookupDisabled( config.getName( ) );
 
94
        newCluster.enable( );
 
95
      } catch ( final NoSuchElementException ex ) {
 
96
        final Cluster newCluster = Clusters.getInstance( ).lookup( config.getName( ) );
 
97
        newCluster.enable( );
 
98
      }
 
99
    } catch ( final NoSuchElementException ex ) {
 
100
      LOG.error( ex, ex );
149
101
    }
150
102
    
151
 
    KeyPair clusterKp = Certs.generateKeyPair( );
152
 
    X509Certificate clusterX509 = Certs.generateServiceCertificate( clusterKp, "cc-" + config.getName( ) );
153
 
    KeyPair nodeKp = Certs.generateKeyPair( );
154
 
    X509Certificate nodeX509 = Certs.generateServiceCertificate( nodeKp, "nc-" + config.getName( ) );
155
 
    FileWriter out = null;
 
103
  }
 
104
  
 
105
  @Override
 
106
  public void fireDisable( final ServiceConfiguration config ) throws ServiceRegistrationException {
 
107
    LOG.info( "Disabling cluster: " + config );
 
108
    EventRecord.here( ClusterBuilder.class, EventType.COMPONENT_SERVICE_DISABLED, config.getComponentId( ).name( ), config.getName( ),
 
109
                      ServiceUris.remote( config ).toASCIIString( ) ).info( );
156
110
    try {
157
 
      PEMFiles.write( directory + File.separator + "cluster-pk.pem", clusterKp.getPrivate( ) );
158
 
      PEMFiles.write( directory + File.separator + "cluster-cert.pem", clusterX509 );
159
 
      PEMFiles.write( directory + File.separator + "node-pk.pem", nodeKp.getPrivate( ) );
160
 
      PEMFiles.write( directory + File.separator + "node-cert.pem", nodeX509 );
161
 
      X509Certificate systemX509 = SystemCredentialProvider.getCredentialProvider( Component.eucalyptus ).getCertificate( );
162
 
      String hexSig = Hmacs.generateSystemToken( "vtunpass".getBytes( ) );
163
 
      PEMFiles.write( directory + File.separator + "cloud-cert.pem", systemX509 );
164
 
      out = new FileWriter( directory + File.separator + "vtunpass" );
165
 
      out.write( hexSig );
166
 
      out.flush( );
167
 
      out.close( );
168
 
    } catch ( IOException ex ) {
169
 
      LOG.error( ex, ex );
170
 
      throw new ServiceRegistrationException( "Failed to store cluster keys: " + ex.getMessage( ), ex );
171
 
    } finally {
172
 
      if ( out != null ) {
 
111
      if ( Clusters.getInstance( ).contains( config.getName( ) ) ) {
173
112
        try {
174
 
          out.close( );
175
 
        } catch ( IOException e ) {
176
 
          LOG.error( e );
177
 
        }
178
 
      }
179
 
    }
180
 
    EntityWrapper<ClusterCredentials> credDb = Authentication.getEntityWrapper( );
181
 
    try {
182
 
      ClusterCredentials componentCredentials = new ClusterCredentials( config.getName( ) );
183
 
      try {
184
 
        componentCredentials = credDb.getUnique( componentCredentials );
185
 
        componentCredentials.setClusterCertificate( X509Cert.fromCertificate( clusterX509 ) );
186
 
        componentCredentials.setNodeCertificate( X509Cert.fromCertificate( nodeX509 ) );
187
 
        credDb.merge( componentCredentials );
188
 
      } catch ( Exception ex ) {
189
 
        componentCredentials.setClusterCertificate( X509Cert.fromCertificate( clusterX509 ) );
190
 
        componentCredentials.setNodeCertificate( X509Cert.fromCertificate( nodeX509 ) );
191
 
        credDb.add( componentCredentials );
192
 
      }
193
 
      credDb.commit( );
194
 
    } catch ( Exception e ) {
195
 
      LOG.error( e, e );
196
 
      credDb.rollback( );
197
 
    }
198
 
  }
199
 
  
200
 
  private static void removeAuthorizations( ServiceConfiguration config ) {
201
 
    for ( Group g : Groups.listAllGroups( ) ) {
202
 
      for ( Authorization auth : g.getAuthorizations( ) ) {
203
 
        if ( auth instanceof AvailabilityZonePermission && config.getName( ).equals( auth.getValue( ) ) ) {
204
 
          g.removeAuthorization( auth );
205
 
        }
206
 
      }
207
 
    }
208
 
  }
209
 
  
210
 
  private static void removeCredentials( ClusterConfiguration config ) {
211
 
    EntityWrapper<ClusterCredentials> credDb = EntityWrapper.get( ClusterCredentials.class );
212
 
    try {
213
 
      for ( ClusterCredentials ccert : credDb.query( new ClusterCredentials( ) ) ) {
214
 
        LOG.debug( "Checking cluster certificate: " + ccert.getClusterName( ) + "\n" + X509Cert.toCertificate( ccert.getClusterCertificate( ) ) + "\n" + X509Cert.toCertificate( ccert.getNodeCertificate( ) ) );
215
 
        if( config.getName( ).equals( ccert.getClusterName( ) ) ) {
216
 
          credDb.recast( X509Cert.class ).delete( ccert.getClusterCertificate( ) );
217
 
          credDb.recast( X509Cert.class ).delete( ccert.getNodeCertificate( ) );
218
 
          credDb.delete( ccert );
219
 
          LOG.debug( "Deleting cluster certificate: " + ccert.getClusterName( ) + "\n" + X509Cert.toCertificate( ccert.getClusterCertificate( ) ) + "\n" + X509Cert.toCertificate( ccert.getNodeCertificate( ) ) );
220
 
        }
221
 
      }
222
 
      credDb.commit( );
223
 
    } catch ( Exception e ) {
224
 
      LOG.error( e, e );
225
 
      credDb.rollback( );
226
 
    }
227
 
  }
228
 
  
229
 
  private static synchronized void removeKeys( ServiceConfiguration config ) {
230
 
    String directory = SubDirectory.KEYS.toString( ) + File.separator + config.getName( );
231
 
    File keyDir = new File( directory );
232
 
    if ( keyDir.exists( ) ) {
233
 
      for ( File f : keyDir.listFiles( ) ) {
234
 
        if ( f.delete( ) ) {
235
 
          LOG.info( "Removing cluster key file: " + f.getAbsolutePath( ) );
236
 
        } else {
237
 
          LOG.info( "Failed to remove cluster key file: " + f.getAbsolutePath( ) );
238
 
        }
239
 
      }
240
 
      if ( keyDir.delete( ) ) {
241
 
        LOG.info( "Removing cluster key directory: " + keyDir.getAbsolutePath( ) );
242
 
      } else {
243
 
        LOG.info( "Failed to remove cluster key directory: " + keyDir.getAbsolutePath( ) );
244
 
      }
245
 
    }
246
 
  }
247
 
 
248
 
  static boolean testClusterCredentialsDirectory( String name ) {
249
 
    String directory = SubDirectory.KEYS.toString( ) + File.separator + name;
250
 
    File keyDir = new File( directory );
251
 
    if ( !keyDir.exists( ) ) {
252
 
      try {
253
 
        return keyDir.mkdir( ) && keyDir.canWrite( );
254
 
      } catch ( Exception e ) {
255
 
        return false;
256
 
      }
257
 
    } else {
258
 
      return keyDir.canWrite( );
259
 
    }
260
 
  }
 
113
          final Cluster newCluster = Clusters.getInstance( ).lookup( config.getName( ) );
 
114
          newCluster.disable( );
 
115
        } catch ( final NoSuchElementException ex ) {
 
116
          final Cluster newCluster = Clusters.getInstance( ).lookupDisabled( config.getName( ) );
 
117
          newCluster.disable( );
 
118
        }
 
119
      }
 
120
    } catch ( final NoSuchElementException ex ) {
 
121
      LOG.error( ex, ex );
 
122
    }
 
123
  }
 
124
  
 
125
  @Override
 
126
  public void fireStop( final ServiceConfiguration config ) throws ServiceRegistrationException {
 
127
    try {
 
128
      LOG.info( "Tearing down cluster: " + config );
 
129
      final Cluster cluster = Clusters.getInstance( ).lookupDisabled( config.getName( ) );
 
130
      EventRecord.here( ClusterBuilder.class, EventType.COMPONENT_SERVICE_STOPPED, config.getComponentId( ).name( ), config.getName( ),
 
131
                        ServiceUris.remote( config ).toASCIIString( ) ).info( );
 
132
      cluster.stop( );
 
133
    } catch ( final NoSuchElementException ex ) {
 
134
      LOG.error( ex, ex );
 
135
    } catch ( final Exception ex ) {
 
136
      LOG.error( ex, ex );
 
137
    }
 
138
  }
 
139
  
 
140
  @Override
 
141
  public void fireCheck( final ServiceConfiguration config ) throws ServiceRegistrationException {
 
142
    try {
 
143
      Clusters.lookup( config ).check( );
 
144
    } catch ( final NoSuchElementException ex ) {
 
145
      throw Faults.failure( config, ex );
 
146
    } catch ( final IllegalStateException ex ) {
 
147
      Logs.exhaust( ).error( ex, ex );
 
148
      throw Faults.failure( config, ex );
 
149
    } catch ( final Exception ex ) {
 
150
      Logs.exhaust( ).error( ex, ex );
 
151
      throw Faults.failure( config, ex );
 
152
    }
 
153
  }
 
154
  
261
155
}