示例#1
0
class RebuildInstanceForm(forms.SelfHandlingForm):
    instance_id = forms.CharField(widget=forms.HiddenInput())
    image = forms.ChoiceField(label=_("Select Image"),
                              widget=SelectWidget(
                                  attrs={'class': 'image-selector'},
                                  data_attrs=('size', 'display-name'),
                                  transform=_image_choice_title))
    password = forms.RegexField(
        label=_("Rebuild Password"),
        required=False,
        widget=forms.PasswordInput(render_value=False),
        regex=validators.password_validator(),
        error_messages={'invalid': validators.password_validator_msg()})
    confirm_password = forms.CharField(
        label=_("Confirm Rebuild Password"),
        required=False,
        widget=forms.PasswordInput(render_value=False))

    def __init__(self, request, *args, **kwargs):
        super(RebuildInstanceForm, self).__init__(request, *args, **kwargs)
        instance_id = kwargs.get('initial', {}).get('instance_id')
        self.fields['instance_id'].initial = instance_id

        images = utils.get_available_images(request, request.user.tenant_id)
        choices = [(image.id, image.name) for image in images]
        if choices:
            choices.insert(0, ("", _("Select Image")))
        else:
            choices.insert(0, ("", _("No images available.")))
        self.fields['image'].choices = choices

    def clean(self):
        cleaned_data = super(RebuildInstanceForm, self).clean()
        if 'password' in cleaned_data:
            passwd = cleaned_data.get('password')
            confirm = cleaned_data.get('confirm_password')
            if passwd is not None and confirm is not None:
                if passwd != confirm:
                    raise forms.ValidationError(_("Passwords do not match."))
        return cleaned_data

    # We have to protect the entire "data" dict because it contains the
    # password and confirm_password strings.
    @sensitive_variables('data', 'password')
    def handle(self, request, data):
        instance = data.get('instance_id')
        image = data.get('image')
        password = data.get('password') or None
        try:
            api.nova.server_rebuild(request, instance, image, password)
            messages.success(request, _('Rebuilding instance %s.') % instance)
        except Exception:
            redirect = reverse('horizon:project:instances:index')
            exceptions.handle(request,
                              _("Unable to rebuild instance."),
                              redirect=redirect)
        return True
示例#2
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)"))
    snapshot_source = forms.ChoiceField(label=_("Use snapshot as a source"),
                                        widget=SelectWidget(
                                          attrs={'class': 'snapshot-selector'},
                                          data_attrs=('size', 'display_name'),
                                          transform=lambda x:
                                                ("%s (%sGB)" % (x.display_name,
                                                                x.size))),
                                        required=False)

    def __init__(self, request, *args, **kwargs):
        super(CreateForm, self).__init__(request, *args, **kwargs)
        if ("snapshot_id" in request.GET):
            try:
                snapshot = self.get_snapshot(request,
                                             request.GET["snapshot_id"])
                self.fields['name'].initial = snapshot.display_name
                self.fields['size'].initial = snapshot.size
                self.fields['snapshot_source'].choices = ((snapshot.id,
                                                           snapshot),)
                self.fields['size'].help_text = _('Volume size must be equal '
                                'to or greater than the snapshot size (%sGB)'
                                % snapshot.size)
            except:
                exceptions.handle(request,
                                  _('Unable to load the specified snapshot.'))
        else:
            try:
                snapshots = api.volume_snapshot_list(request)
                if snapshots:
                    choices = [('', _("Choose a snapshot"))] + \
                              [(s.id, s) for s in snapshots]
                    self.fields['snapshot_source'].choices = choices
                else:
                    del self.fields['snapshot_source']
            except:
                exceptions.handle(request, _("Unable to retrieve "
                        "volume snapshots."))

    def handle(self, request, data):
        try:
            # FIXME(johnp): Nova (cinderclient) currently returns a useless
            # error message when the quota is exceeded when trying to create
            # a volume, so we need to check for that scenario here before we
            # send it off to Nova to try and create.
            usages = api.tenant_quota_usages(request)

            snapshot_id = None
            if (data.get("snapshot_source", None)):
                # Create from Snapshot
                snapshot = self.get_snapshot(request,
                                             data["snapshot_source"])
                snapshot_id = snapshot.id
                if (data['size'] < snapshot.size):
                    error_message = _('The volume size cannot be less than '
                                      'the snapshot size (%sGB)' %
                                      snapshot.size)
                    raise ValidationError(error_message)
            else:
                if type(data['size']) is str:
                    data['size'] = int(data['size'])

            if usages['gigabytes']['available'] < data['size']:
                error_message = _('A volume of %(req)iGB cannot be created as '
                                  'you only have %(avail)iGB of your quota '
                                  'available.')
                params = {'req': data['size'],
                          'avail': usages['gigabytes']['available']}
                raise ValidationError(error_message % params)
            elif usages['volumes']['available'] <= 0:
                error_message = _('You are already using all of your available'
                                  ' volumes.')
                raise ValidationError(error_message)

            volume = api.volume_create(request,
                                       data['size'],
                                       data['name'],
                                       data['description'],
                                       snapshot_id=snapshot_id)
            message = 'Creating volume "%s"' % data['name']
            messages.info(request, message)
            return volume
        except ValidationError, e:
            return self.api_error(e.messages[0])
        except:
示例#3
0
class CreateForm(forms.SelfHandlingForm):
    name = forms.CharField(max_length="255", label=_("Volume Name"))
    description = forms.CharField(widget=forms.Textarea,
                                  label=_("Description"),
                                  required=False)
    type = forms.ChoiceField(label=_("Type"), required=False)
    size = forms.IntegerField(min_value=1, label=_("Size (GB)"))
    encryption = forms.ChoiceField(label=_("Encryption"), required=False)
    volume_source_type = forms.ChoiceField(label=_("Volume Source"),
                                           required=False)
    snapshot_source = forms.ChoiceField(
        label=_("Use snapshot as a source"),
        widget=SelectWidget(attrs={'class': 'snapshot-selector'},
                            data_attrs=('size', 'display_name'),
                            transform=lambda x: ("%s (%sGB)" %
                                                 (x.display_name, x.size))),
        required=False)
    image_source = forms.ChoiceField(
        label=_("Use image as a source"),
        widget=SelectWidget(attrs={'class': 'image-selector'},
                            data_attrs=('size', 'name'),
                            transform=lambda x:
                            ("%s (%s)" % (x.name, filesizeformat(x.bytes)))),
        required=False)

    def __init__(self, request, *args, **kwargs):
        super(CreateForm, self).__init__(request, *args, **kwargs)
        volume_types = cinder.volume_type_list(request)
        self.fields['type'].choices = [("", "")] + \
                                      [(type.name, type.name)
                                       for type in volume_types]

        # Hide the volume encryption field if the hypervisor doesn't support it
        # NOTE: as of Grizzly this is not yet supported in Nova so enabling
        # this setting will not do anything useful
        hypervisor_features = getattr(settings,
                                      "OPENSTACK_HYPERVISOR_FEATURES", {})
        can_encrypt_volumes = hypervisor_features.get("can_encrypt_volumes",
                                                      False)

        if can_encrypt_volumes:
            # TODO(laura-glendenning) get from api call in future
            encryption_options = {"LUKS": "dmcrypt LUKS"}
            self.fields['encryption'].choices = [("", "")] + \
                [(enc, display) for enc, display in encryption_options.items()]
        else:
            self.fields['encryption'].widget = forms.widgets.HiddenInput()
            self.fields['encryption'].required = False

        if ("snapshot_id" in request.GET):
            try:
                snapshot = self.get_snapshot(request,
                                             request.GET["snapshot_id"])
                self.fields['name'].initial = snapshot.display_name
                self.fields['size'].initial = snapshot.size
                self.fields['snapshot_source'].choices = ((snapshot.id,
                                                           snapshot), )
                try:
                    # Set the volume type from the original volume
                    orig_volume = cinder.volume_get(request,
                                                    snapshot.volume_id)
                    self.fields['type'].initial = orig_volume.volume_type
                except Exception:
                    pass
                self.fields['size'].help_text = _(
                    'Volume size must be equal '
                    'to or greater than the snapshot size (%sGB)' %
                    snapshot.size)
                del self.fields['image_source']
                del self.fields['volume_source_type']
            except Exception:
                exceptions.handle(request,
                                  _('Unable to load the specified snapshot.'))
        elif ('image_id' in request.GET):
            try:
                image = self.get_image(request, request.GET["image_id"])
                image.bytes = image.size
                self.fields['name'].initial = image.name
                self.fields['size'].initial = bytes_to_gigabytes(image.size)
                self.fields['image_source'].choices = ((image.id, image), )
                self.fields['size'].help_text = _(
                    'Volume size must be equal '
                    'to or greater than the image size (%s)' %
                    filesizeformat(image.size))
                del self.fields['snapshot_source']
                del self.fields['volume_source_type']
            except Exception:
                msg = _('Unable to load the specified image. %s')
                exceptions.handle(request, msg % request.GET['image_id'])
        else:
            source_type_choices = []

            try:
                snapshots = cinder.volume_snapshot_list(request)
                if snapshots:
                    source_type_choices.append(
                        ("snapshot_source", _("Snapshot")))
                    choices = [('', _("Choose a snapshot"))] + \
                              [(s.id, s) for s in snapshots]
                    self.fields['snapshot_source'].choices = choices
                else:
                    del self.fields['snapshot_source']
            except Exception:
                exceptions.handle(request,
                                  _("Unable to retrieve "
                                    "volume snapshots."))

            images = get_available_images(request, request.user.tenant_id)
            if images:
                source_type_choices.append(("image_source", _("Image")))
                choices = [('', _("Choose an image"))]
                for image in images:
                    image.bytes = image.size
                    image.size = bytes_to_gigabytes(image.bytes)
                    choices.append((image.id, image))
                self.fields['image_source'].choices = choices
            else:
                del self.fields['image_source']

            if source_type_choices:
                choices = (
                    [('no_source_type', _("No source, empty volume."))] +
                    source_type_choices)
                self.fields['volume_source_type'].choices = choices
            else:
                del self.fields['volume_source_type']

    def handle(self, request, data):
        try:
            usages = cinder.tenant_absolute_limits(self.request)
            volumes = cinder.volume_list(self.request)
            total_size = sum(
                [getattr(volume, 'size', 0) for volume in volumes])
            usages['gigabytesUsed'] = total_size
            usages['volumesUsed'] = len(volumes)
            availableGB = usages['maxTotalVolumeGigabytes'] -\
                usages['gigabytesUsed']
            availableVol = usages['maxTotalVolumes'] - usages['volumesUsed']

            snapshot_id = None
            image_id = None
            source_type = data.get('volume_source_type', None)
            if (data.get("snapshot_source", None)
                    and source_type in [None, 'snapshot_source']):
                # Create from Snapshot
                snapshot = self.get_snapshot(request, data["snapshot_source"])
                snapshot_id = snapshot.id
                if (data['size'] < snapshot.size):
                    error_message = _('The volume size cannot be less than '
                                      'the snapshot size (%sGB)' %
                                      snapshot.size)
                    raise ValidationError(error_message)
            elif (data.get("image_source", None)
                  and source_type in [None, 'image_source']):
                # Create from Snapshot
                image = self.get_image(request, data["image_source"])
                image_id = image.id
                image_size = bytes_to_gigabytes(image.size)
                if (data['size'] < image_size):
                    error_message = _('The volume size cannot be less than '
                                      'the image size (%s)' %
                                      filesizeformat(image.size))
                    raise ValidationError(error_message)
            else:
                if type(data['size']) is str:
                    data['size'] = int(data['size'])

            if availableGB < data['size']:
                error_message = _('A volume of %(req)iGB cannot be created as '
                                  'you only have %(avail)iGB of your quota '
                                  'available.')
                params = {'req': data['size'], 'avail': availableGB}
                raise ValidationError(error_message % params)
            elif availableVol <= 0:
                error_message = _('You are already using all of your available'
                                  ' volumes.')
                raise ValidationError(error_message)

            metadata = {}

            if data['encryption']:
                metadata['encryption'] = data['encryption']

            volume = cinder.volume_create(request,
                                          data['size'],
                                          data['name'],
                                          data['description'],
                                          data['type'],
                                          snapshot_id=snapshot_id,
                                          image_id=image_id,
                                          metadata=metadata)
            message = _('Creating volume "%s"') % data['name']
            messages.info(request, message)
            return volume
        except ValidationError as e:
            self.api_error(e.messages[0])
            return False
        except Exception:
            exceptions.handle(request, ignore=True)
            self.api_error(_("Unable to create volume."))
            return False

    @memoized
    def get_snapshot(self, request, id):
        return cinder.volume_snapshot_get(request, id)

    @memoized
    def get_image(self, request, id):
        return glance.image_get(request, id)
示例#4
0
class CreateForm(forms.SelfHandlingForm):
    name = forms.CharField(max_length="255", label=_("Volume Name"))
    description = forms.CharField(widget=forms.Textarea,
                                  label=_("Description"),
                                  required=False)
    type = forms.ChoiceField(label=_("Type"), required=False)
    size = forms.IntegerField(min_value=1, label=_("Size (GB)"))
    encryption = forms.ChoiceField(label=_("Encryption"), required=False)
    snapshot_source = forms.ChoiceField(
        label=_("Use snapshot as a source"),
        widget=SelectWidget(attrs={'class': 'snapshot-selector'},
                            data_attrs=('size', 'display_name'),
                            transform=lambda x: ("%s (%sGB)" %
                                                 (x.display_name, x.size))),
        required=False)

    def __init__(self, request, *args, **kwargs):
        super(CreateForm, self).__init__(request, *args, **kwargs)
        volume_types = cinder.volume_type_list(request)
        self.fields['type'].choices = [("", "")] + \
                                      [(type.name, type.name)
                                       for type in volume_types]

        # Hide the volume encryption field if the hypervisor doesn't support it
        # NOTE: as of Grizzly this is not yet supported in Nova so enabling
        # this setting will not do anything useful
        hypervisor_features = getattr(settings,
                                      "OPENSTACK_HYPERVISOR_FEATURES", {})
        can_encrypt_volumes = hypervisor_features.get("can_encrypt_volumes",
                                                      False)

        if can_encrypt_volumes:
            # TODO(laura-glendenning) get from api call in future
            encryption_options = {"LUKS": "dmcrypt LUKS"}
            self.fields['encryption'].choices = [("", "")] + \
                [(enc, display) for enc, display in encryption_options.items()]
        else:
            self.fields['encryption'].widget = forms.widgets.HiddenInput()
            self.fields['encryption'].required = False

        if ("snapshot_id" in request.GET):
            try:
                snapshot = self.get_snapshot(request,
                                             request.GET["snapshot_id"])
                self.fields['name'].initial = snapshot.display_name
                self.fields['size'].initial = snapshot.size
                self.fields['snapshot_source'].choices = ((snapshot.id,
                                                           snapshot), )
                try:
                    # Set the volume type from the original volume
                    orig_volume = cinder.volume_get(request,
                                                    snapshot.volume_id)
                    self.fields['type'].initial = orig_volume.volume_type
                except:
                    pass
                self.fields['size'].help_text = _(
                    'Volume size must be equal '
                    'to or greater than the snapshot size (%sGB)' %
                    snapshot.size)
            except:
                exceptions.handle(request,
                                  _('Unable to load the specified snapshot.'))
        else:
            try:
                snapshots = cinder.volume_snapshot_list(request)
                if snapshots:
                    choices = [('', _("Choose a snapshot"))] + \
                              [(s.id, s) for s in snapshots]
                    self.fields['snapshot_source'].choices = choices
                else:
                    del self.fields['snapshot_source']
            except:
                exceptions.handle(request,
                                  _("Unable to retrieve "
                                    "volume snapshots."))

    def handle(self, request, data):
        try:
            # FIXME(johnp): cinderclient currently returns a useless
            # error message when the quota is exceeded when trying to create
            # a volume, so we need to check for that scenario here before we
            # send it off to try and create.
            usages = quotas.tenant_quota_usages(request)

            snapshot_id = None
            if (data.get("snapshot_source", None)):
                # Create from Snapshot
                snapshot = self.get_snapshot(request, data["snapshot_source"])
                snapshot_id = snapshot.id
                if (data['size'] < snapshot.size):
                    error_message = _('The volume size cannot be less than '
                                      'the snapshot size (%sGB)' %
                                      snapshot.size)
                    raise ValidationError(error_message)
            else:
                if type(data['size']) is str:
                    data['size'] = int(data['size'])

            if usages['gigabytes']['available'] < data['size']:
                error_message = _('A volume of %(req)iGB cannot be created as '
                                  'you only have %(avail)iGB of your quota '
                                  'available.')
                params = {
                    'req': data['size'],
                    'avail': usages['gigabytes']['available']
                }
                raise ValidationError(error_message % params)
            elif usages['volumes']['available'] <= 0:
                error_message = _('You are already using all of your available'
                                  ' volumes.')
                raise ValidationError(error_message)

            metadata = {}

            if data['encryption']:
                metadata['encryption'] = data['encryption']

            volume = cinder.volume_create(request,
                                          data['size'],
                                          data['name'],
                                          data['description'],
                                          data['type'],
                                          snapshot_id=snapshot_id,
                                          metadata=metadata)
            message = 'Creating volume "%s"' % data['name']
            messages.info(request, message)
            return volume
        except ValidationError, e:
            self.api_error(e.messages[0])
            return False
        except: