diff --git a/openstack_dashboard/dashboards/project/containers/browsers.py b/openstack_dashboard/dashboards/project/containers/browsers.py
deleted file mode 100644
index 5b1c40c34..000000000
--- a/openstack_dashboard/dashboards/project/containers/browsers.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 2012 Nebula, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from django.utils.translation import ugettext_lazy as _
-
-from horizon import browsers
-
-from openstack_dashboard.dashboards.project.containers import tables
-
-
-class ContainerBrowser(browsers.ResourceBrowser):
- name = "swift"
- verbose_name = _("Swift")
- navigation_table_class = tables.ContainersTable
- content_table_class = tables.ObjectsTable
- navigable_item_name = _("Container")
- navigation_kwarg_name = "container_name"
- content_kwarg_name = "subfolder_path"
- has_breadcrumb = True
- breadcrumb_url = "horizon:project:containers:index"
diff --git a/openstack_dashboard/dashboards/project/containers/forms.py b/openstack_dashboard/dashboards/project/containers/forms.py
deleted file mode 100644
index 4e08f2b32..000000000
--- a/openstack_dashboard/dashboards/project/containers/forms.py
+++ /dev/null
@@ -1,244 +0,0 @@
-# Copyright 2012 United States Government as represented by the
-# Administrator of the National Aeronautics and Space Administration.
-# All Rights Reserved.
-#
-# Copyright 2012 Nebula, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from django.core.urlresolvers import reverse
-from django.core import validators
-from django.utils.encoding import force_text
-from django.utils.translation import pgettext_lazy
-from django.utils.translation import ugettext_lazy as _
-
-from horizon import exceptions
-from horizon import forms
-from horizon import messages
-
-from openstack_dashboard import api
-from openstack_dashboard.dashboards.project.containers import utils
-
-
-no_slash_validator = validators.RegexValidator(r'^(?u)[^/]+$',
- _("Slash is not an allowed "
- "character."),
- code="noslash")
-no_begin_or_end_slash = validators.RegexValidator(r'^[^\/](?u).+[^\/]$',
- _("Slash is not allowed at "
- "the beginning or end of "
- "your string."),
- code="nobeginorendslash")
-
-
-class CreateContainer(forms.SelfHandlingForm):
- ACCESS_CHOICES = (
- ("private", _("Private")),
- ("public", _("Public")),
- )
-
- parent = forms.CharField(max_length=255,
- required=False,
- widget=forms.HiddenInput)
- name = forms.CharField(max_length=255,
- label=_("Container Name"),
- validators=[no_slash_validator])
- access = forms.ThemableChoiceField(label=_("Container Access"),
- choices=ACCESS_CHOICES)
-
- def handle(self, request, data):
- try:
- if not data['parent']:
- is_public = data["access"] == "public"
- metadata = ({'is_public': is_public})
- # Create a container
- api.swift.swift_create_container(request,
- data["name"],
- metadata=metadata)
- messages.success(request, _("Container created successfully."))
- else:
- # Create a pseudo-folder
- container, slash, remainder = data['parent'].partition("/")
- remainder = remainder.rstrip("/")
- subfolder_name = "/".join([bit for bit
- in (remainder, data['name'])
- if bit])
- api.swift.swift_create_subfolder(request,
- container,
- subfolder_name)
- messages.success(request, _("Folder created successfully."))
- return True
- except Exception:
- exceptions.handle(request, _('Unable to create container.'))
-
-
-class UploadObject(forms.SelfHandlingForm):
- path = forms.CharField(max_length=255,
- required=False,
- widget=forms.HiddenInput)
- object_file = forms.FileField(label=_("File"),
- required=False,
- allow_empty_file=True)
- name = forms.CharField(max_length=255,
- label=_("Object Name"),
- help_text=_("Slashes are allowed, and are treated "
- "as pseudo-folders by the Object "
- "Store."),
- widget=forms.TextInput(
- attrs={"ng-model": "name",
- "not-blank": ""}
- ))
- container_name = forms.CharField(widget=forms.HiddenInput())
-
- def _set_object_path(self, data):
- if data['path']:
- object_path = "/".join([data['path'].rstrip("/"), data['name']])
- else:
- object_path = data['name']
- return object_path
-
- def clean(self):
- data = super(UploadObject, self).clean()
- if 'object_file' not in self.files:
- self.files['object_file'] = None
-
- return data
-
- def handle(self, request, data):
- object_file = self.files['object_file']
- object_path = self._set_object_path(data)
- try:
- obj = api.swift.swift_upload_object(request,
- data['container_name'],
- object_path,
- object_file)
- msg = force_text(_("Object was successfully uploaded."))
- messages.success(request, msg)
- return obj
- except Exception:
- exceptions.handle(request, _("Unable to upload object."))
-
-
-class UpdateObject(UploadObject):
- def __init__(self, *args, **kwargs):
- super(UpdateObject, self).__init__(*args, **kwargs)
- self.fields['name'].widget = forms.TextInput(
- attrs={"readonly": "readonly"})
- self.fields['name'].help_text = None
-
- def handle(self, request, data):
- object_file = self.files.get('object_file')
- if object_file:
- object_path = self._set_object_path(data)
- try:
- obj = api.swift.swift_upload_object(request,
- data['container_name'],
- object_path,
- object_file)
- messages.success(
- request, _("Object was successfully updated."))
- return obj
- except Exception:
- exceptions.handle(request, _("Unable to update object."))
- return False
- else:
- # If object file is not provided, then a POST method is needed
- # to update ONLY metadata. This must be implemented when
- # object metadata can be updated from this panel.
- return True
-
-
-class CreatePseudoFolder(forms.SelfHandlingForm):
- path = forms.CharField(max_length=255,
- required=False,
- widget=forms.HiddenInput)
- name = forms.CharField(max_length=255,
- label=_("Pseudo-folder Name"),
- validators=[no_begin_or_end_slash])
- container_name = forms.CharField(widget=forms.HiddenInput())
-
- def _set_pseudo_folder_path(self, data):
- if data['path']:
- pseudo_folder_path = "/".join([data['path'].rstrip("/"),
- data['name']]) + "/"
- else:
- pseudo_folder_path = data['name'] + "/"
- return pseudo_folder_path
-
- def handle(self, request, data):
- pseudo_folder_path = self._set_pseudo_folder_path(data)
- try:
- obj = api.swift.swift_create_pseudo_folder(request,
- data['container_name'],
- pseudo_folder_path)
- messages.success(request,
- _("Pseudo-folder was successfully created."))
- return obj
-
- except Exception:
- exceptions.handle(request, _("Unable to create pseudo-folder."))
-
-
-class CopyObject(forms.SelfHandlingForm):
- new_container_name = forms.ChoiceField(label=_("Destination container"),
- validators=[no_slash_validator])
- path = forms.CharField(
- label=pgettext_lazy("Swift pseudo folder path", u"Path"),
- max_length=255, required=False)
- new_object_name = forms.CharField(max_length=255,
- label=_("Destination object name"),
- validators=[no_slash_validator])
- orig_container_name = forms.CharField(widget=forms.HiddenInput())
- orig_object_name = forms.CharField(widget=forms.HiddenInput())
-
- def __init__(self, *args, **kwargs):
- containers = kwargs.pop('containers')
- super(CopyObject, self).__init__(*args, **kwargs)
- self.fields['new_container_name'].choices = containers
-
- def handle(self, request, data):
- index = "horizon:project:containers:index"
- orig_container = data['orig_container_name']
- orig_object = data['orig_object_name']
- new_container = data['new_container_name']
- new_object = data['new_object_name']
- path = data['path']
- if path and not path.endswith("/"):
- path = path + "/"
- new_path = "%s%s" % (path, new_object)
-
- # Now copy the object itself.
- try:
- api.swift.swift_copy_object(request,
- orig_container,
- orig_object,
- new_container,
- new_path)
- dest = "%s/%s" % (new_container, path)
- vals = {"dest": dest.rstrip("/"),
- "orig": orig_object.split("/")[-1],
- "new": new_object}
- messages.success(request,
- _('Copied "%(orig)s" to "%(dest)s" as "%(new)s".')
- % vals)
- return True
- except exceptions.HorizonException as exc:
- messages.error(request, exc)
- raise exceptions.Http302(
- reverse(index, args=[utils.wrap_delimiter(orig_container)]))
- except Exception:
- redirect = reverse(index,
- args=[utils.wrap_delimiter(orig_container)])
- exceptions.handle(request,
- _("Unable to copy object."),
- redirect=redirect)
diff --git a/openstack_dashboard/dashboards/project/containers/tables.py b/openstack_dashboard/dashboards/project/containers/tables.py
deleted file mode 100644
index b283a72d8..000000000
--- a/openstack_dashboard/dashboards/project/containers/tables.py
+++ /dev/null
@@ -1,432 +0,0 @@
-# Copyright 2012 Nebula, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-import logging
-
-from django.core.urlresolvers import reverse
-from django import shortcuts
-from django import template
-from django.template import defaultfilters as filters
-from django.utils import http
-from django.utils.translation import ugettext_lazy as _
-from django.utils.translation import ungettext_lazy
-
-from horizon import exceptions
-from horizon import messages
-from horizon import tables
-
-from openstack_dashboard import api
-from openstack_dashboard.api import swift
-from openstack_dashboard.dashboards.project.containers import utils
-
-LOG = logging.getLogger(__name__)
-
-
-class ViewContainer(tables.LinkAction):
- name = "view"
- verbose_name = _("View Details")
- url = "horizon:project:containers:container_detail"
- classes = ("ajax-modal", "btn-view")
-
- def get_link_url(self, datum=None):
- obj_id = self.table.get_object_id(datum)
- return reverse(self.url, args=(obj_id,))
-
-
-class MakePublicContainer(tables.Action):
- name = "make_public"
- verbose_name = _("Make Public")
- icon = "pencil"
-
- def allowed(self, request, container):
- # Container metadata have not been loaded
- if not hasattr(container, 'is_public'):
- return False
- return not container.is_public
-
- def single(self, table, request, obj_id):
- try:
- api.swift.swift_update_container(request,
- obj_id,
- metadata=({'is_public': True}))
- LOG.info('Updating container "%s" access to public.' % obj_id)
- messages.success(request,
- _('Successfully updated container access to '
- 'public.'))
- except Exception:
- exceptions.handle(request,
- _('Unable to update container access.'))
- return shortcuts.redirect('horizon:project:containers:index')
-
-
-class MakePrivateContainer(tables.Action):
- name = "make_private"
- verbose_name = _("Make Private")
- icon = "pencil"
-
- def allowed(self, request, container):
- # Container metadata have not been loaded
- if not hasattr(container, 'is_public'):
- return False
- return container.is_public
-
- def single(self, table, request, obj_id):
- try:
- api.swift.swift_update_container(request,
- obj_id,
- metadata=({'is_public': False}))
- LOG.info('Updating container "%s" access to private.' % obj_id)
- messages.success(request,
- _('Successfully updated container access to '
- 'private.'))
- except Exception:
- exceptions.handle(request,
- _('Unable to update container access.'))
- return shortcuts.redirect('horizon:project:containers:index')
-
-
-class DeleteContainer(tables.DeleteAction):
- @staticmethod
- def action_present(count):
- return ungettext_lazy(
- u"Delete Container",
- u"Delete Containers",
- count
- )
-
- @staticmethod
- def action_past(count):
- return ungettext_lazy(
- u"Deleted Container",
- u"Deleted Containers",
- count
- )
-
- success_url = "horizon:project:containers:index"
-
- def delete(self, request, obj_id):
- try:
- api.swift.swift_delete_container(request, obj_id)
- except exceptions.Conflict as exc:
- exceptions.handle(request, exc, redirect=self.success_url)
- except Exception:
- exceptions.handle(request,
- _('Unable to delete container.'),
- redirect=self.success_url)
-
- def get_success_url(self, request=None):
- """Returns the URL to redirect to after a successful action.
- """
- current_container = self.table.kwargs.get("container_name", None)
-
- # If the current_container is deleted, then redirect to the default
- # completion url
- if current_container in self.success_ids:
- return self.success_url
- return request.get_full_path()
-
-
-class CreateContainer(tables.LinkAction):
- name = "create"
- verbose_name = _("Create Container")
- url = "horizon:project:containers:create"
- classes = ("ajax-modal",)
- icon = "plus"
-
-
-class ListObjects(tables.LinkAction):
- name = "list_objects"
- verbose_name = _("View Container")
- url = "horizon:project:containers:index"
- icon = "list"
-
- def get_link_url(self, datum=None):
- container_name = http.urlquote(datum.name)
- args = (utils.wrap_delimiter(container_name),)
- return reverse(self.url, args=args)
-
-
-class CreatePseudoFolder(tables.LinkAction):
- name = "create_pseudo_folder"
- verbose_name = _("Create Pseudo-folder")
- url = "horizon:project:containers:create_pseudo_folder"
- classes = ("ajax-modal",)
- icon = "plus"
-
- def get_link_url(self, datum=None):
- # Usable for both the container and object tables
- if getattr(datum, 'container', datum):
- container_name = http.urlquote(datum.name)
- else:
- container_name = self.table.kwargs['container_name']
- subfolders = self.table.kwargs.get('subfolder_path', '')
- args = (bit for bit in (container_name, subfolders) if bit)
- return reverse(self.url, args=args)
-
- def allowed(self, request, datum=None):
- if self.table.kwargs.get('container_name', None):
- return True
- return False
-
- def update(self, request, obj):
- # This will only be called for the row, so we can remove the button
- # styles meant for the table action version.
- self.attrs = {'class': 'ajax-modal'}
-
-
-class UploadObject(tables.LinkAction):
- name = "upload"
- verbose_name = _("Upload Object")
- url = "horizon:project:containers:object_upload"
- classes = ("ajax-modal",)
- icon = "upload"
-
- def get_link_url(self, datum=None):
- # Usable for both the container and object tables
- if getattr(datum, 'container', datum):
- # This is a container
- container_name = datum.name
- else:
- # This is a table action, and we already have the container name
- container_name = self.table.kwargs['container_name']
- subfolders = self.table.kwargs.get('subfolder_path', '')
- args = (bit for bit in (container_name, subfolders) if bit)
- return reverse(self.url, args=args)
-
- def allowed(self, request, datum=None):
- if self.table.kwargs.get('container_name', None):
- return True
- return False
-
- def update(self, request, obj):
- # This will only be called for the row, so we can remove the button
- # styles meant for the table action version.
- self.attrs = {'class': 'ajax-modal'}
-
-
-def get_size_used(container):
- return filters.filesizeformat(container.bytes)
-
-
-def get_container_link(container):
- return reverse("horizon:project:containers:index",
- args=(utils.wrap_delimiter(container.name),))
-
-
-class ContainerAjaxUpdateRow(tables.Row):
- ajax = True
-
- def get_data(self, request, container_name):
- container = api.swift.swift_get_container(request,
- container_name,
- with_data=False)
- return container
-
-
-def get_metadata(container):
- # If the metadata has not been loading, display a loading image
- if not hasattr(container, 'is_public'):
- return template.loader.render_to_string(
- 'project/containers/_container_loader.html'
- )
- template_name = 'project/containers/_container_metadata.html'
- context = {"container": container}
- return template.loader.render_to_string(template_name, context)
-
-
-def get_metadata_loaded(container):
- # Determine if metadata has been loaded if the attribute is already set.
- return hasattr(container, 'is_public') and container.is_public is not None
-
-
-class ContainersTable(tables.DataTable):
- METADATA_LOADED_CHOICES = (
- (False, None),
- (True, True),
- )
- name = tables.Column("name",
- link=get_container_link,
- verbose_name=_("Container Name"))
- metadata = tables.Column(get_metadata,
- verbose_name=_("Container Details"),
- classes=('nowrap-col', ),)
- metadata_loaded = tables.Column(get_metadata_loaded,
- status=True,
- status_choices=METADATA_LOADED_CHOICES,
- hidden=True)
-
- class Meta(object):
- name = "containers"
- verbose_name = _("Containers")
- row_class = ContainerAjaxUpdateRow
- status_columns = ['metadata_loaded', ]
- table_actions = (CreateContainer,)
- row_actions = (ViewContainer, MakePublicContainer,
- MakePrivateContainer, DeleteContainer,)
- browser_table = "navigation"
- footer = False
-
- def get_object_id(self, container):
- return container.name
-
-
-class ViewObject(tables.LinkAction):
- name = "view"
- verbose_name = _("View Details")
- url = "horizon:project:containers:object_detail"
- classes = ("ajax-modal", "btn-view")
- allowed_data_types = ("objects",)
-
- def get_link_url(self, obj):
- container_name = self.table.kwargs['container_name']
- return reverse(self.url, args=(container_name, obj.name))
-
-
-class UpdateObject(tables.LinkAction):
- name = "update_object"
- verbose_name = _("Edit")
- url = "horizon:project:containers:object_update"
- classes = ("ajax-modal",)
- icon = "pencil"
- allowed_data_types = ("objects",)
-
- def get_link_url(self, obj):
- container_name = self.table.kwargs['container_name']
- return reverse(self.url, args=(container_name, obj.name))
-
-
-class DeleteObject(tables.DeleteAction):
- @staticmethod
- def action_present(count):
- return ungettext_lazy(
- u"Delete Object",
- u"Delete Objects",
- count
- )
-
- @staticmethod
- def action_past(count):
- return ungettext_lazy(
- u"Deleted Object",
- u"Deleted Objects",
- count
- )
-
- name = "delete_object"
- allowed_data_types = ("objects", "subfolders",)
-
- def delete(self, request, obj_id):
- obj = self.table.get_object_by_id(obj_id)
- container_name = obj.container_name
- datum_type = getattr(obj, self.table._meta.data_type_name, None)
- if datum_type == 'subfolders':
- obj_id = obj_id[(len(container_name) + 1):] + "/"
- api.swift.swift_delete_object(request, container_name, obj_id)
-
-
-class DeleteMultipleObjects(DeleteObject):
- name = "delete_multiple_objects"
-
-
-class CopyObject(tables.LinkAction):
- name = "copy"
- verbose_name = _("Copy")
- url = "horizon:project:containers:object_copy"
- classes = ("ajax-modal",)
- icon = "circle-arrow-right"
- allowed_data_types = ("objects",)
-
- def get_link_url(self, obj):
- container_name = self.table.kwargs['container_name']
- return reverse(self.url, args=(container_name, obj.name))
-
-
-class DownloadObject(tables.LinkAction):
- name = "download"
- verbose_name = _("Download")
- url = "horizon:project:containers:object_download"
- icon = "download"
- allowed_data_types = ("objects",)
-
- def get_link_url(self, obj):
- container_name = self.table.kwargs['container_name']
- return reverse(self.url, args=(container_name, obj.name))
-
- def allowed(self, request, object):
- return object.bytes and object.bytes > 0
-
-
-class ObjectFilterAction(tables.FilterAction):
- def _filtered_data(self, table, filter_string):
- request = table.request
- container = self.table.kwargs['container_name']
- subfolder = self.table.kwargs['subfolder_path']
- prefix = utils.wrap_delimiter(subfolder) if subfolder else ''
- self.filtered_data = api.swift.swift_filter_objects(request,
- filter_string,
- container,
- prefix=prefix)
- return self.filtered_data
-
- def filter_subfolders_data(self, table, objects, filter_string):
- data = self._filtered_data(table, filter_string)
- return [datum for datum in data if
- datum.content_type == "application/pseudo-folder"]
-
- def filter_objects_data(self, table, objects, filter_string):
- data = self._filtered_data(table, filter_string)
- return [datum for datum in data if
- datum.content_type != "application/pseudo-folder"]
-
- def allowed(self, request, datum=None):
- if self.table.kwargs.get('container_name', None):
- return True
- return False
-
-
-def sanitize_name(name):
- return name.split(swift.FOLDER_DELIMITER)[-1]
-
-
-def get_size(obj):
- if obj.bytes is None:
- return _("pseudo-folder")
- return filters.filesizeformat(obj.bytes)
-
-
-def get_link_subfolder(subfolder):
- container_name = subfolder.container_name
- return reverse("horizon:project:containers:index",
- args=(utils.wrap_delimiter(container_name),
- utils.wrap_delimiter(subfolder.name)))
-
-
-class ObjectsTable(tables.DataTable):
- name = tables.Column("name",
- link=get_link_subfolder,
- allowed_data_types=("subfolders",),
- verbose_name=_("Object Name"),
- filters=(sanitize_name,))
-
- size = tables.Column(get_size, verbose_name=_('Size'))
-
- class Meta(object):
- name = "objects"
- verbose_name = _("Objects")
- table_actions = (ObjectFilterAction, CreatePseudoFolder, UploadObject,
- DeleteMultipleObjects)
- row_actions = (DownloadObject, UpdateObject, CopyObject,
- ViewObject, DeleteObject)
- data_types = ("subfolders", "objects")
- browser_table = "content"
- footer = False
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/_container_detail.html b/openstack_dashboard/dashboards/project/containers/templates/containers/_container_detail.html
deleted file mode 100644
index 659bdcee1..000000000
--- a/openstack_dashboard/dashboards/project/containers/templates/containers/_container_detail.html
+++ /dev/null
@@ -1,29 +0,0 @@
-{% extends "horizon/common/_modal.html" %}
-{% load i18n %}
-
-{% block modal-header %}{% trans "Container Details" %}{% endblock %}
-
-{% block modal-body %}
-
-
- {% trans "Container Name" %}
- {{ container.name }}
- {% trans "Container Access" %}
- {% if container.public_url %}
- {% trans "Public" %}
- {% trans "Public URL" %}
- {{ container.public_url }}
- {% else %}
- {% trans "Private" %}
- {% endif %}
- {% trans "Object Count" %}
- {{ container.container_object_count }}
- {% trans "Size" %}
- {{ container.container_bytes_used|filesizeformat }}
-
-
-{% endblock %}
-
-{% block modal-footer %}
- {% trans "Close" %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/_container_loader.html b/openstack_dashboard/dashboards/project/containers/templates/containers/_container_loader.html
deleted file mode 100644
index 2d0d12b68..000000000
--- a/openstack_dashboard/dashboards/project/containers/templates/containers/_container_loader.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/_container_metadata.html b/openstack_dashboard/dashboards/project/containers/templates/containers/_container_metadata.html
deleted file mode 100644
index e268ff5e7..000000000
--- a/openstack_dashboard/dashboards/project/containers/templates/containers/_container_metadata.html
+++ /dev/null
@@ -1,12 +0,0 @@
-{% load i18n %}
-
- {% trans "Object Count: " %}{{ container.container_object_count }}
- {% trans "Size: " %}{{ container.container_bytes_used|filesizeformat }}
- {% trans "Access: " %}
- {% if container.public_url %}
- {% trans "Public" %}
- {% else %}
- {% trans "Private" %}
- {% endif %}
-
-
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/_copy.html b/openstack_dashboard/dashboards/project/containers/templates/containers/_copy.html
deleted file mode 100644
index 04fc6f2ec..000000000
--- a/openstack_dashboard/dashboards/project/containers/templates/containers/_copy.html
+++ /dev/null
@@ -1,24 +0,0 @@
-{% extends "horizon/common/_modal_form.html" %}
-{% load i18n %}
-
-{% block form_id %}copy_object_form{% endblock %}
-{% block form_action %}{% url 'horizon:project:containers:object_copy' container_name object_name %}{% endblock %}
-
-{% block modal-header %}{% blocktrans %}Copy Object: {{ object_name }}{% endblocktrans %}{% endblock %}
-
-{% block modal-body %}
-
-
- {% include "horizon/common/_form_fields.html" %}
-
-
-
-
{% trans "Description:" %}
-
{% trans "Make a new copy of an existing object to store in this or another container. You may additionally specify the path within the selected container where the new copy should be stored." %}
-
-{% endblock %}
-
-{% block modal-footer %}
-
- {% trans "Cancel" %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/_create.html b/openstack_dashboard/dashboards/project/containers/templates/containers/_create.html
deleted file mode 100644
index 8367ab25a..000000000
--- a/openstack_dashboard/dashboards/project/containers/templates/containers/_create.html
+++ /dev/null
@@ -1,20 +0,0 @@
-{% extends "horizon/common/_modal_form.html" %}
-{% load i18n %}
-
-{% block form_id %}create_container_form{% endblock %}
-{% block form_action %}{% url 'horizon:project:containers:create' %}{% endblock %}
-
-{% block modal-header %}{% trans "Create Container" %}{% endblock %}
-
-{% block modal-body %}
-
-
- {% include "horizon/common/_form_fields.html" %}
-
-
-
-
{% trans "Description:" %}
-
{% trans "A container is a storage compartment for your data and provides a way for you to organize your data. You can think of a container as a folder in Windows ® or a directory in UNIX ®. The primary difference between a container and these other file system concepts is that containers cannot be nested. You can, however, create an unlimited number of containers within your account. Data must be stored in a container so you must have at least one container defined in your account prior to uploading data." %}
-
{% trans "Note: A Public Container will allow anyone with the Public URL to gain access to your objects in the container." %}
-
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/_create_pseudo_folder.html b/openstack_dashboard/dashboards/project/containers/templates/containers/_create_pseudo_folder.html
deleted file mode 100644
index bef492cb1..000000000
--- a/openstack_dashboard/dashboards/project/containers/templates/containers/_create_pseudo_folder.html
+++ /dev/null
@@ -1,26 +0,0 @@
-{% extends "horizon/common/_modal_form.html" %}
-{% load i18n %}
-
-{% block form_id %}create_directory_form{% endblock %}
-{% block form_action %}{% url 'horizon:project:containers:create_pseudo_folder' container_name %}{% endblock %}
-
-{% block modal-header %}
- {% blocktrans %}Create pseudo-folder in container {{ container_name }}{% endblocktrans %}
-{% endblock %}
-
-{% block modal-body %}
-
-
- {% include "horizon/common/_form_fields.html" %}
-
-
-
-
{% trans "Description:" %}
-
{% trans "Pseudo-folder:" %} {% trans "Within a container you can group your objects into pseudo-folders, which behave similarly to folders in your desktop operating system, with the exception that they are virtual collections defined by a common prefix on the object's name. A slash (/) character is used as the delimiter for pseudo-folders in the Object Store." %}
-
-{% endblock %}
-
-{% block modal-footer %}
- {% trans "Cancel" %}
-
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/_object_detail.html b/openstack_dashboard/dashboards/project/containers/templates/containers/_object_detail.html
deleted file mode 100644
index cd6d5b181..000000000
--- a/openstack_dashboard/dashboards/project/containers/templates/containers/_object_detail.html
+++ /dev/null
@@ -1,25 +0,0 @@
-{% extends "horizon/common/_modal.html" %}
-{% load i18n %}
-
-{% block modal-header %}{% trans "Object Details" %}{% endblock %}
-
-{% block modal-body %}
-
-
- {% trans "Name" %}
- {{ object.name }}
- {% trans "Hash" %}
- {{ object.etag }}
- {% trans "Content Type" %}
- {{ object.content_type }}
- {% trans "Last Modified" %}
- {{ object.timestamp|parse_isotime }}
- {% trans "Size" %}
- {{ object.bytes|filesizeformat }}
-
-
-{% endblock %}
-
-{% block modal-footer %}
- {% trans "Close" %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/_update.html b/openstack_dashboard/dashboards/project/containers/templates/containers/_update.html
deleted file mode 100644
index 6bb75c65d..000000000
--- a/openstack_dashboard/dashboards/project/containers/templates/containers/_update.html
+++ /dev/null
@@ -1,28 +0,0 @@
-{% extends "horizon/common/_modal_form.html" %}
-{% load i18n %}
-
-{% block form_id %}update_object_form{% endblock %}
-{% block ng_controller %}DummyController{% endblock %}
-{% block form_name %}updateForm{% endblock %}
-{% block form_action %}{% url 'horizon:project:containers:object_update' container_name subfolder_path object_path %}{% endblock %}
-{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
-
-{% block modal-header %}{% trans "Edit Object" %}{% endblock %}
-
-{% block modal-body %}
-
-
- {% include "horizon/common/_form_fields.html" %}
-
-
-
-
{% trans "Description:" %}
-
{% trans "Object:" %} {% trans "An object is the basic storage entity that represents a file you store in the OpenStack Object Storage system. When you upload data to OpenStack Object Storage, the data is stored as-is (no compression or encryption) and consists of a location (container), the object's name, and any metadata consisting of key/value pairs." %}
-
{% trans "File:" %} {% trans "A new uploaded file will replace the content of the current object" %}
-
-{% endblock %}
-
-{% block modal-footer %}
- {% trans "Cancel" %}
-
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/_upload.html b/openstack_dashboard/dashboards/project/containers/templates/containers/_upload.html
deleted file mode 100644
index e7996a888..000000000
--- a/openstack_dashboard/dashboards/project/containers/templates/containers/_upload.html
+++ /dev/null
@@ -1,29 +0,0 @@
-{% extends "horizon/common/_modal_form.html" %}
-{% load i18n %}
-
-{% block form_id %}upload_object_form{% endblock %}
-{% block form_name %}uploadForm{% endblock %}
-{% block form_action %}{% url 'horizon:project:containers:object_upload' container_name %}{% endblock %}
-{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
-
-{% block modal-header %}
- {% blocktrans %}Upload Object To Container: {{ container_name }}{% endblocktrans %}
-{% endblock %}
-
-{% block modal-body %}
-
-
- {% include "horizon/common/_form_fields.html" %}
-
-
-
-
{% trans "Description:" %}
-
{% trans "Object:" %} {% trans "An object is the basic storage entity that represents a file you store in the OpenStack Object Storage system. When you upload data to OpenStack Object Storage, the data is stored as-is (no compression or encryption) and consists of a location (container), the object's name, and any metadata consisting of key/value pairs." %}
-
{% trans "Pseudo-folder:" %} {% trans "Within a container you can group your objects into pseudo-folders, which behave similarly to folders in your desktop operating system, with the exception that they are virtual collections defined by a common prefix on the object's name. A slash (/) character is used as the delimiter for pseudo-folders in the Object Store." %}
-
-{% endblock %}
-
-{% block modal-footer %}
- {% trans "Cancel" %}
-
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/container_detail.html b/openstack_dashboard/dashboards/project/containers/templates/containers/container_detail.html
deleted file mode 100644
index 5c15d25a1..000000000
--- a/openstack_dashboard/dashboards/project/containers/templates/containers/container_detail.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% extends 'base.html' %}
-{% load i18n %}
-{% block title %}{% trans "Container Details" %}{% endblock %}
-
-{% block main %}
-
-
- {% include 'project/containers/_container_detail.html' %}
-
-
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/copy.html b/openstack_dashboard/dashboards/project/containers/templates/containers/copy.html
deleted file mode 100644
index 9d22bb9ee..000000000
--- a/openstack_dashboard/dashboards/project/containers/templates/containers/copy.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends 'base.html' %}
-{% load i18n %}
-{% block title %}{% trans "Copy Object" %}{% endblock %}
-
-{% block main %}
- {% include 'project/containers/_copy.html' %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/create.html b/openstack_dashboard/dashboards/project/containers/templates/containers/create.html
deleted file mode 100644
index 9278ba545..000000000
--- a/openstack_dashboard/dashboards/project/containers/templates/containers/create.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends 'base.html' %}
-{% load i18n %}
-{% block title %}{% trans "Create Container" %}{% endblock %}
-
-{% block main %}
- {% include "project/containers/_create.html" %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/create_pseudo_folder.html b/openstack_dashboard/dashboards/project/containers/templates/containers/create_pseudo_folder.html
deleted file mode 100644
index 7cc8b099c..000000000
--- a/openstack_dashboard/dashboards/project/containers/templates/containers/create_pseudo_folder.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends 'base.html' %}
-{% load i18n %}
-{% block title %}{% trans "Create Pseudo-folder" %}{% endblock %}
-
-{% block main %}
- {% include 'project/containers/_create_pseudo_folder.html' %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/index.html b/openstack_dashboard/dashboards/project/containers/templates/containers/index.html
deleted file mode 100644
index cbc6dac32..000000000
--- a/openstack_dashboard/dashboards/project/containers/templates/containers/index.html
+++ /dev/null
@@ -1,24 +0,0 @@
-{% extends 'base.html' %}
-{% load i18n %}
-
-{% block title %}{% trans "Containers" %}{% endblock %}
-
-{% block main %}
- {% if subfolders %}
-
- {% endif %}
- {{ swift_browser.render }}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/object_detail.html b/openstack_dashboard/dashboards/project/containers/templates/containers/object_detail.html
deleted file mode 100644
index be652e525..000000000
--- a/openstack_dashboard/dashboards/project/containers/templates/containers/object_detail.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% extends 'base.html' %}
-{% load i18n %}
-{% block title %}{% trans "Object Details" %}{% endblock %}
-
-{% block main %}
-
-
- {% include 'project/containers/_object_detail.html' %}
-
-
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/update.html b/openstack_dashboard/dashboards/project/containers/templates/containers/update.html
deleted file mode 100644
index 96c1577a1..000000000
--- a/openstack_dashboard/dashboards/project/containers/templates/containers/update.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends 'base.html' %}
-{% load i18n %}
-{% block title %}{% trans "Update Object" %}{% endblock %}
-
-{% block main %}
- {% include 'project/containers/_update.html' %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/upload.html b/openstack_dashboard/dashboards/project/containers/templates/containers/upload.html
deleted file mode 100644
index cdf115b17..000000000
--- a/openstack_dashboard/dashboards/project/containers/templates/containers/upload.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends 'base.html' %}
-{% load i18n %}
-{% block title %}{% trans "Upload Object" %}{% endblock %}
-
-{% block main %}
- {% include 'project/containers/_upload.html' %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/containers/tests.py b/openstack_dashboard/dashboards/project/containers/tests.py
deleted file mode 100644
index 1fd672973..000000000
--- a/openstack_dashboard/dashboards/project/containers/tests.py
+++ /dev/null
@@ -1,565 +0,0 @@
-# Copyright 2012 United States Government as represented by the
-# Administrator of the National Aeronautics and Space Administration.
-# All Rights Reserved.
-#
-# Copyright 2012 Nebula, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import copy
-import email.header
-import tempfile
-
-import django
-from django.core.files.uploadedfile import InMemoryUploadedFile # noqa
-from django.core.urlresolvers import reverse
-from django import http
-from django.utils import http as utils_http
-
-from mox3.mox import IsA # noqa
-import six
-
-from openstack_dashboard import api
-from openstack_dashboard.dashboards.project.containers import forms
-from openstack_dashboard.dashboards.project.containers import tables
-from openstack_dashboard.dashboards.project.containers import utils
-from openstack_dashboard.dashboards.project.containers import views
-from openstack_dashboard.test import helpers as test
-
-CONTAINER_NAME_1 = u"container one%\u6346"
-CONTAINER_NAME_2 = u"container_two\u6346"
-CONTAINER_NAME_1_QUOTED = utils_http.urlquote(CONTAINER_NAME_1)
-CONTAINER_NAME_2_QUOTED = utils_http.urlquote(CONTAINER_NAME_2)
-INVALID_CONTAINER_NAME_1 = utils_http.urlquote(CONTAINER_NAME_1_QUOTED)
-INVALID_CONTAINER_NAME_2 = utils_http.urlquote(CONTAINER_NAME_2_QUOTED)
-CONTAINER_INDEX_URL = reverse('horizon:project:containers:index')
-
-INVALID_PATHS = []
-
-
-def invalid_paths():
- if not INVALID_PATHS:
- for x in (CONTAINER_NAME_1_QUOTED, CONTAINER_NAME_2_QUOTED):
- y = reverse('horizon:project:containers:index',
- args=(utils.wrap_delimiter(x), ))
- INVALID_PATHS.append(y)
- for x in (CONTAINER_NAME_1, CONTAINER_NAME_2):
- INVALID_PATHS.append(CONTAINER_INDEX_URL + x)
- return INVALID_PATHS
-
-
-class SwiftTests(test.TestCase):
-
- def _test_invalid_paths(self, response):
- for x in invalid_paths():
- self.assertNotContains(response, x)
-
- @test.create_stubs({api.swift: ('swift_get_containers',)})
- def test_index_no_container_selected(self):
- containers = self.containers.list()
- api.swift.swift_get_containers(IsA(http.HttpRequest), marker=None) \
- .AndReturn((containers, False))
- self.mox.ReplayAll()
-
- res = self.client.get(CONTAINER_INDEX_URL)
-
- self.assertTemplateUsed(res, 'project/containers/index.html')
- self.assertIn('table', res.context)
- resp_containers = res.context['table'].data
- self.assertEqual(len(resp_containers), len(containers))
-
- @test.create_stubs({api.swift: ('swift_delete_container', )})
- def test_delete_container(self):
- for container in self.containers.list():
- self.mox.ResetAll() # mandatory in a for loop
- api.swift.swift_delete_container(IsA(http.HttpRequest),
- container.name)
- self.mox.ReplayAll()
-
- action_string = u"containers__delete__%s" % container.name
- form_data = {"action": action_string}
- req = self.factory.post(CONTAINER_INDEX_URL, form_data)
- table = tables.ContainersTable(req, self.containers.list())
- handled = table.maybe_handle()
- self.assertEqual(handled['location'], CONTAINER_INDEX_URL)
-
- @test.create_stubs({api.swift: ('swift_get_objects', )})
- def test_delete_container_nonempty(self):
- container = self.containers.first()
- objects = self.objects.list()
- api.swift.swift_get_objects(IsA(http.HttpRequest),
- container.name).AndReturn([objects, False])
- self.mox.ReplayAll()
-
- action_string = u"containers__delete__%s" % container.name
- form_data = {"action": action_string}
- req = self.factory.post(CONTAINER_INDEX_URL, form_data)
- req.META['HTTP_REFERER'] = '%s/%s' % (CONTAINER_INDEX_URL,
- container.name)
- table = tables.ContainersTable(req, self.containers.list())
- handled = table.maybe_handle()
-
- self.assertEqual(handled.status_code, 302)
- self.assertEqual(six.text_type(list(req._messages)[0].message),
- u"The container cannot be deleted "
- u"since it is not empty.")
-
- def test_create_container_get(self):
- res = self.client.get(reverse('horizon:project:containers:create'))
- self.assertTemplateUsed(res, 'project/containers/create.html')
-
- @test.create_stubs({api.swift: ('swift_create_container',)})
- def test_create_container_post(self):
- for container in self.containers.list():
- self.mox.ResetAll() # mandatory in a for loop
- api.swift.swift_create_container(IsA(http.HttpRequest),
- container.name,
- metadata=({'is_public': False}))
- self.mox.ReplayAll()
-
- formData = {'name': container.name,
- 'access': "private",
- 'method': forms.CreateContainer.__name__}
- res = self.client.post(
- reverse('horizon:project:containers:create'), formData)
- args = (utils.wrap_delimiter(container.name),)
- url = reverse('horizon:project:containers:index', args=args)
- self.assertRedirectsNoFollow(res, url)
-
- @test.create_stubs({api.swift: ('swift_update_container', )})
- def test_update_container_to_public(self):
- container = self.containers.get(name=u"container one%\u6346")
- api.swift.swift_update_container(IsA(http.HttpRequest),
- container.name,
- metadata=({'is_public': True}))
- self.mox.ReplayAll()
-
- action_string = u"containers__make_public__%s" % container.name
- form_data = {"action": action_string}
- req = self.factory.post(CONTAINER_INDEX_URL, form_data)
- table = tables.ContainersTable(req, self.containers.list())
- handled = table.maybe_handle()
- self.assertEqual(handled['location'], CONTAINER_INDEX_URL)
-
- @test.create_stubs({api.swift: ('swift_update_container', )})
- def test_update_container_to_private(self):
- container = self.containers.get(name=u"container_two\u6346")
- api.swift.swift_update_container(IsA(http.HttpRequest),
- container.name,
- metadata=({'is_public': False}))
- self.mox.ReplayAll()
-
- action_string = u"containers__make_private__%s" % container.name
- form_data = {"action": action_string}
- req = self.factory.post(CONTAINER_INDEX_URL, form_data)
- table = tables.ContainersTable(req, self.containers.list())
- handled = table.maybe_handle()
- self.assertEqual(handled['location'], CONTAINER_INDEX_URL)
-
- @test.create_stubs({api.swift: ('swift_get_containers',
- 'swift_get_objects')})
- def test_index_container_selected(self):
- containers = (self.containers.list(), False)
- ret = (self.objects.list(), False)
- api.swift.swift_get_containers(IsA(http.HttpRequest),
- marker=None).AndReturn(containers)
- api.swift.swift_get_objects(IsA(http.HttpRequest),
- self.containers.first().name,
- marker=None,
- prefix=None).AndReturn(ret)
- self.mox.ReplayAll()
-
- container_name = self.containers.first().name
- res = self.client.get(
- reverse('horizon:project:containers:index',
- args=[utils.wrap_delimiter(container_name)]))
- self.assertTemplateUsed(res, 'project/containers/index.html')
- # UTF8 encoding here to ensure there aren't problems with Nose output.
- expected = [obj.name.encode('utf8') for obj in self.objects.list()]
- self.assertQuerysetEqual(res.context['objects_table'].data,
- expected,
- lambda obj: obj.name.encode('utf8'))
- # Check if the two forms' URL are properly 'urlquote()d'.
- form_action = ' action="%s%s/" ' % (CONTAINER_INDEX_URL,
- CONTAINER_NAME_1_QUOTED)
- self.assertContains(res, form_action, count=2)
- self._test_invalid_paths(res)
-
- @test.create_stubs({api.swift: ('swift_upload_object',)})
- def test_upload(self):
- container = self.containers.first()
- obj = self.objects.first()
- OBJECT_DATA = b'objectData'
-
- temp_file = tempfile.NamedTemporaryFile()
- temp_file.write(OBJECT_DATA)
- temp_file.flush()
- temp_file.seek(0)
-
- api.swift.swift_upload_object(IsA(http.HttpRequest),
- container.name,
- obj.name,
- IsA(InMemoryUploadedFile)).AndReturn(obj)
- self.mox.ReplayAll()
-
- upload_url = reverse('horizon:project:containers:object_upload',
- args=[container.name])
-
- res = self.client.get(upload_url)
- self.assertTemplateUsed(res, 'project/containers/upload.html')
- self.assertContains(res, 'enctype="multipart/form-data"')
- self._test_invalid_paths(res)
-
- formData = {'method': forms.UploadObject.__name__,
- 'container_name': container.name,
- 'name': obj.name,
- 'object_file': temp_file}
- res = self.client.post(upload_url, formData)
-
- args = (utils.wrap_delimiter(container.name),)
- index_url = reverse('horizon:project:containers:index', args=args)
- self.assertRedirectsNoFollow(res, index_url)
-
- @test.create_stubs({api.swift: ('swift_upload_object',)})
- def test_upload_without_file(self):
- container = self.containers.first()
- obj = self.objects.first()
-
- api.swift.swift_upload_object(IsA(http.HttpRequest),
- container.name,
- obj.name,
- None).AndReturn(obj)
- self.mox.ReplayAll()
-
- upload_url = reverse('horizon:project:containers:object_upload',
- args=[container.name])
-
- res = self.client.get(upload_url)
- self.assertTemplateUsed(res, 'project/containers/upload.html')
-
- res = self.client.get(upload_url)
- self.assertContains(res, 'enctype="multipart/form-data"')
- self.assertNotContains(res, INVALID_CONTAINER_NAME_1)
- self.assertNotContains(res, INVALID_CONTAINER_NAME_2)
-
- formData = {'method': forms.UploadObject.__name__,
- 'container_name': container.name,
- 'name': obj.name,
- 'object_file': None}
- res = self.client.post(upload_url, formData)
-
- args = (utils.wrap_delimiter(container.name),)
- index_url = reverse('horizon:project:containers:index', args=args)
- self.assertRedirectsNoFollow(res, index_url)
-
- @test.create_stubs({api.swift: ('swift_create_pseudo_folder',)})
- def test_create_pseudo_folder(self):
- container = self.containers.first()
- obj = self.objects.first()
-
- api.swift.swift_create_pseudo_folder(IsA(http.HttpRequest),
- container.name,
- obj.name + "/").AndReturn(obj)
- self.mox.ReplayAll()
-
- create_pseudo_folder_url = reverse('horizon:project:containers:'
- 'create_pseudo_folder',
- args=[container.name])
-
- res = self.client.get(create_pseudo_folder_url)
- self.assertTemplateUsed(res,
- 'project/containers/create_pseudo_folder.html')
- self._test_invalid_paths(res)
-
- formData = {'method': forms.CreatePseudoFolder.__name__,
- 'container_name': container.name,
- 'name': obj.name}
- res = self.client.post(create_pseudo_folder_url, formData)
-
- index_url = reverse('horizon:project:containers:index',
- args=[utils.wrap_delimiter(container.name)])
-
- self.assertRedirectsNoFollow(res, index_url)
-
- @test.create_stubs({api.swift: ('swift_delete_object',)})
- def test_delete(self):
- container = self.containers.first()
- obj = self.objects.first()
- args = (utils.wrap_delimiter(container.name),)
- index_url = reverse('horizon:project:containers:index', args=args)
- api.swift.swift_delete_object(IsA(http.HttpRequest),
- container.name,
- obj.name)
- self.mox.ReplayAll()
-
- action_string = "objects__delete_object__%s" % obj.name
- form_data = {"action": action_string}
- req = self.factory.post(index_url, form_data)
- kwargs = {"container_name": container.name}
- table = tables.ObjectsTable(req, self.objects.list(), **kwargs)
- handled = table.maybe_handle()
- self.assertEqual(handled['location'], index_url)
-
- @test.create_stubs({api.swift: ('swift_delete_object',)})
- def test_delete_pseudo_folder(self):
- container = self.containers.first()
- folder = self.folder.first()
- args = (utils.wrap_delimiter(container.name),)
- index_url = reverse('horizon:project:containers:index', args=args)
- api.swift.swift_delete_object(IsA(http.HttpRequest),
- container.name,
- folder.name + '/')
- self.mox.ReplayAll()
-
- action_string = "objects__delete_object__%s/%s" % (container.name,
- folder.name)
- form_data = {"action": action_string}
- req = self.factory.post(index_url, form_data)
- kwargs = {"container_name": container.name}
- table = tables.ObjectsTable(req, self.folder.list(), **kwargs)
- handled = table.maybe_handle()
- self.assertEqual(handled['location'], index_url)
-
- @test.create_stubs({api.swift: ('swift_get_object',)})
- def test_download(self):
- for container in self.containers.list():
- for obj in self.objects.list():
- self.mox.ResetAll() # mandatory in a for loop
- obj = copy.copy(obj)
- _data = obj.data
-
- def make_iter():
- yield _data
-
- obj.data = make_iter()
- api.swift.swift_get_object(
- IsA(http.HttpRequest),
- container.name,
- obj.name,
- resp_chunk_size=api.swift.CHUNK_SIZE).AndReturn(obj)
- self.mox.ReplayAll()
-
- download_url = reverse(
- 'horizon:project:containers:object_download',
- args=[container.name, obj.name])
- res = self.client.get(download_url)
-
- self.assertTrue(res.has_header('Content-Disposition'))
- self.assertEqual(b''.join(res.streaming_content), _data)
- self.assertNotContains(res, INVALID_CONTAINER_NAME_1)
- self.assertNotContains(res, INVALID_CONTAINER_NAME_2)
-
- # Check that the returned Content-Disposition filename is
- # correct - some have commas which must be removed
- expected_name = obj.name.replace(',', '')
-
- # some have a path which must be removed
- if '/' in expected_name:
- expected_name = expected_name.split('/')[-1]
-
- # There will also be surrounding double quotes
- expected_name = '"' + expected_name + '"'
-
- expected = 'attachment; filename=%s' % expected_name
- content = res.get('Content-Disposition')
-
- if six.PY3:
- header = email.header.decode_header(content)
- content = header[0][0]
- if isinstance(content, str):
- content = content.encode('utf-8')
- expected = expected.encode('utf-8')
-
- self.assertEqual(content, expected)
-
- @test.create_stubs({api.swift: ('swift_get_containers',)})
- def test_copy_index(self):
- ret = (self.containers.list(), False)
- api.swift.swift_get_containers(IsA(http.HttpRequest)).AndReturn(ret)
- self.mox.ReplayAll()
-
- res = self.client.get(reverse('horizon:project:containers:object_copy',
- args=[self.containers.first().name,
- self.objects.first().name]))
- self.assertTemplateUsed(res, 'project/containers/copy.html')
- self.assertNotContains(res, INVALID_CONTAINER_NAME_1)
- self.assertNotContains(res, INVALID_CONTAINER_NAME_2)
-
- @test.create_stubs({api.swift: ('swift_get_containers',
- 'swift_copy_object')})
- def test_copy(self):
- container_1 = self.containers.get(name=CONTAINER_NAME_1)
- container_2 = self.containers.get(name=CONTAINER_NAME_2)
- obj = self.objects.first()
-
- ret = (self.containers.list(), False)
- api.swift.swift_get_containers(IsA(http.HttpRequest)).AndReturn(ret)
- api.swift.swift_copy_object(IsA(http.HttpRequest),
- container_1.name,
- obj.name,
- container_2.name,
- obj.name)
- self.mox.ReplayAll()
-
- formData = {'method': forms.CopyObject.__name__,
- 'new_container_name': container_2.name,
- 'new_object_name': obj.name,
- 'orig_container_name': container_1.name,
- 'orig_object_name': obj.name}
- copy_url = reverse('horizon:project:containers:object_copy',
- args=[container_1.name, obj.name])
- res = self.client.post(copy_url, formData)
- args = (utils.wrap_delimiter(container_2.name),)
- index_url = reverse('horizon:project:containers:index', args=args)
- self.assertRedirectsNoFollow(res, index_url)
-
- @test.create_stubs({api.swift: ('swift_get_containers',
- 'swift_copy_object')})
- def test_copy_get(self):
- original_name = u"test folder%\u6346/test.txt"
- copy_name = u"test.copy.txt"
- container = self.containers.first()
- obj = self.objects.get(name=original_name)
- ret = (self.containers.list(), False)
- api.swift.swift_get_containers(IsA(http.HttpRequest)).AndReturn(ret)
- self.mox.ReplayAll()
- copy_url = reverse('horizon:project:containers:object_copy',
- args=[container.name, obj.name])
- res = self.client.get(copy_url)
- # The copy's name must appear in initial data
- if django.VERSION >= (1, 10):
- pattern = (' ' % copy_name)
- else:
- pattern = (' ' % copy_name)
- self.assertContains(res, pattern, html=True)
-
- def test_get_copy_name(self):
- self.assertEqual(views.CopyView.get_copy_name('test.txt'),
- 'test.copy.txt')
- self.assertEqual(views.CopyView.get_copy_name('test'),
- 'test.copy')
-
- @test.create_stubs({api.swift: ('swift_upload_object',)})
- def test_update_with_file(self):
- container = self.containers.first()
- obj = self.objects.first()
- OBJECT_DATA = b'objectData'
-
- temp_file = tempfile.NamedTemporaryFile()
- temp_file.write(OBJECT_DATA)
- temp_file.flush()
- temp_file.seek(0)
-
- api.swift.swift_upload_object(IsA(http.HttpRequest),
- container.name,
- obj.name,
- IsA(InMemoryUploadedFile)).AndReturn(obj)
- self.mox.ReplayAll()
-
- update_url = reverse('horizon:project:containers:object_update',
- args=[container.name, obj.name])
-
- res = self.client.get(update_url)
- self.assertTemplateUsed(res, 'project/containers/update.html')
- self.assertContains(res, 'enctype="multipart/form-data"')
- self._test_invalid_paths(res)
-
- formData = {'method': forms.UpdateObject.__name__,
- 'container_name': container.name,
- 'name': obj.name,
- 'object_file': temp_file}
- res = self.client.post(update_url, formData)
-
- args = (utils.wrap_delimiter(container.name),)
- index_url = reverse('horizon:project:containers:index', args=args)
- self.assertRedirectsNoFollow(res, index_url)
-
- @test.create_stubs({api.swift: ('swift_upload_object',)})
- def test_update_without_file(self):
- container = self.containers.first()
- obj = self.objects.first()
-
- self.mox.ReplayAll()
-
- update_url = reverse('horizon:project:containers:object_update',
- args=[container.name, obj.name])
-
- res = self.client.get(update_url)
- self.assertTemplateUsed(res, 'project/containers/update.html')
- self.assertContains(res, 'enctype="multipart/form-data"')
- self._test_invalid_paths(res)
-
- formData = {'method': forms.UpdateObject.__name__,
- 'container_name': container.name,
- 'name': obj.name}
- res = self.client.post(update_url, formData)
-
- args = (utils.wrap_delimiter(container.name),)
- index_url = reverse('horizon:project:containers:index', args=args)
- self.assertRedirectsNoFollow(res, index_url)
-
- @test.create_stubs({api.swift: ('swift_get_container', )})
- def test_view_container(self):
- for container in self.containers.list():
- self.mox.ResetAll() # mandatory in a for loop
- api.swift.swift_get_container(IsA(http.HttpRequest),
- container.name,
- with_data=False) \
- .AndReturn(container)
- self.mox.ReplayAll()
-
- view_url = reverse('horizon:project:containers:container_detail',
- args=[container.name])
- res = self.client.get(view_url)
-
- self.assertTemplateUsed(res,
- 'project/containers/container_detail.html')
- self.assertContains(res, container.name, 1, 200)
- self.assertNotContains(res, INVALID_CONTAINER_NAME_1)
- self.assertNotContains(res, INVALID_CONTAINER_NAME_2)
-
- @test.create_stubs({api.swift: ('swift_get_object', )})
- def test_view_object(self):
- for container in self.containers.list():
- for obj in self.objects.list():
- self.mox.ResetAll() # mandatory in a for loop
- api.swift.swift_get_object(IsA(http.HttpRequest),
- container.name,
- obj.name,
- with_data=False) \
- .AndReturn(obj)
- self.mox.ReplayAll()
- view_url = reverse('horizon:project:containers:object_detail',
- args=[container.name, obj.name])
- res = self.client.get(view_url)
-
- self.assertTemplateUsed(
- res, 'project/containers/object_detail.html')
- self.assertContains(res, obj.name, 1, 200)
- self._test_invalid_paths(res)
-
- def test_wrap_delimiter(self):
- expected = {
- 'containerA': 'containerA/',
- 'containerB%': 'containerB%/', # no urlquote() should occur
- 'containerC/': 'containerC/', # already wrapped name
- 'containerD/objectA': 'containerD/objectA/'
- }
- for name, expected_name in expected.items():
- self.assertEqual(utils.wrap_delimiter(name), expected_name)
diff --git a/openstack_dashboard/dashboards/project/containers/urls.py b/openstack_dashboard/dashboards/project/containers/urls.py
index e3224d0f3..ca3a50452 100644
--- a/openstack_dashboard/dashboards/project/containers/urls.py
+++ b/openstack_dashboard/dashboards/project/containers/urls.py
@@ -16,60 +16,14 @@
# License for the specific language governing permissions and limitations
# under the License.
-from django.conf import settings
from django.conf.urls import url
from openstack_dashboard.dashboards.project.containers import views
-if settings.HORIZON_CONFIG['swift_panel'] == 'angular':
- # New angular containers and objects
- urlpatterns = [
- url(r'^container/((?P.+?)/)?'
- '(?P.+)?$',
- views.NgIndexView.as_view(), name='index'),
- url(r'^$',
- views.NgIndexView.as_view(), name='index')
- ]
-else:
- # Legacy swift containers and objects
- urlpatterns = [
- url(r'^((?P.+?)/)?(?P(.+/)+)?$',
- views.ContainerView.as_view(), name='index'),
-
- url(r'^(?P(.+/)+)?create$',
- views.CreateView.as_view(),
- name='create'),
-
- url(r'^(?P.+?)/(?P(.+/)+)'
- '?container_detail$',
- views.ContainerDetailView.as_view(),
- name='container_detail'),
-
- url(r'^(?P[^/]+)/(?P.+)/object_detail$',
- views.ObjectDetailView.as_view(),
- name='object_detail'),
-
- url(r'^(?P[^/]+)/(?P(.+/)+)?'
- '(?P.+)/update$',
- views.UpdateObjectView.as_view(),
- name='object_update'),
-
- url(r'^(?P.+?)/(?P(.+/)+)?upload$',
- views.UploadView.as_view(),
- name='object_upload'),
-
- url(r'^(?P.+?)/(?P(.+/)+)'
- '?create_pseudo_folder',
- views.CreatePseudoFolderView.as_view(),
- name='create_pseudo_folder'),
-
- url(r'^(?P[^/]+)/'
- r'(?P(.+/)+)?'
- r'(?P.+)/copy$',
- views.CopyView.as_view(),
- name='object_copy'),
-
- url(r'^(?P[^/]+)/(?P.+)/download$',
- views.object_download,
- name='object_download'),
- ]
+urlpatterns = [
+ url(r'^container/((?P.+?)/)?'
+ '(?P.+)?$',
+ views.NgIndexView.as_view(), name='index'),
+ url(r'^$',
+ views.NgIndexView.as_view(), name='index')
+]
diff --git a/openstack_dashboard/dashboards/project/containers/utils.py b/openstack_dashboard/dashboards/project/containers/utils.py
index a7e8e05f8..97dfa2e7f 100644
--- a/openstack_dashboard/dashboards/project/containers/utils.py
+++ b/openstack_dashboard/dashboards/project/containers/utils.py
@@ -10,9 +10,23 @@
# License for the specific language governing permissions and limitations
# under the License.
+from django.core import validators
+from django.utils.translation import ugettext_lazy as _
+
from openstack_dashboard.api import swift
+no_slash_validator = validators.RegexValidator(r'^(?u)[^/]+$',
+ _("Slash is not an allowed "
+ "character."),
+ code="noslash")
+no_begin_or_end_slash = validators.RegexValidator(r'^[^\/](?u).+[^\/]$',
+ _("Slash is not allowed at "
+ "the beginning or end of "
+ "your string."),
+ code="nobeginorendslash")
+
+
def wrap_delimiter(name):
if name and not name.endswith(swift.FOLDER_DELIMITER):
return name + swift.FOLDER_DELIMITER
diff --git a/openstack_dashboard/dashboards/project/containers/views.py b/openstack_dashboard/dashboards/project/containers/views.py
index 0b82701bf..2f0dbbfc0 100644
--- a/openstack_dashboard/dashboards/project/containers/views.py
+++ b/openstack_dashboard/dashboards/project/containers/views.py
@@ -16,327 +16,10 @@
# License for the specific language governing permissions and limitations
# under the License.
-"""
-Views for managing Swift containers.
-"""
-import os
-
-from django.core.urlresolvers import reverse
-from django import http
-from django.utils.functional import cached_property # noqa
-from django.utils.translation import ugettext_lazy as _
from django.views import generic
-import six
-
-from horizon import browsers
-from horizon import exceptions
-from horizon import forms
-from horizon.utils import memoized
-
-from openstack_dashboard import api
-from openstack_dashboard.api import swift
-from openstack_dashboard.dashboards.project.containers \
- import browsers as project_browsers
-from openstack_dashboard.dashboards.project.containers \
- import forms as project_forms
-from openstack_dashboard.dashboards.project.containers import utils
class NgIndexView(generic.TemplateView):
+ """View for managing Swift containers."""
template_name = 'project/containers/ngindex.html'
-
-
-class ContainerView(browsers.ResourceBrowserView):
- browser_class = project_browsers.ContainerBrowser
- template_name = "project/containers/index.html"
- page_title = _("Containers")
-
- def get_containers_data(self):
- containers = []
- self._more = None
- marker = self.request.GET.get('marker', None)
- try:
- containers, self._more = api.swift.swift_get_containers(
- self.request, marker=marker)
- except Exception:
- msg = _('Unable to retrieve container list.')
- exceptions.handle(self.request, msg)
- return containers
-
- @cached_property
- def objects(self):
- """Returns a list of objects given the subfolder's path.
-
- The path is from the kwargs of the request.
- """
- objects = []
- self._more = None
- marker = self.request.GET.get('marker', None)
- container_name = self.kwargs['container_name']
- subfolder = self.kwargs['subfolder_path']
- prefix = None
- if container_name:
- self.navigation_selection = True
- if subfolder:
- prefix = subfolder
- try:
- objects, self._more = api.swift.swift_get_objects(
- self.request,
- container_name,
- marker=marker,
- prefix=prefix)
- except Exception:
- self._more = None
- objects = []
- msg = _('Unable to retrieve object list.')
- exceptions.handle(self.request, msg)
- return objects
-
- def is_subdir(self, item):
- content_type = "application/pseudo-folder"
- return getattr(item, "content_type", None) == content_type
-
- def is_placeholder(self, item):
- object_name = getattr(item, "name", "")
- return object_name.endswith(api.swift.FOLDER_DELIMITER)
-
- def get_objects_data(self):
- """Returns a list of objects within the current folder."""
- filtered_objects = [item for item in self.objects
- if (not self.is_subdir(item) and
- not self.is_placeholder(item))]
- return filtered_objects
-
- def get_subfolders_data(self):
- """Returns a list of subfolders within the current folder."""
- filtered_objects = [item for item in self.objects
- if self.is_subdir(item)]
- return filtered_objects
-
- def get_context_data(self, **kwargs):
- context = super(ContainerView, self).get_context_data(**kwargs)
- context['container_name'] = self.kwargs["container_name"]
- context['subfolders'] = []
- if self.kwargs["subfolder_path"]:
- (parent, slash, folder) = self.kwargs["subfolder_path"] \
- .strip('/').rpartition('/')
- while folder:
- path = "%s%s%s/" % (parent, slash, folder)
- context['subfolders'].insert(0, (folder, path))
- (parent, slash, folder) = parent.rpartition('/')
- return context
-
-
-class CreateView(forms.ModalFormView):
- form_class = project_forms.CreateContainer
- template_name = 'project/containers/create.html'
- success_url = "horizon:project:containers:index"
- page_title = _("Create Container")
-
- def get_success_url(self):
- parent = self.request.POST.get('parent', None)
- if parent:
- container, slash, remainder = parent.partition(
- swift.FOLDER_DELIMITER)
- args = (utils.wrap_delimiter(container),
- utils.wrap_delimiter(remainder))
- return reverse(self.success_url, args=args)
- else:
- container = utils.wrap_delimiter(self.request.POST['name'])
- return reverse(self.success_url, args=[container])
-
- def get_initial(self):
- initial = super(CreateView, self).get_initial()
- initial['parent'] = self.kwargs['container_name']
- return initial
-
-
-class CreatePseudoFolderView(forms.ModalFormView):
- form_class = project_forms.CreatePseudoFolder
- template_name = 'project/containers/create_pseudo_folder.html'
- success_url = "horizon:project:containers:index"
- page_title = _("Create Pseudo-folder")
-
- def get_success_url(self):
- container_name = self.request.POST['container_name']
- return reverse(self.success_url,
- args=(utils.wrap_delimiter(container_name),
- self.request.POST.get('path', '')))
-
- def get_initial(self):
- return {"container_name": self.kwargs["container_name"],
- "path": self.kwargs['subfolder_path']}
-
- def get_context_data(self, **kwargs):
- context = super(CreatePseudoFolderView, self). \
- get_context_data(**kwargs)
- context['container_name'] = self.kwargs["container_name"]
- return context
-
-
-class UploadView(forms.ModalFormView):
- form_class = project_forms.UploadObject
- template_name = 'project/containers/upload.html'
- success_url = "horizon:project:containers:index"
- page_title = _("Upload Objects")
-
- def get_success_url(self):
- container = utils.wrap_delimiter(self.request.POST['container_name'])
- path = utils.wrap_delimiter(self.request.POST.get('path', ''))
- args = (container, path)
- return reverse(self.success_url, args=args)
-
- def get_initial(self):
- return {"container_name": self.kwargs["container_name"],
- "path": self.kwargs['subfolder_path']}
-
- def get_context_data(self, **kwargs):
- context = super(UploadView, self).get_context_data(**kwargs)
- context['container_name'] = self.kwargs["container_name"]
- return context
-
-
-def object_download(request, container_name, object_path):
- try:
- obj = api.swift.swift_get_object(request, container_name, object_path,
- resp_chunk_size=swift.CHUNK_SIZE)
- except Exception:
- redirect = reverse("horizon:project:containers:index")
- exceptions.handle(request,
- _("Unable to retrieve object."),
- redirect=redirect)
- # Add the original file extension back on if it wasn't preserved in the
- # name given to the object.
- filename = object_path.rsplit(swift.FOLDER_DELIMITER)[-1]
- if not os.path.splitext(obj.name)[1] and obj.orig_name:
- name, ext = os.path.splitext(obj.orig_name)
- filename = "%s%s" % (filename, ext)
- response = http.StreamingHttpResponse(obj.data)
- safe_name = filename.replace(",", "")
- if six.PY2:
- safe_name = safe_name.encode('utf-8')
- response['Content-Disposition'] = 'attachment; filename="%s"' % safe_name
- response['Content-Type'] = 'application/octet-stream'
- response['Content-Length'] = obj.bytes
- return response
-
-
-class CopyView(forms.ModalFormView):
- form_class = project_forms.CopyObject
- template_name = 'project/containers/copy.html'
- success_url = "horizon:project:containers:index"
- page_title = _("Copy Object")
-
- def get_success_url(self):
- container = utils.wrap_delimiter(
- self.request.POST['new_container_name'])
- path = utils.wrap_delimiter(self.request.POST.get('path', ''))
- args = (container, path)
- return reverse(self.success_url, args=args)
-
- def get_form_kwargs(self):
- kwargs = super(CopyView, self).get_form_kwargs()
- try:
- containers = api.swift.swift_get_containers(self.request)
- except Exception:
- redirect = reverse("horizon:project:containers:index")
- exceptions.handle(self.request,
- _('Unable to list containers.'),
- redirect=redirect)
- kwargs['containers'] = [(c.name, c.name) for c in containers[0]]
- return kwargs
-
- @staticmethod
- def get_copy_name(object_name):
- filename, ext = os.path.splitext(object_name)
- return "%s.copy%s" % (filename, ext)
-
- def get_initial(self):
- path = self.kwargs["subfolder_path"]
- object_name = self.kwargs["object_name"]
- orig = "%s%s" % (path or '', object_name)
-
- return {"new_container_name": self.kwargs["container_name"],
- "orig_container_name": self.kwargs["container_name"],
- "orig_object_name": orig,
- "path": path,
- "new_object_name": self.get_copy_name(object_name)}
-
- def get_context_data(self, **kwargs):
- context = super(CopyView, self).get_context_data(**kwargs)
- context['container_name'] = self.kwargs["container_name"]
- context['object_name'] = self.kwargs["object_name"]
- return context
-
-
-class ContainerDetailView(forms.ModalFormMixin, generic.TemplateView):
- template_name = 'project/containers/container_detail.html'
- page_title = _("Container Details")
-
- @memoized.memoized_method
- def get_object(self):
- try:
- return api.swift.swift_get_container(
- self.request,
- self.kwargs["container_name"],
- with_data=False)
- except Exception:
- redirect = reverse("horizon:project:containers:index")
- exceptions.handle(self.request,
- _('Unable to retrieve details.'),
- redirect=redirect)
-
- def get_context_data(self, **kwargs):
- context = super(ContainerDetailView, self).get_context_data(**kwargs)
- context['container'] = self.get_object()
- return context
-
-
-class ObjectDetailView(forms.ModalFormMixin, generic.TemplateView):
- template_name = 'project/containers/object_detail.html'
- page_title = _("Object Details")
-
- @memoized.memoized_method
- def get_object(self):
- try:
- return api.swift.swift_get_object(
- self.request,
- self.kwargs["container_name"],
- self.kwargs["object_path"],
- with_data=False)
- except Exception:
- redirect = reverse("horizon:project:containers:index")
- exceptions.handle(self.request,
- _('Unable to retrieve details.'),
- redirect=redirect)
-
- def get_context_data(self, **kwargs):
- context = super(ObjectDetailView, self).get_context_data(**kwargs)
- context['object'] = self.get_object()
- return context
-
-
-class UpdateObjectView(forms.ModalFormView):
- form_class = project_forms.UpdateObject
- template_name = 'project/containers/update.html'
- success_url = "horizon:project:containers:index"
- page_title = _("Update Object")
-
- def get_success_url(self):
- container = utils.wrap_delimiter(self.request.POST['container_name'])
- path = utils.wrap_delimiter(self.request.POST.get('path', ''))
- args = (container, path)
- return reverse(self.success_url, args=args)
-
- def get_initial(self):
- return {"container_name": self.kwargs["container_name"],
- "path": self.kwargs["subfolder_path"],
- "name": self.kwargs["object_name"]}
-
- def get_context_data(self, **kwargs):
- context = super(UpdateObjectView, self).get_context_data(**kwargs)
- context['container_name'] = self.kwargs["container_name"]
- context['subfolder_path'] = self.kwargs["subfolder_path"]
- context['object_name'] = self.kwargs["object_name"]
- return context
diff --git a/openstack_dashboard/dashboards/project/stacks/tests.py b/openstack_dashboard/dashboards/project/stacks/tests.py
index 71e972e0c..cb8e68703 100644
--- a/openstack_dashboard/dashboards/project/stacks/tests.py
+++ b/openstack_dashboard/dashboards/project/stacks/tests.py
@@ -74,7 +74,7 @@ class MappingsTests(test.TestCase):
'AWS::EC2::Instance',
'aaa')
assertMappingUrl(
- '/project/containers/aaa/',
+ '/project/containers/container/aaa/',
'OS::Swift::Container',
'aaa')
assertMappingUrl(
diff --git a/openstack_dashboard/dashboards/project/volumes/backups/forms.py b/openstack_dashboard/dashboards/project/volumes/backups/forms.py
index ae0d7ae8f..31a4fff3b 100644
--- a/openstack_dashboard/dashboards/project/volumes/backups/forms.py
+++ b/openstack_dashboard/dashboards/project/volumes/backups/forms.py
@@ -26,7 +26,7 @@ from horizon import messages
from openstack_dashboard import api
from openstack_dashboard.dashboards.project.containers \
- import forms as containers_forms
+ import utils as containers_utils
class CreateBackupForm(forms.SelfHandlingForm):
@@ -37,7 +37,7 @@ class CreateBackupForm(forms.SelfHandlingForm):
container_name = forms.CharField(
max_length=255,
label=_("Container Name"),
- validators=[containers_forms.no_slash_validator],
+ validators=[containers_utils.no_slash_validator],
required=False)
volume_id = forms.CharField(widget=forms.HiddenInput())
diff --git a/openstack_dashboard/enabled/_1920_project_containers_panel.py b/openstack_dashboard/enabled/_1920_project_containers_panel.py
index 305bdf3c6..9bbfee66b 100644
--- a/openstack_dashboard/enabled/_1920_project_containers_panel.py
+++ b/openstack_dashboard/enabled/_1920_project_containers_panel.py
@@ -25,13 +25,6 @@ ADD_PANEL = ('openstack_dashboard.dashboards.project.'
DISABLED = False
-# Which implementation of the panel should we use? Valid options
-# here are 'angular' (new implementation) and 'legacy' (old
-# implementation.)
-UPDATE_HORIZON_CONFIG = {
- 'swift_panel': 'angular'
-}
-
ADD_SCSS_FILES = [
'dashboard/project/containers/_containers.scss',
]
diff --git a/openstack_dashboard/test/settings.py b/openstack_dashboard/test/settings.py
index 24d073c2f..42cd7c45e 100644
--- a/openstack_dashboard/test/settings.py
+++ b/openstack_dashboard/test/settings.py
@@ -121,10 +121,6 @@ settings_utils.update_dashboards(
INSTALLED_APPS,
)
-# Remove this when the legacy panel is removed, along with its tests and
-# the stacks MappingsTests are updated with the new URL path.
-HORIZON_CONFIG['swift_panel'] = 'legacy'
-
settings_utils.find_static_files(HORIZON_CONFIG, AVAILABLE_THEMES,
THEME_COLLECTION_DIR, ROOT_PATH)
diff --git a/releasenotes/notes/remove-deprecated-swift-ui-1165b60bab5771d6.yaml b/releasenotes/notes/remove-deprecated-swift-ui-1165b60bab5771d6.yaml
new file mode 100644
index 000000000..499b82bc1
--- /dev/null
+++ b/releasenotes/notes/remove-deprecated-swift-ui-1165b60bab5771d6.yaml
@@ -0,0 +1,8 @@
+---
+upgrade:
+ - Any past use of the Django based Swift UI is no longer
+ supported and the code is being removed. The new
+ angularJS based version should be used instead.
+deprecations:
+ - Removing formerly deprecated Swift UI code that was
+ replaced with an improved Angular version in Mitaka.