2020import com .cloud .api .ApiGsonHelper ;
2121import com .cloud .api .ApiServer ;
2222import com .cloud .exception .InvalidParameterValueException ;
23- import com .cloud .utils .Pair ;
24- import com .cloud .utils .UuidUtils ;
2523import com .cloud .utils .component .ComponentContext ;
2624import com .cloud .utils .db .EntityManager ;
2725import com .cloud .utils .exception .CloudRuntimeException ;
2826import org .apache .cloudstack .api .BaseAsyncCmd ;
2927import org .apache .cloudstack .api .BaseAsyncCreateCmd ;
3028import org .apache .cloudstack .api .BaseCmd ;
31- import org .apache .cloudstack .api .command .user .vmgroup .CreateVMGroupCmd ;
32- import org .apache .cloudstack .api .command .user .vpc .CreateVPCCmd ;
3329import org .apache .cloudstack .context .CallContext ;
3430import org .apache .cloudstack .framework .jobs .AsyncJob ;
3531import org .apache .cloudstack .framework .jobs .AsyncJobDispatcher ;
4844import org .apache .commons .lang3 .ObjectUtils ;
4945import org .apache .logging .log4j .LogManager ;
5046import org .apache .logging .log4j .Logger ;
51- import org .apache .logging .log4j .ThreadContext ;
5247
5348import javax .inject .Inject ;
5449import javax .inject .Named ;
5853import java .util .LinkedHashMap ;
5954import java .util .List ;
6055import java .util .Map ;
61- import java .util .Random ;
6256import java .util .Set ;
63- import java .util .UUID ;
6457import java .util .concurrent .CompletableFuture ;
6558import java .util .concurrent .CompletionException ;
6659import java .util .concurrent .ExecutorService ;
@@ -105,19 +98,20 @@ public void deployIacTemplate(String iacTemplateContent) {
10598 private Map <String , CompletableFuture <String >> createProvisioningTasksFutures (ToscaServiceTemplate serviceTemplate ) {
10699 logger .debug ("Building provisioning tasks for the service template based on its graph topological sort." );
107100 Map <String , CompletableFuture <String >> futures = new HashMap <>();
101+ CallContext callContext = CallContext .current ();
108102 getServiceTemplateTopologicalSort (serviceTemplate ).forEach ((node , dependencies ) -> {
109103 ToscaNodeTemplate nodeTemplate = serviceTemplate .getNodeTemplates ().get (node );
110104 CompletableFuture <String > taskFuture ;
111105 if (dependencies .isEmpty ()) {
112106 logger .debug ("Node [{}] has no dependencies. Building its provisioning task, which will be ready to be allocated for execution." , node );
113- taskFuture = buildNodeProvisioningTask (nodeTemplate );
107+ taskFuture = buildNodeProvisioningTask (nodeTemplate , callContext );
114108 } else {
115109 logger .debug ("Node [{}] has [{}] dependencies. Building its provisioning task, which will only be allocated for execution when all dependencies are ready." , node , dependencies .size ());
116110 CompletableFuture <?>[] dependenciesFutures = dependencies .stream ()
117111 .map ((dep ) -> futures .get (dep .getName ())).toArray (CompletableFuture []::new );
118112 taskFuture = CompletableFuture .allOf (dependenciesFutures ).thenCompose (v -> {
119113 logger .debug ("All dependencies of the node [{}] are ready. Building its provisioning task." , node );
120- return buildNodeProvisioningTask (nodeTemplate );
114+ return buildNodeProvisioningTask (nodeTemplate , callContext );
121115 });
122116 }
123117
@@ -160,8 +154,8 @@ private void depthFirstSearch(LinkedHashMap<String, Set<ToscaNodeTemplate>> topo
160154 topologicalSort .put (node , graph .getOrDefault (node , Collections .emptySet ()));
161155 }
162156
163- private CompletableFuture <String > buildNodeProvisioningTask (ToscaNodeTemplate nodeTemplate ) {
164- return provisionNode (nodeTemplate )
157+ private CompletableFuture <String > buildNodeProvisioningTask (ToscaNodeTemplate nodeTemplate , CallContext callContext ) {
158+ return provisionNode (nodeTemplate , callContext )
165159// .orTimeout(5, TimeUnit.SECONDS)
166160 .thenApply (result -> {
167161 logger .debug ("SUCCESS [{}] [{}]" , nodeTemplate .getName (), Thread .currentThread ().getName ());
@@ -172,14 +166,11 @@ private CompletableFuture<String> buildNodeProvisioningTask(ToscaNodeTemplate no
172166 });
173167 }
174168
175- private CompletableFuture <String > provisionNode (ToscaNodeTemplate nodeTemplate ) {
176- CallContext callerContext = CallContext .current ();
177- String newTaskLogContextId = UuidUtils .first (UUID .randomUUID ().toString ());
178- logger .info ("Submitting new task with [logcontextid] equal to [{}] for handling the provisioning of the following node: [{}]." , newTaskLogContextId , nodeTemplate .getName ());
169+ private CompletableFuture <String > provisionNode (ToscaNodeTemplate nodeTemplate , CallContext callContext ) {
179170 return CompletableFuture .supplyAsync (() -> {
180- ThreadContext . put ( "logcontextid" , newTaskLogContextId );
171+ CallContext . register ( callContext , null );
181172 ManagedContextExecutor .execute (() -> {
182- dispatchProvisioningCommand (nodeTemplate , callerContext );
173+ dispatchProvisioningCommand (nodeTemplate , callContext );
183174 });
184175 return "res-" + nodeTemplate .getName ();
185176 }, executorPool );
@@ -192,7 +183,7 @@ private void dispatchProvisioningCommand(ToscaNodeTemplate nodeTemplate, CallCon
192183 if (cmd instanceof BaseAsyncCreateCmd ) {
193184 dispatchProvisioningAsynchronousCommand ((BaseAsyncCreateCmd ) cmd , nodeTemplate .getApiParams (), callContext );
194185 } else if (cmd instanceof BaseCmd && !(cmd instanceof BaseAsyncCmd )) {
195- dispatchProvisioningSynchronousCommand ((BaseCmd ) cmd , nodeTemplate .getApiParams (), callContext );
186+ dispatchProvisioningSynchronousCommand ((BaseCmd ) cmd , nodeTemplate .getApiParams ());
196187 } else {
197188 throw new CloudRuntimeException (String .format ("The provisioning API associated with the node template [%s] is not available." , nodeTemplate .getName ()));
198189 }
@@ -202,43 +193,42 @@ private void dispatchProvisioningCommand(ToscaNodeTemplate nodeTemplate, CallCon
202193 }
203194 }
204195
205- private void dispatchProvisioningSynchronousCommand (BaseCmd syncCmd , Map <String , String > apiParams , CallContext callContext ) {
206- CallContext . register ( callContext , null );
196+ private void dispatchProvisioningSynchronousCommand (BaseCmd syncCmd , Map <String , String > apiParams ) throws Exception {
197+ logger . info ( "Dispatching the provisioning synchronous command [{}] with the following parameters {}." , syncCmd . getClass (). getName (), apiParams );
207198 syncCmd = ComponentContext .inject (syncCmd );
208- try {
209- apiDispatcher .dispatch (syncCmd , apiParams , false );
210- logger .info (syncCmd .getResponseObject ());
211- } catch (Exception e ) {
212- throw new CloudRuntimeException (String .format ("Unable to dispatch the API command [%s]." , syncCmd .getCommandName ()));
213- } finally {
214- CallContext .unregister ();
215- }
199+ apiDispatcher .dispatch (syncCmd , apiParams , false );
200+ logger .info ("Result of the [{}] execution: {}." , syncCmd .getClass ().getName (), syncCmd .getResponseObject ());
216201 }
217202
218- private void dispatchProvisioningAsynchronousCommand (BaseAsyncCreateCmd asyncCmd , Map <String , String > apiParams , CallContext callContext ) {
219- asyncCmd = ComponentContext .inject (asyncCmd );
203+ private void dispatchProvisioningAsynchronousCommand (BaseAsyncCreateCmd asyncCmd , Map <String , String > apiParams , CallContext callContext ) throws Exception {
204+ logger .info ("Dispatching the provisioning asynchronous command [{}] with the following parameters {}." , asyncCmd .getClass ().getName (), apiParams );
205+ AsyncJobExecutionContext executionContext = AsyncJobExecutionContext .getCurrentExecutionContext ();
220206 try {
221- CallContext .register (callContext , null );
207+ asyncCmd = ComponentContext .inject (asyncCmd );
208+ logger .debug ("Dispatching the create workflow for the command [{}]." , asyncCmd .getClass ().getName ());
222209 apiDispatcher .dispatchCreateCmd (asyncCmd , apiParams );
223- apiParams .put ("ctxStartEventId" , "1" );
224- Long objectId = ObjectUtils .defaultIfNull (asyncCmd .getEntityId (), asyncCmd .getApiResourceId ());
225- apiParams .put ("id" , objectId .toString ());
210+
211+ logger .debug ("Successfully executed the create workflow for the command [{}]. Thus, dispatching its async job." , asyncCmd .getClass ().getName ());
226212 AsyncJobVO job = dispatchAsyncJob (asyncCmd , apiParams , callContext );
227- AsyncJobExecutionContext executionContext = AsyncJobExecutionContext .getCurrentExecutionContext ();
228213 executionContext .joinJob (job .getId ());
229214 Outcome <String > outcome = new NodeTemplateProvisioningOutcome (job );
230- String jobResult = outcome .get ();
231- logger .info ("Provisioning outcome: {}" , jobResult );
232- asyncJobManager .expungeAsyncJob ((AsyncJobVO ) executionContext .getJob ());
233- } catch (Exception e ) {
234- throw new RuntimeException (e );
215+ String asyncCmdResult = outcome .get ();
216+ logger .info ("Result of the [{}] execution: {}." , asyncJobManager .getClass ().getName (), asyncCmdResult );
235217 } finally {
236- CallContext .unregister ();
218+ if (executionContext .getJob () != null ) {
219+ asyncJobManager .expungeAsyncJob ((AsyncJobVO ) executionContext .getJob ());
220+ }
237221 }
238222 }
239223
240224 private AsyncJobVO dispatchAsyncJob (BaseAsyncCreateCmd asyncCmd , Map <String , String > apiParams , CallContext callContext ) {
241- AsyncJobVO job = new AsyncJobVO ("" , callContext .getCallingUserId (), callContext .getCallingAccountId (), CreateVPCCmd .class .getName (),
225+ apiParams .put ("ctxStartEventId" , "1" );
226+ Long objectId = ObjectUtils .defaultIfNull (asyncCmd .getEntityId (), asyncCmd .getApiResourceId ());
227+ apiParams .put ("id" , objectId .toString ());
228+ apiParams .put ("ctxUserId" , String .valueOf (callContext .getCallingUserId ()));
229+ apiParams .put ("ctxAccountId" , String .valueOf (callContext .getCallingAccountId ()));
230+
231+ AsyncJobVO job = new AsyncJobVO ("" , callContext .getCallingUserId (), callContext .getCallingAccountId (), asyncCmd .getClass ().getName (),
242232 ApiGsonHelper .getBuilder ().create ().toJson (apiParams ), objectId ,
243233 asyncCmd .getApiResourceType () != null ? asyncCmd .getApiResourceType ().toString () : null ,
244234 null );
0 commit comments