diff --git a/doc/source/user/index.rst b/doc/source/user/index.rst
index d605df1f..16c64480 100644
--- a/doc/source/user/index.rst
+++ b/doc/source/user/index.rst
@@ -112,17 +112,22 @@ Edit share
A message indicates whether the action was successful.
-Extend share
+Resize share
------------
#. Log in to the dashboard, choose a project, and click :guilabel:`Shares`.
-#. Go to the share that you want to edit and choose :guilabel:`Extend Share`
+#. Go to the share that you want to edit and choose :guilabel:`Resize Share`
from Actions.
-#. :guilabel:`New Size (GB)`: Enter new size.
+#. :guilabel:`New Size (GB)`: Enter new size. It can be increased or decreased
+ from the original size. The size of the share cannot be lower than the size
+ of the data stored in the share.
+
+ If increased, the size of the share will be extended.
+ If decreased, the size of the share will be shrinked.
-#. Click :guilabel:`Extend Share`.
+#. Click :guilabel:`Resize Share`.
A message indicates whether the action was successful.
diff --git a/manila_ui/api/manila.py b/manila_ui/api/manila.py
index f8800ce2..e08d9903 100644
--- a/manila_ui/api/manila.py
+++ b/manila_ui/api/manila.py
@@ -194,8 +194,11 @@ def share_unmanage(request, share):
return manilaclient(request).shares.unmanage(share)
-def share_extend(request, share_id, new_size):
- return manilaclient(request).shares.extend(share_id, new_size)
+def share_resize(request, share_id, new_size, orig_size):
+ if orig_size > new_size:
+ return manilaclient(request).shares.shrink(share_id, new_size)
+ else:
+ return manilaclient(request).shares.extend(share_id, new_size)
def share_revert(request, share, snapshot):
diff --git a/manila_ui/dashboards/project/shares/forms.py b/manila_ui/dashboards/project/shares/forms.py
index 1684bc69..33739201 100644
--- a/manila_ui/dashboards/project/shares/forms.py
+++ b/manila_ui/dashboards/project/shares/forms.py
@@ -26,6 +26,7 @@ from manila_ui.api import manila
from manila_ui.dashboards import utils
from manila_ui import features
from manilaclient.common.apiclient import exceptions as m_exceptions
+import time
class CreateForm(forms.SelfHandlingForm):
@@ -346,7 +347,7 @@ class AddRule(forms.SelfHandlingForm):
request, _('Unable to add rule.'), redirect=redirect)
-class ExtendForm(forms.SelfHandlingForm):
+class ResizeForm(forms.SelfHandlingForm):
name = forms.CharField(
max_length="255", label=_("Share Name"),
widget=forms.TextInput(attrs={'readonly': 'readonly'}),
@@ -360,16 +361,21 @@ class ExtendForm(forms.SelfHandlingForm):
)
new_size = forms.IntegerField(
- label=_("New Size (GiB)"),
+ label=_("New Size (GiB)")
)
def clean(self):
- cleaned_data = super(ExtendForm, self).clean()
+ cleaned_data = super(ResizeForm, self).clean()
new_size = cleaned_data.get('new_size')
orig_size = self.initial['orig_size']
- if new_size <= orig_size:
- message = _("New size must be greater than current size.")
+ if new_size == orig_size:
+ message = _("New size must be different than the existing size")
+ self._errors["new_size"] = self.error_class([message])
+ return cleaned_data
+
+ if new_size <= 0:
+ message = _("New size should not be less than or equal to zero")
self._errors["new_size"] = self.error_class([message])
return cleaned_data
@@ -386,16 +392,33 @@ class ExtendForm(forms.SelfHandlingForm):
def handle(self, request, data):
share_id = self.initial['share_id']
+ new_size = data['new_size']
+ orig_size = data['orig_size']
try:
- manila.share_extend(request, share_id, data['new_size'])
- message = _('Extend share "%s"') % data['name']
- messages.success(request, message)
- return True
+ manila.share_resize(request, share_id, new_size, orig_size)
+ return self.check_size(request, share_id, new_size)
except Exception:
redirect = reverse("horizon:project:shares:index")
- exceptions.handle(request,
- _('Unable to extend share.'),
- redirect=redirect)
+ exceptions.handle(request, _(
+ 'Unable to resize share.'), redirect=redirect)
+
+ def check_size(self, request, share_id, new_size):
+ share = manila.share_get(request, share_id)
+ timeout = 30
+ interval = 0.35
+ time_elapsed = 0
+ while share.status != 'available':
+ time.sleep(interval)
+ time_elapsed += interval
+ share = manila.share_get(request, share_id)
+ if time_elapsed > timeout:
+ break
+
+ if share.size == new_size:
+ message = _('Resized share "%s"') % share.name
+ messages.success(request, message)
+ return True
+ raise Exception
class RevertForm(forms.SelfHandlingForm):
diff --git a/manila_ui/dashboards/project/shares/tables.py b/manila_ui/dashboards/project/shares/tables.py
index 259306c4..ecabf233 100644
--- a/manila_ui/dashboards/project/shares/tables.py
+++ b/manila_ui/dashboards/project/shares/tables.py
@@ -142,12 +142,12 @@ class EditShareMetadata(tables.LinkAction):
return share.status in ("available", "in-use")
-class ExtendShare(tables.LinkAction):
- name = "extend_share"
- verbose_name = _("Extend Share")
- url = "horizon:project:shares:extend"
+class ResizeShare(tables.LinkAction):
+ name = "resize_share"
+ verbose_name = _("Resize Share")
+ url = "horizon:project:shares:resize"
classes = ("ajax-modal", "btn-create")
- policy_rules = (("share", "share:extend"),)
+ policy_rules = (("share", "share:resize"),)
def get_policy_target(self, request, datum=None):
project_id = None
@@ -213,6 +213,8 @@ class SharesTableBase(tables.DataTable):
("MANAGE_ERROR", False),
("UNMANAGE_ERROR", False),
("extending_error", False),
+ ("shrinking_error", False),
+ ("shrinking_possible_data_loss_error", False),
("reverting_error", False),
)
STATUS_DISPLAY_CHOICES = (
@@ -237,6 +239,10 @@ class SharesTableBase(tables.DataTable):
u"Unmanage Error")),
("extending_error", pgettext_lazy("Current status of share",
u"Extending Error")),
+ ("shrinking_error", pgettext_lazy("Current status of share",
+ u"Shrinking Error")),
+ ("shrinking_possible_data_loss_error", pgettext_lazy(
+ "Current status of share", u"Shrinking Error")),
("reverting_error", pgettext_lazy("Current status of share",
u"Reverting Error")),
)
@@ -411,7 +417,7 @@ class SharesTable(SharesTableBase):
DeleteShare)
row_actions = (
EditShare,
- ExtendShare,
+ ResizeShare,
RevertShare,
ss_tables.CreateShareSnapshot,
ManageRules,
diff --git a/manila_ui/dashboards/project/shares/templates/shares/_extend.html b/manila_ui/dashboards/project/shares/templates/shares/_resize.html
similarity index 71%
rename from manila_ui/dashboards/project/shares/templates/shares/_extend.html
rename to manila_ui/dashboards/project/shares/templates/shares/_resize.html
index 8d87895c..b896de8e 100644
--- a/manila_ui/dashboards/project/shares/templates/shares/_extend.html
+++ b/manila_ui/dashboards/project/shares/templates/shares/_resize.html
@@ -2,6 +2,6 @@
{% load i18n %}
{% block modal-body-right %}
- {% include "project/shares/_extend_limits.html" with usages=usages %}
+ {% include "project/shares/_resize_limits.html" with usages=usages %}
{% endblock %}
diff --git a/manila_ui/dashboards/project/shares/templates/shares/_extend_limits.html b/manila_ui/dashboards/project/shares/templates/shares/_resize_limits.html
similarity index 95%
rename from manila_ui/dashboards/project/shares/templates/shares/_extend_limits.html
rename to manila_ui/dashboards/project/shares/templates/shares/_resize_limits.html
index 0e37fe27..ba75e500 100644
--- a/manila_ui/dashboards/project/shares/templates/shares/_extend_limits.html
+++ b/manila_ui/dashboards/project/shares/templates/shares/_resize_limits.html
@@ -2,7 +2,7 @@
{% trans "Description" %}:
-{% trans "Extend the size of a share. " %}
+{% trans "Resize the size of a share. " %}
{% trans "Share Limits" %}
diff --git a/manila_ui/dashboards/project/shares/templates/shares/extend.html b/manila_ui/dashboards/project/shares/templates/shares/extend.html
deleted file mode 100644
index 9658518f..00000000
--- a/manila_ui/dashboards/project/shares/templates/shares/extend.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends 'base.html' %}
-{% load i18n %}
-{% block title %}{% trans "Extend Share" %}{% endblock %}
-
-{% block main %}
- {% include 'project/shares/_extend.html' %}
-{% endblock %}
diff --git a/manila_ui/dashboards/project/shares/templates/shares/resize.html b/manila_ui/dashboards/project/shares/templates/shares/resize.html
new file mode 100644
index 00000000..bc6d210a
--- /dev/null
+++ b/manila_ui/dashboards/project/shares/templates/shares/resize.html
@@ -0,0 +1,7 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Resize Share" %}{% endblock %}
+
+{% block main %}
+ {% include 'project/shares/_resize.html' %}
+{% endblock %}
diff --git a/manila_ui/dashboards/project/shares/urls.py b/manila_ui/dashboards/project/shares/urls.py
index 4508e5a3..7d81011b 100644
--- a/manila_ui/dashboards/project/shares/urls.py
+++ b/manila_ui/dashboards/project/shares/urls.py
@@ -49,9 +49,9 @@ urlpatterns = [
shares_views.UpdateMetadataView.as_view(),
name='update_metadata'),
urls.url(
- r'^(?P[^/]+)/extend/$',
- shares_views.ExtendView.as_view(),
- name='extend'),
+ r'^(?P[^/]+)/resize/$',
+ shares_views.ResizeView.as_view(),
+ name='resize'),
urls.url(
r'^(?P[^/]+)/revert/$',
shares_views.RevertView.as_view(),
diff --git a/manila_ui/dashboards/project/shares/views.py b/manila_ui/dashboards/project/shares/views.py
index 288037d3..019adb66 100644
--- a/manila_ui/dashboards/project/shares/views.py
+++ b/manila_ui/dashboards/project/shares/views.py
@@ -276,16 +276,16 @@ class ManageRulesView(tables.DataTableView):
return rules
-class ExtendView(forms.ModalFormView):
- form_class = share_form.ExtendForm
- form_id = "extend_share"
- template_name = 'project/shares/extend.html'
- modal_header = _("Extend Share")
- modal_id = "extend_share_modal"
- submit_label = _("Extend")
- submit_url = "horizon:project:shares:extend"
+class ResizeView(forms.ModalFormView):
+ form_class = share_form.ResizeForm
+ form_id = "resize_share"
+ template_name = 'project/shares/resize.html'
+ modal_header = _("Resize Share")
+ modal_id = "resize_share_modal"
+ submit_label = _("Resize")
+ submit_url = "horizon:project:shares:resize"
success_url = reverse_lazy("horizon:project:shares:index")
- page_title = _('Extend Share')
+ page_title = _('Resize Share')
@memoized.memoized_method
def get_object(self):
@@ -295,7 +295,7 @@ class ExtendView(forms.ModalFormView):
exceptions.handle(self.request, _('Unable to retrieve share.'))
def get_context_data(self, **kwargs):
- context = super(ExtendView, self).get_context_data(**kwargs)
+ context = super(ResizeView, self).get_context_data(**kwargs)
args = (self.get_object().id,)
context['submit_url'] = reverse(self.submit_url, args=args)
try:
@@ -315,7 +315,7 @@ class ExtendView(forms.ModalFormView):
'share_id': self.kwargs["share_id"],
'name': share.name or share.id,
'orig_size': share.size,
- 'new_size': int(share.size) + 1,
+ 'new_size': int(share.size),
}
diff --git a/manila_ui/tests/api/test_manila.py b/manila_ui/tests/api/test_manila.py
index 02684f2d..fdeaa738 100644
--- a/manila_ui/tests/api/test_manila.py
+++ b/manila_ui/tests/api/test_manila.py
@@ -210,15 +210,18 @@ class ManilaApiTests(base.APITestCase):
assert_called_once_with('fake_share'))
# Share resize tests
-
- def test_share_extend(self):
- new_size = "123"
-
- api.share_extend(self.request, self.id, new_size)
-
- self.manilaclient.shares.extend.assert_called_once_with(
- self.id, new_size
- )
+ @ddt.data(("123", "78"), ("2", "5"),
+ ("75", "21"), ("0", "2"),
+ ("18", "62"), ("-1", "3"))
+ @ddt.unpack
+ def test_share_resize(self, new_size, orig_size):
+ api.share_resize(self.request, self.id, new_size, orig_size)
+ if orig_size > new_size:
+ self.manilaclient.shares.shrink.assert_called_once_with(
+ self.id, new_size)
+ else:
+ self.manilaclient.shares.extend.assert_called_once_with(
+ self.id, new_size)
# Share snapshots tests
diff --git a/manila_ui/tests/dashboards/project/shares/tests.py b/manila_ui/tests/dashboards/project/shares/tests.py
index 0df98e18..f5c01fc0 100644
--- a/manila_ui/tests/dashboards/project/shares/tests.py
+++ b/manila_ui/tests/dashboards/project/shares/tests.py
@@ -354,9 +354,9 @@ class ShareViewTests(test.APITestCase):
mock.ANY, self.share.id, rule.id)
api_manila.share_rules_list.assert_called_with(mock.ANY, self.share.id)
- def test_extend_share_get(self):
+ def test_resize_share_get(self):
share = test_data.share
- url = reverse('horizon:project:shares:extend', args=[share.id])
+ url = reverse('horizon:project:shares:resize', args=[share.id])
self.mock_object(
neutron, "is_service_enabled", mock.Mock(return_value=[True]))
@@ -364,24 +364,24 @@ class ShareViewTests(test.APITestCase):
api_manila.share_get.assert_called_once_with(mock.ANY, share.id)
self.assertNoMessages()
- self.assertTemplateUsed(res, 'project/shares/extend.html')
+ self.assertTemplateUsed(res, 'project/shares/resize.html')
- def test_extend_share_open_form_successfully(self):
+ def test_resize_share_open_form_successfully(self):
self.share.size = 5
- url = reverse('horizon:project:shares:extend', args=[self.share.id])
- self.mock_object(api_manila, "share_extend")
+ url = reverse('horizon:project:shares:resize', args=[self.share.id])
+ self.mock_object(api_manila, "share_resize")
response = self.client.get(url)
self.assertEqual(200, response.status_code)
- self.assertTemplateUsed(response, 'project/shares/extend.html')
+ self.assertTemplateUsed(response, 'project/shares/resize.html')
api_manila.share_get.assert_called_once_with(mock.ANY, self.share.id)
- self.assertFalse(api_manila.share_extend.called)
+ self.assertFalse(api_manila.share_resize.called)
api_manila.tenant_absolute_limits.assert_called_once_with(mock.ANY)
- def test_extend_share_get_with_api_exception(self):
- url = reverse('horizon:project:shares:extend', args=[self.share.id])
- self.mock_object(api_manila, "share_extend")
+ def test_resize_share_get_with_api_exception(self):
+ url = reverse('horizon:project:shares:resize', args=[self.share.id])
+ self.mock_object(api_manila, "share_resize")
self.mock_object(
api_manila, "share_get",
mock.Mock(return_value=Exception('Fake share NotFound exception')))
@@ -390,22 +390,22 @@ class ShareViewTests(test.APITestCase):
self.assertEqual(404, response.status_code)
self.assertTemplateNotUsed(
- response, 'project/shares/shares/extend.html')
- self.assertFalse(api_manila.share_extend.called)
+ response, 'project/shares/shares/resize.html')
+ self.assertFalse(api_manila.share_resize.called)
api_manila.share_get.assert_called_once_with(mock.ANY, self.share.id)
self.assertFalse(api_manila.tenant_absolute_limits.called)
- @ddt.data(6, 54, 55)
- def test_extend_share_post_successfully(self, new_size):
+ @ddt.data(6, 54, 1, 2, 21)
+ def test_resize_share_post_successfully(self, new_size):
self.share.size = 5
- form_data = {'new_size': new_size}
+ form_data = {'new_size': new_size, 'orig_size': self.share.size}
usage_limit = {
'maxTotalShareGigabytes': self.share.size + 50,
'totalShareGigabytesUsed': self.share.size,
}
- url = reverse('horizon:project:shares:extend', args=[self.share.id])
- self.mock_object(api_manila, "share_extend")
+ url = reverse('horizon:project:shares:resize', args=[self.share.id])
+ self.mock_object(api_manila, "share_resize")
self.mock_object(
api_manila, 'tenant_absolute_limits',
mock.Mock(return_value=usage_limit))
@@ -414,23 +414,28 @@ class ShareViewTests(test.APITestCase):
self.assertEqual(302, response.status_code)
self.assertTemplateNotUsed(
- response, 'project/shares/extend.html')
- api_manila.share_get.assert_called_once_with(mock.ANY, self.share.id)
- api_manila.share_extend.assert_called_once_with(
- mock.ANY, self.share.id, form_data['new_size'])
+ response, 'project/shares/resize.html')
+ calls = [
+ mock.call(mock.ANY, self.share.id),
+ mock.call(mock.ANY, self.share.id)]
+ api_manila.share_get.assert_has_calls(calls)
+ api_manila.share_resize.assert_called_once_with(
+ mock.ANY, self.share.id, form_data['new_size'],
+ form_data['orig_size'])
api_manila.tenant_absolute_limits.assert_called_once_with(mock.ANY)
self.assertRedirectsNoFollow(response, INDEX_URL)
- @ddt.data(0, 5, 56)
- def test_extend_share_post_with_invalid_value(self, new_size):
+ @ddt.data(5, 56, 0, -1)
+ def test_resize_share_post_with_invalid_value(self, new_size):
self.share.size = 5
- form_data = {'new_size': new_size}
- url = reverse('horizon:project:shares:extend', args=[self.share.id])
+ form_data = {'new_size': new_size, 'orig_size': self.share.size}
+
+ url = reverse('horizon:project:shares:resize', args=[self.share.id])
usage_limit = {
'maxTotalShareGigabytes': self.share.size + 50,
'totalShareGigabytesUsed': self.share.size,
}
- self.mock_object(api_manila, "share_extend")
+ self.mock_object(api_manila, "share_resize")
self.mock_object(
api_manila, 'tenant_absolute_limits',
mock.Mock(return_value=usage_limit))
@@ -438,27 +443,31 @@ class ShareViewTests(test.APITestCase):
response = self.client.post(url, form_data)
self.assertEqual(200, response.status_code)
- self.assertTemplateUsed(response, 'project/shares/extend.html')
- self.assertFalse(api_manila.share_extend.called)
+ self.assertTemplateUsed(response, 'project/shares/resize.html')
+ self.assertFalse(api_manila.share_resize.called)
api_manila.share_get.assert_called_once_with(mock.ANY, self.share.id)
api_manila.tenant_absolute_limits.assert_called_with(mock.ANY)
- def test_extend_share_post_with_api_exception(self):
+ def test_resize_share_post_with_api_exception(self):
self.share.size = 5
- form_data = {'new_size': 30}
- url = reverse('horizon:project:shares:extend', args=[self.share.id])
+ form_data = {'new_size': 30, 'orig_size': self.share.size}
+ url = reverse('horizon:project:shares:resize', args=[self.share.id])
self.mock_object(
- api_manila, "share_extend",
+ api_manila, "share_resize",
mock.Mock(return_value=Exception('Fake API exception')))
response = self.client.post(url, form_data)
self.assertEqual(302, response.status_code)
self.assertTemplateNotUsed(
- response, 'project/shares/extend.html')
- api_manila.share_extend.assert_called_once_with(
- mock.ANY, self.share.id, form_data['new_size'])
- api_manila.share_get.assert_called_once_with(mock.ANY, self.share.id)
+ response, 'project/shares/resize.html')
+ api_manila.share_resize.assert_called_once_with(
+ mock.ANY, self.share.id, form_data['new_size'],
+ form_data['orig_size'])
+ calls = [
+ mock.call(mock.ANY, self.share.id),
+ mock.call(mock.ANY, self.share.id)]
+ api_manila.share_get.assert_has_calls(calls)
api_manila.tenant_absolute_limits.assert_called_once_with(mock.ANY)
self.assertRedirectsNoFollow(response, INDEX_URL)
diff --git a/releasenotes/notes/share-shrinking-c1d46fc1c3ce29b7.yaml b/releasenotes/notes/share-shrinking-c1d46fc1c3ce29b7.yaml
new file mode 100644
index 00000000..4cd1276b
--- /dev/null
+++ b/releasenotes/notes/share-shrinking-c1d46fc1c3ce29b7.yaml
@@ -0,0 +1,6 @@
+---
+features:
+ - |
+ Existing "Extend Share" feature in Manila-UI was renamed
+ "Resize Share" and share shrinking feature was added. Now
+ users can both extend and shrink shares.