示例#1
0
class UpdateTenant(forms.SelfHandlingForm):
    id = forms.CharField(
        label=_("ID"), widget=forms.TextInput(attrs={'readonly': 'readonly'}))
    name = forms.CharField(
        label=_("Name"),
        widget=forms.TextInput(attrs={'readonly': 'readonly'}))
    description = forms.CharField(required=False,
                                  widget=forms.widgets.Textarea(),
                                  label=_("Description"))
    enabled = forms.BooleanField(required=False, label=_("Enabled"))

    def handle(self, request, data):
        try:
            LOG.info('Updating tenant with id "%s"' % data['id'])
            api.tenant_update(request, data['id'], data['name'],
                              data['description'] or '', data['enabled'])
            messages.success(request,
                             _('%s was successfully updated.') % data['name'])
        except api_exceptions.ApiException, e:
            LOG.exception(
                'ApiException while updating tenant\n'
                'Id: "%s", Name: "%s", Description: "%s", Enabled "%s"' %
                (data['id'], data['name'], data['description'],
                 data['enabled']))
            messages.error(request,
                           _('Unable to update tenant: %s') % e.message)
        return shortcuts.redirect('steer:syspanel:tenants:index')
示例#2
0
class CreateSnapshot(forms.SelfHandlingForm):
    tenant_id = forms.CharField(widget=forms.HiddenInput())
    instance_id = forms.CharField(widget=forms.TextInput(
        attrs={'readonly': 'readonly'}))
    name = forms.CharField(max_length="20", label=_("Snapshot Name"))

    def handle(self, request, data):
        try:
            LOG.info('Creating snapshot "%s"' % data['name'])
            snapshot = api.snapshot_create(request, data['instance_id'],
                                           data['name'])
            instance = api.server_get(request, data['instance_id'])

            messages.info(
                request,
                _('Snapshot "%(name)s" created for instance "%(inst)s"') % {
                    "name": data['name'],
                    "inst": instance.name
                })
            return shortcuts.redirect('steer:engine:images_and_snapshots'
                                      ':snapshots:index')
        except api_exceptions.ApiException, e:
            msg = _('Error Creating Snapshot: %s') % e.message
            LOG.exception(msg)
            messages.error(request, msg)
            return shortcuts.redirect(request.build_absolute_uri())
示例#3
0
class AttachPort(forms.SelfHandlingForm):
    network = forms.CharField(widget=forms.HiddenInput())
    port = forms.CharField(widget=forms.HiddenInput())
    vif_id = forms.ChoiceField(label=_("Select VIF to connect"))

    def __init__(self, request, *args, **kwargs):
        super(AttachPort, self).__init__(*args, **kwargs)
        # Populate VIF choices
        vif_choices = [('', "Select a VIF")]
        for vif in api.get_vif_ids(request):
            if vif['available']:
                name = "Instance %s VIF %s" % (vif['instance_name'], vif['id'])
                vif_choices.append((vif['id'], name,))
        self.fields['vif_id'].choices = vif_choices

    @classmethod
    def _instantiate(cls, request, *args, **kwargs):
        return cls(request, *args, **kwargs)

    def handle(self, request, data):
        try:
            LOG.info('Attaching %s port to VIF %s' %
                     (data['port'], data['vif_id']))
            body = {'attachment': {'id': '%s' % data['vif_id']}}
            api.quantum_attach_port(request,
                                        data['network'], data['port'], body)
        except Exception, e:
            if not hasattr(e, 'message'):
                e.message = str(e)
            messages.error(request,
                _('Unable to attach port %(port)s to VIF %(vif)s: %(msg)s') %
                {"port": data['port'],
                 "vif": data['vif_id'],
                 "msg": e.message})
        else:
示例#4
0
class UpdateUserForm(BaseUserForm):
    id = forms.CharField(
        label=_("ID"), widget=forms.TextInput(attrs={'readonly': 'readonly'}))
    # FIXME: keystone doesn't return the username from a get API call.
    #name = forms.CharField(label=_("Name"))
    email = forms.CharField(label=_("Email"))
    password = forms.CharField(label=_("Password"),
                               widget=forms.PasswordInput(render_value=False),
                               required=False)
    tenant_id = forms.ChoiceField(label=_("Primary Tenant"))

    def handle(self, request, data):
        updated = []
        if data['email']:
            updated.append('email')
            api.user_update_email(request, data['id'], data['email'])
        if data['password']:
            updated.append('password')
            api.user_update_password(request, data['id'], data['password'])
        if data['tenant_id']:
            updated.append('tenant')
            api.user_update_tenant(request, data['id'], data['tenant_id'])
        messages.success(
            request,
            _('Updated %(attrib)s for %(user)s.') % {
                "attrib": ', '.join(updated),
                "user": data['id']
            })
        return shortcuts.redirect('steer:syspanel:users:index')
示例#5
0
class AddRule(forms.SelfHandlingForm):
    ip_protocol = forms.ChoiceField(choices=[('tcp', 'tcp'),
                                             ('udp', 'udp'),
                                             ('icmp', 'icmp')])
    from_port = forms.CharField()
    to_port = forms.CharField()
    cidr = forms.CharField()
    # TODO (anthony) source group support
    # group_id = forms.CharField()

    security_group_id = forms.CharField(widget=forms.HiddenInput())
    tenant_id = forms.CharField(widget=forms.HiddenInput())

    def handle(self, request, data):
        tenant_id = data['tenant_id']
        try:
            LOG.info('Add security_group_rule: "%s"' % data)

            rule = api.security_group_rule_create(request,
                                                  data['security_group_id'],
                                                  data['ip_protocol'],
                                                  data['from_port'],
                                                  data['to_port'],
                                                  data['cidr'])
            messages.success(request, _('Successfully added rule: %s') \
                                    % rule.id)
        except engineclient_exceptions.ClientException, e:
            LOG.exception("ClientException in AddRule")
            messages.error(request, _('Error adding rule security group: %s')
                                     % e.message)
        return shortcuts.redirect(request.build_absolute_uri())
示例#6
0
class FloatingIpAssociate(forms.SelfHandlingForm):
    floating_ip_id = forms.CharField(widget=forms.HiddenInput())
    floating_ip = forms.CharField(widget=forms.TextInput(
        attrs={'readonly': 'readonly'}))
    instance_id = forms.ChoiceField()

    def __init__(self, *args, **kwargs):
        super(FloatingIpAssociate, self).__init__(*args, **kwargs)
        instancelist = kwargs.get('initial', {}).get('instances', [])
        self.fields['instance_id'] = forms.ChoiceField(choices=instancelist,
                                                       label=_("Instance"))

    def handle(self, request, data):
        try:
            api.server_add_floating_ip(request, data['instance_id'],
                                       data['floating_ip_id'])
            LOG.info('Associating Floating IP "%s" with Instance "%s"' %
                     (data['floating_ip'], data['instance_id']))
            messages.info(
                request,
                _('Successfully associated Floating IP \
                                    %(ip)s with Instance: %(inst)s' % {
                    "ip": data['floating_ip'],
                    "inst": data['instance_id']
                }))
        except engineclient_exceptions.ClientException, e:
            LOG.exception("ClientException in FloatingIpAssociate")
            messages.error(request, _('Error associating Floating IP: %s') % e)
        return shortcuts.redirect('steer:engine:access_and_security:index')
示例#7
0
class CopyObject(forms.SelfHandlingForm):
    new_container_name = forms.ChoiceField(
        label=_("Container to store object in"))

    new_object_name = forms.CharField(max_length="255",
                                      label=_("New object name"))
    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):
        orig_container_name = data['orig_container_name']
        orig_object_name = data['orig_object_name']
        new_container_name = data['new_container_name']
        new_object_name = data['new_object_name']

        api.chase_copy_object(request, orig_container_name, orig_object_name,
                              new_container_name, new_object_name)

        messages.success(
            request,
            _('Object was successfully copied to %(container)s\%(obj)s') % {
                "container": new_container_name,
                "obj": new_object_name
            })

        return shortcuts.redirect("steer:engine:containers:object_index",
                                  data['new_container_name'])
示例#8
0
class LoginWithTenant(Login):
    """
    Exactly like :class:`.Login` but includes the tenant id as a field
    so that the process of choosing a default tenant is bypassed.
    """
    username = forms.CharField(
        max_length="20",
        widget=forms.TextInput(attrs={'readonly': 'readonly'}))
    tenant = forms.CharField(widget=forms.HiddenInput())
示例#9
0
class DeleteObject(forms.SelfHandlingForm):
    object_name = forms.CharField(widget=forms.HiddenInput())
    container_name = forms.CharField(widget=forms.HiddenInput())

    def handle(self, request, data):
        api.chase_delete_object(request, data['container_name'],
                                data['object_name'])
        messages.info(
            request,
            _('Successfully deleted object: %s') % data['object_name'])
        return shortcuts.redirect(request.build_absolute_uri())
示例#10
0
class UploadObject(forms.SelfHandlingForm):
    name = forms.CharField(max_length="255", label=_("Object Name"))
    object_file = forms.FileField(label=_("File"))
    container_name = forms.CharField(widget=forms.HiddenInput())

    def handle(self, request, data):
        api.chase_upload_object(request, data['container_name'], data['name'],
                                self.files['object_file'].read())

        messages.success(request, _("Object was successfully uploaded."))
        return shortcuts.redirect("steer:engine:containers:object_index",
                                  data['container_name'])
示例#11
0
class DeleteForm(forms.SelfHandlingForm):
    volume_id = forms.CharField(widget=forms.HiddenInput())
    volume_name = forms.CharField(widget=forms.HiddenInput())

    def handle(self, request, data):
        try:
            api.volume_delete(request, data['volume_id'])
            message = 'Deleting volume "%s"' % data['volume_id']
            LOG.info(message)
            messages.info(request, message)
        except engineclient_exceptions.ClientException, e:
            LOG.exception("ClientException in DeleteVolume")
            messages.error(request, _('Error deleting volume: %s') % e.message)
        return shortcuts.redirect(request.build_absolute_uri())
示例#12
0
class CreateFlavor(forms.SelfHandlingForm):
    flavorid = forms.IntegerField(label=_("Flavor ID"))
    name = forms.CharField(max_length="25", label=_("Name"))
    vcpus = forms.CharField(max_length="5", label=_("VCPUs"))
    memory_mb = forms.CharField(max_length="5", label=_("Memory MB"))
    disk_gb = forms.CharField(max_length="5", label=_("Disk GB"))

    def handle(self, request, data):
        api.flavor_create(request, data['name'], int(data['memory_mb']),
                          int(data['vcpus']), int(data['disk_gb']),
                          int(data['flavorid']))
        msg = _('%s was successfully added to flavors.') % data['name']
        LOG.info(msg)
        messages.success(request, msg)
        return shortcuts.redirect('steer:syspanel:flavors:index')
示例#13
0
class DetachPort(forms.SelfHandlingForm):
    network = forms.CharField(widget=forms.HiddenInput())
    port = forms.CharField(widget=forms.HiddenInput())

    def handle(self, request, data):
        try:
            LOG.info('Detaching port %s' % data['port'])
            api.quantum_detach_port(request, data['network'], data['port'])
        except Exception, e:
            if not hasattr(e, 'message'):
                e.message = str(e)
            messages.error(request,
                _('Unable to detach port %(port)s: %(message)s') %
                {"port": data['port'], "message": e.message})
        else:
示例#14
0
class DeleteImage(forms.SelfHandlingForm):
    image_id = forms.CharField(required=True)

    def handle(self, request, data):
        image_id = data['image_id']
        tenant_id = request.user.tenant_id
        try:
            image = api.image_get_meta(request, image_id)
            if image.owner == request.user.username:
                api.image_delete(request, image_id)
            else:
                messages.info(
                    request,
                    _("Unable to delete image, you are not \
                                         its owner."))
                return redirect('dash_images_update', tenant_id, image_id)
        except tank_exception.ClientConnectionError, e:
            LOG.exception("Error connecting to tank")
            messages.error(request,
                           _("Error connecting to tank: %s") % e.message)
        except tank_exception.Error, e:
            LOG.exception('Error deleting image with id "%s"' % image_id)
            messages.error(
                request,
                _("Error deleting image: %(image)s: %i(msg)s") % {
                    "image": image_id,
                    "msg": e.message
                })
示例#15
0
class CreateContainer(forms.SelfHandlingForm):
    name = forms.CharField(max_length="255", label=_("Container Name"))

    def handle(self, request, data):
        api.chase_create_container(request, data['name'])
        messages.success(request, _("Container was successfully created."))
        return shortcuts.redirect("steer:engine:containers:index")
示例#16
0
class RenameNetwork(forms.SelfHandlingForm):
    network = forms.CharField(widget=forms.HiddenInput())
    new_name = forms.CharField(required=True)

    def handle(self, request, data):
        try:
            LOG.info('Renaming network %s to %s' %
                     (data['network'], data['new_name']))
            send_data = {'network': {'name': '%s' % data['new_name']}}
            api.quantum_update_network(request, data['network'], send_data)
        except Exception, e:
            if not hasattr(e, 'message'):
                e.message = str(e)
            messages.error(request,
                    _('Unable to rename network %(network)s: %(msg)s') %
                    {"network": data['network'], "msg": e.message})
        else:
示例#17
0
class UpdateImageForm(forms.SelfHandlingForm):
    image_id = forms.CharField(widget=forms.HiddenInput())
    name = forms.CharField(max_length="25", label=_("Name"))
    kernel = forms.CharField(max_length="25",
                             label=_("Kernel ID"),
                             required=False)
    ramdisk = forms.CharField(max_length="25",
                              label=_("Ramdisk ID"),
                              required=False)
    architecture = forms.CharField(label=_("Architecture"), required=False)
    container_format = forms.CharField(label=_("Container Format"),
                                       required=False)
    disk_format = forms.CharField(label=_("Disk Format"))

    def handle(self, request, data):
        image_id = data['image_id']
        tenant_id = request.user.tenant_id
        error_retrieving = _('Unable to retrieve image info from tank: %s' %
                             image_id)
        error_updating = _('Error updating image with id: %s' % image_id)

        try:
            image = api.image_get_meta(request, image_id)
        except tank_exception.ClientConnectionError, e:
            LOG.exception(_('Error connecting to tank'))
            messages.error(request, error_retrieving)
        except tank_exception.Error, e:
            LOG.exception(error_retrieving)
            messages.error(request, error_retrieving)
示例#18
0
class ImportKeypair(forms.SelfHandlingForm):
    name = forms.CharField(max_length="20", label=_("Keypair Name"),
                 validators=[validators.RegexValidator('\w+')])
    public_key = forms.CharField(label=_("Public Key"), widget=forms.Textarea)

    def handle(self, request, data):
        try:
            LOG.info('Importing keypair "%s"' % data['name'])
            api.keypair_import(request, data['name'], data['public_key'])
            messages.success(request, _('Successfully imported public key: %s')
                                       % data['name'])
            return shortcuts.redirect(
                            'steer:engine:access_and_security:index')
        except engineclient_exceptions.ClientException, e:
            LOG.exception("ClientException in ImportKeypair")
            messages.error(request,
                           _('Error Importing Keypair: %s') % e.message)
            return shortcuts.redirect(request.build_absolute_uri())
示例#19
0
class TogglePort(forms.SelfHandlingForm):
    network = forms.CharField(widget=forms.HiddenInput())
    port = forms.CharField(widget=forms.HiddenInput())
    state = forms.CharField(widget=forms.HiddenInput())

    def handle(self, request, data):
        try:
            LOG.info('Toggling port state to %s' % data['state'])
            body = {'port': {'state': '%s' % data['state']}}
            api.quantum_set_port_state(request,
                                       data['network'], data['port'], body)
        except Exception, e:
            if not hasattr(e, 'message'):
                e.message = str(e)
            messages.error(request,
                _('Unable to set port state to %(state)s: %(message)s') %
                {"state": data['state'], "message": e.message})
        else:
示例#20
0
class FilterObjects(forms.SelfHandlingForm):
    container_name = forms.CharField(widget=forms.HiddenInput())
    object_prefix = forms.CharField(required=False)

    def handle(self, request, data):
        object_prefix = data['object_prefix'] or None

        objects, more = api.chase_get_objects(request,
                                              data['container_name'],
                                              prefix=object_prefix)

        if not objects:
            messages.info(
                request,
                _('There are no objects matching that prefix in %s') %
                data['container_name'])

        return (objects, more)
示例#21
0
class CreateForm(forms.SelfHandlingForm):
    name = forms.CharField(max_length="255", label="Volume Name")
    description = forms.CharField(widget=forms.Textarea,
                                  label=_("Description"),
                                  required=False)
    size = forms.IntegerField(min_value=1, label="Size (GB)")

    def handle(self, request, data):
        try:
            api.volume_create(request, data['size'], data['name'],
                              data['description'])
            message = 'Creating volume "%s"' % data['name']
            LOG.info(message)
            messages.info(request, message)
        except engineclient_exceptions.ClientException, e:
            LOG.exception("ClientException in CreateVolume")
            messages.error(request, _('Error Creating Volume: %s') % e.message)
        return shortcuts.redirect(
            "steer:engine:instances_and_volumes:volumes:index")
示例#22
0
class RemoveUser(forms.SelfHandlingForm):
    user = forms.CharField()
    tenant = forms.CharField()

    def handle(self, request, data):
        try:
            api.role_delete_for_tenant_user(request, data['tenant'],
                                            data['user'],
                                            settings.X7_KEYSTONE_DEFAULT_ROLE)
            messages.success(
                request,
                _('%(user)s was successfully removed from %(tenant)s.') % {
                    "user": data['user'],
                    "tenant": data['tenant']
                })
        except api_exceptions.ApiException, e:
            messages.error(request,
                           _('Unable to create tenant: %s') % (e.message))
        return shortcuts.redirect('steer:syspanel:tenants:users',
                                  tenant_id=data['tenant'])
示例#23
0
class CreateGroup(forms.SelfHandlingForm):
    name = forms.CharField(validators=[validators.validate_slug])
    description = forms.CharField()
    tenant_id = forms.CharField(widget=forms.HiddenInput())

    def handle(self, request, data):
        try:
            LOG.info('Add security_group: "%s"' % data)

            security_group = api.security_group_create(request,
                                                       data['name'],
                                                       data['description'])
            messages.success(request,
                             _('Successfully created security_group: %s')
                                    % data['name'])
            return shortcuts.redirect(
                    'steer:engine:access_and_security:index')
        except engineclient_exceptions.ClientException, e:
            LOG.exception("ClientException in CreateGroup")
            messages.error(request, _('Error creating security group: %s') %
                                     e.message)
示例#24
0
class DetachForm(forms.SelfHandlingForm):
    volume_id = forms.CharField(widget=forms.HiddenInput())
    instance_id = forms.CharField(widget=forms.HiddenInput())
    attachment_id = forms.CharField(widget=forms.HiddenInput())

    def handle(self, request, data):
        try:
            api.volume_detach(request, data['instance_id'],
                              data['attachment_id'])
            message = (_('Detaching volume %(vol)s from instance %(inst)s') % {
                "vol": data['volume_id'],
                "inst": data['instance_id']
            })
            LOG.info(message)
            messages.info(request, message)
        except engineclient_exceptions.ClientException, e:
            LOG.exception("ClientException in DetachVolume")
            messages.error(request,
                           _('Error detaching volume: %s') % e.message)
        return shortcuts.redirect(
            "steer:engine:instances_and_volumes:volumes:index")
示例#25
0
class CreateUserForm(BaseUserForm):
    name = forms.CharField(label=_("Name"))
    email = forms.CharField(label=_("Email"))
    password = forms.CharField(label=_("Password"),
                               widget=forms.PasswordInput(render_value=False),
                               required=False)
    tenant_id = forms.ChoiceField(label=_("Primary Tenant"))

    def handle(self, request, data):
        try:
            LOG.info('Creating user with name "%s"' % data['name'])
            new_user = api.user_create(request, data['name'], data['email'],
                                       data['password'], data['tenant_id'],
                                       True)
            messages.success(
                request,
                _('User "%s" was successfully created.') % data['name'])
            try:
                api.role_add_for_tenant_user(request, data['tenant_id'],
                                             new_user.id,
                                             settings.X7_KEYSTONE_DEFAULT_ROLE)
            except Exception, e:
                LOG.exception('Exception while assigning \
                               role to new user: %s' % new_user.id)
                if not hasattr(e, 'message'):
                    e.message = str(e)
                messages.error(
                    request,
                    _('Error assigning role to user: %s') % e.message)

            return shortcuts.redirect('steer:syspanel:users:index')

        except Exception, e:
            LOG.exception('Exception while creating user\n'
                          'name: "%s", email: "%s", tenant_id: "%s"' %
                          (data['name'], data['email'], data['tenant_id']))
            if not hasattr(e, 'message'):
                e.message = str(e)
            messages.error(request, _('Error creating user: %s') % e.message)
            return shortcuts.redirect('steer:syspanel:users:index')
示例#26
0
class UpdateQuotas(forms.SelfHandlingForm):
    tenant_id = forms.CharField(
        label=_("ID (name)"),
        widget=forms.TextInput(attrs={'readonly': 'readonly'}))
    metadata_items = forms.CharField(label=_("Metadata Items"))
    injected_files = forms.CharField(label=_("Injected Files"))
    injected_file_content_bytes = forms.CharField(label=_("Injected File "
                                                          "Content Bytes"))
    cores = forms.CharField(label=_("VCPUs"))
    instances = forms.CharField(label=_("Instances"))
    volumes = forms.CharField(label=_("Volumes"))
    gigabytes = forms.CharField(label=_("Gigabytes"))
    ram = forms.CharField(label=_("RAM (in MB)"))
    floating_ips = forms.CharField(label=_("Floating IPs"))

    def handle(self, request, data):
        try:
            api.admin_api(request).quota_sets.update(
                data['tenant_id'],
                metadata_items=data['metadata_items'],
                injected_file_content_bytes=data[
                    'injected_file_content_bytes'],
                volumes=data['volumes'],
                gigabytes=data['gigabytes'],
                ram=int(data['ram']),
                floating_ips=data['floating_ips'],
                instances=data['instances'],
                injected_files=data['injected_files'],
                cores=data['cores'],
            )
            messages.success(
                request,
                _('Quotas for %s were successfully updated.') %
                data['tenant_id'])
        except api_exceptions.ApiException, e:
            messages.error(request,
                           _('Unable to update quotas: %s') % e.message)
        return shortcuts.redirect('steer:syspanel:tenants:index')
示例#27
0
class DeleteNetwork(forms.SelfHandlingForm):
    network = forms.CharField(widget=forms.HiddenInput())

    def handle(self, request, data):
        try:
            LOG.info('Deleting network %s ' % data['network'])
            api.quantum_delete_network(request, data['network'])
        except Exception, e:
            if not hasattr(e, 'message'):
                e.message = str(e)
            messages.error(request,
                    _('Unable to delete network %(network)s: %(msg)s') %
                    {"network": data['network'], "msg": e.message})
        else:
示例#28
0
class DeleteImage(forms.SelfHandlingForm):
    image_id = forms.CharField(required=True)

    def handle(self, request, data):
        image_id = data['image_id']
        try:
            api.image_delete(request, image_id)
        except tank_exception.ClientConnectionError, e:
            LOG.exception("Error connecting to tank")
            messages.error(request,
                           _("Error connecting to tank: %s") % e.message)
        except tank_exception.Error, e:
            LOG.exception('Error deleting image with id "%s"' % image_id)
            messages.error(request, _("Error deleting image: %s") % e.message)
示例#29
0
class DeleteContainer(forms.SelfHandlingForm):
    container_name = forms.CharField(widget=forms.HiddenInput())

    def handle(self, request, data):
        try:
            api.chase_delete_container(request, data['container_name'])
        except ContainerNotEmpty, e:
            messages.error(
                request,
                _('Unable to delete non-empty container: %s') %
                data['container_name'])
            LOG.exception('Unable to delete container "%s".  Exception: "%s"' %
                          (data['container_name'], str(e)))
        else:
示例#30
0
class CreateTenant(forms.SelfHandlingForm):
    name = forms.CharField(label=_("Name"))
    description = forms.CharField(required=False,
                                  widget=forms.widgets.Textarea(),
                                  label=_("Description"))
    enabled = forms.BooleanField(label=_("Enabled"),
                                 required=False,
                                 initial=True)

    def handle(self, request, data):
        try:
            LOG.info('Creating tenant with name "%s"' % data['name'])
            api.tenant_create(request, data['name'], data['description'] or '',
                              data['enabled'])
            messages.success(request,
                             _('%s was successfully created.') % data['name'])
        except api_exceptions.ApiException, e:
            LOG.exception('ApiException while creating tenant\n'
                          'Id: "%s", Description: "%s", Enabled "%s"' %
                          (data['name'], data['description'], data['enabled']))
            messages.error(request,
                           _('Unable to create tenant: %s') % (e.message))
        return shortcuts.redirect('steer:syspanel:tenants:index')