Repository: StackStorm/st2

Issue:
Reinstalling mmonit pack fails as the venv is being used
Im sure this is due the sensor being run, so you cant create the virtualenv again as its being used.

Should the packs action check if there is sensors and try to stop them before reinstalling a pack?

```
  "stderr": "st2.actions.python.SetupVirtualEnvironmentAction: DEBUG    Setting up virtualenv for pack \"mmonit\"\nst2.actions.python.SetupVirtualEnvironmentAction: DEBUG    Creating virtualenv for pack \"mmonit\" in \"/opt/stackstorm/virtualenvs/mmonit\"\nst2.actions.python.SetupVirtualEnvironmentAction: DEBUG    Creating virtualenv in \"/opt/stackstorm/virtualenvs/mmonit\" using Python binary \"/usr/bin/python2.7\"\nTraceback (most recent call last):\n  File \"/usr/lib/python2.7/dist-packages/st2actions/runners/python_action_wrapper.py\", line 116, in <module>\n    obj.run()\n  File \"/usr/lib/python2.7/dist-packages/st2actions/runners/python_action_wrapper.py\", line 61, in run\n    output = action.run(**self._parameters)\n  File \"/opt/stackstorm/packs/packs/actions/pack_mgmt/setup_virtualenv.py\", line 52, in run\n    self._setup_pack_virtualenv(pack_name=pack_name)\n  File \"/opt/stackstorm/packs/packs/actions/pack_mgmt/setup_virtualenv.py\", line 89, in _setup_pack_virtualenv\n    self._create_virtualenv(virtualenv_path=virtualenv_path)\n  File \"/opt/stackstorm/packs/packs/actions/pack_mgmt/setup_virtualenv.py\", line 125, in _create_virtualenv\n    (virtualenv_path, stderr))\nException: Failed to create virtualenv in \"/opt/stackstorm/virtualenvs/mmonit\": Traceback (most recent call last):\n  File \"/usr/local/lib/python2.7/dist-packages/virtualenv.py\", line 2363, in <module>\n    main()\n  File \"/usr/local/lib/python2.7/dist-packages/virtualenv.py\", line 832, in main\n    symlink=options.symlink)\n  File \"/usr/local/lib/python2.7/dist-packages/virtualenv.py\", line 994, in create_environment\n    site_packages=site_packages, clear=clear, symlink=symlink))\n  File \"/usr/local/lib/python2.7/dist-packages/virtualenv.py\", line 1288, in install_python\n    shutil.copyfile(executable, py_executable)\n  File \"/usr/lib/python2.7/shutil.py\", line 83, in copyfile\n    with open(dst, 'wb') as fdst:\nIOError: [Errno 26] Text file busy: '/opt/stackstorm/virtualenvs/mmonit/bin/python2.7'\n\n",
```



Discussion:
Perhaps. We have run into this issue a few times ourselves and have been debating how to get this fixed. Perhaps, shutting down the `sensor` from the reloaded pack might be a good answer or avoid creation of `virtualenv` might be another. 

Thanks for the report!


Resolving patch:
diff --git a/contrib/packs/actions/pack_mgmt/setup_virtualenv.py b/contrib/packs/actions/pack_mgmt/setup_virtualenv.py
--- a/contrib/packs/actions/pack_mgmt/setup_virtualenv.py
+++ b/contrib/packs/actions/pack_mgmt/setup_virtualenv.py
@@ -15,6 +15,7 @@
 
 import os
 import re
+import shutil
 
 from oslo_config import cfg
 
@@ -83,6 +84,9 @@ def _setup_pack_virtualenv(self, pack_name):
         if not os.path.exists(self._base_virtualenvs_path):
             os.makedirs(self._base_virtualenvs_path)
 
+        # 0. Delete virtual environment if it exists
+        self._remove_virtualenv(virtualenv_path=virtualenv_path)
+
         # 1. Create virtual environment
         self.logger.debug('Creating virtualenv for pack "%s" in "%s"' %
                           (pack_name, virtualenv_path))
@@ -126,6 +130,20 @@ def _create_virtualenv(self, virtualenv_path):
 
         return True
 
+    def _remove_virtualenv(self, virtualenv_path):
+        if not os.path.exists(virtualenv_path):
+            self.logger.info('Virtualenv path "%s" doesn\'t exist' % virtualenv_path)
+            return True
+
+        self.logger.debug('Removing virtualenv in "%s"' % virtualenv_path)
+        try:
+            shutil.rmtree(virtualenv_path)
+        except Exception as error:
+            self.logger.error('Error while removing virtualenv at "%s": "%s"' %
+                              (virtualenv_path, error))
+            raise
+        return True
+
     def _install_requirements(self, virtualenv_path, requirements_file_path):
         """
         Install requirements from a file.


Test patch: