Add support for instance datastore-flavors
Update the launch wizard to use datastore-flavors instead of flavor-list. When selecting a datastore the flavor list will change to display only flavors for the selected datastore. If the datastore flavor is not configured then the default flavor list will be used. Updated unit tests to use the datastore flavors. Change-Id: I4bf0033a3e6b2a117f93db2c0c16a6d02642f368 Closes-Bug: #1549367
This commit is contained in:
parent
acb3d96ef0
commit
e1c44b2092
@ -13,6 +13,7 @@
|
|||||||
# 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 binascii
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import django
|
import django
|
||||||
@ -128,7 +129,7 @@ class DatabaseTests(test.TestCase):
|
|||||||
self.assertMessageCount(res, error=1)
|
self.assertMessageCount(res, error=1)
|
||||||
|
|
||||||
@test.create_stubs({
|
@test.create_stubs({
|
||||||
api.trove: ('flavor_list', 'backup_list',
|
api.trove: ('datastore_flavors', 'backup_list',
|
||||||
'datastore_list', 'datastore_version_list',
|
'datastore_list', 'datastore_version_list',
|
||||||
'instance_list'),
|
'instance_list'),
|
||||||
dash_api.cinder: ('volume_type_list',),
|
dash_api.cinder: ('volume_type_list',),
|
||||||
@ -137,8 +138,10 @@ class DatabaseTests(test.TestCase):
|
|||||||
})
|
})
|
||||||
def test_launch_instance(self):
|
def test_launch_instance(self):
|
||||||
policy.check((), IsA(http.HttpRequest)).MultipleTimes().AndReturn(True)
|
policy.check((), IsA(http.HttpRequest)).MultipleTimes().AndReturn(True)
|
||||||
api.trove.flavor_list(IsA(http.HttpRequest)).AndReturn(
|
api.trove.datastore_flavors(IsA(http.HttpRequest),
|
||||||
self.flavors.list())
|
IsA(six.string_types),
|
||||||
|
IsA(six.string_types)).\
|
||||||
|
MultipleTimes().AndReturn(self.flavors.list())
|
||||||
api.trove.backup_list(IsA(http.HttpRequest)).AndReturn(
|
api.trove.backup_list(IsA(http.HttpRequest)).AndReturn(
|
||||||
self.database_backups.list())
|
self.database_backups.list())
|
||||||
api.trove.instance_list(IsA(http.HttpRequest)).AndReturn(
|
api.trove.instance_list(IsA(http.HttpRequest)).AndReturn(
|
||||||
@ -197,7 +200,7 @@ class DatabaseTests(test.TestCase):
|
|||||||
log.setLevel(level)
|
log.setLevel(level)
|
||||||
|
|
||||||
@test.create_stubs({
|
@test.create_stubs({
|
||||||
api.trove: ('flavor_list', 'backup_list', 'instance_create',
|
api.trove: ('datastore_flavors', 'backup_list', 'instance_create',
|
||||||
'datastore_list', 'datastore_version_list',
|
'datastore_list', 'datastore_version_list',
|
||||||
'instance_list'),
|
'instance_list'),
|
||||||
dash_api.cinder: ('volume_type_list',),
|
dash_api.cinder: ('volume_type_list',),
|
||||||
@ -206,8 +209,10 @@ class DatabaseTests(test.TestCase):
|
|||||||
})
|
})
|
||||||
def test_create_simple_instance(self):
|
def test_create_simple_instance(self):
|
||||||
policy.check((), IsA(http.HttpRequest)).MultipleTimes().AndReturn(True)
|
policy.check((), IsA(http.HttpRequest)).MultipleTimes().AndReturn(True)
|
||||||
api.trove.flavor_list(IsA(http.HttpRequest)).AndReturn(
|
api.trove.datastore_flavors(IsA(http.HttpRequest),
|
||||||
self.flavors.list())
|
IsA(six.string_types),
|
||||||
|
IsA(six.string_types)).\
|
||||||
|
MultipleTimes().AndReturn(self.flavors.list())
|
||||||
|
|
||||||
api.trove.backup_list(IsA(http.HttpRequest)).AndReturn(
|
api.trove.backup_list(IsA(http.HttpRequest)).AndReturn(
|
||||||
self.database_backups.list())
|
self.database_backups.list())
|
||||||
@ -236,6 +241,10 @@ class DatabaseTests(test.TestCase):
|
|||||||
|
|
||||||
nics = [{"net-id": self.networks.first().id, "v4-fixed-ip": ''}]
|
nics = [{"net-id": self.networks.first().id, "v4-fixed-ip": ''}]
|
||||||
|
|
||||||
|
datastore = 'mysql'
|
||||||
|
datastore_version = '5.5'
|
||||||
|
field_name = self._build_flavor_widget_name(datastore,
|
||||||
|
datastore_version)
|
||||||
# Actual create database call
|
# Actual create database call
|
||||||
api.trove.instance_create(
|
api.trove.instance_create(
|
||||||
IsA(http.HttpRequest),
|
IsA(http.HttpRequest),
|
||||||
@ -243,8 +252,8 @@ class DatabaseTests(test.TestCase):
|
|||||||
IsA(int),
|
IsA(int),
|
||||||
IsA(six.text_type),
|
IsA(six.text_type),
|
||||||
databases=None,
|
databases=None,
|
||||||
datastore=IsA(six.text_type),
|
datastore=datastore,
|
||||||
datastore_version=IsA(six.text_type),
|
datastore_version=datastore_version,
|
||||||
restore_point=None,
|
restore_point=None,
|
||||||
replica_of=None,
|
replica_of=None,
|
||||||
users=None,
|
users=None,
|
||||||
@ -257,8 +266,9 @@ class DatabaseTests(test.TestCase):
|
|||||||
'name': "MyDB",
|
'name': "MyDB",
|
||||||
'volume': '1',
|
'volume': '1',
|
||||||
'flavor': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
|
'flavor': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
|
||||||
|
'datastore': field_name,
|
||||||
|
field_name: 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
|
||||||
'network': self.networks.first().id,
|
'network': self.networks.first().id,
|
||||||
'datastore': 'mysql,5.5',
|
|
||||||
'volume_type': 'no_type'
|
'volume_type': 'no_type'
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,7 +276,7 @@ class DatabaseTests(test.TestCase):
|
|||||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||||
|
|
||||||
@test.create_stubs({
|
@test.create_stubs({
|
||||||
api.trove: ('flavor_list', 'backup_list', 'instance_create',
|
api.trove: ('datastore_flavors', 'backup_list', 'instance_create',
|
||||||
'datastore_list', 'datastore_version_list',
|
'datastore_list', 'datastore_version_list',
|
||||||
'instance_list'),
|
'instance_list'),
|
||||||
dash_api.cinder: ('volume_type_list',),
|
dash_api.cinder: ('volume_type_list',),
|
||||||
@ -276,8 +286,10 @@ class DatabaseTests(test.TestCase):
|
|||||||
def test_create_simple_instance_exception(self):
|
def test_create_simple_instance_exception(self):
|
||||||
policy.check((), IsA(http.HttpRequest)).MultipleTimes().AndReturn(True)
|
policy.check((), IsA(http.HttpRequest)).MultipleTimes().AndReturn(True)
|
||||||
trove_exception = self.exceptions.nova
|
trove_exception = self.exceptions.nova
|
||||||
api.trove.flavor_list(IsA(http.HttpRequest)).AndReturn(
|
api.trove.datastore_flavors(IsA(http.HttpRequest),
|
||||||
self.flavors.list())
|
IsA(six.string_types),
|
||||||
|
IsA(six.string_types)).\
|
||||||
|
MultipleTimes().AndReturn(self.flavors.list())
|
||||||
|
|
||||||
api.trove.backup_list(IsA(http.HttpRequest)).AndReturn(
|
api.trove.backup_list(IsA(http.HttpRequest)).AndReturn(
|
||||||
self.database_backups.list())
|
self.database_backups.list())
|
||||||
@ -306,6 +318,10 @@ class DatabaseTests(test.TestCase):
|
|||||||
|
|
||||||
nics = [{"net-id": self.networks.first().id, "v4-fixed-ip": ''}]
|
nics = [{"net-id": self.networks.first().id, "v4-fixed-ip": ''}]
|
||||||
|
|
||||||
|
datastore = 'mysql'
|
||||||
|
datastore_version = '5.5'
|
||||||
|
field_name = self._build_flavor_widget_name(datastore,
|
||||||
|
datastore_version)
|
||||||
# Actual create database call
|
# Actual create database call
|
||||||
api.trove.instance_create(
|
api.trove.instance_create(
|
||||||
IsA(http.HttpRequest),
|
IsA(http.HttpRequest),
|
||||||
@ -313,8 +329,8 @@ class DatabaseTests(test.TestCase):
|
|||||||
IsA(int),
|
IsA(int),
|
||||||
IsA(six.text_type),
|
IsA(six.text_type),
|
||||||
databases=None,
|
databases=None,
|
||||||
datastore=IsA(six.text_type),
|
datastore=datastore,
|
||||||
datastore_version=IsA(six.text_type),
|
datastore_version=datastore_version,
|
||||||
restore_point=None,
|
restore_point=None,
|
||||||
replica_of=None,
|
replica_of=None,
|
||||||
users=None,
|
users=None,
|
||||||
@ -327,8 +343,9 @@ class DatabaseTests(test.TestCase):
|
|||||||
'name': "MyDB",
|
'name': "MyDB",
|
||||||
'volume': '1',
|
'volume': '1',
|
||||||
'flavor': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
|
'flavor': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
|
||||||
|
'datastore': field_name,
|
||||||
|
field_name: 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
|
||||||
'network': self.networks.first().id,
|
'network': self.networks.first().id,
|
||||||
'datastore': 'mysql,5.5',
|
|
||||||
'volume_type': 'no_type'
|
'volume_type': 'no_type'
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -964,7 +981,7 @@ class DatabaseTests(test.TestCase):
|
|||||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||||
|
|
||||||
@test.create_stubs({
|
@test.create_stubs({
|
||||||
api.trove: ('flavor_list', 'backup_list', 'instance_create',
|
api.trove: ('datastore_flavors', 'backup_list', 'instance_create',
|
||||||
'datastore_list', 'datastore_version_list',
|
'datastore_list', 'datastore_version_list',
|
||||||
'instance_list_all', 'instance_get'),
|
'instance_list_all', 'instance_get'),
|
||||||
dash_api.cinder: ('volume_type_list',),
|
dash_api.cinder: ('volume_type_list',),
|
||||||
@ -973,8 +990,10 @@ class DatabaseTests(test.TestCase):
|
|||||||
})
|
})
|
||||||
def test_create_replica_instance(self):
|
def test_create_replica_instance(self):
|
||||||
policy.check((), IsA(http.HttpRequest)).MultipleTimes().AndReturn(True)
|
policy.check((), IsA(http.HttpRequest)).MultipleTimes().AndReturn(True)
|
||||||
api.trove.flavor_list(IsA(http.HttpRequest)).AndReturn(
|
api.trove.datastore_flavors(IsA(http.HttpRequest),
|
||||||
self.flavors.list())
|
IsA(six.string_types),
|
||||||
|
IsA(six.string_types)).\
|
||||||
|
MultipleTimes().AndReturn(self.flavors.list())
|
||||||
|
|
||||||
api.trove.backup_list(IsA(http.HttpRequest)).AndReturn(
|
api.trove.backup_list(IsA(http.HttpRequest)).AndReturn(
|
||||||
self.database_backups.list())
|
self.database_backups.list())
|
||||||
@ -1005,6 +1024,10 @@ class DatabaseTests(test.TestCase):
|
|||||||
api.trove.instance_get(IsA(http.HttpRequest), IsA(six.text_type))\
|
api.trove.instance_get(IsA(http.HttpRequest), IsA(six.text_type))\
|
||||||
.AndReturn(self.databases.first())
|
.AndReturn(self.databases.first())
|
||||||
|
|
||||||
|
datastore = 'mysql'
|
||||||
|
datastore_version = '5.5'
|
||||||
|
field_name = self._build_flavor_widget_name(datastore,
|
||||||
|
datastore_version)
|
||||||
# Actual create database call
|
# Actual create database call
|
||||||
api.trove.instance_create(
|
api.trove.instance_create(
|
||||||
IsA(http.HttpRequest),
|
IsA(http.HttpRequest),
|
||||||
@ -1012,8 +1035,8 @@ class DatabaseTests(test.TestCase):
|
|||||||
IsA(int),
|
IsA(int),
|
||||||
IsA(six.text_type),
|
IsA(six.text_type),
|
||||||
databases=None,
|
databases=None,
|
||||||
datastore=IsA(six.text_type),
|
datastore=datastore,
|
||||||
datastore_version=IsA(six.text_type),
|
datastore_version=datastore_version,
|
||||||
restore_point=None,
|
restore_point=None,
|
||||||
replica_of=self.databases.first().id,
|
replica_of=self.databases.first().id,
|
||||||
users=None,
|
users=None,
|
||||||
@ -1026,8 +1049,9 @@ class DatabaseTests(test.TestCase):
|
|||||||
'name': "MyDB",
|
'name': "MyDB",
|
||||||
'volume': '1',
|
'volume': '1',
|
||||||
'flavor': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
|
'flavor': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
|
||||||
|
'datastore': field_name,
|
||||||
|
field_name: 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
|
||||||
'network': self.networks.first().id,
|
'network': self.networks.first().id,
|
||||||
'datastore': 'mysql,5.5',
|
|
||||||
'initial_state': 'master',
|
'initial_state': 'master',
|
||||||
'master': self.databases.first().id,
|
'master': self.databases.first().id,
|
||||||
'replica_count': 2,
|
'replica_count': 2,
|
||||||
@ -1159,3 +1183,10 @@ class DatabaseTests(test.TestCase):
|
|||||||
advanced_page = create_instance.AdvancedAction(request, None)
|
advanced_page = create_instance.AdvancedAction(request, None)
|
||||||
choices = advanced_page.populate_master_choices(request, None)
|
choices = advanced_page.populate_master_choices(request, None)
|
||||||
self.assertTrue(len(choices) == len(self.databases.list()) + 1)
|
self.assertTrue(len(choices) == len(self.databases.list()) + 1)
|
||||||
|
|
||||||
|
def _build_datastore_display_text(self, datastore, datastore_version):
|
||||||
|
return datastore + ' - ' + datastore_version
|
||||||
|
|
||||||
|
def _build_flavor_widget_name(self, datastore, datastore_version):
|
||||||
|
return binascii.hexlify(self._build_datastore_display_text(
|
||||||
|
datastore, datastore_version))
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
# 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 binascii
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@ -34,10 +35,15 @@ from trove_dashboard import api
|
|||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_datastore_and_version_text(datastore_and_version):
|
||||||
|
if datastore_and_version:
|
||||||
|
datastore, datastore_version = datastore_and_version.split('-', 1)
|
||||||
|
return datastore.strip(), datastore_version.strip()
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
|
||||||
class SetInstanceDetailsAction(workflows.Action):
|
class SetInstanceDetailsAction(workflows.Action):
|
||||||
name = forms.CharField(max_length=80, label=_("Instance Name"))
|
name = forms.CharField(max_length=80, label=_("Instance Name"))
|
||||||
flavor = forms.ChoiceField(label=_("Flavor"),
|
|
||||||
help_text=_("Size of image to launch."))
|
|
||||||
volume = forms.IntegerField(label=_("Volume Size"),
|
volume = forms.IntegerField(label=_("Volume Size"),
|
||||||
min_value=0,
|
min_value=0,
|
||||||
initial=1,
|
initial=1,
|
||||||
@ -46,24 +52,53 @@ class SetInstanceDetailsAction(workflows.Action):
|
|||||||
label=_("Volume Type"),
|
label=_("Volume Type"),
|
||||||
required=False,
|
required=False,
|
||||||
help_text=_("Applicable only if the volume size is specified."))
|
help_text=_("Applicable only if the volume size is specified."))
|
||||||
datastore = forms.ChoiceField(label=_("Datastore"),
|
datastore = forms.ChoiceField(
|
||||||
help_text=_(
|
label=_("Datastore"),
|
||||||
"Type and version of datastore."))
|
help_text=_("Type and version of datastore."),
|
||||||
|
widget=forms.Select(attrs={
|
||||||
|
'class': 'switchable',
|
||||||
|
'data-slug': 'datastore'
|
||||||
|
}))
|
||||||
|
|
||||||
class Meta(object):
|
class Meta(object):
|
||||||
name = _("Details")
|
name = _("Details")
|
||||||
help_text_template = "project/databases/_launch_details_help.html"
|
help_text_template = "project/databases/_launch_details_help.html"
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
if self.data.get("datastore", None) == "select_datastore_type_version":
|
datastore_and_version = self.data.get("datastore", None)
|
||||||
|
if not datastore_and_version:
|
||||||
msg = _("You must select a datastore type and version.")
|
msg = _("You must select a datastore type and version.")
|
||||||
self._errors["datastore"] = self.error_class([msg])
|
self._errors["datastore"] = self.error_class([msg])
|
||||||
|
else:
|
||||||
|
datastore, datastore_version = parse_datastore_and_version_text(
|
||||||
|
binascii.unhexlify(datastore_and_version))
|
||||||
|
field_name = self._build_flavor_field_name(datastore,
|
||||||
|
datastore_version)
|
||||||
|
flavor = self.data.get(field_name, None)
|
||||||
|
if not flavor:
|
||||||
|
msg = _("You must select a flavor.")
|
||||||
|
self._errors[field_name] = self.error_class([msg])
|
||||||
|
|
||||||
return self.cleaned_data
|
return self.cleaned_data
|
||||||
|
|
||||||
|
def handle(self, request, context):
|
||||||
|
datastore_and_version = context["datastore"]
|
||||||
|
if datastore_and_version:
|
||||||
|
datastore, datastore_version = parse_datastore_and_version_text(
|
||||||
|
binascii.unhexlify(context["datastore"]))
|
||||||
|
field_name = self._build_flavor_field_name(datastore,
|
||||||
|
datastore_version)
|
||||||
|
flavor = self.data[field_name]
|
||||||
|
if flavor:
|
||||||
|
context["flavor"] = flavor
|
||||||
|
return context
|
||||||
|
return None
|
||||||
|
|
||||||
@memoized.memoized_method
|
@memoized.memoized_method
|
||||||
def flavors(self, request):
|
def datastore_flavors(self, request, datastore_name, datastore_version):
|
||||||
try:
|
try:
|
||||||
return api.trove.flavor_list(request)
|
return api.trove.datastore_flavors(
|
||||||
|
request, datastore_name, datastore_version)
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.exception("Exception while obtaining flavors list")
|
LOG.exception("Exception while obtaining flavors list")
|
||||||
redirect = reverse("horizon:project:databases:index")
|
redirect = reverse("horizon:project:databases:index")
|
||||||
@ -71,12 +106,6 @@ class SetInstanceDetailsAction(workflows.Action):
|
|||||||
_('Unable to obtain flavors.'),
|
_('Unable to obtain flavors.'),
|
||||||
redirect=redirect)
|
redirect=redirect)
|
||||||
|
|
||||||
def populate_flavor_choices(self, request, context):
|
|
||||||
flavors = self.flavors(request)
|
|
||||||
if flavors:
|
|
||||||
return instance_utils.sort_flavor_list(request, flavors)
|
|
||||||
return []
|
|
||||||
|
|
||||||
@memoized.memoized_method
|
@memoized.memoized_method
|
||||||
def populate_volume_type_choices(self, request, context):
|
def populate_volume_type_choices(self, request, context):
|
||||||
try:
|
try:
|
||||||
@ -106,36 +135,66 @@ class SetInstanceDetailsAction(workflows.Action):
|
|||||||
|
|
||||||
def populate_datastore_choices(self, request, context):
|
def populate_datastore_choices(self, request, context):
|
||||||
choices = ()
|
choices = ()
|
||||||
set_initial = False
|
|
||||||
datastores = self.datastores(request)
|
datastores = self.datastores(request)
|
||||||
if datastores is not None:
|
if datastores is not None:
|
||||||
num_datastores_with_one_version = 0
|
|
||||||
for ds in datastores:
|
for ds in datastores:
|
||||||
versions = self.datastore_versions(request, ds.name)
|
versions = self.datastore_versions(request, ds.name)
|
||||||
if not set_initial:
|
|
||||||
if len(versions) >= 2:
|
|
||||||
set_initial = True
|
|
||||||
elif len(versions) == 1:
|
|
||||||
num_datastores_with_one_version += 1
|
|
||||||
if num_datastores_with_one_version > 1:
|
|
||||||
set_initial = True
|
|
||||||
if versions:
|
if versions:
|
||||||
# only add to choices if datastore has at least one version
|
# only add to choices if datastore has at least one version
|
||||||
version_choices = ()
|
version_choices = ()
|
||||||
for v in versions:
|
for v in versions:
|
||||||
if hasattr(v, 'active') and not v.active:
|
if hasattr(v, 'active') and not v.active:
|
||||||
continue
|
continue
|
||||||
|
selection_text = self._build_datastore_display_text(
|
||||||
|
ds.name, v.name)
|
||||||
|
widget_text = self._build_widget_field_name(
|
||||||
|
ds.name, v.name)
|
||||||
version_choices = (version_choices +
|
version_choices = (version_choices +
|
||||||
((ds.name + ',' + v.name, v.name),))
|
((widget_text, selection_text),))
|
||||||
datastore_choices = (ds.name, version_choices)
|
self._add_datastore_flavor_field(request,
|
||||||
choices = choices + (datastore_choices,)
|
ds.name,
|
||||||
if set_initial:
|
v.name)
|
||||||
# prepend choice to force user to choose
|
choices = choices + version_choices
|
||||||
initial = (('select_datastore_type_version',
|
|
||||||
_('Select datastore type and version')))
|
|
||||||
choices = (initial,) + choices
|
|
||||||
return choices
|
return choices
|
||||||
|
|
||||||
|
def _add_datastore_flavor_field(self,
|
||||||
|
request,
|
||||||
|
datastore,
|
||||||
|
datastore_version):
|
||||||
|
name = self._build_widget_field_name(datastore, datastore_version)
|
||||||
|
attr_key = 'data-datastore-' + name
|
||||||
|
field_name = self._build_flavor_field_name(datastore,
|
||||||
|
datastore_version)
|
||||||
|
self.fields[field_name] = forms.ChoiceField(
|
||||||
|
label=_("Flavor"),
|
||||||
|
help_text=_("Size of image to launch."),
|
||||||
|
required=False,
|
||||||
|
widget=forms.Select(attrs={
|
||||||
|
'class': 'switched',
|
||||||
|
'data-switch-on': 'datastore',
|
||||||
|
attr_key: _("Flavor")
|
||||||
|
}))
|
||||||
|
valid_flavors = self.datastore_flavors(request,
|
||||||
|
datastore,
|
||||||
|
datastore_version)
|
||||||
|
if valid_flavors:
|
||||||
|
self.fields[field_name].choices = instance_utils.sort_flavor_list(
|
||||||
|
request, valid_flavors)
|
||||||
|
|
||||||
|
def _build_datastore_display_text(self, datastore, datastore_version):
|
||||||
|
return datastore + ' - ' + datastore_version
|
||||||
|
|
||||||
|
def _build_widget_field_name(self, datastore, datastore_version):
|
||||||
|
# Since the fieldnames cannot contain an uppercase character
|
||||||
|
# we generate a hex encoded string representation of the
|
||||||
|
# datastore and version as the fieldname
|
||||||
|
return binascii.hexlify(
|
||||||
|
self._build_datastore_display_text(datastore, datastore_version))
|
||||||
|
|
||||||
|
def _build_flavor_field_name(self, datastore, datastore_version):
|
||||||
|
return self._build_widget_field_name(datastore,
|
||||||
|
datastore_version)
|
||||||
|
|
||||||
|
|
||||||
TROVE_ADD_USER_PERMS = getattr(settings, 'TROVE_ADD_USER_PERMS', [])
|
TROVE_ADD_USER_PERMS = getattr(settings, 'TROVE_ADD_USER_PERMS', [])
|
||||||
TROVE_ADD_DATABASE_PERMS = getattr(settings, 'TROVE_ADD_DATABASE_PERMS', [])
|
TROVE_ADD_DATABASE_PERMS = getattr(settings, 'TROVE_ADD_DATABASE_PERMS', [])
|
||||||
@ -387,8 +446,8 @@ class LaunchInstance(workflows.Workflow):
|
|||||||
|
|
||||||
def handle(self, request, context):
|
def handle(self, request, context):
|
||||||
try:
|
try:
|
||||||
datastore = self.context['datastore'].split(',')[0]
|
datastore, datastore_version = parse_datastore_and_version_text(
|
||||||
datastore_version = self.context['datastore'].split(',')[1]
|
binascii.unhexlify(self.context['datastore']))
|
||||||
LOG.info("Launching database instance with parameters "
|
LOG.info("Launching database instance with parameters "
|
||||||
"{name=%s, volume=%s, volume_type=%s, flavor=%s, "
|
"{name=%s, volume=%s, volume_type=%s, flavor=%s, "
|
||||||
"datastore=%s, datastore_version=%s, "
|
"datastore=%s, datastore_version=%s, "
|
||||||
|
Loading…
Reference in New Issue
Block a user