Merge "Added volume type description for volume type"

This commit is contained in:
Jenkins 2015-08-19 07:01:34 +00:00 committed by Gerrit Code Review
commit 41c6c7b735
17 changed files with 454 additions and 19 deletions

View File

@ -0,0 +1,75 @@
horizon.Volumes = {
selected_volume_type: null,
volume_types: [],
initWithTypes: function(volume_types) {
this.volume_types = volume_types;
this._attachInputHandlers();
this.getSelectedType();
this.showTypeDescription();
},
/*
*Returns the type object for the selected type in the form.
*/
getSelectedType: function() {
this.selected_volume_type = $.grep(this.volume_types, function(type) {
var selected_name = $("#id_type").children(":selected").val();
return type.name === selected_name;
})[0];
return this.selected_volume_type;
},
showTypeDescription: function() {
this.getSelectedType();
if (this.selected_volume_type) {
var description = this.selected_volume_type.description;
var name = this.selected_volume_type.name;
if (name === 'no_type') {
$("#id_show_volume_type_name").html("");
} else {
$("#id_show_volume_type_name").html(name);
}
if (description) {
$("#id_show_volume_type_desc").html(description);
} else {
$("#id_show_volume_type_desc").html(
gettext('No description available.'));
}
}
},
toggleTypeDescription: function() {
var selected_volume_source =
$("#id_volume_source_type").children(":selected").val();
if(selected_volume_source === 'volume_source' ||
selected_volume_source === 'snapshot_source') {
$("#id_show_volume_type_desc_div").hide();
}
else {
$("#id_show_volume_type_desc_div").show();
}
},
_attachInputHandlers: function() {
var scope = this;
var eventCallback_type = function() {
scope.showTypeDescription();
};
$('#id_type').on('change', eventCallback_type);
var eventCallback_volume_source_type = function() {
scope.toggleTypeDescription();
};
$('#id_volume_source_type').on('change', eventCallback_volume_source_type);
}
};

View File

@ -448,6 +448,24 @@ def volume_type_list_with_qos_associations(request):
return vol_types
def volume_type_get_with_qos_association(request, volume_type_id):
vol_type = volume_type_get(request, volume_type_id)
vol_type.associated_qos_spec = ""
# get all currently defined qos specs
qos_specs = qos_spec_list(request)
for qos_spec in qos_specs:
# get all volume types this qos spec is associated with
assoc_vol_types = qos_spec_get_associations(request, qos_spec.id)
for assoc_vol_type in assoc_vol_types:
if vol_type.id == assoc_vol_type.id:
# update volume type to hold this association info
vol_type.associated_qos_spec = qos_spec.name
return vol_type
return vol_type
def default_quota_update(request, **kwargs):
cinderclient(request).quota_classes.update(DEFAULT_QUOTA_NAME, **kwargs)
@ -456,8 +474,18 @@ def volume_type_list(request):
return cinderclient(request).volume_types.list()
def volume_type_create(request, name):
return cinderclient(request).volume_types.create(name)
def volume_type_create(request, name, description=None):
return cinderclient(request).volume_types.create(name, description)
def volume_type_update(request, volume_type_id, name=None, description=None):
return cinderclient(request).volume_types.update(volume_type_id,
name,
description)
def volume_type_default(request):
return cinderclient(request).volume_types.default()
def volume_type_delete(request, volume_type_id):

View File

@ -0,0 +1,21 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% load url from future %}
{% block form_id %}{% endblock %}
{% block form_action %}{% url 'horizon:admin:volumes:volume_types:update_type' volume_type.id %}{% endblock %}
{% block modal_id %}update_volume_type_modal{% endblock %}
{% block modal-header %}{% trans "Edit Volume Type" %}{% endblock %}
{% block modal-body %}
<div class="left">
<fieldset>
{% include "horizon/common/_form_fields.html" %}
</fieldset>
</div>
<div class="right">
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Modify volume type name and description." %}</p>
</div>
{% endblock %}

View File

@ -0,0 +1,11 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Edit Volume Type" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Edit Volume Type") %}
{% endblock page_header %}
{% block main %}
{% include 'admin/volumes/volume_types/_update_volume_type.html' %}
{% endblock %}

View File

@ -10,8 +10,8 @@
# License for the specific language governing permissions and limitations
# under the License.
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
@ -166,3 +166,41 @@ class EditQosSpecConsumer(forms.SelfHandlingForm):
redirect = reverse("horizon:admin:volumes:index")
exceptions.handle(request, _('Error editing QoS Spec consumer.'),
redirect=redirect)
class EditVolumeType(forms.SelfHandlingForm):
name = forms.CharField(max_length=255,
label=_("Name"))
description = forms.CharField(max_length=255,
widget=forms.Textarea(attrs={'rows': 4}),
label=_("Description"),
required=False)
def clean_name(self):
cleaned_name = self.cleaned_data['name']
if len(cleaned_name.strip()) == 0:
msg = _('New name cannot be empty.')
self._errors['name'] = self.error_class([msg])
return cleaned_name
def handle(self, request, data):
volume_type_id = self.initial['id']
try:
cinder.volume_type_update(request,
volume_type_id,
data['name'],
data['description'])
message = _('Successfully updated volume type.')
messages.success(request, message)
return True
except Exception as ex:
redirect = reverse("horizon:admin:volumes:index")
if ex.code == 409:
error_message = _('New name conflicts with another '
'volume type.')
else:
error_message = _('Unable to update volume type.')
exceptions.handle(request, error_message,
redirect=redirect)

View File

@ -15,9 +15,11 @@ from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext_lazy
from horizon import exceptions
from horizon import forms
from horizon import tables
from openstack_dashboard.api import cinder
from openstack_dashboard import policy
class CreateVolumeType(tables.LinkAction):
@ -29,11 +31,21 @@ class CreateVolumeType(tables.LinkAction):
policy_rules = (("volume", "volume_extension:types_manage"),)
class EditVolumeType(tables.LinkAction):
name = "edit"
verbose_name = _("Edit Volume Type")
url = "horizon:admin:volumes:volume_types:update_type"
classes = ("ajax-modal",)
icon = "pencil"
policy_rules = (("volume", "volume_extension:types_manage"),)
class ViewVolumeTypeExtras(tables.LinkAction):
name = "extras"
verbose_name = _("View Extra Specs")
url = "horizon:admin:volumes:volume_types:extras:index"
classes = ("btn-edit",)
classes = ("ajax-modal",)
icon = "pencil"
policy_rules = (("volume", "volume_extension:types_manage"),)
@ -142,8 +154,64 @@ class VolumeTypesFilterAction(tables.FilterAction):
if query in volume_type.name.lower()]
class UpdateRow(tables.Row):
ajax = True
def get_data(self, request, volume_type_id):
try:
volume_type = \
cinder.volume_type_get_with_qos_association(request,
volume_type_id)
except Exception:
exceptions.handle(request,
_('Unable to retrieve volume type qos.'))
return volume_type
class UpdateCell(tables.UpdateAction):
def allowed(self, request, volume_type, cell):
return policy.check(
("volume_extension", "volume_extension:types_manage"), request)
def update_cell(self, request, data, volume_type_id,
cell_name, new_cell_value):
# inline update volume type name and/or description
try:
vol_type_obj = data
# updating changed value by new value
setattr(vol_type_obj, cell_name, new_cell_value)
name_value = getattr(vol_type_obj, 'name', None)
desc_value = getattr(vol_type_obj, 'description', None)
cinder.volume_type_update(
request,
volume_type_id,
name=name_value,
description=desc_value)
except Exception as ex:
if ex.code and ex.code == 409:
error_message = _('New name conflicts with another '
'volume type.')
else:
error_message = _('Unable to update the volume type.')
exceptions.handle(request, error_message)
return False
return True
class VolumeTypesTable(tables.DataTable):
name = tables.Column("name", verbose_name=_("Name"))
name = tables.Column("name", verbose_name=_("Name"),
form_field=forms.CharField(
max_length=64, required=True),
update_action=UpdateCell)
description = tables.Column(lambda obj: getattr(obj, 'description', None),
verbose_name=_('Description'),
form_field=forms.CharField(
widget=forms.Textarea(attrs={'rows': 4}),
required=False),
update_action=UpdateCell)
assoc_qos_spec = tables.Column("associated_qos_spec",
verbose_name=_("Associated QoS Spec"))
encryption = tables.Column(get_volume_type_encryption,
@ -166,8 +234,10 @@ class VolumeTypesTable(tables.DataTable):
row_actions = (CreateVolumeTypeEncryption,
ViewVolumeTypeExtras,
ManageQosSpecAssociation,
EditVolumeType,
DeleteVolumeTypeEncryption,
DeleteVolumeType,)
row_class = UpdateRow
# QOS Specs section of panel

View File

@ -23,18 +23,42 @@ from openstack_dashboard.test import helpers as test
class VolumeTypeTests(test.BaseAdminViewTests):
@test.create_stubs({cinder: ('volume_type_create',)})
def test_create_volume_type(self):
formData = {'name': 'volume type 1'}
cinder.volume_type_create(IsA(http.HttpRequest),
formData['name']).\
AndReturn(self.volume_types.first())
formData = {'name': 'volume type 1',
'vol_type_description': 'test desc'}
cinder.volume_type_create(
IsA(http.HttpRequest),
formData['name'],
formData['vol_type_description']).AndReturn(
self.volume_types.first())
self.mox.ReplayAll()
res = self.client.post(
reverse('horizon:admin:volumes:volume_types:create_type'),
formData)
redirect = reverse('horizon:admin:volumes:volume_types_tab')
self.assertNoFormErrors(res)
redirect = reverse('horizon:admin:volumes:volume_types_tab')
self.assertRedirectsNoFollow(res, redirect)
@test.create_stubs({cinder: ('volume_type_get',
'volume_type_update')})
def test_update_volume_type(self):
volume_type = self.cinder_volume_types.first()
formData = {'name': volume_type.name,
'description': 'test desc updated'}
volume_type = cinder.volume_type_get(
IsA(http.HttpRequest), volume_type.id).AndReturn(volume_type)
cinder.volume_type_update(
IsA(http.HttpRequest),
volume_type.id,
formData['name'],
formData['description']).AndReturn(volume_type)
self.mox.ReplayAll()
url = reverse('horizon:admin:volumes:volume_types:update_type',
args=[volume_type.id])
res = self.client.post(url, formData)
self.assertNoFormErrors(res)
redirect = reverse('horizon:admin:volumes:volume_types_tab')
self.assertRedirectsNoFollow(res, redirect)
@test.create_stubs({api.nova: ('server_list',),
@ -45,7 +69,7 @@ class VolumeTypeTests(test.BaseAdminViewTests):
'volume_encryption_type_list'),
keystone: ('tenant_list',)})
def test_delete_volume_type(self):
volume_type = self.volume_types.first()
volume_type = self.cinder_volume_types.first()
formData = {'action': 'volume_types__delete__%s' % volume_type.id}
encryption_list = (self.cinder_volume_encryption_types.list()[0],
self.cinder_volume_encryption_types.list()[1])
@ -58,7 +82,7 @@ class VolumeTypeTests(test.BaseAdminViewTests):
cinder.volume_encryption_type_list(IsA(http.HttpRequest))\
.AndReturn(encryption_list)
cinder.volume_type_delete(IsA(http.HttpRequest),
str(volume_type.id))
volume_type.id)
self.mox.ReplayAll()
res = self.client.post(

View File

@ -27,6 +27,9 @@ urlpatterns = patterns(
'VIEWS_MOD',
url(r'^create_type$', views.CreateVolumeTypeView.as_view(),
name='create_type'),
url(r'^(?P<type_id>[^/]+)/update_type/$',
views.EditVolumeTypeView.as_view(),
name='update_type'),
url(r'^create_qos_spec$', views.CreateQosSpecView.as_view(),
name='create_qos_spec'),
url(r'^(?P<type_id>[^/]+)/manage_qos_spec_association/$',

View File

@ -116,6 +116,45 @@ class CreateVolumeTypeEncryptionView(forms.ModalFormView):
'volume_type_id': self.kwargs['volume_type_id']}
class EditVolumeTypeView(forms.ModalFormView):
form_class = volume_types_forms.EditVolumeType
template_name = 'admin/volumes/volume_types/update_volume_type.html'
success_url = 'horizon:admin:volumes:volume_types_tab'
cancel_url = 'horizon:admin:volumes:volume_types_tab'
submit_label = _('Edit')
def get_success_url(self):
return reverse(self.success_url)
@memoized.memoized_method
def get_data(self):
try:
volume_type_id = self.kwargs['type_id']
volume_type = api.cinder.volume_type_get(self.request,
volume_type_id)
except Exception:
error_message = _(
'Unable to retrieve volume type for: "%s"') \
% volume_type_id
exceptions.handle(self.request,
error_message,
redirect=self.success_url)
return volume_type
def get_context_data(self, **kwargs):
context = super(EditVolumeTypeView, self).get_context_data(**kwargs)
context['volume_type'] = self.get_data()
return context
def get_initial(self):
volume_type = self.get_data()
return {'id': self.kwargs['type_id'],
'name': volume_type.name,
'description': getattr(volume_type, 'description', "")}
class CreateQosSpecView(forms.ModalFormView):
form_class = volumes_forms.CreateQosSpec
modal_header = _("Create QoS Spec")

View File

@ -201,6 +201,13 @@ class MigrateVolume(forms.SelfHandlingForm):
class CreateVolumeType(forms.SelfHandlingForm):
name = forms.CharField(max_length=255, label=_("Name"))
vol_type_description = forms.CharField(
max_length=255,
widget=forms.Textarea(
attrs={'class': 'modal-body-fixed-width',
'rows': 4}),
label=_("Description"),
required=False)
def clean_name(self):
cleaned_name = self.cleaned_data['name']
@ -212,8 +219,10 @@ class CreateVolumeType(forms.SelfHandlingForm):
def handle(self, request, data):
try:
# Remove any new lines in the public key
volume_type = cinder.volume_type_create(request,
data['name'])
volume_type = cinder.volume_type_create(
request,
data['name'],
data['vol_type_description'])
messages.success(request, _('Successfully created volume type: %s')
% data['name'])
return volume_type

View File

@ -2,7 +2,16 @@
<h3>{% trans "Description:" %}</h3>
<p>{% block title %}{% trans "Volumes are block devices that can be attached to instances." %}{% endblock %}</p>
<p>{% blocktrans %}
Volumes are block devices that can be attached to instances.
{% endblocktrans %}
</p>
<div id="id_show_volume_type_desc_div">
<h3>{% trans "Volume Type Description:" %}</h3>
<h4><b><span id="id_show_volume_type_name"></span></b></h4>
<p id="id_show_volume_type_desc"></p>
</div>
<h3>{% block head %}{% trans "Volume Limits" %}{% endblock %}</h3>
@ -22,7 +31,6 @@
<div id={% block type_id %}"quota_volumes"{% endblock %} data-progress-indicator-step-by="1" data-quota-limit={% block total_progress %}"{{ usages.maxTotalVolumes }}"{% endblock %} data-quota-used={% block used_progress %}"{{ usages.volumesUsed }}"{% endblock %} class="quota_bar">
</div>
<script type="text/javascript" charset="utf-8">
if(typeof horizon.Quota !== 'undefined') {
horizon.Quota.init();
@ -31,4 +39,12 @@
horizon.Quota.init();
});
}
if(typeof horizon.Volumes !== 'undefined'){
horizon.Volumes.initWithTypes({{ volume_types|safe|default:"{}" }});
} else {
addHorizonLoadEvent(function() {
horizon.Volumes.initWithTypes({{ volume_types|safe|default:"{}" }});
});
}
</script>

View File

@ -265,7 +265,7 @@ class CreateForm(forms.SelfHandlingForm):
def __init__(self, request, *args, **kwargs):
super(CreateForm, self).__init__(request, *args, **kwargs)
volume_types = cinder.volume_type_list(request)
self.fields['type'].choices = [("", _("No volume type"))] + \
self.fields['type'].choices = [("no_type", _("No volume type"))] + \
[(type.name, type.name)
for type in volume_types]
@ -379,6 +379,9 @@ class CreateForm(forms.SelfHandlingForm):
metadata = {}
if data['type'] == 'no_type':
data['type'] = ''
volume = cinder.volume_create(request,
data['size'],
data['name'],

View File

@ -103,6 +103,7 @@ class VolumeViewTests(test.TestCase):
url = reverse('horizon:project:volumes:volumes:create')
res = self.client.post(url, formData)
self.assertNoFormErrors(res)
redirect_url = VOLUME_VOLUMES_TAB_URL
self.assertRedirectsNoFollow(res, redirect_url)
@ -436,6 +437,7 @@ class VolumeViewTests(test.TestCase):
@test.create_stubs({cinder: ('volume_snapshot_get',
'volume_type_list',
'volume_type_default',
'volume_get'),
api.glance: ('image_list_detailed',),
quotas: ('tenant_limit_usages',)})
@ -452,6 +454,10 @@ class VolumeViewTests(test.TestCase):
cinder.volume_type_list(IsA(http.HttpRequest)).\
AndReturn(self.volume_types.list())
cinder.volume_type_list(IsA(http.HttpRequest)).\
AndReturn(self.volume_types.list())
cinder.volume_type_default(IsA(http.HttpRequest)).\
AndReturn(self.volume_types.first())
quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
AndReturn(usage_limit)
cinder.volume_snapshot_get(IsA(http.HttpRequest),
@ -600,6 +606,7 @@ class VolumeViewTests(test.TestCase):
self.assertRedirectsNoFollow(res, redirect_url)
@test.create_stubs({cinder: ('volume_type_list',
'volume_type_default',
'availability_zone_list',
'extension_supported'),
api.glance: ('image_get',
@ -618,6 +625,10 @@ class VolumeViewTests(test.TestCase):
cinder.volume_type_list(IsA(http.HttpRequest)).\
AndReturn(self.volume_types.list())
cinder.volume_type_list(IsA(http.HttpRequest)).\
AndReturn(self.volume_types.list())
cinder.volume_type_default(IsA(http.HttpRequest)).\
AndReturn(self.volume_types.first())
quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
AndReturn(usage_limit)
api.glance.image_get(IsA(http.HttpRequest),
@ -664,6 +675,8 @@ class VolumeViewTests(test.TestCase):
'method': u'CreateForm',
'size': 5, 'image_source': image.id}
cinder.volume_type_list(IsA(http.HttpRequest)).\
AndReturn(self.volume_types.list())
cinder.volume_type_list(IsA(http.HttpRequest)).\
AndReturn(self.volume_types.list())
quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
@ -701,6 +714,7 @@ class VolumeViewTests(test.TestCase):
@test.create_stubs({cinder: ('volume_snapshot_list',
'volume_type_list',
'volume_type_default',
'volume_list',
'availability_zone_list',
'extension_supported'),
@ -718,6 +732,10 @@ class VolumeViewTests(test.TestCase):
cinder.volume_type_list(IsA(http.HttpRequest)).\
AndReturn(self.volume_types.list())
cinder.volume_type_list(IsA(http.HttpRequest)).\
AndReturn(self.volume_types.list())
cinder.volume_type_default(IsA(http.HttpRequest)).\
AndReturn(self.volume_types.first())
quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
AndReturn(usage_limit)
cinder.volume_snapshot_list(IsA(http.HttpRequest),
@ -768,6 +786,8 @@ class VolumeViewTests(test.TestCase):
'method': u'CreateForm',
'size': 10}
cinder.volume_type_list(IsA(http.HttpRequest)).\
AndReturn(self.volume_types.list())
cinder.volume_type_list(IsA(http.HttpRequest)).\
AndReturn(self.volume_types.list())
quotas.tenant_limit_usages(IsA(http.HttpRequest)).\

View File

@ -16,8 +16,11 @@
Views for managing volumes.
"""
import json
from django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse_lazy
from django.utils import encoding
from django.utils.translation import ugettext_lazy as _
from django.views import generic
@ -29,6 +32,7 @@ from horizon.utils import memoized
from openstack_dashboard import api
from openstack_dashboard.api import cinder
from openstack_dashboard import exceptions as dashboard_exception
from openstack_dashboard.usage import quotas
from openstack_dashboard.dashboards.project.volumes \
@ -97,10 +101,49 @@ class CreateView(forms.ModalFormView):
context = super(CreateView, self).get_context_data(**kwargs)
try:
context['usages'] = quotas.tenant_limit_usages(self.request)
context['volume_types'] = self._get_volume_types()
except Exception:
exceptions.handle(self.request)
return context
def _get_volume_types(self):
try:
volume_types = cinder.volume_type_list(self.request)
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve volume type list.'))
# check if we have default volume type so we can present the
# description of no volume type differently
default_type = None
try:
default_type = cinder.volume_type_default(self.request)
except dashboard_exception.NOT_FOUND:
pass
if default_type is not None:
d_name = getattr(default_type, "name", "")
message =\
_("If \"No volume type\" is selected, the default "
"volume type \"%(name)s\" will be set for the "
"created volume.")
params = {'name': d_name}
no_type_description = encoding.force_text(message % params)
else:
message = \
_("If \"No volume type\" is selected, the volume will be "
"created without a volume type.")
no_type_description = encoding.force_text(message)
type_descriptions = [{'name': 'no_type',
'description': no_type_description}] + \
[{'name': type.name,
'description': getattr(type, "description", "")}
for type in volume_types]
return json.dumps(type_descriptions)
class ExtendView(forms.ModalFormView):
form_class = project_forms.ExtendForm

View File

@ -52,6 +52,7 @@
<script src='{{ STATIC_URL }}horizon/js/horizon.d3linechart.js'></script>
<script src='{{ STATIC_URL }}horizon/js/horizon.d3barchart.js'></script>
<script src='{{ STATIC_URL }}horizon/js/horizon.firewalls.js'></script>
<script src='{{ STATIC_URL }}horizon/js/horizon.volumes.js'></script>
<script src='{{ STATIC_URL }}horizon/lib/jsencrypt/jsencrypt.js'></script>
{% for file in HORIZON_CONFIG.js_files %}

View File

@ -94,6 +94,28 @@ class CinderApiTests(test.APITestCase):
associate_spec = assoc_vol_types[0].associated_qos_spec
self.assertTrue(associate_spec, qos_specs_only_one[0].name)
def test_volume_type_get_with_qos_association(self):
volume_type = self.cinder_volume_types.first()
qos_specs_full = self.cinder_qos_specs.list()
qos_specs_only_one = [qos_specs_full[0]]
associations = self.cinder_qos_spec_associations.list()
cinderclient = self.stub_cinderclient()
cinderclient.volume_types = self.mox.CreateMockAnything()
cinderclient.volume_types.get(volume_type.id).AndReturn(volume_type)
cinderclient.qos_specs = self.mox.CreateMockAnything()
cinderclient.qos_specs.list().AndReturn(qos_specs_only_one)
cinderclient.qos_specs.get_associations = self.mox.CreateMockAnything()
cinderclient.qos_specs.get_associations(qos_specs_only_one[0].id).\
AndReturn(associations)
self.mox.ReplayAll()
assoc_vol_type = \
api.cinder.volume_type_get_with_qos_association(self.request,
volume_type.id)
associate_spec = assoc_vol_type.associated_qos_spec
self.assertTrue(associate_spec, qos_specs_only_one[0].name)
def test_absolute_limits_with_negative_values(self):
values = {"maxTotalVolumes": -1, "totalVolumesUsed": -1}
expected_results = {"maxTotalVolumes": float("inf"),
@ -126,6 +148,16 @@ class CinderApiTests(test.APITestCase):
# No assertions are necessary. Verification is handled by mox.
api.cinder.pool_list(self.request, detailed=True)
def test_volume_type_default(self):
volume_type = self.cinder_volume_types.first()
cinderclient = self.stub_cinderclient()
cinderclient.volume_types = self.mox.CreateMockAnything()
cinderclient.volume_types.default().AndReturn(volume_type)
self.mox.ReplayAll()
default_volume_type = api.cinder.volume_type_default(self.request)
self.assertEqual(default_volume_type, volume_type)
class CinderApiVersionTests(test.TestCase):

View File

@ -144,10 +144,12 @@ def data(TEST):
vol_type1 = volume_types.VolumeType(volume_types.VolumeTypeManager(None),
{'id': u'1',
'name': u'vol_type_1',
'description': 'type 1 description',
'extra_specs': {'foo': 'bar'}})
vol_type2 = volume_types.VolumeType(volume_types.VolumeTypeManager(None),
{'id': u'2',
'name': u'vol_type_2'})
'name': u'vol_type_2',
'description': 'type 2 description'})
TEST.cinder_volume_types.add(vol_type1, vol_type2)
# Volumes - Cinder v2