]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Spawn a new thread to handle deployPkg.deploy RPC
authorOliver Kurth <okurth@vmware.com>
Fri, 15 Sep 2017 18:23:39 +0000 (11:23 -0700)
committerOliver Kurth <okurth@vmware.com>
Fri, 15 Sep 2017 18:23:39 +0000 (11:23 -0700)
Deploypkg takes some time to complete, so separating
it to a new thread helps guarantee that the main
tools thread can still respond to VMX ping/heartbeat
messages.

Before this change, the state changes on the vmx side are:
   ToolsDeployPkg_Begin
   ToolsDeployPkg begin finished
   ToolsDeployPkg finished copy
   deployPkg.deploy
   deployPkg.update.state 3    -- TOOLSDEPLOYPKG_DEPLOYING
   deployPkg.update.state 4 0  -- TOOLSDEPLOYPKG_RUNNING
   deployPkg.update.state 4 103 -- TOOLSDEPLOYPKG_RUNNING GUESTCUST_EVENT_ENABLE_NICS
   deployPkg.update.state 4 104  -- TOOLSDEPLOYPKG_RUNNING GUESTCUST_EVENT_QUERY_NICS
   ToolsDeployPkg finished deploy

   ToolsDeployPkg_Begin
   ToolsDeployPkg deploy state: 4
   deployPkg.update.state 5 0     -- TOOLSDEPLOYPKG_DONE

After this change, the state changes are:
   ToolsDeployPkg_Begin
   ToolsDeployPkg begin finished
   ToolsDeployPkg finished copy
   deployPkg.deploy
   deployPkg.update.state 3
   ToolsDeployPkg finished deploy

   deployPkg.update.state 4 0
   deployPkg.update.state 4 103
   deployPkg.update.state 4 104

   ToolsDeployPkg_Begin
   ToolsDeployPkg deploy state: 4
   deployPkg.update.state 5 0

There are no specific changes on vmx side.

open-vm-tools/services/plugins/deployPkg/Makefile.am
open-vm-tools/services/plugins/deployPkg/deployPkg.c

index 6f6873cde54bdbcf12dc0bff5f76c086e844309d..781f47df81c663b7fda950696da5e628cdc3c451 100644 (file)
@@ -28,6 +28,7 @@ libdeployPkgPlugin_la_LDFLAGS += @PLUGIN_LDFLAGS@
 
 libdeployPkgPlugin_la_LIBADD =
 libdeployPkgPlugin_la_LIBADD += @VMTOOLS_LIBS@
+libdeployPkgPlugin_la_LIBADD += @GOBJECT_LIBS@
 libdeployPkgPlugin_la_LIBADD += $(top_builddir)/libDeployPkg/libDeployPkg.la
 
 libdeployPkgPlugin_la_SOURCES =
index f5479400f1d254d89bdb3f528a4a65af773222b2..df18663c80be634bc015f5cae3c315e67ea06dee 100644 (file)
@@ -41,6 +41,7 @@
 extern "C" {
 #endif
    #include "vmware/tools/plugin.h"
+   #include "vmware/tools/threadPool.h"
 #ifdef __cplusplus
 }
 #endif
@@ -149,16 +150,77 @@ DeployPkg_TcloBegin(RpcInData *data)   // IN
 }
 
 
+/*
+ * ---------------------------------------------------------------------------
+ * DeployPkgExecDeploy --
+ *
+ *    Start the deploy execution in a new thread.
+ *
+ * Return Value:
+ *    None.
+ *
+ * Side effects:
+ *    None.
+ *
+ * ---------------------------------------------------------------------------
+ */
+
+void
+DeployPkgExecDeploy(ToolsAppCtx *ctx,   // IN: app context
+                    void *pkgName)      // IN: pkg file name
+{
+   char errMsg[2048];
+   ToolsDeployPkgError ret;
+   gchar *msg;
+   char *pkgNameStr = (char *) pkgName;
+
+   g_debug("%s: Deploypkg deploy task started.\n", __FUNCTION__);
+
+   /* Unpack the package and run the command. */
+   ret = DeployPkgDeployPkgInGuest(pkgNameStr, errMsg, sizeof errMsg);
+   if (ret != TOOLSDEPLOYPKG_ERROR_SUCCESS) {
+      msg = g_strdup_printf("deployPkg.update.state %d %d %s",
+                            TOOLSDEPLOYPKG_DEPLOYING,
+                            TOOLSDEPLOYPKG_ERROR_DEPLOY_FAILED,
+                            errMsg);
+      if (!RpcChannel_Send(ctx->rpc, msg, strlen(msg), NULL, NULL)) {
+         g_warning("%s: failed to send error code %d for state TOOLSDEPLOYPKG_DEPLOYING\n",
+                   __FUNCTION__,
+                   TOOLSDEPLOYPKG_ERROR_DEPLOY_FAILED);
+      }
+      g_free(msg);
+      g_warning("DeployPkgInGuest failed, error = %d\n", ret);
+   }
+
+   /* Attempt to delete the package file and tempdir. */
+   Log("Deleting file %s\n", pkgNameStr);
+   if (File_Unlink(pkgNameStr) == 0) {
+      char *vol, *dir, *path;
+      File_SplitName(pkgNameStr, &vol, &dir, NULL);
+      path = Str_Asprintf(NULL, "%s%s", vol, dir);
+      if (path != NULL) {
+         Log("Deleting directory %s\n", path);
+         File_DeleteEmptyDirectory(path);
+         free(path);
+      }
+      free(vol);
+      free(dir);
+   } else {
+      g_warning("Unable to delete the file: %s\n", pkgNameStr);
+   }
+}
+
+
 /*
  *-----------------------------------------------------------------------------
  *
- * DeployPkgTcloDeploy --
+ * DeployPkg_TcloDeploy --
  *
  *    TCLO handler for "deployPkg.deploy". Start image guest package deployment.
  *
  * Return value:
  *    TRUE if success
- *    FALSE if anything failed
+ *    FALSE if pkg file path is not valid
  *
  * Side effects:
  *    None
@@ -169,9 +231,7 @@ DeployPkg_TcloBegin(RpcInData *data)   // IN
 gboolean
 DeployPkg_TcloDeploy(RpcInData *data)  // IN
 {
-   char errMsg[2048];
-   ToolsDeployPkgError ret;
-   char *argCopy, *pkgStart, *pkgEnd;
+   char *argCopy, *pkgStart, *pkgEnd, *pkgName;
    const char *white = " \t\r\n";
 
    /* Set state to DEPLOYING. */
@@ -181,7 +241,7 @@ DeployPkg_TcloDeploy(RpcInData *data)  // IN
    msg = g_strdup_printf("deployPkg.update.state %d",
                          TOOLSDEPLOYPKG_DEPLOYING);
    if (!RpcChannel_Send(ctx->rpc, msg, strlen(msg), NULL, NULL)) {
-      g_warning("%s: failed update state to TOOLSDEPLOYPKG_DEPLOYING\n",
+      g_warning("%s: failed to update state to TOOLSDEPLOYPKG_DEPLOYING\n",
                 __FUNCTION__);
    }
    g_free(msg);
@@ -205,44 +265,31 @@ DeployPkg_TcloDeploy(RpcInData *data)  // IN
                             TOOLSDEPLOYPKG_ERROR_DEPLOY_FAILED,
                             pkgStart);
       if (!RpcChannel_Send(ctx->rpc, msg, strlen(msg), NULL, NULL)) {
-         g_warning("%s: failed update state to TOOLSDEPLOYPKG_DEPLOYING\n",
-                   __FUNCTION__);
+         g_warning("%s: failed to send error code %d for state TOOLSDEPLOYPKG_DEPLOYING\n",
+                   __FUNCTION__,
+                   TOOLSDEPLOYPKG_ERROR_DEPLOY_FAILED);
       }
       g_free(msg);
       g_warning("Package file '%s' doesn't exist!!\n", pkgStart);
-      goto ExitPoint;
+
+      free(argCopy);
+      return RPCIN_SETRETVALS(data, "failed to get package file", FALSE);
    }
 
-   /* Unpack the package and run the command. */
-   ret = DeployPkgDeployPkgInGuest(pkgStart, errMsg, sizeof errMsg);
-   if (ret != TOOLSDEPLOYPKG_ERROR_SUCCESS) {
+   pkgName = Util_SafeStrdup(pkgStart);
+   if (!ToolsCorePool_SubmitTask(ctx, DeployPkgExecDeploy, pkgName, free)) {
+      g_warning("%s: failed to start deploy execution thread\n",
+                __FUNCTION__);
       msg = g_strdup_printf("deployPkg.update.state %d %d %s",
                             TOOLSDEPLOYPKG_DEPLOYING,
                             TOOLSDEPLOYPKG_ERROR_DEPLOY_FAILED,
-                            errMsg);
+                            "failed to spawn deploy execution thread");
       if (!RpcChannel_Send(ctx->rpc, msg, strlen(msg), NULL, NULL)) {
-         g_warning("%s: failed update state to TOOLSDEPLOYPKG_DEPLOYING\n",
-                   __FUNCTION__);
+         g_warning("%s: failed to send error code %d for state TOOLSDEPLOYPKG_DEPLOYING\n",
+                   __FUNCTION__,
+                   TOOLSDEPLOYPKG_ERROR_DEPLOY_FAILED);
       }
       g_free(msg);
-      g_warning("DeployPkgInGuest failed, error = %d\n", ret);
-   }
-
- ExitPoint:
-
-   /* Attempt to delete the package file and tempdir. */
-   Log("Deleting file %s\n", pkgStart);
-   if (File_Unlink(pkgStart) == 0) {
-      char *vol, *dir, *path;
-      File_SplitName(pkgStart, &vol, &dir, NULL);
-      path = Str_Asprintf(NULL, "%s%s", vol, dir);
-      if (path != NULL) {
-         Log("Deleting directory %s\n", path);
-         File_DeleteEmptyDirectory(path);
-         free(path);
-      }
-      free(vol);
-      free(dir);
    }
 
    free(argCopy);