~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/callback/VmRunCallback.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
/*******************************************************************************
2
 
*Copyright (c) 2009  Eucalyptus Systems, Inc.
3
 
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.
7
 
8
 
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
12
 
*  for more details.
13
 
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/>.
16
 
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.
20
 
21
 
*  This file may incorporate work covered under the following copyright and
22
 
*  permission notice:
23
 
24
 
*    Software License Agreement (BSD License)
25
 
26
 
*    Copyright (c) 2008, Regents of the University of California
27
 
*    All rights reserved.
28
 
29
 
*    Redistribution and use of this software in source and binary forms, with
30
 
*    or without modification, are permitted provided that the following
31
 
*    conditions are met:
32
 
33
 
*      Redistributions of source code must retain the above copyright notice,
34
 
*      this list of conditions and the following disclaimer.
35
 
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.
39
 
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
 
*******************************************************************************/
 
2
 *Copyright (c) 2009  Eucalyptus Systems, Inc.
 
3
 * 
 
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.
 
7
 * 
 
8
 * 
 
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
 
12
 *  for more details.
 
13
 * 
 
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/>.
 
16
 * 
 
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.
 
20
 * 
 
21
 *  This file may incorporate work covered under the following copyright and
 
22
 *  permission notice:
 
23
 * 
 
24
 *    Software License Agreement (BSD License)
 
25
 * 
 
26
 *    Copyright (c) 2008, Regents of the University of California
 
27
 *    All rights reserved.
 
28
 * 
 
29
 *    Redistribution and use of this software in source and binary forms, with
 
30
 *    or without modification, are permitted provided that the following
 
31
 *    conditions are met:
 
32
 * 
 
33
 *      Redistributions of source code must retain the above copyright notice,
 
34
 *      this list of conditions and the following disclaimer.
 
35
 * 
 
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.
 
39
 * 
 
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
61
/*
62
62
 * Author: chris grzegorczyk <grze@eucalyptus.com>
63
63
 */
64
64
package com.eucalyptus.cluster.callback;
65
65
 
66
 
import java.util.List;
67
 
import java.util.NoSuchElementException;
68
 
import java.util.Set;
 
66
import java.util.concurrent.Callable;
 
67
import java.util.ArrayList;
 
68
import javax.persistence.EntityTransaction;
69
69
import org.apache.log4j.Logger;
70
70
import com.eucalyptus.address.Address;
71
71
import com.eucalyptus.address.Addresses;
 
72
import com.eucalyptus.blockstorage.Volume;
 
73
import com.eucalyptus.cloud.ResourceToken;
 
74
import com.eucalyptus.cloud.VmRunType;
 
75
import com.eucalyptus.cluster.Cluster;
72
76
import com.eucalyptus.cluster.Clusters;
73
 
import com.eucalyptus.cluster.Networks;
74
 
import com.eucalyptus.cluster.VmInstance;
75
 
import com.eucalyptus.cluster.VmInstances;
 
77
import com.eucalyptus.cluster.ResourceState.NoSuchTokenException;
 
78
import com.eucalyptus.component.ServiceConfiguration;
 
79
import com.eucalyptus.component.Topology;
 
80
import com.eucalyptus.component.id.ClusterController;
 
81
import com.eucalyptus.component.id.Eucalyptus;
 
82
import com.eucalyptus.component.id.Storage;
 
83
import com.eucalyptus.entities.Entities;
 
84
import com.eucalyptus.records.Logs;
 
85
import com.eucalyptus.system.Threads;
 
86
import com.eucalyptus.util.Callback;
76
87
import com.eucalyptus.util.EucalyptusClusterException;
77
88
import com.eucalyptus.util.Exceptions;
78
89
import com.eucalyptus.util.LogUtil;
79
 
import com.eucalyptus.vm.SystemState.Reason;
80
 
import com.eucalyptus.vm.VmState;
81
 
import com.google.common.collect.Lists;
82
 
import com.google.common.collect.Sets;
83
 
import edu.ucsb.eucalyptus.cloud.Network;
84
 
import edu.ucsb.eucalyptus.cloud.NetworkToken;
85
 
import edu.ucsb.eucalyptus.cloud.ResourceToken;
 
90
import com.eucalyptus.util.async.AsyncRequests;
 
91
import com.eucalyptus.util.async.CheckedListenableFuture;
 
92
import com.eucalyptus.util.async.MessageCallback;
 
93
import com.eucalyptus.vm.VmInstance;
 
94
import com.eucalyptus.vm.VmInstance.VmState;
 
95
import com.eucalyptus.vm.VmInstances;
 
96
import com.eucalyptus.vm.VmVolumeAttachment;
 
97
import com.eucalyptus.vm.VmVolumeAttachment.AttachmentState;
 
98
import com.google.common.base.Function;
 
99
import com.google.common.base.Functions;
 
100
import com.google.common.base.Predicate;
86
101
import edu.ucsb.eucalyptus.cloud.VmInfo;
87
102
import edu.ucsb.eucalyptus.cloud.VmRunResponseType;
88
 
import edu.ucsb.eucalyptus.cloud.VmRunType;
89
 
 
90
 
public class VmRunCallback extends QueuedEventCallback<VmRunType,VmRunResponseType> {
91
 
 
92
 
  private static Logger LOG = Logger.getLogger( VmRunCallback.class );
93
 
 
94
 
  private ResourceToken token;
 
103
import edu.ucsb.eucalyptus.msgs.AttachStorageVolumeResponseType;
 
104
import edu.ucsb.eucalyptus.msgs.AttachStorageVolumeType;
 
105
import edu.ucsb.eucalyptus.msgs.AttachVolumeType;
 
106
import edu.ucsb.eucalyptus.msgs.BaseMessage;
 
107
 
 
108
public class VmRunCallback extends MessageCallback<VmRunType, VmRunResponseType> {
 
109
  
 
110
  private static Logger       LOG = Logger.getLogger( VmRunCallback.class );
 
111
  
 
112
  private final ResourceToken token;
95
113
  
96
114
  public VmRunCallback( final VmRunType msg, final ResourceToken token ) {
 
115
    super( msg );
97
116
    this.token = token;
98
 
    this.setRequest( msg );
 
117
    LOG.debug( this.token );
99
118
  }
100
 
 
101
 
  public void prepare( final VmRunType msg ) throws Exception {
102
 
//    LOG.trace( LogUtil.subheader( msg.toString( ) ) );
103
 
    for( String vmId : msg.getInstanceIds( ) ) {
 
119
  
 
120
  @Override
 
121
  public void initialize( final VmRunType msg ) {
 
122
    LOG.debug( this.token + ":" + msg );
 
123
    try {
 
124
      this.token.submit( );
 
125
    } catch ( final NoSuchTokenException e2 ) {
 
126
      LOG.error( e2 );
 
127
      Logs.extreme( ).error( e2, e2 );
 
128
    }
 
129
    EntityTransaction db = Entities.get( VmInstance.class );
 
130
    try {
 
131
      final VmInstance vm = VmInstances.lookup( msg.getInstanceId( ) );
 
132
      msg.setUserId( vm.getOwnerUserId( ) );
 
133
      msg.setOwnerId( vm.getOwnerUserId( ) );
 
134
      msg.setAccountId( vm.getOwnerAccountNumber( ) );
 
135
      if ( !VmState.PENDING.equals( vm.getState( ) ) ) {
 
136
        throw new EucalyptusClusterException( "Intercepted a RunInstances request for an instance which has meanwhile been terminated." );
 
137
      }
 
138
      db.rollback( );
 
139
    } catch ( final Exception e ) {
 
140
      LOG.error( e );
 
141
      Logs.extreme( ).error( e, e );
 
142
      db.rollback( );
104
143
      try {
105
 
        VmInstance vm = VmInstances.getInstance( ).lookup( vmId );
106
 
        if( !VmState.PENDING.equals( vm.getState( ) ) ) {
107
 
          throw new EucalyptusClusterException("Intercepted a RunInstances request for an instance which has meanwhile been terminated." );
108
 
        }
109
 
      } catch ( Exception e ) {
110
 
        LOG.debug( e, e );
 
144
        this.token.abort( );
 
145
      } catch ( Exception ex ) {
 
146
        LOG.error( ex );
 
147
        Logs.extreme( ).error( ex, ex );
111
148
      }
112
 
    }
113
 
    try {
114
 
      Clusters.getInstance().lookup( token.getCluster() ).getNodeState().submitToken( token );
115
 
    } catch ( Exception e2 ) {
116
 
      LOG.debug( e2, e2 );
117
 
      throw e2;
 
149
      throw new EucalyptusClusterException( "Error while initializing request state: " + this.getRequest( ), e );
118
150
    }
119
151
  }
120
 
 
 
152
  
121
153
  @Override
122
 
  public void verify( VmRunResponseType reply ) throws Exception {
123
 
    try {
124
 
      Clusters.getInstance().lookup( token.getCluster() ).getNodeState().redeemToken( token );
125
 
    } catch ( Throwable e ) {
126
 
      this.fail( e );
127
 
      LOG.debug( e, e );
128
 
      return;
129
 
    } 
130
 
    try {
131
 
      if ( reply != null && reply.getVms( ).isEmpty( ) ) {
132
 
        this.fail( new EucalyptusClusterException( "Failed to run the requested instances because the request was rejected: " + token.toString( ) ) );
133
 
      } else if ( reply != null && !reply.getVms( ).isEmpty( ) ) {
134
 
        Set<String> liveIds = Sets.newHashSet( );
135
 
        for ( VmInfo vmInfo : reply.getVms() ) {
136
 
          liveIds.add( vmInfo.getInstanceId( ) );
137
 
          try {
138
 
            VmInstance vm = VmInstances.getInstance().lookup( vmInfo.getInstanceId() );
139
 
            vm.updateAddresses( vmInfo.getNetParams().getIpAddress(), vmInfo.getNetParams().getIgnoredPublicIp() );
140
 
            vm.clearPending( );
141
 
          } catch ( Throwable ex ) {
142
 
            Exceptions.eat( "UNIDENTIFIED VM: " + vmInfo.toString( ) );
143
 
          }
144
 
        }
145
 
        Set<String> requestIds = Sets.newHashSet( token.getInstanceIds( ) );
146
 
        requestIds.removeAll( liveIds );
147
 
        for( String id : requestIds ) {
148
 
          int idx = token.getInstanceIds( ).indexOf( id );
149
 
          try {
150
 
            VmInstance vm = VmInstances.getInstance().lookup( id );
151
 
            vm.clearPending( );
152
 
            vm.setState( VmState.TERMINATED, Reason.FAILED, "This instance failed to be run by the CC." );
153
 
            LOG.error( "Failed virtual machine: " + vm.toString( ) );
154
 
          } catch ( Throwable ex ) {
155
 
            LOG.trace( "Failed virtual machine: " + id );
156
 
          }          
157
 
          if( idx > 0 && token.getAddresses( ).size( ) > idx ) {
158
 
            try {
159
 
              String addr = token.getAddresses( ).get( idx );
160
 
              LOG.warn( "Failed virtual machine: " + id + " releasing address: " + addr ); 
161
 
              Addresses.getInstance( ).lookup( addr ).release( );
162
 
            } catch ( Throwable ex ) {
163
 
              LOG.error( ex , ex );
 
154
  public void fire( final VmRunResponseType reply ) {
 
155
    Logs.extreme( ).error( reply );
 
156
    try {
 
157
      this.token.redeem( );
 
158
    } catch ( Exception ex ) {
 
159
      LOG.error( this.token + ": " + ex );
 
160
      Logs.extreme( ).error( this.token + ": " + ex, ex );
 
161
    }
 
162
    final Volume rootVolume = this.token.getRootVolume( );
 
163
    final String rootVolumeId = ( rootVolume != null ? rootVolume.getDisplayName( ) : null );
 
164
    Function<VmInfo, Boolean> updateInstance = new Function<VmInfo, Boolean>( ) {
 
165
      @Override
 
166
      public Boolean apply( final VmInfo input ) {
 
167
        final VmInstance vm = VmInstances.lookup( input.getInstanceId( ) );
 
168
        vm.updateAddresses( input.getNetParams( ).getIpAddress( ), input.getNetParams( ).getIgnoredPublicIp( ) );
 
169
        try {
 
170
          vm.getRuntimeState( ).setServiceTag( input.getServiceTag( ) );
 
171
          final Predicate<VmVolumeAttachment> attachVolumes = new Predicate<VmVolumeAttachment>( ) {
 
172
            public boolean apply( VmVolumeAttachment input ) {
 
173
              final String volumeId = input.getVolumeId( );
 
174
              if ( !volumeId.equals( rootVolumeId ) ) {
 
175
                try {
 
176
                  if ( !AttachmentState.attached.equals( input.getAttachmentState( ) ) && !AttachmentState.attaching.equals( input.getAttachmentState( ) ) ) {
 
177
                    input.setStatus( AttachmentState.attaching.name( ) );
 
178
                  }
 
179
                } catch ( Exception ex ) {
 
180
                  input.setStatus( AttachmentState.attaching_failed.name( ) );
 
181
                  LOG.error( VmRunCallback.this.token + ": " + ex );
 
182
                  Logs.extreme( ).error( ex, ex );
 
183
                }
 
184
              }
 
185
              return true;
164
186
            }
165
 
          }
166
 
        }
167
 
      } else {
168
 
        this.fail( new EucalyptusClusterException( "RunInstances returned false." + this.getRequest( ) ) );
169
 
      }
170
 
    } catch ( Exception e ) { 
171
 
      LOG.debug( e, e );
172
 
      throw e; 
 
187
          };
 
188
          try {
 
189
            vm.eachVolumeAttachment( attachVolumes );
 
190
          } catch ( Exception ex ) {
 
191
            LOG.error( VmRunCallback.this.token + ": " + ex );
 
192
            Logs.extreme( ).error( VmRunCallback.this.token + ": " + ex, ex );
 
193
          }
 
194
        } catch ( Exception ex ) {
 
195
          LOG.error( VmRunCallback.this.token + ": " + ex );
 
196
          Logs.extreme( ).error( VmRunCallback.this.token + ": " + ex, ex );
 
197
        }
 
198
        final Address addr = VmRunCallback.this.token.getAddress( );
 
199
        if ( addr != null ) {
 
200
          try {
 
201
            AsyncRequests.newRequest( addr.assign( vm ).getCallback( ) )
 
202
                         .then( new Callback.Success<BaseMessage>( ) {
 
203
                           @Override
 
204
                           public void fire( final BaseMessage response ) {
 
205
                             vm.updateAddresses( addr.getInstanceAddress( ), addr.getName( ) );
 
206
                           }
 
207
                         } ).dispatch( vm.getPartition( ) );
 
208
          } catch ( Exception ex ) {
 
209
            LOG.error( VmRunCallback.this.token + ": " + ex );
 
210
            Logs.extreme( ).error( VmRunCallback.this.token + ": " + ex, ex );
 
211
            Addresses.release( addr );
 
212
          }
 
213
          
 
214
        }
 
215
        return true;
 
216
      }
 
217
    };
 
218
    for ( final VmInfo vmInfo : reply.getVms( ) ) {
 
219
      if ( this.token.getInstanceId( ).equals( vmInfo.getInstanceId( ) ) ) {
 
220
        try {
 
221
          Entities.asTransaction( VmInstance.class, updateInstance, 10 ).apply( vmInfo );
 
222
          break;
 
223
        } catch ( RuntimeException ex ) {
 
224
          LOG.error( "Failed: " + this.token + " because of " + ex.getMessage( ), ex );
 
225
          throw ex;
 
226
        }
 
227
      }
 
228
      throw new EucalyptusClusterException( "ccRunInstancesResponse: does not contain requested instance information for: "
 
229
                                            + this.token.getInstanceId( )
 
230
                                            + " but return status is "
 
231
                                            + reply.get_return( )
 
232
                                            + "\nccRunInstancesResponse:vms="
 
233
                                            + reply.getVms( ) );
173
234
    }
174
235
  }
175
 
 
176
 
 
 
236
  
177
237
  @Override
178
 
  public void fail( Throwable e ) {
 
238
  public void fireException( final Throwable e ) {
179
239
    LOG.debug( LogUtil.header( "Failing run instances because of: " + e.getMessage( ) ), e );
180
 
    LOG.debug( LogUtil.subheader( this.getRequest( ).toString( ) ) );
181
 
    for( String addr : this.token.getAddresses() ) {
182
 
      try {
 
240
    LOG.debug( LogUtil.subheader( VmRunCallback.this.getRequest( ).toString( ) ) );
 
241
    Predicate<Throwable> rollbackAddr = new Predicate<Throwable>( ) {
 
242
      
 
243
      @Override
 
244
      public boolean apply( Throwable input ) {
 
245
        final Address addr = VmRunCallback.this.token.getAddress( );
183
246
        LOG.debug( "-> Release addresses from failed vm run allocation: " + addr );
184
 
        Addresses.getInstance().lookup( addr ).release( );
185
 
      } catch ( NoSuchElementException e1 ) {
186
 
        LOG.debug( "-> Failed to release addresses from failed vm run allocation: " + addr );
187
 
      }
188
 
    }
189
 
    LOG.debug( "-> Release network index allocation." );
190
 
    if( this.token.getPrimaryNetwork( ) != null ) {
191
 
      try {
192
 
        NetworkToken net = this.token.getPrimaryNetwork( );
193
 
        Network network = Networks.getInstance( ).lookup( net.getName( ) );
194
 
        for( Integer index : this.token.getPrimaryNetwork( ).getIndexes( ) ) {
195
 
          network.returnNetworkIndex( index );
196
 
        }
197
 
      } catch ( Throwable e2 ) {
198
 
        LOG.debug( e2, e2 );
199
 
      }
200
 
    }
201
 
    LOG.debug( "-> Release resource tokens for unused resources." );
202
 
    try {
203
 
      Clusters.getInstance().lookup( token.getCluster() ).getNodeState().releaseToken( token );
204
 
    } catch ( Throwable e2 ) {
205
 
      LOG.debug( e2, e2 );
206
 
    }
207
 
  }
208
 
 
209
 
 
 
247
        try {
 
248
          addr.release( );
 
249
        } catch ( final Exception ex ) {
 
250
          LOG.error( ex.getMessage( ) );
 
251
          Logs.extreme( ).error( ex, ex );
 
252
        }
 
253
        return true;
 
254
      }
 
255
    };
 
256
    try {
 
257
      Entities.asTransaction( VmInstance.class, Functions.forPredicate( rollbackAddr ) ).apply( e );
 
258
    } catch ( Exception ex ) {
 
259
      Logs.extreme( ).error( ex, ex );
 
260
    }
 
261
    Predicate<Throwable> rollbackToken = new Predicate<Throwable>( ) {
 
262
      
 
263
      @Override
 
264
      public boolean apply( Throwable input ) {
 
265
        LOG.debug( "-> Release resource tokens for unused resources." );
 
266
        try {
 
267
          VmRunCallback.this.token.abort( );
 
268
        } catch ( final Exception ex ) {
 
269
          LOG.error( ex.getMessage( ) );
 
270
          Logs.extreme( ).error( ex, ex );
 
271
        }
 
272
        return true;
 
273
      }
 
274
    };
 
275
    try {
 
276
      Entities.asTransaction( VmInstance.class, Functions.forPredicate( rollbackToken ) ).apply( e );
 
277
    } catch ( Exception ex ) {
 
278
      Logs.extreme( ).error( ex, ex );
 
279
    }
 
280
  }
 
281
  
 
282
  @Override
 
283
  public String toString( ) {
 
284
    return "VmRunCallback " + this.token;
 
285
  }
210
286
}