API v2.45, adds metadata support to access rules
Added access metadata for share access and also introduced the GET /share-access-rules API. The prior API to retrieve access rules will not work with API version >=2.45 Closes-Bug: #1920687 Change-Id: Iec3a3fad5e2bdf854f04ae974248d899f90bd894
This commit is contained in:

committed by
Dina Saparbaeva

parent
eb52c16c65
commit
8b5b9cb83b
@@ -81,6 +81,21 @@ Deny access
|
|||||||
|
|
||||||
A message indicates whether the action was successful.
|
A message indicates whether the action was successful.
|
||||||
|
|
||||||
|
Edit share access metadata
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
#. Log in to the dashboard, choose a project, and click :guilabel:`Shares`.
|
||||||
|
|
||||||
|
#. Go to the share that you want to deny access and choose
|
||||||
|
:guilabel:`Manage Rules` from Actions.
|
||||||
|
|
||||||
|
#. Choose the rule you want to edit.
|
||||||
|
|
||||||
|
#. Click :guilabel:`Edit Rule Metadata`: To add share access metadata, use key=value.
|
||||||
|
To unset metadata, use key.
|
||||||
|
|
||||||
|
A message indicates whether the action was successful.
|
||||||
|
|
||||||
Edit share metadata
|
Edit share metadata
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
@@ -28,7 +28,7 @@ from manilaclient import client as manila_client
|
|||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
MANILA_UI_USER_AGENT_REPR = "manila_ui_plugin_for_horizon"
|
MANILA_UI_USER_AGENT_REPR = "manila_ui_plugin_for_horizon"
|
||||||
MANILA_VERSION = "2.44"
|
MANILA_VERSION = "2.45"
|
||||||
MANILA_SERVICE_TYPE = "sharev2"
|
MANILA_SERVICE_TYPE = "sharev2"
|
||||||
|
|
||||||
# API static values
|
# API static values
|
||||||
@@ -125,7 +125,21 @@ def share_update(request, share_id, name, description, is_public=False):
|
|||||||
|
|
||||||
|
|
||||||
def share_rules_list(request, share_id):
|
def share_rules_list(request, share_id):
|
||||||
return manilaclient(request).shares.access_list(share_id)
|
return manilaclient(request).share_access_rules.access_list(share_id)
|
||||||
|
|
||||||
|
|
||||||
|
def share_rule_get(request, rule_id):
|
||||||
|
return manilaclient(request).share_access_rules.get(rule_id)
|
||||||
|
|
||||||
|
|
||||||
|
def share_rule_set_metadata(request, rule, metadata):
|
||||||
|
return manilaclient(request).share_access_rules.set_metadata(
|
||||||
|
rule, metadata)
|
||||||
|
|
||||||
|
|
||||||
|
def share_rule_unset_metadata(request, rule, keys):
|
||||||
|
return manilaclient(request).share_access_rules.unset_metadata(
|
||||||
|
rule, keys)
|
||||||
|
|
||||||
|
|
||||||
def share_export_location_list(request, share_id):
|
def share_export_location_list(request, share_id):
|
||||||
@@ -137,9 +151,10 @@ def share_instance_export_location_list(request, share_instance_id):
|
|||||||
share_instance_id)
|
share_instance_id)
|
||||||
|
|
||||||
|
|
||||||
def share_allow(request, share_id, access_type, access_to, access_level):
|
def share_allow(request, share_id, access_type, access_to, access_level,
|
||||||
|
metadata=None):
|
||||||
return manilaclient(request).shares.allow(
|
return manilaclient(request).shares.allow(
|
||||||
share_id, access_type, access_to, access_level)
|
share_id, access_type, access_to, access_level, metadata)
|
||||||
|
|
||||||
|
|
||||||
def share_deny(request, share_id, rule_id):
|
def share_deny(request, share_id, rule_id):
|
||||||
|
@@ -334,15 +334,29 @@ class AddRule(forms.SelfHandlingForm):
|
|||||||
choices=(('rw', 'read-write'), ('ro', 'read-only'),))
|
choices=(('rw', 'read-write'), ('ro', 'read-only'),))
|
||||||
access_to = forms.CharField(
|
access_to = forms.CharField(
|
||||||
label=_("Access To"), max_length="255", required=True)
|
label=_("Access To"), max_length="255", required=True)
|
||||||
|
metadata = forms.CharField(
|
||||||
|
label=_("Metadata"), required=False,
|
||||||
|
widget=forms.Textarea(attrs={'rows': 4}))
|
||||||
|
|
||||||
def handle(self, request, data):
|
def handle(self, request, data):
|
||||||
share_id = self.initial['share_id']
|
share_id = self.initial['share_id']
|
||||||
|
metadata = {}
|
||||||
|
try:
|
||||||
|
set_dict, unset_list = utils.parse_str_meta(data['metadata'])
|
||||||
|
if unset_list:
|
||||||
|
msg = _("Expected only pairs of key=value.")
|
||||||
|
raise ValidationError(message=msg)
|
||||||
|
metadata = set_dict
|
||||||
|
except ValidationError as e:
|
||||||
|
self.api_error(e.messages[0])
|
||||||
|
return False
|
||||||
try:
|
try:
|
||||||
manila.share_allow(
|
manila.share_allow(
|
||||||
request, share_id,
|
request, share_id,
|
||||||
access_to=data['access_to'],
|
access_to=data['access_to'],
|
||||||
access_type=data['access_type'],
|
access_type=data['access_type'],
|
||||||
access_level=data['access_level'])
|
access_level=data['access_level'],
|
||||||
|
metadata=metadata)
|
||||||
message = _('Creating rule for "%s"') % data['access_to']
|
message = _('Creating rule for "%s"') % data['access_to']
|
||||||
messages.success(request, message)
|
messages.success(request, message)
|
||||||
return True
|
return True
|
||||||
@@ -353,6 +367,39 @@ class AddRule(forms.SelfHandlingForm):
|
|||||||
request, _('Unable to add rule.'), redirect=redirect)
|
request, _('Unable to add rule.'), redirect=redirect)
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateRuleMetadataForm(forms.SelfHandlingForm):
|
||||||
|
metadata = forms.CharField(widget=forms.Textarea,
|
||||||
|
label=_("Metadata"), required=False)
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(UpdateRuleMetadataForm, self).__init__(*args, **kwargs)
|
||||||
|
rule_metadata = utils.metadata_to_str(
|
||||||
|
self.initial["metadata"]
|
||||||
|
).replace('<br/>', '\r\n')
|
||||||
|
self.initial["metadata"] = rule_metadata
|
||||||
|
|
||||||
|
def handle(self, request, data):
|
||||||
|
rule_id = self.initial['rule_id']
|
||||||
|
try:
|
||||||
|
rule = manila.share_rule_get(self.request, rule_id)
|
||||||
|
set_dict, unset_list = utils.parse_str_meta(data['metadata'])
|
||||||
|
if set_dict:
|
||||||
|
manila.share_rule_set_metadata(request, rule, set_dict)
|
||||||
|
if unset_list:
|
||||||
|
manila.share_rule_unset_metadata(request, rule, unset_list)
|
||||||
|
message = _('Updating share access rule metadata ')
|
||||||
|
messages.success(request, message)
|
||||||
|
return True
|
||||||
|
except ValidationError as e:
|
||||||
|
self.api_error(e.messages[0])
|
||||||
|
return False
|
||||||
|
except Exception:
|
||||||
|
redirect = reverse("horizon:project:shares:manage_rules")
|
||||||
|
exceptions.handle(request,
|
||||||
|
_('Unable to update rule metadata.'),
|
||||||
|
redirect=redirect)
|
||||||
|
|
||||||
|
|
||||||
class ResizeForm(forms.SelfHandlingForm):
|
class ResizeForm(forms.SelfHandlingForm):
|
||||||
name = forms.CharField(
|
name = forms.CharField(
|
||||||
max_length="255", label=_("Share Name"),
|
max_length="255", label=_("Share Name"),
|
||||||
|
@@ -347,16 +347,30 @@ class DeleteRule(tables.DeleteAction):
|
|||||||
exceptions.handle(request, msg)
|
exceptions.handle(request, msg)
|
||||||
|
|
||||||
|
|
||||||
|
class EditRuleMetadata(tables.LinkAction):
|
||||||
|
name = "update_rule_metadata"
|
||||||
|
verbose_name = _("Edit Rule Metadata")
|
||||||
|
url = "horizon:project:shares:update_rule_metadata"
|
||||||
|
classes = ("ajax-modal", "btn-create")
|
||||||
|
policy_rules = (("share_access_metadata", "share_access_metadata:update"),)
|
||||||
|
|
||||||
|
def get_policy_target(self, request, datum=None):
|
||||||
|
project_id = None
|
||||||
|
if datum:
|
||||||
|
project_id = getattr(datum, "os-share-tenant-attr:tenant_id", None)
|
||||||
|
return {"project_id": project_id}
|
||||||
|
|
||||||
|
def allowed(self, request, rule=None):
|
||||||
|
return rule.state == "active"
|
||||||
|
|
||||||
|
|
||||||
class UpdateRuleRow(tables.Row):
|
class UpdateRuleRow(tables.Row):
|
||||||
ajax = True
|
ajax = True
|
||||||
|
|
||||||
def get_data(self, request, rule_id):
|
def get_data(self, request, rule_id):
|
||||||
rules = manila.share_rules_list(request, self.table.kwargs['share_id'])
|
rule = manila.share_rule_get(request, rule_id)
|
||||||
if rules:
|
rule.metadata = utils.metadata_to_str(rule.metadata)
|
||||||
for rule in rules:
|
|
||||||
if rule.id == rule_id:
|
|
||||||
return rule
|
return rule
|
||||||
raise exceptions.NotFound
|
|
||||||
|
|
||||||
|
|
||||||
class RulesTable(tables.DataTable):
|
class RulesTable(tables.DataTable):
|
||||||
@@ -364,6 +378,8 @@ class RulesTable(tables.DataTable):
|
|||||||
access_to = tables.Column("access_to", verbose_name=_("Access to"))
|
access_to = tables.Column("access_to", verbose_name=_("Access to"))
|
||||||
access_level = tables.Column(
|
access_level = tables.Column(
|
||||||
"access_level", verbose_name=_("Access Level"))
|
"access_level", verbose_name=_("Access Level"))
|
||||||
|
metadata = tables.Column(
|
||||||
|
"metadata", verbose_name=_("Metadata"))
|
||||||
status = tables.Column("state", verbose_name=_("Status"))
|
status = tables.Column("state", verbose_name=_("Status"))
|
||||||
access_key = tables.Column("access_key", verbose_name=_("Access Key"))
|
access_key = tables.Column("access_key", verbose_name=_("Access Key"))
|
||||||
created_at = tables.Column("created_at", verbose_name=_("Created At"),
|
created_at = tables.Column("created_at", verbose_name=_("Created At"),
|
||||||
@@ -383,7 +399,8 @@ class RulesTable(tables.DataTable):
|
|||||||
AddRule,
|
AddRule,
|
||||||
DeleteRule)
|
DeleteRule)
|
||||||
row_actions = (
|
row_actions = (
|
||||||
DeleteRule,)
|
DeleteRule,
|
||||||
|
EditRuleMetadata,)
|
||||||
|
|
||||||
|
|
||||||
def get_share_network(share):
|
def get_share_network(share):
|
||||||
|
@@ -0,0 +1,13 @@
|
|||||||
|
{% extends "horizon/common/_modal_form.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block modal-body-right %}
|
||||||
|
<h3>{% trans "Metadata" %}:</h3>
|
||||||
|
<p>
|
||||||
|
{% trans "One line - one action. Empty strings will be ignored." %}<br />
|
||||||
|
{% trans "To add metadata use:" %}
|
||||||
|
<pre>key=value</pre>
|
||||||
|
{% trans "To unset metadata use:" %}
|
||||||
|
<pre>key</pre>
|
||||||
|
{% trans "All pairs that are in field for left are set for this metadata." %}
|
||||||
|
</p>
|
||||||
|
{% endblock %}
|
@@ -0,0 +1,7 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block title %}{% trans "Edit Rule Metadata" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
{% include 'project/shares/_update_rule_metadata.html' %}
|
||||||
|
{% endblock %}
|
@@ -36,6 +36,10 @@ urlpatterns = [
|
|||||||
r'^(?P<share_id>[^/]+)/rule_add/$',
|
r'^(?P<share_id>[^/]+)/rule_add/$',
|
||||||
shares_views.AddRuleView.as_view(),
|
shares_views.AddRuleView.as_view(),
|
||||||
name='rule_add'),
|
name='rule_add'),
|
||||||
|
urls.url(
|
||||||
|
r'^rules/(?P<rule_id>[^/]+)/update_rule_metadata/$',
|
||||||
|
shares_views.UpdateRuleMetadataView.as_view(),
|
||||||
|
name='update_rule_metadata'),
|
||||||
urls.url(
|
urls.url(
|
||||||
r'^(?P<share_id>[^/]+)/$',
|
r'^(?P<share_id>[^/]+)/$',
|
||||||
shares_views.DetailView.as_view(),
|
shares_views.DetailView.as_view(),
|
||||||
|
@@ -249,6 +249,53 @@ class AddRuleView(forms.ModalFormView):
|
|||||||
args=[self.kwargs['share_id']])
|
args=[self.kwargs['share_id']])
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateRuleMetadataView(forms.ModalFormView):
|
||||||
|
form_class = share_form.UpdateRuleMetadataForm
|
||||||
|
form_id = ""
|
||||||
|
template_name = 'project/shares/update_rule_metadata.html'
|
||||||
|
modal_header = _("Edit Rule Metadata")
|
||||||
|
modal_id = "update_rule_metadata_modal"
|
||||||
|
submit_label = _("Save Changes")
|
||||||
|
submit_url = "horizon:project:shares:update_rule_metadata"
|
||||||
|
success_url = reverse_lazy("horizon:project:shares:index")
|
||||||
|
page_title = _('Edit Rule Metadata')
|
||||||
|
|
||||||
|
def get_object(self):
|
||||||
|
if not hasattr(self, "_object"):
|
||||||
|
rule_id = self.kwargs['rule_id']
|
||||||
|
try:
|
||||||
|
self._object = manila.share_rule_get(self.request, rule_id)
|
||||||
|
except Exception:
|
||||||
|
msg = _('Unable to retrieve share access rule.')
|
||||||
|
url = reverse('horizon:project:shares:manage_rules')
|
||||||
|
exceptions.handle(self.request, msg, redirect=url)
|
||||||
|
return self._object
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super(UpdateRuleMetadataView, self).\
|
||||||
|
get_context_data(**kwargs)
|
||||||
|
args = (self.get_object().id,)
|
||||||
|
context['submit_url'] = reverse(self.submit_url, args=args)
|
||||||
|
return context
|
||||||
|
|
||||||
|
def get_initial(self):
|
||||||
|
rule = self.get_object()
|
||||||
|
return {'rule_id': self.kwargs["rule_id"],
|
||||||
|
'metadata': rule.metadata}
|
||||||
|
|
||||||
|
# To redirect to Rules Table page, after updating the rule
|
||||||
|
# metadata. Loop is to get the share_id neccessary to display
|
||||||
|
# Rules Table page.
|
||||||
|
def get_success_url(self):
|
||||||
|
shares = manila.share_list(self.request)
|
||||||
|
for share in shares:
|
||||||
|
rules = manila.share_rules_list(self.request, share.id)
|
||||||
|
for rule in rules:
|
||||||
|
if rule.id == self.kwargs["rule_id"]:
|
||||||
|
return reverse("horizon:project:shares:manage_rules",
|
||||||
|
args=[share.id])
|
||||||
|
|
||||||
|
|
||||||
class ManageRulesView(tables.DataTableView):
|
class ManageRulesView(tables.DataTableView):
|
||||||
table_class = shares_tables.RulesTable
|
table_class = shares_tables.RulesTable
|
||||||
template_name = 'project/shares/manage_rules.html'
|
template_name = 'project/shares/manage_rules.html'
|
||||||
@@ -257,7 +304,6 @@ class ManageRulesView(tables.DataTableView):
|
|||||||
context = super(ManageRulesView, self).get_context_data(**kwargs)
|
context = super(ManageRulesView, self).get_context_data(**kwargs)
|
||||||
share = manila.share_get(self.request, self.kwargs['share_id'])
|
share = manila.share_get(self.request, self.kwargs['share_id'])
|
||||||
context['share_display_name'] = share.name or share.id
|
context['share_display_name'] = share.name or share.id
|
||||||
context["share"] = self.get_data()
|
|
||||||
context["page_title"] = _("Share Rules: "
|
context["page_title"] = _("Share Rules: "
|
||||||
"%(share_display_name)s") % {
|
"%(share_display_name)s") % {
|
||||||
'share_display_name': context['share_display_name']}
|
'share_display_name': context['share_display_name']}
|
||||||
@@ -273,6 +319,11 @@ class ManageRulesView(tables.DataTableView):
|
|||||||
exceptions.handle(self.request,
|
exceptions.handle(self.request,
|
||||||
_('Unable to retrieve share rules.'),
|
_('Unable to retrieve share rules.'),
|
||||||
redirect=redirect)
|
redirect=redirect)
|
||||||
|
return []
|
||||||
|
|
||||||
|
for rule in rules:
|
||||||
|
rule.metadata = ui_utils.metadata_to_str(rule.metadata)
|
||||||
|
|
||||||
return rules
|
return rules
|
||||||
|
|
||||||
|
|
||||||
|
@@ -103,9 +103,42 @@ class ManilaApiTests(base.APITestCase):
|
|||||||
result = api.share_rules_list(self.request, self.id)
|
result = api.share_rules_list(self.request, self.id)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.manilaclient.shares.access_list.return_value, result)
|
self.manilaclient.share_access_rules.
|
||||||
|
access_list.return_value, result)
|
||||||
|
|
||||||
self.manilaclient.shares.access_list.assert_called_once_with(self.id)
|
self.manilaclient.share_access_rules.\
|
||||||
|
access_list.assert_called_once_with(self.id)
|
||||||
|
|
||||||
|
def test_share_rule_get(self):
|
||||||
|
result = api.share_rule_get(self.request, self.id)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
self.manilaclient.share_access_rules.get.
|
||||||
|
return_value, result)
|
||||||
|
|
||||||
|
self.manilaclient.share_access_rules.get.\
|
||||||
|
assert_called_once_with(self.id)
|
||||||
|
|
||||||
|
def test_share_rule_set_metadata(self):
|
||||||
|
fake_metadata = {
|
||||||
|
"aim": "testing",
|
||||||
|
"project": "test",
|
||||||
|
}
|
||||||
|
|
||||||
|
api.share_rule_set_metadata(
|
||||||
|
self.request, self.id, fake_metadata)
|
||||||
|
|
||||||
|
self.manilaclient.share_access_rules.\
|
||||||
|
set_metadata.assert_called_once_with(self.id, fake_metadata)
|
||||||
|
|
||||||
|
def test_share_rule_unset_metadata(self):
|
||||||
|
fake_key = "test"
|
||||||
|
|
||||||
|
api.share_rule_unset_metadata(
|
||||||
|
self.request, self.id, fake_key)
|
||||||
|
|
||||||
|
self.manilaclient.share_access_rules.\
|
||||||
|
unset_metadata.assert_called_once_with(self.id, fake_key)
|
||||||
|
|
||||||
def test_list_share_export_locations(self):
|
def test_list_share_export_locations(self):
|
||||||
api.share_export_location_list(self.request, self.id)
|
api.share_export_location_list(self.request, self.id)
|
||||||
@@ -120,19 +153,22 @@ class ManilaApiTests(base.APITestCase):
|
|||||||
client.share_instance_export_locations.list.assert_called_once_with(
|
client.share_instance_export_locations.list.assert_called_once_with(
|
||||||
self.id)
|
self.id)
|
||||||
|
|
||||||
@ddt.data(("ip", "10.0.0.13", "rw"), ("ip", "10.0.0.13", None),
|
@ddt.data(("ip", "10.0.0.13", "rw", {'testkey': "testval"}),
|
||||||
("ip", "10.0.0.13", "ro"),
|
("ip", "10.0.0.13", None, None),
|
||||||
("user", "demo", "rw"),
|
("ip", "10.0.0.13", "ro", {'key1': "val1"}),
|
||||||
("user", "demo", None), ("user", "demo", "ro"),
|
("user", "demo", "rw", {'key2': "val2"}),
|
||||||
("cephx", "alice", "rw"),
|
("user", "demo", None, None),
|
||||||
("cephx", "alice", None), ("cephx", "alice", "ro"))
|
("user", "demo", "ro", None),
|
||||||
|
("cephx", "alice", "rw", {'test': "some"}),
|
||||||
|
("cephx", "alice", None, None),
|
||||||
|
("cephx", "alice", "ro", None))
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
def test_share_allow(self, access_type, access_to, access_level):
|
def test_share_allow(self, access_type, access_to, access_level, metadata):
|
||||||
api.share_allow(self.request, self.id, access_type,
|
api.share_allow(self.request, self.id, access_type,
|
||||||
access_to, access_level)
|
access_to, access_level, metadata)
|
||||||
|
|
||||||
self.manilaclient.shares.allow.assert_called_once_with(
|
self.manilaclient.shares.allow.assert_called_once_with(
|
||||||
self.id, access_type, access_to, access_level)
|
self.id, access_type, access_to, access_level, metadata)
|
||||||
|
|
||||||
def test_share_deny(self):
|
def test_share_deny(self):
|
||||||
fake_rule_id = "fake_rule_id"
|
fake_rule_id = "fake_rule_id"
|
||||||
|
@@ -300,7 +300,7 @@ class ShareViewTests(test.APITestCase):
|
|||||||
[mock.call(mock.ANY, self.share.id) for i in (1, 2)])
|
[mock.call(mock.ANY, self.share.id) for i in (1, 2)])
|
||||||
|
|
||||||
def test_list_rules(self):
|
def test_list_rules(self):
|
||||||
rules = [test_data.ip_rule, test_data.user_rule, test_data.cephx_rule]
|
rules = test_data.share_access_list
|
||||||
self.mock_object(
|
self.mock_object(
|
||||||
api_manila, "share_rules_list", mock.Mock(return_value=rules))
|
api_manila, "share_rules_list", mock.Mock(return_value=rules))
|
||||||
url = reverse(
|
url = reverse(
|
||||||
@@ -331,6 +331,7 @@ class ShareViewTests(test.APITestCase):
|
|||||||
'method': 'CreateForm',
|
'method': 'CreateForm',
|
||||||
'access_to': 'someuser',
|
'access_to': 'someuser',
|
||||||
'access_level': 'rw',
|
'access_level': 'rw',
|
||||||
|
'metadata': {},
|
||||||
}
|
}
|
||||||
|
|
||||||
res = self.client.post(url, formData)
|
res = self.client.post(url, formData)
|
||||||
@@ -338,7 +339,8 @@ class ShareViewTests(test.APITestCase):
|
|||||||
api_manila.share_allow.assert_called_once_with(
|
api_manila.share_allow.assert_called_once_with(
|
||||||
mock.ANY, self.share.id, access_type=formData['access_type'],
|
mock.ANY, self.share.id, access_type=formData['access_type'],
|
||||||
access_to=formData['access_to'],
|
access_to=formData['access_to'],
|
||||||
access_level=formData['access_level'])
|
access_level=formData['access_level'],
|
||||||
|
metadata=formData['metadata'])
|
||||||
self.assertRedirectsNoFollow(
|
self.assertRedirectsNoFollow(
|
||||||
res,
|
res,
|
||||||
reverse('horizon:project:shares:manage_rules',
|
reverse('horizon:project:shares:manage_rules',
|
||||||
@@ -360,6 +362,43 @@ class ShareViewTests(test.APITestCase):
|
|||||||
mock.ANY, self.share.id, rule.id)
|
mock.ANY, self.share.id, rule.id)
|
||||||
api_manila.share_rules_list.assert_called_with(mock.ANY, self.share.id)
|
api_manila.share_rules_list.assert_called_with(mock.ANY, self.share.id)
|
||||||
|
|
||||||
|
def test_update_share_rule_metadata_get(self):
|
||||||
|
rule = test_data.user_rule
|
||||||
|
url = reverse(
|
||||||
|
'horizon:project:shares:update_rule_metadata', args=[rule.id])
|
||||||
|
self.mock_object(
|
||||||
|
api_manila, "share_rule_get", mock.Mock(return_value=rule))
|
||||||
|
res = self.client.get(url)
|
||||||
|
api_manila.share_rule_get.assert_called_once_with(mock.ANY, rule.id)
|
||||||
|
self.assertNoMessages()
|
||||||
|
self.assertTemplateUsed(
|
||||||
|
res, 'project/shares/update_rule_metadata.html')
|
||||||
|
|
||||||
|
def test_update_share_rule_metadata_post(self):
|
||||||
|
rule = test_data.user_rule
|
||||||
|
data = {
|
||||||
|
'metadata': 'aaa=ccc',
|
||||||
|
}
|
||||||
|
form_data = {
|
||||||
|
'metadata': {'aaa': 'ccc'},
|
||||||
|
}
|
||||||
|
url = reverse(
|
||||||
|
'horizon:project:shares:update_rule_metadata', args=[rule.id])
|
||||||
|
self.mock_object(
|
||||||
|
api_manila, "share_list", mock.Mock(
|
||||||
|
return_value=test_data.shares_list))
|
||||||
|
self.mock_object(
|
||||||
|
api_manila, "share_rules_list", mock.Mock(
|
||||||
|
return_value=test_data.share_access_list))
|
||||||
|
self.mock_object(
|
||||||
|
api_manila, "share_rule_get", mock.Mock(return_value=rule))
|
||||||
|
self.mock_object(api_manila, "share_rule_set_metadata")
|
||||||
|
|
||||||
|
self.client.post(url, data)
|
||||||
|
|
||||||
|
api_manila.share_rule_set_metadata.assert_called_once_with(
|
||||||
|
mock.ANY, rule, form_data['metadata'])
|
||||||
|
|
||||||
def test_resize_share_get(self):
|
def test_resize_share_get(self):
|
||||||
share = test_data.share
|
share = test_data.share
|
||||||
url = reverse('horizon:project:shares:resize', args=[share.id])
|
url = reverse('horizon:project:shares:resize', args=[share.id])
|
||||||
|
@@ -11,10 +11,10 @@
|
|||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
import collections
|
|
||||||
|
|
||||||
from manilaclient.v2 import messages
|
from manilaclient.v2 import messages
|
||||||
from manilaclient.v2 import security_services
|
from manilaclient.v2 import security_services
|
||||||
|
from manilaclient.v2 import share_access_rules
|
||||||
from manilaclient.v2 import share_export_locations
|
from manilaclient.v2 import share_export_locations
|
||||||
from manilaclient.v2 import share_group_snapshots
|
from manilaclient.v2 import share_group_snapshots
|
||||||
from manilaclient.v2 import share_group_types
|
from manilaclient.v2 import share_group_types
|
||||||
@@ -102,6 +102,8 @@ other_share = shares.Share(
|
|||||||
'replication_type': 'readable',
|
'replication_type': 'readable',
|
||||||
'mount_snapshot_support': False})
|
'mount_snapshot_support': False})
|
||||||
|
|
||||||
|
shares_list = [share, nameless_share, other_share]
|
||||||
|
|
||||||
share_replica = share_replicas.ShareReplica(
|
share_replica = share_replicas.ShareReplica(
|
||||||
share_replicas.ShareReplicaManager(FakeAPIClient),
|
share_replicas.ShareReplicaManager(FakeAPIClient),
|
||||||
{'id': '11023e92-8008-4c8b-8059-replica00001',
|
{'id': '11023e92-8008-4c8b-8059-replica00001',
|
||||||
@@ -207,17 +209,46 @@ user_snapshot_export_locations = [
|
|||||||
'path': '1.1.1.2:/not/too/long/path/to/user/share_snapshot'}
|
'path': '1.1.1.2:/not/too/long/path/to/user/share_snapshot'}
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
ip_rule = share_access_rules.ShareAccessRule(
|
||||||
|
share_access_rules.ShareAccessRuleManager(FakeAPIClient),
|
||||||
|
{'id': 'ca8b755c-fe13-497f-81d0-fd2f13a30a78',
|
||||||
|
'access_level': 'rw',
|
||||||
|
'access_to': '1.1.1.1',
|
||||||
|
'access_type': 'ip',
|
||||||
|
'state': 'active',
|
||||||
|
'access_key': '',
|
||||||
|
'created_at': '2021-03-03T14:29:41.000000',
|
||||||
|
'updated_at': '',
|
||||||
|
"metadata": {},
|
||||||
|
})
|
||||||
|
|
||||||
rule = collections.namedtuple('Access', ['access_type', 'access_to', 'state',
|
user_rule = share_access_rules.ShareAccessRule(
|
||||||
'id', 'access_level', 'access_key'])
|
share_access_rules.ShareAccessRuleManager(FakeAPIClient),
|
||||||
|
{'id': '0837072-c49e-11e3-bd64-60a44c371189',
|
||||||
|
'access_level': 'rw',
|
||||||
|
'access_to': 'someuser',
|
||||||
|
'access_type': 'user',
|
||||||
|
'state': 'active',
|
||||||
|
'access_key': '',
|
||||||
|
'created_at': '2021-03-03T14:29:41.000000',
|
||||||
|
'updated_at': '',
|
||||||
|
'metadata': {'abc': 'ddd'},
|
||||||
|
})
|
||||||
|
|
||||||
user_rule = rule('user', 'someuser', 'active',
|
cephx_rule = share_access_rules.ShareAccessRule(
|
||||||
'10837072-c49e-11e3-bd64-60a44c371189', 'rw', '')
|
share_access_rules.ShareAccessRuleManager(FakeAPIClient),
|
||||||
ip_rule = rule('ip', '1.1.1.1', 'active',
|
{'id': '235481bc-1a84-11e6-9666-68f728a0492e',
|
||||||
'2cc8e2f8-c49e-11e3-bd64-60a44c371189', 'rw', '')
|
'access_level': 'rw',
|
||||||
cephx_rule = rule('cephx', 'alice', 'active',
|
'access_to': 'alice',
|
||||||
'235481bc-1a84-11e6-9666-68f728a0492e', 'rw',
|
'access_type': 'cephx',
|
||||||
'AQAdFCNYDCapMRAANuK/CiEZbog2911a+t5dcQ==')
|
'state': 'active',
|
||||||
|
'access_key': 'AQAdFCNYDCapMRAANuK/CiEZbog2911a+t5dcQ==',
|
||||||
|
'created_at': '2021-03-03T14:29:41.000000',
|
||||||
|
'updated_at': '',
|
||||||
|
'metadata': {'test': 'true'},
|
||||||
|
})
|
||||||
|
|
||||||
|
share_access_list = [user_rule, cephx_rule, ip_rule]
|
||||||
|
|
||||||
snapshot = share_snapshots.ShareSnapshot(
|
snapshot = share_snapshots.ShareSnapshot(
|
||||||
share_snapshots.ShareSnapshotManager(FakeAPIClient),
|
share_snapshots.ShareSnapshotManager(FakeAPIClient),
|
||||||
|
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Added access metadata for share access and
|
||||||
|
also introduced the GET /share-access-rules API.
|
Reference in New Issue
Block a user