diff --git a/circle/dashboard/static/dashboard/vm-common.js b/circle/dashboard/static/dashboard/vm-common.js
index bc3f0ef..fb4d0b6 100644
--- a/circle/dashboard/static/dashboard/vm-common.js
+++ b/circle/dashboard/static/dashboard/vm-common.js
@@ -3,7 +3,7 @@
 $(function() {
 
   /* vm operations */
-  $('#ops, #vm-details-resources-disk, #vm-details-renew-op, #vm-details-pw-reset, #vm-details-add-interface').on('click', '.operation', function(e) {
+  $('#ops, #vm-details-resources-disk, #vm-details-renew-op, #vm-details-pw-reset, #vm-details-add-interface, .operation-wrapper').on('click', '.operation', function(e) {
     var icon = $(this).children("i").addClass('fa-spinner fa-spin');
 
     $.ajax({
diff --git a/circle/dashboard/templates/dashboard/vm-detail/home.html b/circle/dashboard/templates/dashboard/vm-detail/home.html
index 536b5eb..1ec326f 100644
--- a/circle/dashboard/templates/dashboard/vm-detail/home.html
+++ b/circle/dashboard/templates/dashboard/vm-detail/home.html
@@ -100,6 +100,20 @@
         {% endif %}
       </dd>
     </dl>
+
+    {% if op.mount_store %}
+      <strong>{% trans "Store" %}</strong>
+      <p>
+        {{ op.mount_store.description }}
+      </p>
+      <div class="operation-wrapper">
+        <a href="{{ op.mount_store.get_url }}" class="btn btn-info btn-xs operation"
+        {% if op.mount_store.disabled %}disabled{% endif %}>
+          <i class="fa fa-{{op.mount_store.icon}}"></i>
+          {{ op.mount_store.name }}
+        </a>
+      </div>
+    {% endif %}
   </div>
   <div class="col-md-8">
     {% if graphite_enabled %}
diff --git a/circle/dashboard/views.py b/circle/dashboard/views.py
index 1924e37..33d3954 100644
--- a/circle/dashboard/views.py
+++ b/circle/dashboard/views.py
@@ -966,6 +966,10 @@ vm_ops = OrderedDict([
     ('password_reset', VmOperationView.factory(
         op='password_reset', icon='unlock', effect='warning',
         show_in_toolbar=False, wait_for_result=0.5, with_reload=True)),
+    ('mount_store', VmOperationView.factory(
+        op='mount_store', icon='briefcase', effect='info',
+        show_in_toolbar=False,
+    )),
 ])
 
 
diff --git a/circle/vm/models/instance.py b/circle/vm/models/instance.py
index 236a8d0..4335a8b 100644
--- a/circle/vm/models/instance.py
+++ b/circle/vm/models/instance.py
@@ -293,6 +293,10 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
         message = ugettext_noop(
             "Instance %(instance)s has already been destroyed.")
 
+    class NoAgentError(InstanceError):
+        message = ugettext_noop(
+            "No agent software is running on instance %(instance)s.")
+
     class WrongStateError(InstanceError):
         message = ugettext_noop(
             "Current state (%(state)s) of instance %(instance)s is "
diff --git a/circle/vm/operations.py b/circle/vm/operations.py
index b3f3412..5f7322e 100644
--- a/circle/vm/operations.py
+++ b/circle/vm/operations.py
@@ -19,10 +19,12 @@ from __future__ import absolute_import, unicode_literals
 from logging import getLogger
 from re import search
 from string import ascii_lowercase
+from urlparse import urlsplit
 
 from django.core.exceptions import PermissionDenied
 from django.utils import timezone
 from django.utils.translation import ugettext_lazy as _, ugettext_noop
+from django.conf import settings
 
 from sizefield.utils import filesizeformat
 
@@ -41,6 +43,8 @@ from .models import (
 )
 from .tasks import agent_tasks
 
+from dashboard.store_api import Store, NoStoreException
+
 logger = getLogger(__name__)
 
 
@@ -934,8 +938,27 @@ class ResourcesOperation(InstanceOperation):
 register_operation(ResourcesOperation)
 
 
-class PasswordResetOperation(InstanceOperation):
-    activity_code_suffix = 'Password reset'
+class EnsureAgentMixin(object):
+    accept_states = ('RUNNING', )
+
+    def check_precond(self):
+        super(EnsureAgentMixin, self).check_precond()
+
+        last_boot_time = self.instance.activity_log.filter(
+            succeeded=True, activity_code__in=(
+                "vm.Instance.deploy", "vm.Instance.reset",
+                "vm.Instance.reboot")).latest("finished").finished
+
+        try:
+            InstanceActivity.objects.filter(
+                activity_code="vm.Instance.agent.starting",
+                started__gt=last_boot_time).latest("started")
+        except InstanceActivity.DoesNotExist:  # no agent since last boot
+            raise self.instance.NoAgentError(self.instance)
+
+
+class PasswordResetOperation(EnsureAgentMixin, InstanceOperation):
+    activity_code_suffix = 'password_reset'
     id = 'password_reset'
     name = _("password reset")
     description = _("Generate and set a new login password on the virtual "
@@ -945,7 +968,6 @@ class PasswordResetOperation(InstanceOperation):
                     "it.")
     acl_level = "owner"
     required_perms = ()
-    accept_states = ('RUNNING', )
 
     def _operation(self):
         self.instance.pw = pwgen()
@@ -956,3 +978,34 @@ class PasswordResetOperation(InstanceOperation):
 
 
 register_operation(PasswordResetOperation)
+
+
+class MountStoreOperation(EnsureAgentMixin, InstanceOperation):
+    activity_code_suffix = 'mount_store'
+    id = 'mount_store'
+    name = _("mount store")
+    description = _(
+        "This operation attaches your personal file store. Other users who "
+        "have access to this machine can see these files as well."
+    )
+    acl_level = "owner"
+    required_perms = ()
+
+    def check_auth(self, user):
+        super(MountStoreOperation, self).check_auth(user)
+        try:
+            Store(user)
+        except NoStoreException:
+            raise PermissionDenied  # not show the button at all
+
+    def _operation(self):
+        inst = self.instance
+        queue = self.instance.get_remote_queue_name("agent")
+        host = urlsplit(settings.STORE_URL).hostname
+        username = Store(inst.owner).username
+        password = inst.owner.profile.smb_password
+        agent_tasks.mount_store.apply_async(
+            queue=queue, args=(inst.vm_name, host, username, password))
+
+
+register_operation(MountStoreOperation)