Merge "Restrict launch fields when restoring from backup"
This commit is contained in:
commit
f278d12a57
@ -0,0 +1,6 @@
|
||||
---
|
||||
fixes:
|
||||
- Adds support for restricting the launch instance datastore field
|
||||
to the datastore and datastore version that the backup is
|
||||
relevant to. It also populates the restored backup as the only
|
||||
option in the advanced step backup field.
|
@ -12,19 +12,27 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import binascii
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django import http
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from mox3.mox import IsA # noqa
|
||||
import six
|
||||
|
||||
from openstack_auth import policy
|
||||
from openstack_dashboard import api as dash_api
|
||||
|
||||
from troveclient import common
|
||||
|
||||
from trove_dashboard import api
|
||||
from trove_dashboard.content.databases.workflows import create_instance
|
||||
from trove_dashboard.test import helpers as test
|
||||
|
||||
INDEX_URL = reverse('horizon:project:database_backups:index')
|
||||
BACKUP_URL = reverse('horizon:project:database_backups:create')
|
||||
DETAILS_URL = reverse('horizon:project:database_backups:detail', args=['id'])
|
||||
RESTORE_URL = reverse('horizon:project:databases:launch')
|
||||
|
||||
|
||||
class DatabasesBackupsTests(test.TestCase):
|
||||
@ -191,3 +199,63 @@ class DatabasesBackupsTests(test.TestCase):
|
||||
args=[incr_backup.id])
|
||||
res = self.client.get(url)
|
||||
self.assertTemplateUsed(res, 'project/database_backups/details.html')
|
||||
|
||||
@test.create_stubs({
|
||||
api.trove: ('backup_get', 'backup_list', 'configuration_list',
|
||||
'datastore_flavors', 'datastore_list',
|
||||
'datastore_version_list', 'instance_list'),
|
||||
dash_api.cinder: ('volume_type_list',),
|
||||
dash_api.neutron: ('network_list',),
|
||||
dash_api.nova: ('availability_zone_list',),
|
||||
policy: ('check',),
|
||||
})
|
||||
def test_restore_backup(self):
|
||||
policy.check((), IsA(http.HttpRequest)).MultipleTimes().AndReturn(True)
|
||||
backup = self.database_backups.first()
|
||||
api.trove.backup_get(IsA(http.HttpRequest), IsA(six.text_type)) \
|
||||
.AndReturn(self.database_backups.first())
|
||||
api.trove.backup_list(IsA(http.HttpRequest)).AndReturn(
|
||||
self.database_backups.list())
|
||||
api.trove.configuration_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.database_configurations.list())
|
||||
api.trove.datastore_flavors(IsA(http.HttpRequest),
|
||||
IsA(six.string_types),
|
||||
IsA(six.string_types)) \
|
||||
.AndReturn(self.flavors.list())
|
||||
api.trove.datastore_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.datastores.list())
|
||||
api.trove.datastore_version_list(IsA(http.HttpRequest),
|
||||
backup.datastore['type']) \
|
||||
.AndReturn(self.datastore_versions.list())
|
||||
api.trove.instance_list(IsA(http.HttpRequest), marker=None) \
|
||||
.AndReturn(common.Paginated(self.databases.list()))
|
||||
dash_api.cinder.volume_type_list(IsA(http.HttpRequest)).AndReturn([])
|
||||
dash_api.neutron.network_list(IsA(http.HttpRequest),
|
||||
tenant_id=self.tenant.id,
|
||||
shared=False).\
|
||||
AndReturn(self.networks.list()[:1])
|
||||
dash_api.nova.availability_zone_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.availability_zones.list())
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = RESTORE_URL + '?backup=%s' % self.database_backups.first().id
|
||||
res = self.client.get(url)
|
||||
self.assertTemplateUsed(res, 'project/databases/launch.html')
|
||||
|
||||
set_instance_detail_step = \
|
||||
[step for step in res.context_data['workflow'].steps
|
||||
if isinstance(step, create_instance.SetInstanceDetails)][0]
|
||||
fields = set_instance_detail_step.action.fields
|
||||
self.assertTrue(len(fields['datastore'].choices), 1)
|
||||
text = 'mysql - 5.6'
|
||||
choice = fields['datastore'].choices[0]
|
||||
self.assertTrue(choice[0], binascii.hexlify(text))
|
||||
self.assertTrue(choice[1], text)
|
||||
|
||||
advanced_step = [step for step in res.context_data['workflow'].steps
|
||||
if isinstance(step, create_instance.Advanced)][0]
|
||||
fields = advanced_step.action.fields
|
||||
self.assertTrue(len(fields['initial_state'].choices), 1)
|
||||
choice = fields['initial_state'].choices[0]
|
||||
self.assertTrue(choice[0], 'backup')
|
||||
self.assertTrue(choice[1], _('Restore from Backup'))
|
||||
|
@ -64,6 +64,11 @@ class SetInstanceDetailsAction(workflows.Action):
|
||||
}))
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
if args:
|
||||
self.backup_id = args[0].get('backup', None)
|
||||
else:
|
||||
self.backup_id = None
|
||||
|
||||
super(SetInstanceDetailsAction, self).__init__(request,
|
||||
*args,
|
||||
**kwargs)
|
||||
@ -184,11 +189,24 @@ class SetInstanceDetailsAction(workflows.Action):
|
||||
LOG.exception("Exception while obtaining datastore version list")
|
||||
self._datastore_versions = []
|
||||
|
||||
@memoized.memoized_method
|
||||
def get_backup(self, request, backup_id):
|
||||
try:
|
||||
return api.trove.backup_get(request, backup_id)
|
||||
except Exception:
|
||||
LOG.exception("Exception while obtaining backup information")
|
||||
return None
|
||||
|
||||
def populate_datastore_choices(self, request, context):
|
||||
choices = ()
|
||||
datastores = self.datastores(request)
|
||||
if datastores is not None:
|
||||
if self.backup_id:
|
||||
backup = self.get_backup(request, self.backup_id)
|
||||
for ds in datastores:
|
||||
if self.backup_id:
|
||||
if ds.name != backup.datastore['type']:
|
||||
continue
|
||||
versions = self.datastore_versions(request, ds.name)
|
||||
if versions:
|
||||
# only add to choices if datastore has at least one version
|
||||
@ -196,6 +214,9 @@ class SetInstanceDetailsAction(workflows.Action):
|
||||
for v in versions:
|
||||
if hasattr(v, 'active') and not v.active:
|
||||
continue
|
||||
if self.backup_id:
|
||||
if v.id != backup.datastore['version_id']:
|
||||
continue
|
||||
selection_text = self._build_datastore_display_text(
|
||||
ds.name, v.name)
|
||||
widget_text = self._build_widget_field_name(
|
||||
@ -350,6 +371,18 @@ class AdvancedAction(workflows.Action):
|
||||
'data-initial_state-master': _('Replica Count')
|
||||
}))
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
if args[0]:
|
||||
self.backup_id = args[0].get('backup', None)
|
||||
else:
|
||||
self.backup_id = None
|
||||
|
||||
super(AdvancedAction, self).__init__(request, *args, **kwargs)
|
||||
|
||||
if self.backup_id:
|
||||
self.fields['initial_state'].choices = [('backup',
|
||||
_('Restore from Backup'))]
|
||||
|
||||
class Meta(object):
|
||||
name = _("Advanced")
|
||||
help_text_template = "project/databases/_launch_advanced_help.html"
|
||||
@ -374,9 +407,13 @@ class AdvancedAction(workflows.Action):
|
||||
|
||||
def populate_backup_choices(self, request, context):
|
||||
try:
|
||||
choices = []
|
||||
backups = api.trove.backup_list(request)
|
||||
choices = [(b.id, b.name) for b in backups
|
||||
if b.status == 'COMPLETED']
|
||||
for b in backups:
|
||||
if self.backup_id and b.id != self.backup_id:
|
||||
continue
|
||||
if b.status == 'COMPLETED':
|
||||
choices.append((b.id, b.name))
|
||||
except Exception:
|
||||
choices = []
|
||||
|
||||
|
@ -229,6 +229,11 @@ BACKUP_ONE = {
|
||||
"size": 0.13,
|
||||
"id": "0edb3c14-8919-4583-9add-00df9e524081",
|
||||
"description": "Long description of backup",
|
||||
"datastore": {
|
||||
"type": "mysql",
|
||||
"version": "5.6",
|
||||
"version_id": "500a6d52-8347-4e00-8e4c-f4fa9cf96ae9"
|
||||
},
|
||||
}
|
||||
|
||||
BACKUP_TWO = {
|
||||
@ -241,6 +246,11 @@ BACKUP_TWO = {
|
||||
"size": 0.13,
|
||||
"id": "e4602a3c-2bca-478f-b059-b6c215510fb4",
|
||||
"description": "Longer description of backup",
|
||||
"datastore": {
|
||||
"type": "mysql",
|
||||
"version": "5.6",
|
||||
"version_id": "500a6d52-8347-4e00-8e4c-f4fa9cf96ae9"
|
||||
},
|
||||
}
|
||||
|
||||
BACKUP_TWO_INC = {
|
||||
@ -254,6 +264,11 @@ BACKUP_TWO_INC = {
|
||||
"id": "e4602a3c-2bca-478f-b059-b6c215510fb5",
|
||||
"description": "Longer description of backup",
|
||||
"parent_id": "e4602a3c-2bca-478f-b059-b6c215510fb4",
|
||||
"datastore": {
|
||||
"type": "mysql",
|
||||
"version": "5.6",
|
||||
"version_id": "500a6d52-8347-4e00-8e4c-f4fa9cf96ae9"
|
||||
},
|
||||
}
|
||||
|
||||
CONFIG_ONE = {
|
||||
|
Loading…
Reference in New Issue
Block a user