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
*******************************************************************************/
62
* Author: chris grzegorczyk <grze@eucalyptus.com>
65
package edu.ucsb.eucalyptus.cloud.cluster;
67
import com.eucalyptus.bootstrap.Component;
68
import com.eucalyptus.util.EucalyptusProperties;
69
import com.eucalyptus.util.HasName;
70
import com.google.common.collect.Lists;
71
import edu.ucsb.eucalyptus.cloud.Network;
72
import edu.ucsb.eucalyptus.cloud.VmImageInfo;
73
import edu.ucsb.eucalyptus.cloud.VmKeyInfo;
74
import edu.ucsb.eucalyptus.constants.VmState;
75
import edu.ucsb.eucalyptus.msgs.AttachedVolume;
76
import edu.ucsb.eucalyptus.msgs.NetworkConfigType;
77
import edu.ucsb.eucalyptus.msgs.RunningInstancesItemType;
78
import edu.ucsb.eucalyptus.msgs.VmTypeInfo;
79
import org.apache.commons.lang.time.StopWatch;
80
import org.apache.log4j.Logger;
82
import java.util.ArrayList;
83
import java.util.Date;
84
import java.util.HashMap;
85
import java.util.List;
88
public class VmInstance implements HasName {
89
private static Logger LOG = Logger.getLogger( VmInstance.class );
91
public static String DEFAULT_IP = "0.0.0.0";
92
public static String DEFAULT_TYPE = "m1.small";
93
private String reservationId;
94
private int launchIndex;
95
private String instanceId;
96
private String ownerId;
97
private String placement;
98
private Date launchTime;
99
private StopWatch stopWatch;
100
private volatile int networkIndex;
102
private String userData;
103
private String serviceTag;
104
private String reason;
105
private VmImageInfo imageInfo;
106
private VmKeyInfo keyInfo;
107
private VmTypeInfo vmTypeInfo;
108
private List<Network> networks = Lists.newArrayList( );
109
private VmState state;
110
private StringBuffer consoleOutput;
111
private List<AttachedVolume> volumes = Lists.newArrayList( );
112
private NetworkConfigType networkConfig;
113
private Boolean privateNetwork;
114
private List<String> ancestorIds = Lists.newArrayList( );
116
public VmInstance( ) {
117
this.launchTime = new Date( );
118
this.state = VmState.PENDING;
119
this.networkConfig = new NetworkConfigType( );
120
this.stopWatch = new StopWatch( );
121
this.stopWatch.start( );
122
this.consoleOutput = new StringBuffer( );
123
this.volumes = new ArrayList<AttachedVolume>( );
126
public VmInstance( final String reservationId, final int launchIndex, final String instanceId, final String ownerId, final String placement, final String userData, final VmImageInfo imageInfo, final VmKeyInfo keyInfo, final VmTypeInfo vmTypeInfo, final List<Network> networks, String networkIndex ) {
129
this.reservationId = reservationId;
130
this.launchIndex = launchIndex;
131
this.instanceId = instanceId;
132
this.ownerId = ownerId;
133
this.placement = placement;
134
this.userData = userData;
135
this.imageInfo = imageInfo;
136
this.keyInfo = keyInfo;
137
this.vmTypeInfo = vmTypeInfo;
138
this.networks = networks;
139
this.networkIndex = Integer.parseInt( networkIndex );
140
String mac = String.format( "%s:%s:%s:%s", this.instanceId.substring( 2, 4 ), this.instanceId.substring( 4, 6 ), this.instanceId.substring( 6, 8 ), this.instanceId.substring( 8, 10 ) );
141
this.networkConfig.setMacAddress( "d0:0d:" + mac );
142
this.networkConfig.setIgnoredMacAddress( "d0:0f:" + mac );
143
this.networkConfig.setIpAddress( DEFAULT_IP );
144
this.networkConfig.setIgnoredPublicIp( DEFAULT_IP );
147
public String getName( ) {
148
return this.instanceId;
151
public boolean equals( Object o ) {
152
if ( this == o ) return true;
153
if ( o == null || getClass( ) != o.getClass( ) ) return false;
155
VmInstance vmInstance = ( VmInstance ) o;
157
if ( !instanceId.equals( vmInstance.instanceId ) ) return false;
162
public void setLaunchTime( final Date launchTime ) {
163
this.launchTime = launchTime;
166
public int hashCode( ) {
167
return instanceId.hashCode( );
170
public String getReservationId( ) {
171
return reservationId;
174
public String getInstanceId( ) {
178
public String getOwnerId( ) {
182
public int getLaunchIndex( ) {
186
public String getPlacement( ) {
190
public Date getLaunchTime( ) {
194
public VmState getState( ) {
198
public void setState( final VmState state ) {
199
if ( this.getState( ) != null && !this.getState( ).equals( state ) ) {
200
LOG.info( String.format( "%s state change: %s -> %s", this.getInstanceId( ), this.getState( ), state ) );
205
public String getUserData( ) {
209
public void setUserData( final String userData ) {
210
this.userData = userData;
213
public RunningInstancesItemType getAsRunningInstanceItemType( boolean dns ) {
214
RunningInstancesItemType runningInstance = new RunningInstancesItemType( );
216
runningInstance.setAmiLaunchIndex( Integer.toString( this.launchIndex ) );
217
runningInstance.setStateCode( Integer.toString( this.state.getCode( ) ) );
218
runningInstance.setStateName( this.state.getName( ) );
220
runningInstance.setInstanceId( this.instanceId );
221
runningInstance.setImageId( this.imageInfo.getImageId( ) );
222
runningInstance.setKernel( this.imageInfo.getKernelId( ) );
223
runningInstance.setRamdisk( this.imageInfo.getRamdiskId( ) );
224
runningInstance.setProductCodes( this.imageInfo.getProductCodes( ) );
227
runningInstance.setDnsName( this.getNetworkConfig( ).getPublicDnsName( ) );
228
runningInstance.setPrivateDnsName( this.getNetworkConfig( ).getPrivateDnsName( ) );
230
runningInstance.setPrivateDnsName( this.getNetworkConfig( ).getIpAddress( ) );
231
if ( !VmInstance.DEFAULT_IP.equals( this.getNetworkConfig( ).getIgnoredPublicIp( ) ) ) {
232
runningInstance.setDnsName( this.getNetworkConfig( ).getIgnoredPublicIp( ) );
234
runningInstance.setDnsName( this.getNetworkConfig( ).getIpAddress( ) );
237
if ( this.getReason( ) != null || !"".equals( this.getReason( ) ) ) runningInstance.setReason( this.getReason( ) );
239
if ( this.getKeyInfo( ) != null ) runningInstance.setKeyName( this.getKeyInfo( ).getName( ) );
240
else runningInstance.setKeyName( "" );
242
runningInstance.setInstanceType( this.getVmTypeInfo( ).getName( ) );
243
runningInstance.setPlacement( this.placement );
245
runningInstance.setLaunchTime( this.launchTime );
247
return runningInstance;
253
public VmKeyInfo getKeyInfo( ) {
257
public void setKeyInfo( final VmKeyInfo keyInfo ) {
258
this.keyInfo = keyInfo;
261
public VmTypeInfo getVmTypeInfo( ) {
265
public void setVmTypeInfo( final VmTypeInfo vmTypeInfo ) {
266
this.vmTypeInfo = vmTypeInfo;
269
public List<Network> getNetworks( ) {
273
public List<String> getNetworkNames( ) {
274
List<String> nets = new ArrayList<String>( );
275
for ( Network net : this.getNetworks( ) )
276
nets.add( net.getNetworkName( ) );
280
public void setNetworks( final List<Network> networks ) {
281
this.networks = networks;
284
public NetworkConfigType getNetworkConfig( ) {
285
return networkConfig;
288
public void setNetworkConfig( final NetworkConfigType networkConfig ) {
289
this.networkConfig = networkConfig;
292
public VmImageInfo getImageInfo( ) {
296
public void setImageInfo( final VmImageInfo imageInfo ) {
297
this.imageInfo = imageInfo;
300
public List<AttachedVolume> getVolumes( ) {
304
public void setVolumes( final List<AttachedVolume> volumes ) {
305
this.volumes = volumes;
308
public List<String> getAncestorIds( ) {
312
public void setAncestorIds( final List<String> ancestorIds ) {
313
this.ancestorIds = ancestorIds;
316
public String getByKey( String path ) {
317
Map<String, String> m = getMetadataMap( );
318
if ( path == null ) path = "";
319
LOG.debug( "Servicing metadata request:" + path + " -> " + m.get( path ) );
320
if ( m.containsKey( path + "/" ) ) path += "/";
321
return m.get( path ).replaceAll( "\n*\\z", "" );
324
private Map<String, String> getMetadataMap( ) {
325
Map<String, String> m = new HashMap<String, String>( );
326
m.put( "ami-id", this.getImageInfo( ).getImageId( ) );
327
m.put( "product-codes", this.getImageInfo( ).getProductCodes( ).toString( ).replaceAll( "[\\Q[]\\E]", "" ).replaceAll( ", ", "\n" ) );
328
m.put( "ami-launch-index", "" + this.getLaunchIndex( ) );
329
m.put( "ancestor-ami-ids", this.getImageInfo( ).getAncestorIds( ).toString( ).replaceAll( "[\\Q[]\\E]", "" ).replaceAll( ", ", "\n" ) );
331
m.put( "ami-manifest-path", this.getImageInfo( ).getImageLocation( ) );
332
m.put( "hostname", this.getNetworkConfig( ).getIgnoredPublicIp( ) );
333
m.put( "instance-id", this.getInstanceId( ) );
334
m.put( "instance-type", this.getVmTypeInfo( ).getName( ) );
335
if( Component.dns.isLocal( ) ) {
336
m.put( "local-hostname", this.getNetworkConfig( ).getPrivateDnsName( ) );
338
m.put( "local-hostname", this.getNetworkConfig( ).getIpAddress( ) );
340
m.put( "local-ipv4", this.getNetworkConfig( ).getIpAddress( ) );
341
if( Component.dns.isLocal( ) ) {
342
m.put( "public-hostname", this.getNetworkConfig( ).getPublicDnsName( ) );
344
m.put( "public-hostname", this.getNetworkConfig( ).getIgnoredPublicIp( ) );
346
m.put( "public-ipv4", this.getNetworkConfig( ).getIgnoredPublicIp( ) );
347
m.put( "reservation-id", this.getReservationId( ) );
348
m.put( "kernel-id", this.getImageInfo( ).getKernelId( ) );
349
if( this.getImageInfo( ).getRamdiskId( ) != null ) {
350
m.put( "ramdisk-id", this.getImageInfo( ).getRamdiskId( ) );
352
m.put( "security-groups", this.getNetworkNames( ).toString( ).replaceAll( "[\\Q[]\\E]", "" ).replaceAll( ", ", "\n" ) );
354
m.put( "block-device-mapping/", "emi\nephemeral0\nroot\nswap" );
355
m.put( "block-device-mapping/emi", "sda1" );
356
m.put( "block-device-mapping/ami", "sda1" );
357
m.put( "block-device-mapping/ephemeral0", "sda2" );
358
m.put( "block-device-mapping/swap", "sda3" );
359
m.put( "block-device-mapping/root", "/dev/sda1" );
361
m.put( "public-keys/", "0=" + this.getKeyInfo( ).getName( ) );
362
m.put( "public-keys/0", "openssh-key" );
363
m.put( "public-keys/0/", "openssh-key" );
364
m.put( "public-keys/0/openssh-key", this.getKeyInfo( ).getValue( ) );
366
m.put( "placement/", "availability-zone" );
367
m.put( "placement/availability-zone", this.getPlacement( ) );
369
for ( String entry : m.keySet( ) ) {
370
if ( entry.contains( "/" ) && !entry.endsWith( "/" ) ) continue;
377
public int compareTo( final Object o ) {
378
VmInstance that = ( VmInstance ) o;
379
return this.getName( ).compareTo( that.getName( ) );
382
public synchronized long resetStopWatch( ) {
383
this.stopWatch.stop( );
384
long ret = this.stopWatch.getTime( );
385
this.stopWatch.reset( );
386
this.stopWatch.start( );
390
public synchronized long getSplitTime( ) {
391
this.stopWatch.split( );
392
long ret = this.stopWatch.getSplitTime( );
393
this.stopWatch.unsplit( );
397
public String getReason( ) {
401
public void setReason( final String reason ) {
402
this.reason = reason;
405
public StringBuffer getConsoleOutput( ) {
406
return consoleOutput;
409
public void setConsoleOutput( final StringBuffer consoleOutput ) {
410
this.consoleOutput = consoleOutput;
413
public int getNetworkIndex( ) {
417
public void setNetworkIndex( int networkIndex ) {
418
this.networkIndex = networkIndex;
422
public String toString( ) {
423
return String.format(
424
"VmInstance [imageInfo=%s, instanceId=%s, keyInfo=%s, launchIndex=%s, launchTime=%s, networkConfig=%s, networkIndex=%s, networks=%s, ownerId=%s, placement=%s, privateNetwork=%s, reason=%s, reservationId=%s, state=%s, stopWatch=%s, userData=%s, vmTypeInfo=%s, volumes=%s]",
425
this.imageInfo, this.instanceId, this.keyInfo, this.launchIndex, this.launchTime,
426
this.networkConfig, this.networkIndex, this.networks, this.ownerId, this.placement,
427
this.privateNetwork, this.reason, this.reservationId, this.state, this.stopWatch,
428
this.userData, this.vmTypeInfo, this.volumes );
431
public void setServiceTag( String serviceTag ) {
432
this.serviceTag = serviceTag;
435
public String getServiceTag( ) {
439
public boolean hasPublicAddress() {
440
NetworkConfigType conf = getNetworkConfig( );
441
return conf != null && !( DEFAULT_IP.equals(conf.getIgnoredPublicIp( )) || conf.getIpAddress( ).equals( conf.getIgnoredPublicIp( ) ) );