Exemple #1
0
class ImportForm(forms.SelfHandlingForm):
    name = forms.CharField(
        label=_("Stack name"),
        required=True,
        max_length=80,
        help_text=_("Stack name should be unique in the project"))

    importing = forms.FileField(label=_('OVA File'),
                                help_text=_('A local importing to upload.'),
                                widget=forms.FileInput(),
                                required=False)

    def clean(self):
        cleaned_data = super(ImportForm, self).clean()
        return cleaned_data

    def handle(self, request, data):
        try:
            context = {}
            if data:
                context['name'] = data.get("name", "")
                context['importing'] = data.get("importing", "")
                utils.importOVA(self, request, context)
            return True
        except Exception:
            print traceback.format_exc()
            exceptions.handle(request, _("Unable to add importing OVA"))
            return False
Exemple #2
0
 def __init__(self, request, *args, **kwargs):
     super(DecryptPasswordInstanceForm,
           self).__init__(request, *args, **kwargs)
     instance_id = kwargs.get('initial', {}).get('instance_id')
     self.fields['instance_id'].initial = instance_id
     keypair_name = kwargs.get('initial', {}).get('keypair_name')
     self.fields['keypair_name'].initial = keypair_name
     try:
         result = api.nova.get_password(request, instance_id)
         if not result:
             _unavailable = _("Instance Password is not set"
                              " or is not yet available")
             self.fields['encrypted_password'].initial = _unavailable
         else:
             self.fields['encrypted_password'].initial = result
             self.fields['private_key_file'] = forms.FileField(
                 label=_('Private Key File'),
                 widget=forms.FileInput(),
                 required=True)
             self.fields['private_key'] = forms.CharField(
                 widget=forms.widgets.Textarea(),
                 label=_("OR Copy/Paste your Private Key"),
                 required=True)
             _attrs = {'readonly': 'readonly'}
             self.fields['decrypted_password'] = forms.CharField(
                 widget=forms.widgets.TextInput(_attrs),
                 label=_("Password"),
                 required=False)
     except Exception:
         redirect = reverse('horizon:project:instances:index')
         _error = _("Unable to retrieve instance password.")
         exceptions.handle(request, _error, redirect=redirect)
Exemple #3
0
class CreateForm(forms.SelfHandlingForm):
    definition_source = forms.ChoiceField(
        label=_('Definition Source'),
        choices=[('file', _('File')), ('raw', _('Direct Input'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'definitionsource'
        }))
    definition_upload = forms.FileField(
        label=_('Definition File'),
        help_text=_('A local definition to upload.'),
        widget=forms.FileInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'definitionsource',
                'data-required-when-shown': 'true',
                'data-definitionsource-file': _('Definition File')
            }),
        required=False)
    definition_data = forms.CharField(
        label=_('Definition Data'),
        help_text=_('The raw contents of the definition.'),
        widget=forms.widgets.Textarea(
            attrs={
                'class': 'switched',
                'data-switch-on': 'definitionsource',
                'data-required-when-shown': 'true',
                'data-definitionsource-raw': _('Definition Data'),
                'rows': 4
            }),
        required=False)

    def clean(self):
        cleaned_data = super(CreateForm, self).clean()

        if cleaned_data.get('definition_upload'):
            files = self.request.FILES
            cleaned_data['definition'] = files['definition_upload'].read()
        elif cleaned_data.get('definition_data'):
            cleaned_data['definition'] = cleaned_data['definition_data']
        else:
            raise forms.ValidationError(
                _('You must specify the definition source.'))

        return cleaned_data

    def handle(self, request, data):
        try:
            api.action_create(request, data['definition'])
            msg = _('Successfully created action.')
            messages.success(request, msg)

            return True
        except Exception:
            msg = _('Failed to create action.')
            redirect = reverse('horizon:mistral:actions:index')
            exceptions.handle(request, msg, redirect=redirect)
Exemple #4
0
class UploadPatchForm(forms.SelfHandlingForm):
    failure_url = 'horizon:admin:software_management:index'
    patch_files = forms.FileField(
        label=_("Patch File(s)"),
        widget=forms.FileInput(attrs={
            'data-source-file': _('Patch File(s)'),
            'multiple': "multiple"
        }),
        required=True)

    def __init__(self, *args, **kwargs):
        super(UploadPatchForm, self).__init__(*args, **kwargs)

    def clean(self):
        data = super(UploadPatchForm, self).clean()
        return data

    def handle(self, request, data):
        success_responses = []
        failure_responses = []

        for f in request.FILES.getlist('patch_files'):
            try:
                success_responses.append(
                    stx_api.patch.upload_patch(request, f, f.name))
            except Exception as ex:
                failure_responses.append(str(ex))

        # Consolidate server responses into one success/error message
        # respectively
        if success_responses:
            if len(success_responses) == 1:
                messages.success(request, success_responses[0])
            else:
                success_msg = ""
                for i in range(len(success_responses)):
                    success_msg += str(i + 1) + ") " + success_responses[i]
                messages.success(request, success_msg)

        if failure_responses:
            if len(failure_responses) == 1:
                messages.error(request, failure_responses[0])
            else:
                error_msg = ""
                for i in range(len(failure_responses)):
                    error_msg += str(i + 1) + ") " + failure_responses[i]
                messages.error(request, error_msg)

        return True
Exemple #5
0
class DeployVNF(forms.SelfHandlingForm):
    vnf_name = forms.CharField(max_length=255, label=_("VNF Name"))
    description = forms.CharField(
        widget=forms.widgets.Textarea(attrs={'rows': 4}),
        label=_("Description"),
        required=False)
    vnfd_id = forms.ChoiceField(label=_("VNF Catalog Name"), required=False)
    template_source = forms.ChoiceField(
        label=_('VNFD template Source'),
        required=False,
        choices=[('file', _('File')), ('raw', _('Direct Input'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'template'
        }))
    template_file = forms.FileField(
        label=_('VNFD template File'),
        help_text=_('VNFD template to create VNF'),
        widget=forms.FileInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'template',
                'data-template-file': _('TOSCA Template File')
            }),
        required=False)
    template_input = forms.CharField(
        label=_('VNFD template'),
        help_text=_('The YAML formatted contents of VNFD template.'),
        widget=forms.widgets.Textarea(
            attrs={
                'class': 'switched',
                'data-switch-on': 'template',
                'data-template-raw': _('VNFD template')
            }),
        required=False)
    vim_id = forms.ChoiceField(label=_("VIM Name"), required=False)
    region_name = forms.CharField(label=_("Region Name"), required=False)
    source_type = forms.ChoiceField(
        label=_('Parameter Value Source'),
        required=False,
        choices=[('file', _('File')), ('raw', _('Direct Input'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'source'
        }))

    param_file = forms.FileField(
        label=_('Parameter Value File'),
        help_text=_('A local Parameter Value file to upload.'),
        widget=forms.FileInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'source',
                'data-source-file': _('Parameter Value File')
            }),
        required=False)

    direct_input = forms.CharField(
        label=_('Parameter Value YAML'),
        help_text=_('The YAML formatted contents of Parameter Values.'),
        widget=forms.widgets.Textarea(
            attrs={
                'class': 'switched',
                'data-switch-on': 'source',
                'data-source-raw': _('Parameter Values')
            }),
        required=False)

    config_type = forms.ChoiceField(
        label=_('Configuration Value Source'),
        required=False,
        choices=[('file', _('File')), ('raw', _('Direct Input'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'config'
        }))

    config_file = forms.FileField(
        label=_('Configuration Value File'),
        help_text=_('VNF Configuration file with YAML '
                    'formatted contents to upload.'),
        widget=forms.FileInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'config',
                'data-config-file': _('Configuration Value File')
            }),
        required=False)

    config_input = forms.CharField(
        label=_('Configuration Value YAML'),
        help_text=_('YAML formatted VNF configuration text.'),
        widget=forms.widgets.Textarea(
            attrs={
                'class': 'switched',
                'data-switch-on': 'config',
                'data-config-raw': _('Configuration Values')
            }),
        required=False)

    def __init__(self, request, *args, **kwargs):
        super(DeployVNF, self).__init__(request, *args, **kwargs)

        try:
            vnfd_list = api.tacker.vnfd_list(request,
                                             template_source='onboarded')
            available_choices_vnfd = [(vnf['id'], vnf['name'])
                                      for vnf in vnfd_list]
        except Exception as e:
            available_choices_vnfd = []
            msg = _('Failed to retrieve available VNF Catalog names: %s') % e
            LOG.error(msg)

        try:
            vim_list = api.tacker.vim_list(request)
            available_choices_vims = [(vim['id'], vim['name'])
                                      for vim in vim_list]

        except Exception as e:
            available_choices_vims = []
            msg = _('Failed to retrieve available VIM names: %s') % e
            LOG.error(msg)

        self.fields['vnfd_id'].choices = [('', _('Select a VNF Catalog Name'))
                                          ] + available_choices_vnfd
        self.fields['vim_id'].choices = [('', _('Select a VIM Name'))
                                         ] + available_choices_vims

    def clean(self):
        data = super(DeployVNF, self).clean()

        template_file = data.get('template_file', None)
        template_raw = data.get('template_input', None)

        if template_raw and template_file:
            raise ValidationError(
                _("Cannot specify both file and direct input."))

        if template_file and not template_file.name.endswith('.yaml'):
            raise ValidationError(_("Please upload .yaml file only."))

        if template_file:
            data['vnfd_template'] = yaml.load(template_file,
                                              Loader=yaml.SafeLoader)
        elif template_raw:
            data['vnfd_template'] = yaml.load(data['template_input'],
                                              Loader=yaml.SafeLoader)
        else:
            data['vnfd_template'] = None

        param_file = data.get('param_file', None)
        param_raw = data.get('direct_input', None)

        if param_raw and param_file:
            raise ValidationError(
                _("Cannot specify both file and direct input."))

        if param_file and not param_file.name.endswith('.yaml'):
            raise ValidationError(_("Please upload .yaml file only."))

        if param_file:
            data['param_values'] = self.files['param_file'].read()
        elif param_raw:
            data['param_values'] = data['direct_input']
        else:
            data['param_values'] = None

        config_file = data.get('config_file', None)
        config_raw = data.get('config_input', None)

        if config_file and config_raw:
            raise ValidationError(
                _("Cannot specify both file and direct input."))

        if config_file and not config_file.name.endswith('.yaml'):
            raise ValidationError(_("Only .yaml file uploads supported"))

        if config_file:
            data['config_values'] = self.files['config_file'].read()
        elif config_raw:
            data['config_values'] = data['config_input']
        else:
            data['config_values'] = None

        return data

    def handle(self, request, data):
        try:
            vnf_name = data['vnf_name']
            description = data['description']
            vnfd_id = data.get('vnfd_id')
            vnfd_template = data.get('vnfd_template')
            vim_id = data['vim_id']
            region_name = data['region_name']
            param_val = data['param_values']
            config_val = data['config_values']

            if (vnfd_id == '') and (vnfd_template is None):
                raise ValidationError(
                    _("Both VNFD id and template cannot be "
                      "empty. Please specify one of them"))

            if (vnfd_id != '') and (vnfd_template is not None):
                raise ValidationError(
                    _("Both VNFD id and template cannot be "
                      "specified. Please specify any one"))

            vnf_arg = {
                'vnf': {
                    'vnfd_id': vnfd_id,
                    'name': vnf_name,
                    'description': description,
                    'vim_id': vim_id,
                    'vnfd_template': vnfd_template
                }
            }
            if region_name:
                vnf_arg.setdefault('placement_attr',
                                   {})[region_name] = region_name
            vnf_attr = vnf_arg['vnf'].setdefault('attributes', {})
            if param_val:
                vnf_attr['param_values'] = param_val
            if config_val:
                vnf_attr['config'] = config_val

            api.tacker.create_vnf(request, vnf_arg)
            messages.success(
                request,
                _('VNF %s create operation initiated.') % vnf_name)
            return True
        except Exception:
            exceptions.handle(request, _('Failed to create VNF.'))
class TemplateForm(forms.SelfHandlingForm):
    class Meta:
        name = _('Select Template')
        help_text = _('Select a template to launch a stack.')

    # TODO(jomara) - update URL choice for template & environment files
    # w/ client side download when applicable
    base_choices = [('file', _('File')), ('raw', _('Direct Input'))]
    url_choice = [('url', _('URL'))]
    attributes = {'class': 'switchable', 'data-slug': 'templatesource'}
    template_source = forms.ChoiceField(label=_('Template Source'),
                                        choices=base_choices + url_choice,
                                        widget=forms.Select(attrs=attributes))

    attributes = create_upload_form_attributes('template', 'file',
                                               _('Template File'))
    template_upload = forms.FileField(
        label=_('Template File'),
        help_text=_('A local template to upload.'),
        widget=forms.FileInput(attrs=attributes),
        required=False)

    attributes = create_upload_form_attributes('template', 'url',
                                               _('Template URL'))
    template_url = forms.URLField(
        label=_('Template URL'),
        help_text=_('An external (HTTP) URL to load the template from.'),
        widget=forms.TextInput(attrs=attributes),
        required=False)

    attributes = create_upload_form_attributes('template', 'raw',
                                               _('Template Data'))
    template_data = forms.CharField(
        label=_('Template Data'),
        help_text=_('The raw contents of the template.'),
        widget=forms.widgets.Textarea(attrs=attributes),
        required=False)

    attributes = {'data-slug': 'envsource', 'class': 'switchable'}
    environment_source = forms.ChoiceField(
        label=_('Environment Source'),
        choices=base_choices,
        widget=forms.Select(attrs=attributes),
        required=False)

    attributes = create_upload_form_attributes('env', 'file',
                                               _('Environment File'))
    environment_upload = forms.FileField(
        label=_('Environment File'),
        help_text=_('A local environment to upload.'),
        widget=forms.FileInput(attrs=attributes),
        required=False)

    attributes = create_upload_form_attributes('env', 'raw',
                                               _('Environment Data'))
    environment_data = forms.CharField(
        label=_('Environment Data'),
        help_text=_('The raw contents of the environment file.'),
        widget=forms.widgets.Textarea(attrs=attributes),
        required=False)

    def __init__(self, *args, **kwargs):
        self.next_view = kwargs.pop('next_view')
        super(TemplateForm, self).__init__(*args, **kwargs)

    def clean(self):
        cleaned = super(TemplateForm, self).clean()

        files = self.request.FILES
        self.clean_uploaded_files('template', _('template'), cleaned, files)
        self.clean_uploaded_files('environment', _('environment'), cleaned,
                                  files)

        # Validate the template and get back the params.
        kwargs = {}
        if cleaned['template_data']:
            kwargs['template'] = cleaned['template_data']
        else:
            kwargs['template_url'] = cleaned['template_url']

        if cleaned['environment_data']:
            kwargs['environment'] = cleaned['environment_data']

        try:
            validated = api.heat.template_validate(self.request, **kwargs)
            cleaned['template_validate'] = validated
        except Exception as e:
            raise forms.ValidationError(unicode(e))

        return cleaned

    def clean_uploaded_files(self, prefix, field_label, cleaned, files):
        """Cleans Template & Environment data from form upload.

        Does some of the crunchy bits for processing uploads vs raw
        data depending on what the user specified. Identical process
        for environment data & template data.

        :type prefix: str
        :param prefix: prefix (environment, template) of field
        :type field_label: str
        :param field_label: translated prefix str for messages
        :type input_type: dict
        :param prefix: existing cleaned fields from form
        :rtype: dict
        :return: cleaned dict including environment & template data
        """

        upload_str = prefix + "_upload"
        data_str = prefix + "_data"
        url = cleaned.get(prefix + '_url')
        data = cleaned.get(prefix + '_data')

        has_upload = upload_str in files
        # Uploaded file handler
        if has_upload and not url:
            log_template_name = files[upload_str].name
            LOG.info('got upload %s' % log_template_name)

            tpl = files[upload_str].read()
            if tpl.startswith('{'):
                try:
                    json.loads(tpl)
                except Exception as e:
                    msg = _('There was a problem parsing the'
                            ' %(prefix)s: %(error)s')
                    msg = msg % {'prefix': prefix, 'error': e}
                    raise forms.ValidationError(msg)
            cleaned[data_str] = tpl

        # URL handler
        elif url and (has_upload or data):
            msg = _('Please specify a %s using only one source method.')
            msg = msg % field_label
            raise forms.ValidationError(msg)

        elif prefix == 'template':
            # Check for raw template input - blank environment allowed
            if not url and not data:
                msg = _('You must specify a template via one of the '
                        'available sources.')
                raise forms.ValidationError(msg)

    def create_kwargs(self, data):
        kwargs = {
            'parameters': data['template_validate'],
            'environment_data': data['environment_data'],
            'template_data': data['template_data'],
            'template_url': data['template_url']
        }
        if data.get('stack_id'):
            kwargs['stack_id'] = data['stack_id']
        return kwargs

    def handle(self, request, data):
        kwargs = self.create_kwargs(data)
        # NOTE (gabriel): This is a bit of a hack, essentially rewriting this
        # request so that we can chain it as an input to the next view...
        # but hey, it totally works.
        request.method = 'GET'

        return self.next_view.as_view()(request, **kwargs)
Exemple #7
0
class CreateImageForm(CreateParent):
    name = forms.CharField(max_length=255, label=_("Name"))
    description = forms.CharField(max_length=255,
                                  widget=forms.Textarea(attrs={'rows': 4}),
                                  label=_("Description"),
                                  required=False)
    source_type = forms.ChoiceField(
        label=_('Image Source'),
        required=False,
        choices=[('url', _('Image Location')), ('file', _('Image File'))],
        widget=forms.ThemableSelectWidget(attrs={
            'class': 'switchable',
            'data-slug': 'source'
        }))
    image_url_attrs = {
        'class': 'switched',
        'data-switch-on': 'source',
        'data-source-url': _('Image Location'),
        'ng-model': 'ctrl.copyFrom',
        'ng-change': 'ctrl.selectImageFormat(ctrl.copyFrom)',
        'placeholder': 'http://example.com/image.img'
    }
    image_url = ImageURLField(label=_("Image Location"),
                              help_text=_("An external (HTTP/HTTPS) URL to "
                                          "load the image from."),
                              widget=forms.TextInput(attrs=image_url_attrs),
                              required=False)
    image_attrs = {
        'class': 'switched',
        'data-switch-on': 'source',
        'data-source-file': _('Image File'),
        'ng-model': 'ctrl.imageFile',
        'ng-change': 'ctrl.selectImageFormat(ctrl.imageFile.name)',
        'image-file-on-change': None
    }
    image_file = FileField(label=_("Image File"),
                           help_text=_("A local image to upload."),
                           widget=forms.FileInput(attrs=image_attrs),
                           required=False)
    kernel = forms.ChoiceField(
        label=_('Kernel'),
        required=False,
        widget=forms.ThemableSelectWidget(transform=lambda x: "%s (%s)" % (
            x.name, defaultfilters.filesizeformat(x.size))))
    ramdisk = forms.ChoiceField(
        label=_('Ramdisk'),
        required=False,
        widget=forms.ThemableSelectWidget(transform=lambda x: "%s (%s)" % (
            x.name, defaultfilters.filesizeformat(x.size))))
    disk_format = forms.ChoiceField(
        label=_('Format'),
        choices=[],
        widget=forms.ThemableSelectWidget(attrs={
            'class': 'switchable',
            'ng-model': 'ctrl.diskFormat'
        }))
    architecture = forms.CharField(
        max_length=255,
        label=_("Architecture"),
        help_text=_('CPU architecture of the image.'),
        required=False)
    min_disk = forms.IntegerField(
        label=_("Minimum Disk (GB)"),
        min_value=0,
        help_text=_('The minimum disk size required to boot the image. '
                    'If unspecified, this value defaults to 0 (no minimum).'),
        required=False)
    min_ram = forms.IntegerField(
        label=_("Minimum RAM (MB)"),
        min_value=0,
        help_text=_('The minimum memory size required to boot the image. '
                    'If unspecified, this value defaults to 0 (no minimum).'),
        required=False)
    is_copying = forms.BooleanField(
        label=_("Copy Data"),
        initial=True,
        required=False,
        help_text=_('Specify this option to copy image data to the image '
                    'service. If unspecified, image data will be used in its '
                    'current location.'),
        widget=forms.CheckboxInput(
            attrs={
                'class': 'switched',
                'data-source-url': _('Image Location'),
                'data-switch-on': 'source'
            }))
    is_public = forms.BooleanField(
        label=_("Public"),
        help_text=_('Make the image visible across projects.'),
        required=False)
    protected = forms.BooleanField(
        label=_("Protected"),
        help_text=_('Prevent the deletion of the image.'),
        required=False)

    def __init__(self, request, *args, **kwargs):
        super().__init__(request, *args, **kwargs)

        if (api.glance.get_image_upload_mode() == 'off' or not policy.check(
            (("image", "upload_image"), ), request)):
            self._hide_file_source_type()
        if not policy.check((("image", "set_image_location"), ), request):
            self._hide_url_source_type()

        # GlanceV2 feature removals
        if api.glance.VERSIONS.active >= 2:
            # NOTE: GlanceV2 doesn't support copy-from feature, sorry!
            self._hide_is_copying()
            if not settings.IMAGES_ALLOW_LOCATION:
                self._hide_url_source_type()
                if (api.glance.get_image_upload_mode() == 'off'
                        or not policy.check(
                            (("image", "upload_image"), ), request)):
                    # Neither setting a location nor uploading image data is
                    # allowed, so throw an error.
                    msg = _('The current Horizon settings indicate no valid '
                            'image creation methods are available. Providing '
                            'an image location and/or uploading from the '
                            'local file system must be allowed to support '
                            'image creation.')
                    messages.error(request, msg)
                    raise ValidationError(msg)
        if not policy.check((("image", "publicize_image"), ), request):
            self._hide_is_public()

        self.fields['disk_format'].choices = \
            api.glance.get_image_formats(request)

        try:
            kernel_images = api.glance.image_list_detailed(
                request, filters={'disk_format': 'aki'})[0]
        except Exception:
            kernel_images = []
            msg = _('Unable to retrieve image list.')
            messages.error(request, msg)

        if kernel_images:
            choices = [('', _("Choose an image"))]
            for image in kernel_images:
                choices.append((image.id, image))
            self.fields['kernel'].choices = choices
        else:
            del self.fields['kernel']

        try:
            ramdisk_images = api.glance.image_list_detailed(
                request, filters={'disk_format': 'ari'})[0]
        except Exception:
            ramdisk_images = []
            msg = _('Unable to retrieve image list.')
            messages.error(request, msg)

        if ramdisk_images:
            choices = [('', _("Choose an image"))]
            for image in ramdisk_images:
                choices.append((image.id, image))
            self.fields['ramdisk'].choices = choices
        else:
            del self.fields['ramdisk']

    def _hide_file_source_type(self):
        self.fields['image_file'].widget = HiddenInput()
        source_type = self.fields['source_type']
        source_type.choices = [
            choice for choice in source_type.choices if choice[0] != 'file'
        ]
        if len(source_type.choices) == 1:
            source_type.widget = HiddenInput()

    def _hide_url_source_type(self):
        self.fields['image_url'].widget = HiddenInput()
        source_type = self.fields['source_type']
        source_type.choices = [
            choice for choice in source_type.choices if choice[0] != 'url'
        ]
        if len(source_type.choices) == 1:
            source_type.widget = HiddenInput()

    def _hide_is_public(self):
        self.fields['is_public'].widget = HiddenInput()
        self.fields['is_public'].initial = False

    def _hide_is_copying(self):
        self.fields['is_copying'].widget = HiddenInput()
        self.fields['is_copying'].initial = False

    def clean(self):
        data = super().clean()

        # The image_file key can be missing based on particular upload
        # conditions. Code defensively for it here...
        source_type = data.get('source_type', None)
        image_file = data.get('image_file', None)
        image_url = data.get('image_url', None)

        if not image_url and not image_file:
            msg = _("An image file or an external location must be specified.")
            if source_type == 'file':
                error_msg = {
                    'image_file': [
                        msg,
                    ]
                }
            else:
                error_msg = {
                    'image_url': [
                        msg,
                    ]
                }
            raise ValidationError(error_msg)

        return data

    def handle(self, request, data):
        meta = api.glance.create_image_metadata(data)

        # Add image source file or URL to metadata
        if (api.glance.get_image_upload_mode() != 'off' and policy.check(
            (("image", "upload_image"), ), request)
                and data.get('image_file', None)):
            meta['data'] = data['image_file']
        elif data.get('is_copying'):
            meta['copy_from'] = data['image_url']
        else:
            meta['location'] = data['image_url']

        try:
            image = api.glance.image_create(request, **meta)
            messages.info(
                request,
                _('Your image %s has been queued for creation.') %
                meta['name'])
            return image
        except Exception as e:
            msg = _('Unable to create new image')
            # TODO(nikunj2512): Fix this once it is fixed in glance client
            if hasattr(e, 'code') and e.code == 400:
                if "Invalid disk format" in e.details:
                    msg = _('Unable to create new image: Invalid disk format '
                            '%s for image.') % meta['disk_format']
                elif "Image name too long" in e.details:
                    msg = _('Unable to create new image: Image name too long.')
                elif "not supported" in e.details:
                    msg = _('Unable to create new image: URL scheme not '
                            'supported.')

            exceptions.handle(request, msg)

            return False
Exemple #8
0
class TemplateForm(forms.SelfHandlingForm):

    class Meta:
        name = _('Select Template')
        help_text = _('From here you can select a template to launch '
                      'a stack.')

    template_source = forms.ChoiceField(label=_('Template Source'),
                                        choices=[('url', _('URL')),
                                                 ('file', _('File')),
                                                 ('raw', _('Direct Input'))],
                                        widget=forms.Select(attrs={
                                            'class': 'switchable',
                                            'data-slug': 'source'}))
    template_upload = forms.FileField(
        label=_('Template File'),
        help_text=_('A local template to upload.'),
        widget=forms.FileInput(attrs={'class': 'switched',
                                      'data-switch-on': 'source',
                                      'data-source-file': _('Template File')}),
        required=False)
    template_url = forms.URLField(
        label=_('Template URL'),
        help_text=_('An external (HTTP) URL to load the template from.'),
        widget=forms.TextInput(attrs={'class': 'switched',
                                      'data-switch-on': 'source',
                                      'data-source-url': _('Template URL')}),
        required=False)
    template_data = forms.CharField(
        label=_('Template Data'),
        help_text=_('The raw contents of the template.'),
        widget=forms.widgets.Textarea(attrs={
                                      'class': 'switched',
                                      'data-switch-on': 'source',
                                      'data-source-raw': _('Template Data')}),
        required=False)

    def __init__(self, *args, **kwargs):
        self.next_view = kwargs.pop('next_view')
        super(TemplateForm, self).__init__(*args, **kwargs)

    def clean(self):
        cleaned = super(TemplateForm, self).clean()
        template_url = cleaned.get('template_url')
        template_data = cleaned.get('template_data')
        files = self.request.FILES
        has_upload = 'template_upload' in files

        # Uploaded file handler
        if has_upload and not template_url:
            log_template_name = self.request.FILES['template_upload'].name
            LOG.info('got upload %s' % log_template_name)

            tpl = self.request.FILES['template_upload'].read()
            if tpl.startswith('{'):
                try:
                    json.loads(tpl)
                except Exception as e:
                    msg = _('There was a problem parsing the template: %s') % e
                    raise forms.ValidationError(msg)
            cleaned['template_data'] = tpl

        # URL handler
        elif template_url and (has_upload or template_data):
            msg = _('Please specify a template using only one source method.')
            raise forms.ValidationError(msg)

        # Check for raw template input
        elif not template_url and not template_data:
            msg = _('You must specify a template via one of the '
                    'available sources.')
            raise forms.ValidationError(msg)

        # Validate the template and get back the params.
        kwargs = {}
        if cleaned['template_data']:
            kwargs['template'] = cleaned['template_data']
        else:
            kwargs['template_url'] = cleaned['template_url']

        try:
            validated = api.heat.template_validate(self.request, **kwargs)
            cleaned['template_validate'] = validated
        except Exception as e:
            msg = exception_to_validation_msg(e)
            if not msg:
                msg = _('An unknown problem occurred validating the template.')
                LOG.exception(msg)
            raise forms.ValidationError(msg)

        return cleaned

    def handle(self, request, data):
        kwargs = {'parameters': data['template_validate'],
                  'template_data': data['template_data'],
                  'template_url': data['template_url']}
        # NOTE (gabriel): This is a bit of a hack, essentially rewriting this
        # request so that we can chain it as an input to the next view...
        # but hey, it totally works.
        request.method = 'GET'
        return self.next_view.as_view()(request, **kwargs)
class CreateImageForm(forms.SelfHandlingForm):
    name = forms.CharField(max_length=255, label=_("Name"))
    description = forms.CharField(max_length=255, label=_("Description"),
                                  required=False)

    source_type = forms.ChoiceField(
        label=_('Image Source'),
        required=False,
        choices=[('url', _('Image Location')),
                 ('file', _('Image File'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'source'}))

    image_url = forms.CharField(max_length=255,
                                label=_("Image Location"),
                                help_text=_("An external (HTTP) URL to load "
                                            "the image from."),
                                widget=forms.TextInput(attrs={
                                    'class': 'switched',
                                    'data-switch-on': 'source',
                                    'data-source-url': _('Image Location'),
                                    'ng-model': 'copyFrom',
                                    'ng-change':
                                    'selectImageFormat(copyFrom)'}),
                                required=False)
    image_file = forms.FileField(label=_("Image File"),
                                 help_text=_("A local image to upload."),
                                 widget=forms.FileInput(attrs={
                                     'class': 'switched',
                                     'data-switch-on': 'source',
                                     'data-source-file': _('Image File'),
                                     'ng-model': 'imageFile',
                                     'ng-change':
                                     'selectImageFormat(imageFile.name)',
                                     'image-file-on-change': None}),
                                 required=False)
    disk_format = forms.ChoiceField(label=_('Format'),
                                    choices=[],
                                    widget=forms.Select(attrs={
                                        'class': 'switchable',
                                        'ng-model': 'diskFormat'}))
    architecture = forms.CharField(max_length=255, label=_("Architecture"),
                                   initial='x86_64',
                                   required=False)
    os_type = forms.CharField(max_length=255, label=_("OS Type"),
                                   help_text=_('optional value: windows/linux'),
                                   initial='linux',
                                   required=True)
    minimum_disk = forms.IntegerField(
        label=_("Minimum Disk (GB)"),
        min_value=0,
        help_text=_('The minimum disk size required to boot the image. '
                    'If unspecified, this value defaults to 0 (no minimum).'),
        initial=1,
        required=False)
    minimum_ram = forms.IntegerField(
        label=_("Minimum RAM (MB)"),
        min_value=0,
        help_text=_('The minimum memory size required to boot the image. '
                    'If unspecified, this value defaults to 0 (no minimum).'),
        initial=1024,
        required=False)
    is_copying = forms.BooleanField(
        label=_("Copy Data"), initial=True, required=False,
        help_text=_('Specify this option to copy image data to the image '
                    'service. If unspecified, image data will be used in its '
                    'current location.'),
        widget=forms.CheckboxInput(attrs={
            'class': 'switched',
            'data-source-url': _('Image Location'),
            'data-switch-on': 'source'}))
    is_allow_inject_passwd = forms.BooleanField(
        label=_("Allow inject user password"), initial=True, required=False)
    is_public = forms.BooleanField(label=_("Public"), required=False)
    protected = forms.BooleanField(label=_("Protected"), required=False)

    def __init__(self, request, *args, **kwargs):
        super(CreateImageForm, self).__init__(request, *args, **kwargs)
        if (not settings.HORIZON_IMAGES_ALLOW_UPLOAD or
                not policy.check((("image", "upload_image"),), request)):
            self._hide_file_source_type()
        if not policy.check((("image", "set_image_location"),), request):
            self._hide_url_source_type()
        if not policy.check((("image", "publicize_image"),), request):
            self._hide_is_public()
        self.fields['disk_format'].choices = IMAGE_FORMAT_CHOICES
        self.fields['minimum_ram'].widget = forms.widgets.HiddenInput()

    def _hide_file_source_type(self):
        self.fields['image_file'].widget = HiddenInput()
        source_type = self.fields['source_type']
        source_type.choices = [choice for choice in source_type.choices
                               if choice[0] != 'file']
        if len(source_type.choices) == 1:
            source_type.widget = HiddenInput()

    def _hide_url_source_type(self):
        self.fields['image_url'].widget = HiddenInput()
        source_type = self.fields['source_type']
        source_type.choices = [choice for choice in source_type.choices
                               if choice[0] != 'url']
        if len(source_type.choices) == 1:
            source_type.widget = HiddenInput()

    def _hide_is_public(self):
        self.fields['is_public'].widget = HiddenInput()
        self.fields['is_public'].initial = False

    def clean(self):
        data = super(CreateImageForm, self).clean()

        # The image_file key can be missing based on particular upload
        # conditions. Code defensively for it here...
        image_file = data.get('image_file', None)
        image_url = data.get('image_url', None)

        if not image_url and not image_file:
            raise ValidationError(
                _("A image or external image location must be specified."))
        elif image_url and image_file:
            raise ValidationError(
                _("Can not specify both image and external image location."))
        else:
            return data

    def handle(self, request, data):
        # Glance does not really do anything with container_format at the
        # moment. It requires it is set to the same disk_format for the three
        # Amazon image types, otherwise it just treats them as 'bare.' As such
        # we will just set that to be that here instead of bothering the user
        # with asking them for information we can already determine.
        if data['disk_format'] in ('ami', 'aki', 'ari',):
            container_format = data['disk_format']
        else:
            data['disk_format'] = 'raw'
            container_format = 'bare'

        data['minimum_ram'] = 512

        meta = {'is_public': data['is_public'],
                'protected': data['protected'],
                'disk_format': data['disk_format'],
                'container_format': container_format,
                'min_disk': (data['minimum_disk'] or 0),
                'min_ram': (data['minimum_ram'] or 0),
                'name': data['name'],
                'properties': {}}

        if data['description']:
            meta['properties']['description'] = data['description']
        if data['architecture']:
            meta['properties']['architecture'] = data['architecture']
        if data['os_type']:
            meta['properties']['os_type'] = data['os_type']
        if (settings.HORIZON_IMAGES_ALLOW_UPLOAD and
                policy.check((("image", "upload_image"),), request) and
                data.get('image_file', None)):
            meta['data'] = self.files['image_file']
        elif data['is_copying']:
            meta['copy_from'] = data['image_url']
        else:
            meta['location'] = data['image_url']
     
        meta['is_allow_inject_passwd'] = data['is_allow_inject_passwd']

        try:
            image = api.glance.image_create(request, **meta)
            messages.success(request,
                             _('Your image %s has been queued for creation.') %
                             data['name'])
            return image
        except Exception as e:
            msg = _('Unable to create new image')
            # TODO(nikunj2512): Fix this once it is fixed in glance client
            if hasattr(e, 'code') and e.code == 400:
                if "Invalid disk format" in e.details:
                    msg = _('Unable to create new image: Invalid disk format '
                            '%s for image.') % data['disk_format']
                elif "Image name too long" in e.details:
                    msg = _('Unable to create new image: Image name too long.')

            exceptions.handle(request, msg)

            return False
Exemple #10
0
class CreateImageForm(forms.SelfHandlingForm):
    name = forms.CharField(max_length=255, label=_("Name"))
    description = forms.CharField(widget=forms.widgets.Textarea(attrs={
        'class': 'modal-body-fixed-width',
        'rows': 4
    }),
                                  label=_("Description"),
                                  required=False)
    source_type = forms.ChoiceField(
        label=_('Image Source'),
        required=False,
        choices=[('url', _('Image Location')), ('file', _('Image File'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'source'
        }))
    image_url_attrs = {
        'class': 'switched',
        'data-switch-on': 'source',
        'data-source-url': _('Image Location'),
        'ng-model': 'ctrl.copyFrom',
        'ng-change': 'ctrl.selectImageFormat(ctrl.copyFrom)'
    }
    image_url = ImageURLField(label=_("Image Location"),
                              help_text=_("An external (HTTP/HTTPS) URL to "
                                          "load the image from."),
                              widget=forms.TextInput(attrs=image_url_attrs),
                              required=False)
    image_attrs = {
        'class': 'switched',
        'data-switch-on': 'source',
        'data-source-file': _('Image File'),
        'ng-model': 'ctrl.imageFile',
        'ng-change': 'ctrl.selectImageFormat(ctrl.imageFile.name)',
        'image-file-on-change': None
    }
    image_file = forms.FileField(label=_("Image File"),
                                 help_text=_("A local image to upload."),
                                 widget=forms.FileInput(attrs=image_attrs),
                                 required=False)
    kernel = forms.ChoiceField(
        label=_('Kernel'),
        required=False,
        widget=forms.SelectWidget(transform=lambda x: "%s (%s)" % (
            x.name, defaultfilters.filesizeformat(x.size))))
    ramdisk = forms.ChoiceField(
        label=_('Ramdisk'),
        required=False,
        widget=forms.SelectWidget(transform=lambda x: "%s (%s)" % (
            x.name, defaultfilters.filesizeformat(x.size))))
    disk_format = forms.ChoiceField(
        label=_('Format'),
        choices=[],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'ng-model': 'ctrl.diskFormat'
        }))
    architecture = forms.CharField(max_length=255,
                                   label=_("Architecture"),
                                   required=False)
    minimum_disk = forms.IntegerField(
        label=_("Minimum Disk (GB)"),
        min_value=0,
        help_text=_('The minimum disk size required to boot the image. '
                    'If unspecified, this value defaults to 0 (no minimum).'),
        required=False)
    minimum_ram = forms.IntegerField(
        label=_("Minimum RAM (MB)"),
        min_value=0,
        help_text=_('The minimum memory size required to boot the image. '
                    'If unspecified, this value defaults to 0 (no minimum).'),
        required=False)
    is_copying = forms.BooleanField(
        label=_("Copy Data"),
        initial=True,
        required=False,
        help_text=_('Specify this option to copy image data to the image '
                    'service. If unspecified, image data will be used in its '
                    'current location.'),
        widget=forms.CheckboxInput(
            attrs={
                'class': 'switched',
                'data-source-url': _('Image Location'),
                'data-switch-on': 'source'
            }))
    is_public = forms.BooleanField(label=_("Public"), required=False)
    protected = forms.BooleanField(label=_("Protected"), required=False)

    def __init__(self, request, *args, **kwargs):
        super(CreateImageForm, self).__init__(request, *args, **kwargs)

        if (not settings.HORIZON_IMAGES_ALLOW_UPLOAD or not policy.check(
            (("image", "upload_image"), ), request)):
            self._hide_file_source_type()
        if not policy.check((("image", "set_image_location"), ), request):
            self._hide_url_source_type()
        if not policy.check((("image", "publicize_image"), ), request):
            self._hide_is_public()

        self.fields['disk_format'].choices = IMAGE_FORMAT_CHOICES

        try:
            kernel_images = api.glance.image_list_detailed(
                request, filters={'disk_format': 'aki'})[0]
        except Exception:
            kernel_images = []
            msg = _('Unable to retrieve image list.')
            messages.error(request, msg)

        if kernel_images:
            choices = [('', _("Choose an image"))]
            for image in kernel_images:
                choices.append((image.id, image))
            self.fields['kernel'].choices = choices
        else:
            del self.fields['kernel']

        try:
            ramdisk_images = api.glance.image_list_detailed(
                request, filters={'disk_format': 'ari'})[0]
        except Exception:
            ramdisk_images = []
            msg = _('Unable to retrieve image list.')
            messages.error(request, msg)

        if ramdisk_images:
            choices = [('', _("Choose an image"))]
            for image in ramdisk_images:
                choices.append((image.id, image))
            self.fields['ramdisk'].choices = choices
        else:
            del self.fields['ramdisk']

    def _hide_file_source_type(self):
        self.fields['image_file'].widget = HiddenInput()
        source_type = self.fields['source_type']
        source_type.choices = [
            choice for choice in source_type.choices if choice[0] != 'file'
        ]
        if len(source_type.choices) == 1:
            source_type.widget = HiddenInput()

    def _hide_url_source_type(self):
        self.fields['image_url'].widget = HiddenInput()
        source_type = self.fields['source_type']
        source_type.choices = [
            choice for choice in source_type.choices if choice[0] != 'url'
        ]
        if len(source_type.choices) == 1:
            source_type.widget = HiddenInput()

    def _hide_is_public(self):
        self.fields['is_public'].widget = HiddenInput()
        self.fields['is_public'].initial = False

    def clean(self):
        data = super(CreateImageForm, self).clean()

        # The image_file key can be missing based on particular upload
        # conditions. Code defensively for it here...
        image_file = data.get('image_file', None)
        image_url = data.get('image_url', None)

        if not image_url and not image_file:
            raise ValidationError(
                _("A image or external image location must be specified."))
        elif image_url and image_file:
            raise ValidationError(
                _("Can not specify both image and external image location."))
        else:
            return data

    def handle(self, request, data):
        meta = create_image_metadata(data, False)

        # Add image source file or URL to metadata
        if (settings.HORIZON_IMAGES_ALLOW_UPLOAD and policy.check(
            (("image", "upload_image"), ), request)
                and data.get('image_file', None)):
            meta['data'] = self.files['image_file']
        elif data['is_copying']:
            meta['copy_from'] = data['image_url']
        else:
            meta['location'] = data['image_url']

        try:
            image = api.glance.image_create(request, **meta)
            messages.success(
                request,
                _('Your image %s has been queued for creation.') %
                meta['name'])
            return image
        except Exception as e:
            msg = _('Unable to create new image')
            # TODO(nikunj2512): Fix this once it is fixed in glance client
            if hasattr(e, 'code') and e.code == 400:
                if "Invalid disk format" in e.details:
                    msg = _('Unable to create new image: Invalid disk format '
                            '%s for image.') % meta['disk_format']
                elif "Image name too long" in e.details:
                    msg = _('Unable to create new image: Image name too long.')
                elif "not supported" in e.details:
                    msg = _('Unable to create new image: URL scheme not '
                            'supported.')

            exceptions.handle(request, msg)

            return False
Exemple #11
0
class CreateScriptForm(forms.SelfHandlingForm):
    help_text = _('Create a new rating script.')
    name = forms.CharField(label=_("Name"))
    source_choices = [('raw', _('Direct Input')),
                      ('file', _('File'))]
    script_source = forms.ChoiceField(
        label=_('Rating Script Source'),
        choices=source_choices,
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'scriptsource'}))
    script_help = _("A script or set of python commands to modify rating "
                    "calculations.")
    script_upload = forms.FileField(
        label=_('Script File'),
        help_text=script_help,
        widget=forms.FileInput(attrs={
            'class': 'switched',
            'data-switch-on': 'scriptsource',
            'data-scriptsource-file': _('Script File')}),
        required=False)
    script_data = forms.CharField(
        label=_('Script Data'),
        help_text=script_help,
        widget=forms.widgets.Textarea(attrs={
            'class': 'switched',
            'data-switch-on': 'scriptsource',
            'data-scriptsource-raw': _('Script Data')}),
        required=False)

    class Meta(object):
        name = _('Create Script')

    def clean(self):
        cleaned = super(CreateScriptForm, self).clean()

        files = self.request.FILES
        script = self.clean_uploaded_files('script', files)

        if script is not None:
            cleaned['script_data'] = script

        return cleaned

    def clean_uploaded_files(self, prefix, files):
        upload_str = prefix + "_upload"

        has_upload = upload_str in files
        if has_upload:
            upload_file = files[upload_str]
            log_script_name = upload_file.name
            LOG.info('got upload %s' % log_script_name)
            script = upload_file.read()
            if script != "":
                try:
                    normalize_newlines(script)
                except Exception as e:
                    msg = _('There was a problem parsing the'
                            ' %(prefix)s: %(error)s')
                    msg = msg % {'prefix': prefix, 'error': e}
                    raise forms.ValidationError(msg)
            return script
        else:
            return None

    def handle(self, request, data):
        name = data['name']
        LOG.info('Creating script with name %s' % (name))
        ck_client = api.cloudkittyclient(request)
        return ck_client.rating.pyscripts.create_script(
            name=name,
            data=data['script_data'])
Exemple #12
0
class ImportOpaqueData(forms.SelfHandlingForm):
    name = forms.RegexField(required=False,
                            max_length=255,
                            label=_("Data Name"),
                            regex=shared_forms.NAME_REGEX,
                            error_messages=shared_forms.ERROR_MESSAGES)
    source_type = forms.ChoiceField(
        label=_('Source'),
        required=False,
        choices=[('file', _('File')), ('raw', _('Direct Input'))],
        widget=forms.ThemableSelectWidget(attrs={
            'class': 'switchable',
            'data-slug': 'source'
        }))
    object_file = forms.FileField(label=_("Choose file"),
                                  help_text=_("A local file to upload."),
                                  widget=forms.FileInput(
                                      attrs={
                                          'class': 'switched',
                                          'data-switch-on': 'source',
                                          'data-source-file': _('File')
                                      }),
                                  required=False)
    direct_input = forms.CharField(
        label=_('Object Bytes'),
        help_text=_('The bytes of the object, represented in hex.'),
        widget=forms.widgets.Textarea(
            attrs={
                'class': 'switched',
                'data-switch-on': 'source',
                'data-source-raw': _('Bytes')
            }),
        required=False)

    def __init__(self, request, *args, **kwargs):
        super(ImportOpaqueData, self).__init__(request, *args, **kwargs)

    def clean(self):
        data = super(ImportOpaqueData, self).clean()

        # The data can be missing based on particular upload
        # conditions. Code defensively for it here...
        data_file = data.get('object_file', None)
        data_raw = data.get('direct_input', None)

        if data_raw and data_file:
            raise forms.ValidationError(
                _("Cannot specify both file and direct input."))
        if not data_raw and not data_file:
            raise forms.ValidationError(
                _("No input was provided for the object value."))
        try:
            if data_file:
                data_bytes = self.files['object_file'].read()
            else:
                data_str = data['direct_input']
                data_bytes = binascii.unhexlify(data_str)
            data['object_bytes'] = base64.b64encode(data_bytes)
        except Exception as e:
            msg = _('There was a problem loading the object: %s. '
                    'Is the object valid and in the correct format?') % e
            raise forms.ValidationError(msg)

        return data

    def handle(self, request, data):
        try:
            data_bytes = data.get('object_bytes')
            data_uuid = client.import_object(
                request,
                data=data_bytes,
                name=data['name'],
                object_type=opaque_data.OpaqueData)

            if data['name']:
                data_identifier = data['name']
            else:
                data_identifier = data_uuid
            messages.success(
                request,
                _('Successfully imported object: %s') % data_identifier)
            return data_uuid
        except Exception as e:
            msg = _('Unable to import object: %s')
            messages.error(msg % e)
            exceptions.handle(request, ignore=True)
            self.api_error(_('Unable to import object.'))
            return False
Exemple #13
0
class ImportX509Certificate(forms.SelfHandlingForm):
    name = forms.RegexField(required=False,
                            max_length=255,
                            label=_("Certificate Name"),
                            regex=NAME_REGEX,
                            error_messages=ERROR_MESSAGES)
    source_type = forms.ChoiceField(
        label=_('Source'),
        required=False,
        choices=[('file', _('Import File')), ('raw', _('Direct Input'))],
        widget=forms.ThemableSelectWidget(attrs={
            'class': 'switchable',
            'data-slug': 'source'
        }))
    cert_file = forms.FileField(
        label=_("Choose file"),
        widget=forms.FileInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'source',
                'data-source-file': _('PEM Certificate File')
            }),
        required=False)
    direct_input = forms.CharField(
        label=_('PEM Certificate'),
        widget=forms.widgets.Textarea(
            attrs={
                'class': 'switched',
                'data-switch-on': 'source',
                'data-source-raw': _('PEM Certificate')
            }),
        required=False)

    def clean(self):
        data = super(ImportX509Certificate, self).clean()

        # The cert can be missing based on particular upload
        # conditions. Code defensively for it here...
        cert_file = data.get('cert_file', None)
        cert_raw = data.get('direct_input', None)

        if cert_raw and cert_file:
            raise forms.ValidationError(
                _("Cannot specify both file and direct input."))
        if not cert_raw and not cert_file:
            raise forms.ValidationError(
                _("No input was provided for the certificate value."))
        try:
            if cert_file:
                cert_pem = self.files['cert_file'].read()
            else:
                cert_pem = str(data['direct_input'])
            cert_obj = load_pem_x509_certificate(cert_pem.encode('utf-8'),
                                                 default_backend())
            cert_der = cert_obj.public_bytes(Encoding.DER)
        except Exception as e:
            msg = _('There was a problem loading the certificate: %s. '
                    'Is the certificate valid and in PEM format?') % e
            raise forms.ValidationError(msg)

        data['cert_data'] = base64.b64encode(cert_der).decode('utf-8')

        return data

    def handle(self, request, data):
        try:
            cert_pem = data.get('cert_data')
            cert_uuid = client.import_object(request,
                                             data=cert_pem,
                                             name=data['name'],
                                             object_type=x_509.X509)

            if data['name']:
                identifier = data['name']
            else:
                identifier = cert_uuid
            messages.success(
                request,
                _('Successfully imported certificate: %s') % identifier)
            return cert_uuid
        except Exception as e:
            msg = _('Unable to import certificate: %s')
            messages.error(request, msg % e)
            exceptions.handle(request, ignore=True)
            self.api_error(_('Unable to import certificate.'))
            return False
Exemple #14
0
class CreateProfileForm(forms.SelfHandlingForm):
    name = forms.CharField(max_length=255, label=_("Name"))
    source_type = forms.ThemableChoiceField(
        label=_('Spec Source'),
        required=False,
        choices=[('file', _('File')),
                 ('yaml', _('YAML'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'source'}))
    spec_file = forms.FileField(
        label=_("Spec File"),
        widget=forms.FileInput(attrs={
            'class': 'switched',
            'data-switch-on': 'source',
            'data-source-file': _('Spec File')}),
        required=False,
        help_text=_("The spec file used to create the profile."))
    spec_yaml = forms.CharField(
        label=_("Spec YAML"),
        required=False,
        widget=forms.Textarea(attrs={
            'rows': 6,
            'class': 'switched',
            'data-switch-on': 'source',
            'data-source-yaml': _('Spec YAML')}),
        help_text=_("The spec yaml used to create the profile."))
    metadata = forms.CharField(
        label=_("Metadata"),
        required=False,
        widget=forms.Textarea(attrs={'rows': 4}),
        help_text=_("YAML formatted metadata."))

    def clean(self):
        data = super(CreateProfileForm, self).clean()

        spec_file = data.get('spec_file', None)
        spec_yaml = data.get('spec_yaml', None)

        if not spec_file and not spec_yaml:
            raise ValidationError(
                _("A spec file or yaml must be specified."))
        elif spec_file and spec_yaml:
            raise ValidationError(
                _("Can not specify both sepc file and yaml."))
        else:
            return data

    def handle(self, request, data):
        source_type = data.get('source_type')
        if source_type == "yaml":
            spec = data.get("spec_yaml")
        else:
            spec = self.files['spec_file'].read()
        opts = _populate_profile_params(
            name=data.get('name'),
            spec=spec,
            metadata=data.get('metadata')
        )

        try:
            profile = senlin.profile_create(request, **opts)
            messages.success(request,
                             _('Your profile %s has been created.') %
                             opts['name'])
            return profile
        except ValidationError as e:
            self.api_error(e.messages[0])
            return False
        except Exception:
            redirect = reverse(INDEX_URL)
            msg = _('Unable to create new profile')
            exceptions.handle(request, msg, redirect=redirect)
            return False
Exemple #15
0
class CreateForm(forms.SelfHandlingForm):
    name = forms.CharField(max_length=255,
                           label=_("Name"),
                           help_text=_('Cron Trigger name.'),
                           required=True)

    workflow_id = forms.ChoiceField(
        label=_('Workflow ID'),
        help_text=_('Select Workflow ID.'),
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'workflow_select'
        }))

    input_source = forms.ChoiceField(
        label=_('Input'),
        help_text=_('JSON of input values defined in the workflow. '
                    'Select either file or raw content.'),
        choices=[('file', _('File')), ('raw', _('Direct Input'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'inputsource'
        }))
    input_upload = forms.FileField(
        label=_('Input File'),
        help_text=_('A local input to upload.'),
        widget=forms.FileInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'inputsource',
                'data-required-when-shown': 'true',
                'data-inputsource-file': _('Input File')
            }),
        required=False)
    input_data = forms.CharField(
        label=_('Input Data'),
        help_text=_('The raw contents of the input.'),
        widget=forms.widgets.Textarea(
            attrs={
                'class': 'switched',
                'data-switch-on': 'inputsource',
                'data-required-when-shown': 'true',
                'data-inputsource-raw': _('Input Data'),
                'rows': 4
            }),
        required=False)

    params_source = forms.ChoiceField(
        label=_('Params'),
        help_text=_('JSON of params values defined in the workflow. '
                    'Select either file or raw content.'),
        choices=[('file', _('File')), ('raw', _('Direct Input'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'paramssource'
        }))
    params_upload = forms.FileField(
        label=_('Params File'),
        help_text=_('A local input to upload.'),
        widget=forms.FileInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'paramssource',
                'data-required-when-shown': 'true',
                'data-paramssource-file': _('Params File')
            }),
        required=False)
    params_data = forms.CharField(
        label=_('Params Data'),
        help_text=_('The raw contents of the params.'),
        widget=forms.widgets.Textarea(
            attrs={
                'class': 'switched',
                'data-switch-on': 'paramssource',
                'data-required-when-shown': 'true',
                'data-paramssource-raw': _('Params Data'),
                'rows': 4
            }),
        required=False)
    first_time = forms.CharField(
        label=_('First Time (YYYY-MM-DD HH:MM)'),
        help_text=_('Date and time of the first execution.'),
        widget=forms.widgets.TextInput(),
        required=False)
    schedule_count = forms.CharField(
        label=_('Count'),
        help_text=_('Number of desired executions.'),
        widget=forms.widgets.TextInput(),
        required=False)
    schedule_pattern = forms.CharField(
        label=_('Pattern (* * * * *)'),
        help_text=_('Cron Trigger pattern, mind the space between each char.'),
        widget=forms.widgets.TextInput(),
        required=False)

    def __init__(self, request, *args, **kwargs):
        super(CreateForm, self).__init__(request, *args, **kwargs)
        workflow_list = api.workflow_list(request)
        workflow_id_list = []
        for wf in workflow_list:
            workflow_id_list.append(
                (wf.id, "{id} ({name})".format(id=wf.id, name=wf.name)))

        self.fields['workflow_id'].choices = workflow_id_list

    def clean(self):
        cleaned_data = super(CreateForm, self).clean()
        cleaned_data['input'] = ""
        cleaned_data['params'] = ""

        if cleaned_data.get('input_upload'):
            files = self.request.FILES
            cleaned_data['input'] = files['input_upload'].read()
        elif cleaned_data.get('input_data'):
            cleaned_data['input'] = cleaned_data['input_data']

        del (cleaned_data['input_upload'])
        del (cleaned_data['input_data'])

        if len(cleaned_data['input']) > 0:
            try:
                cleaned_data['input'] = json.loads(cleaned_data['input'])
            except Exception as e:
                msg = _('Input is invalid JSON: %s') % str(e)
                raise forms.ValidationError(msg)

        if cleaned_data.get('params_upload'):
            files = self.request.FILES
            cleaned_data['params'] = files['params_upload'].read()
        elif cleaned_data.get('params_data'):
            cleaned_data['params'] = cleaned_data['params_data']

        del (cleaned_data['params_upload'])
        del (cleaned_data['params_data'])

        if len(cleaned_data['params']) > 0:
            try:
                cleaned_data['params'] = json.loads(cleaned_data['params'])
            except Exception as e:
                msg = _('Params is invalid JSON: %s') % str(e)
                raise forms.ValidationError(msg)

        return cleaned_data

    @handle_errors(_("Unable to create Cron Trigger"), [])
    def handle(self, request, data):
        data['input'] = convert_empty_string_to_none(data['input'])
        data['params'] = convert_empty_string_to_none(data['params'])
        data['schedule_pattern'] = convert_empty_string_to_none(
            data['schedule_pattern'])
        data['first_time'] = convert_empty_string_to_none(data['first_time'])
        data['schedule_count'] = convert_empty_string_to_none(
            data['schedule_count'])

        try:
            api.cron_trigger_create(
                request,
                data['name'],
                data['workflow_id'],
                data['input'],
                data['params'],
                data['schedule_pattern'],
                data['first_time'],
                data['schedule_count'],
            )
            msg = _('Successfully created Cron Trigger.')
            messages.success(request, msg)

            return True

        finally:
            pass
Exemple #16
0
class CreateServiceChainNodeForm(forms.SelfHandlingForm):
    name = forms.CharField(max_length=80, label=_("Name"))
    description = forms.CharField(
        max_length=80, label=_("Description"), required=False)
    service_type = forms.ChoiceField(
        label=_("Service Type"), choices=SERVICE_TYPES)
    config_type = forms.ChoiceField(label=_("Config Type"),
                                    choices=[('file', 'Heat Template'),
                                             ('string', 'Config String')],
                                    widget=forms.Select(attrs={'class':
                                                'switchable',
                                                'data-slug': 'source'}))
    template_file = forms.FileField(label=_('Configuration File'),
                        help_text=_('A local Heat template file to upload.'),
                        required=False,
                        widget=forms.FileInput(attrs={'class': 'switched',
                            'data-switch-on': 'source',
                            'data-source-file': _("Configuration File")}))
    template_string = forms.CharField(label=_("Configuration String"),
                          help_text=_('A local Heat template string.'),
                          widget=forms.Textarea(attrs={'class': 'switched',
                                                'data-switch-on': 'source',
                                                'data-source-string':
                                                _("Configuration String")}),
                                            required=False)

    def clean(self):
        cleaned_data = super(CreateServiceChainNodeForm, self).clean()
        files = self.request.FILES
        template_str = None
        if 'template_file' in files:
            temp = files['template_file'].read()
            try:
                template_str = json.loads(temp)
            except Exception:
                msg = _('Invalid file format.')
                raise forms.ValidationError(msg)
        else:
            try:
                tstr = cleaned_data["template_string"]
                if bool(tstr):
                    template_str = json.loads(tstr)
            except Exception:
                msg = _("Invalid template string.")
                raise forms.ValidationError(msg)
        if template_str is not None:
            cleaned_data['config'] = template_str
        else:
            msg = _("Please choose a template file or enter template string.")
            raise forms.ValidationError(msg)
        return cleaned_data

    def handle(self, request, context):
        url = reverse("horizon:project:network_services:index")
        try:
            try:
                del context['template_string']
                del context['template_file']
                del context['config_type']
            except KeyError:
                pass
            context['config'] = json.dumps(context['config'])
            client.create_servicechain_node(request, **context)
            msg = _("Service Chain Node Created Successfully!")
            LOG.debug(msg)
            return http.HttpResponseRedirect(url)
        except Exception as e:
            msg = _("Failed to create Service Chain Node. %s") % (str(e))
            LOG.error(msg)
            exceptions.handle(request, msg, redirect=shortcuts.redirect)
Exemple #17
0
class UploadFileForm(forms.SelfHandlingForm):
    name = forms.ChoiceField(label=_('Name'), choices=[])

    description = forms.CharField(widget=forms.widgets.Textarea(attrs={
        'class': 'modal-body-fixed-width',
        'rows': 4
    }),
                                  label=_("Description"),
                                  required=False)
    image_file = forms.FileField(
        label=_("Load File"),
        help_text=_("A local file to upload."),
        widget=forms.FileInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'source',
                'data-source-file': _('Load File'),
                'ng-model': 'File',
                'ng-change': 'selectImageFormat(File.name)',
                'image-file-on-change': None
            }),
        required=False)

    #is_public = forms.BooleanField(label=_("Public"), required=False)
    #protected = forms.BooleanField(label=_("Protected"), required=False)

    def __init__(self, request, *args, **kwargs):
        super(UploadFileForm, self).__init__(request, *args, **kwargs)
        if (api.glance.get_image_upload_mode() == 'off' or not policy.check(
            (("image", "upload_image"), ), request)):
            self._hide_file_source_type()
        if not policy.check((("image", "publicize_image"), ), request):
            self._hide_is_public()
        self.fields['name'].choices = NAME_CHOICES

    def _hide_file_source_type(self):
        self.fields['image_file'].widget = HiddenInput()

    def _hide_is_public(self):
        self.fields['is_public'].widget = HiddenInput()
        self.fields['is_public'].initial = False

    def clean(self):
        data = super(UploadFileForm, self).clean()
        image_file = data.get('image_file', None)
        if not image_file:
            raise ValidationError(_("A file location must be specified."))
        else:
            return data

    def handle(self, request, data):
        container_format = 'bare'
        data['is_public'] = True
        data['disk_format'] = 'raw'
        properties = {}
        if data.get('description'):
            properties['description'] = data['description']
        properties['image_type'] = 'file'
        meta = {
            'public': 'public',
            'protected': False,
            'disk_format': data['disk_format'],
            'container_format': container_format,
            'min_disk': 0,
            'min_ram': 0,
            'name': data['name'],
            #'properties': {'image_type': 'file'},
            'data': self.files['image_file']
        }
        meta.update(properties)
        LOG.info("properties ========================%s" % meta)
        try:
            image = api.glance.image_create(request, **meta)
            messages.success(
                request,
                _('Your file %s has been queued for upload.') % data['name'])
            return image
        except Exception:
            exceptions.handle(request, _('Unable to upload the file.'))
Exemple #18
0
class ImportKey(forms.SelfHandlingForm):
    algorithm = forms.CharField(label=_("Algorithm"), help_text=ALG_HELP_TEXT)
    bit_length = forms.IntegerField(label=_("Bit Length"),
                                    min_value=0,
                                    help_text=LENGTH_HELP_TEXT)
    name = forms.RegexField(required=False,
                            max_length=255,
                            label=_("Key Name"),
                            regex=NAME_REGEX,
                            error_messages=ERROR_MESSAGES)
    source_type = forms.ChoiceField(
        label=_('Source'),
        required=False,
        choices=[('file', _('Key File')), ('raw', _('Direct Input'))],
        widget=forms.ThemableSelectWidget(attrs={
            'class': 'switchable',
            'data-slug': 'source'
        }))
    key_file = forms.FileField(label=_("Choose file"),
                               widget=forms.FileInput(
                                   attrs={
                                       'class': 'switched',
                                       'data-switch-on': 'source',
                                       'data-source-file': _('Key File')
                                   }),
                               required=False)
    direct_input = forms.CharField(label=_('Key Value'),
                                   widget=forms.widgets.Textarea(
                                       attrs={
                                           'class': 'switched',
                                           'data-switch-on': 'source',
                                           'data-source-raw': _('Key Value')
                                       }),
                                   required=False)

    def __init__(self, request, *args, **kwargs):
        algorithms = kwargs.pop('algorithms', None)
        super(ImportKey, self).__init__(request, *args, **kwargs)
        self.fields['algorithm'].widget = ListTextWidget(data_list=algorithms,
                                                         name='algorithms')

    @abc.abstractmethod
    def clean_key_data(self, key_pem):
        """This should be implemented for the specific key import form"""
        return

    def clean(self):
        data = super(ImportKey, self).clean()

        # The key can be missing based on particular upload
        # conditions. Code defensively for it here...
        key_file = data.get('key_file', None)
        key_raw = data.get('direct_input', None)

        if key_raw and key_file:
            raise forms.ValidationError(
                _("Cannot specify both file and direct input."))
        if not key_raw and not key_file:
            raise forms.ValidationError(
                _("No input was provided for the key value."))
        try:
            if key_file:
                key_pem = self.files['key_file'].read()
            else:
                key_pem = data['direct_input']

            data['key_data'] = self.clean_key_data(key_pem)

        except Exception as e:
            msg = _('There was a problem loading the key: %s. '
                    'Is the key valid and in the correct format?') % e
            raise forms.ValidationError(msg)

        return data

    def handle(self, request, data, key_type):
        try:
            key_uuid = client.import_object(request,
                                            algorithm=data['algorithm'],
                                            bit_length=data['bit_length'],
                                            key=data['key_data'],
                                            name=data['name'],
                                            object_type=key_type)

            if data['name']:
                key_identifier = data['name']
            else:
                key_identifier = key_uuid
            messages.success(
                request,
                _('Successfully imported key: %s') % key_identifier)
            return key_uuid
        except Exception as e:
            msg = _('Unable to import key: %s')
            messages.error(request, msg % e)
            exceptions.handle(request, ignore=True)
            self.api_error(_('Unable to import key.'))
            return False
Exemple #19
0
class DefinitionForm(forms.SelfHandlingForm):
    definition_source = forms.ChoiceField(
        label=_('Definition Source'),
        choices=[('file', _('File')), ('raw', _('Direct Input'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'definitionsource'
        }))
    definition_upload = forms.FileField(
        label=_('Definition File'),
        help_text=_('A local definition to upload.'),
        widget=forms.FileInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'definitionsource',
                'data-required-when-shown': 'true',
                'data-definitionsource-file': _('Definition File')
            }),
        required=False)
    definition_data = forms.CharField(
        label=_('Definition Data'),
        help_text=_('The raw contents of the definition.'),
        widget=forms.widgets.Textarea(
            attrs={
                'class': 'switched',
                'data-switch-on': 'definitionsource',
                'data-required-when-shown': 'true',
                'data-definitionsource-raw': _('Definition Data'),
                'rows': 4
            }),
        required=False)

    def __init__(self, *args, **kwargs):
        self.next_view = kwargs.pop('next_view')
        super(DefinitionForm, self).__init__(*args, **kwargs)

    def clean(self):
        cleaned_data = super(DefinitionForm, self).clean()

        if cleaned_data.get('definition_upload'):
            files = self.request.FILES
            cleaned_data['definition'] = files['definition_upload'].read()
        elif cleaned_data.get('definition_data'):
            cleaned_data['definition'] = cleaned_data['definition_data']
        else:
            raise forms.ValidationError(
                _('You must specify the definition source.'))
        try:
            validated = api.workbook_validate(self.request,
                                              cleaned_data['definition'])
        except Exception as e:
            raise forms.ValidationError(six.text_type(e))

        if not validated.get('valid'):
            raise forms.ValidationError(
                validated.get('error', _('Validated failed')))

        return cleaned_data

    def handle(self, request, data):
        kwargs = {'definition': data['definition']}
        request.method = 'GET'

        return self.next_view.as_view()(request, **kwargs)
Exemple #20
0
class CreateNamespaceForm(forms.SelfHandlingForm):
    source_type = forms.ChoiceField(
        label=_('Namespace Definition Source'),
        required=False,
        choices=[('file', _('Metadata Definition File')),
                 ('raw', _('Direct Input'))],
        widget=forms.Select(
            attrs={'class': 'switchable', 'data-slug': 'source'}))

    metadef_file = forms.FileField(
        label=_("Metadata Definition File"),
        help_text=_("A local metadata definition file to upload."),
        widget=forms.FileInput(
            attrs={'class': 'switched', 'data-switch-on': 'source',
                   'data-source-file': _('Metadata Definition File')}),
        required=False)

    direct_input = forms.CharField(
        label=_('Namespace JSON'),
        help_text=_('The JSON formatted contents of a namespace.'),
        widget=forms.widgets.Textarea(
            attrs={'class': 'switched', 'data-switch-on': 'source',
                   'data-source-raw': _('Namespace JSON')}),
        required=False)

    public = forms.BooleanField(label=_("Public"), required=False)
    protected = forms.BooleanField(label=_("Protected"), required=False)

    def __init__(self, request, *args, **kwargs):
        super(CreateNamespaceForm, self).__init__(request, *args, **kwargs)

    def clean(self):
        data = super(CreateNamespaceForm, self).clean()

        # The key can be missing based on particular upload
        # conditions. Code defensively for it here...
        metadef_file = data.get('metadef_file', None)
        metadata_raw = data.get('direct_input', None)

        if metadata_raw and metadef_file:
            raise ValidationError(
                _("Cannot specify both file and direct input."))
        if not metadata_raw and not metadef_file:
            raise ValidationError(
                _("No input was provided for the namespace content."))
        try:
            if metadef_file:
                ns_str = self.files['metadef_file'].read()
            else:
                ns_str = data['direct_input']
            namespace = json.loads(ns_str)

            if data['public']:
                namespace['visibility'] = 'public'
            else:
                namespace['visibility'] = 'private'

            namespace['protected'] = data['protected']

            for protected_prop in constants.METADEFS_PROTECTED_PROPS:
                namespace.pop(protected_prop, None)

            data['namespace'] = namespace
        except Exception as e:
            msg = _('There was a problem loading the namespace: %s.') % e
            raise forms.ValidationError(msg)

        return data

    def handle(self, request, data):
        try:
            namespace = glance.metadefs_namespace_create(request,
                                                         data['namespace'])
            messages.success(request,
                             _('Namespace %s has been created.') %
                             namespace['namespace'])
            return namespace
        except Exception as e:
            msg = _('Unable to create new namespace. %s')
            msg %= e.message.split('Failed validating', 1)[0]
            exceptions.handle(request, message=msg)
            return False
Exemple #21
0
class OnBoardVNF(forms.SelfHandlingForm):
    name = forms.CharField(max_length=80, label=_("Name"), required=False)
    source_type = forms.ChoiceField(
        label=_('TOSCA Template Source'),
        required=False,
        choices=[('file', _('TOSCA Template File')),
                 ('raw', _('Direct Input'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'source'
        }))

    toscal_file = forms.FileField(
        label=_("TOSCA Template File"),
        help_text=_("A local TOSCA template file to upload."),
        widget=forms.FileInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'source',
                'data-source-file': _('TOSCA Template File')
            }),
        required=False)

    direct_input = forms.CharField(
        label=_('TOSCA YAML'),
        help_text=_('The YAML formatted contents of a TOSCA template.'),
        widget=forms.widgets.Textarea(
            attrs={
                'class': 'switched',
                'data-switch-on': 'source',
                'data-source-raw': _('TOSCA YAML')
            }),
        required=False)

    def __init__(self, request, *args, **kwargs):
        super(OnBoardVNF, self).__init__(request, *args, **kwargs)

    def clean(self):
        data = super(OnBoardVNF, self).clean()

        # The key can be missing based on particular upload
        # conditions. Code defensively for it here...
        toscal_file = data.get('toscal_file', None)
        toscal_raw = data.get('direct_input', None)

        if toscal_raw and toscal_file:
            raise ValidationError(
                _("Cannot specify both file and direct input."))
        if not toscal_raw and not toscal_file:
            raise ValidationError(
                _("No input was provided for the namespace content."))
        try:
            if toscal_file:
                toscal_str = self.files['toscal_file'].read()
            else:
                toscal_str = data['direct_input']
            #toscal = yaml.loads(toscal_str)
            data['tosca'] = toscal_str
        except Exception as e:
            msg = _('There was a problem loading the namespace: %s.') % e
            raise forms.ValidationError(msg)

        return data

    def handle(self, request, data):
        try:
            toscal = data['tosca']
            print "VNFD TOSCA: " + toscal
            tosca_arg = {'vnfd': {'vnfd': toscal}}
            vnfd_instance = api.tacker.create_vnfd(request, tosca_arg)
            print "VNFD Instance: " + str(vnfd_instance)
            print "VNFD name: " + vnfd_instance['vnfd']['name']
            messages.success(
                request,
                _('VNF Catalog entry %s has been created.') %
                vnfd_instance['vnfd']['name'])
            return toscal
        except Exception as e:
            msg = _('Unable to create TOSCA. %s')
            msg %= e.message.split('Failed validating', 1)[0]
            exceptions.handle(request, message=msg)
            return False
Exemple #22
0
class DeployMECA(forms.SelfHandlingForm):
    mca_name = forms.CharField(max_length=255, label=_("MECA Name"))
    description = forms.CharField(
        widget=forms.widgets.Textarea(attrs={'rows': 4}),
        label=_("Description"),
        required=False)
    mcad_id = forms.ChoiceField(label=_("MECA Catalog Name"))
    vim_id = forms.ChoiceField(label=_("VIM Name"), required=False)
    source_type = forms.ChoiceField(
        label=_('Parameter Value Source'),
        required=False,
        choices=[('file', _('File')), ('raw', _('Direct Input'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'source'
        }))

    param_file = forms.FileField(
        label=_('Parameter Value File'),
        help_text=_('A local Parameter Value file to upload.'),
        widget=forms.FileInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'source',
                'data-source-file': _('Parameter Value File')
            }),
        required=False)

    direct_input = forms.CharField(
        label=_('Parameter Value YAML'),
        help_text=_('The YAML formatted contents of Parameter Values.'),
        widget=forms.widgets.Textarea(
            attrs={
                'class': 'switched',
                'data-switch-on': 'source',
                'data-source-raw': _('Parameter Values')
            }),
        required=False)

    config_type = forms.ChoiceField(
        label=_('Configuration Value Source'),
        required=False,
        choices=[('file', _('File')), ('raw', _('Direct Input'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'config'
        }))

    config_file = forms.FileField(
        label=_('Configuration Value File'),
        help_text=_('MECA Configuration file with YAML '
                    'formatted contents to upload.'),
        widget=forms.FileInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'config',
                'data-config-file': _('Configuration Value File')
            }),
        required=False)

    config_input = forms.CharField(
        label=_('Configuration Value YAML'),
        help_text=_('YAML formatted MECA configuration text.'),
        widget=forms.widgets.Textarea(
            attrs={
                'class': 'switched',
                'data-switch-on': 'config',
                'data-config-raw': _('Configuration Values')
            }),
        required=False)

    def __init__(self, request, *args, **kwargs):
        super(DeployMECA, self).__init__(request, *args, **kwargs)

        try:
            mecad_list = api.apmec.mecad_list(request)
            available_choices_mecad = [(meca['id'], meca['name'])
                                       for meca in mecad_list]
        except Exception as e:
            available_choices_mecad = []
            msg = _('Failed to retrieve available MECA Catalog nameca: %s') % e
            LOG.error(msg)

        try:
            vim_list = api.apmec.vim_list(request)
            available_choices_vims = [(vim['id'], vim['name'])
                                      for vim in vim_list]

        except Exception as e:
            available_choices_vims = []
            msg = _('Failed to retrieve available VIM nameca: %s') % e
            LOG.error(msg)

        self.fields['mecad_id'].choices = [
            ('', _('Select a MECA Catalog Name'))
        ] + available_choices_mecad
        self.fields['vim_id'].choices = [('', _('Select a VIM Name'))
                                         ] + available_choices_vims

    def clean(self):
        data = super(DeployMECA, self).clean()

        param_file = data.get('param_file', None)
        param_raw = data.get('direct_input', None)

        if param_raw and param_file:
            raise ValidationError(
                _("Cannot specify both file and direct input."))

        if param_file and not param_file.name.endswith('.yaml'):
            raise ValidationError(_("Please upload .yaml file only."))

        if param_file:
            data['param_values'] = self.files['param_file'].read()
        elif param_raw:
            data['param_values'] = data['direct_input']
        else:
            data['param_values'] = None

        config_file = data.get('config_file', None)
        config_raw = data.get('config_input', None)

        if config_file and config_raw:
            raise ValidationError(
                _("Cannot specify both file and direct input."))

        if config_file and not config_file.name.endswith('.yaml'):
            raise ValidationError(_("Only .yaml file uploads supported"))

        if config_file:
            data['config_values'] = self.files['config_file'].read()
        elif config_raw:
            data['config_values'] = data['config_input']
        else:
            data['config_values'] = None

        return data

    def handle(self, request, data):
        try:
            meca_name = data['meca_name']
            description = data['description']
            mecad_id = data['mecad_id']
            vim_id = data['vim_id']
            param_val = data['param_values']
            config_val = data['config_values']
            meca_arg = {
                'meca': {
                    'mecad_id': mecad_id,
                    'name': meca_name,
                    'description': description,
                    'vim_id': vim_id
                }
            }
            meca_attr = meca_arg['meca'].setdefault('attributes', {})
            if param_val:
                meca_attr['param_values'] = param_val
            if config_val:
                meca_attr['config'] = config_val

            api.apmec.create_meca(request, meca_arg)
            mecasages.success(
                request,
                _('MECA %s create operation initiated.') % meca_name)
            return True
        except Exception as e:
            exceptions.handle(request,
                              _('Failed to create MECA: %s') % e.message)
Exemple #23
0
class AddCertificateAction(workflows.Action):
    multipart = True
    name = forms.CharField(max_length=255, label=_("Name"))

    key_source_choices = [('', _('Select Key Source')),
                          ('raw', _('Direct Input')), ('file', _('File'))]
    cert_source_choices = [('', _('Select Certificate Source')),
                           ('raw', _('Direct Input')), ('file', _('File'))]

    attributes = {'class': 'switchable', 'data-slug': 'keysource'}
    key_source = forms.ChoiceField(label=_('Key Source'),
                                   choices=key_source_choices,
                                   widget=forms.Select(attrs=attributes),
                                   required=True)

    key_file_help = _("Choose a file containing your private key.")
    key_paste_help = _("Paste a private key (max 16kb).")

    key_upload = forms.FileField(label=_('Key File'),
                                 help_text=key_file_help,
                                 widget=forms.FileInput(
                                     attrs={
                                         'class': 'switched',
                                         'data-switch-on': 'keysource',
                                         'data-keysource-file': _('Key File')
                                     }),
                                 required=False)

    key_data = forms.CharField(label=_('Key Data'),
                               help_text=key_paste_help,
                               widget=forms.widgets.Textarea(
                                   attrs={
                                       'class': 'switched',
                                       'data-switch-on': 'keysource',
                                       'data-keysource-raw': _('Key Data')
                                   }),
                               required=False)

    passphrase = forms.CharField(max_length=255,
                                 widget=forms.PasswordInput(),
                                 label=_("Key Passphrase"),
                                 required=False)
    attributes = {'class': 'switchable', 'data-slug': 'certsource'}
    cert_source = forms.ChoiceField(label=_('Cert Source'),
                                    choices=cert_source_choices,
                                    widget=forms.Select(attrs=attributes),
                                    required=True)

    cert_file_help = _("Choose a file containing your certificate.")
    cert_paste_help = _("Paste a certificate (max 16kb).")

    cert_upload = forms.FileField(
        label=_('Cert File'),
        help_text=cert_file_help,
        widget=forms.FileInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'certsource',
                'data-certsource-file': _('Cert File')
            }),
        required=False)

    cert_data = forms.CharField(label=_('Cert Data'),
                                help_text=cert_paste_help,
                                widget=forms.widgets.Textarea(
                                    attrs={
                                        'class': 'switched',
                                        'data-switch-on': 'certsource',
                                        'data-certsource-raw': _('Cert Data')
                                    }),
                                required=False)

    def __init__(self, request, *args, **kwargs):
        super(AddCertificateAction, self).__init__(request, *args, **kwargs)

    def clean(self):
        cleaned_data = super(AddCertificateAction, self).clean()
        files = self.request.FILES
        LOG.info("In cleanup files %s cleaned_date %s", files, cleaned_data)
        key = self.clean_uploaded_files('key', files)
        LOG.info("key: %s", key)
        if key is not None:
            cleaned_data['key_data'] = key
        cert = self.clean_uploaded_files('cert', files)
        LOG.info("cert: %s", cert)
        if cert is not None:
            cleaned_data['cert_data'] = cert
        return cleaned_data

    def clean_uploaded_files(self, prefix, files):
        upload_str = prefix + "_upload"

        has_upload = upload_str in files
        if has_upload:
            upload_file = files[upload_str]
            log_script_name = upload_file.name
            LOG.info('got upload %s' % log_script_name)

            if upload_file._size > 16 * 1024:  # 16kb
                msg = _('File exceeds maximum size (16kb)')
                raise forms.ValidationError(msg)
            else:
                script = upload_file.read()
                LOG.info("script: %s", script)
                if script != "":
                    try:
                        normalize_newlines(script)
                    except Exception as e:
                        msg = _('There was a problem parsing the'
                                ' %(prefix)s: %(error)s')
                        msg = msg % {'prefix': prefix, 'error': e}
                        raise forms.ValidationError(msg)
                return script
        else:
            return None

    class Meta(object):
        name = _("Add New Certificate")
        permissions = ('openstack.services.network', )
        help_text = _("Use PEM for key and certificate format")
Exemple #24
0
class OnBoardVNF(forms.SelfHandlingForm):
    name = forms.CharField(max_length=255, label=_("Name"))
    description = forms.CharField(
        widget=forms.widgets.Textarea(attrs={'rows': 4}),
        label=_("Description"),
        required=False)
    source_type = forms.ChoiceField(
        label=_('TOSCA Template Source'),
        required=False,
        choices=[('file', _('TOSCA Template File')),
                 ('raw', _('Direct Input'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'source'
        }))

    toscal_file = forms.FileField(
        label=_("TOSCA Template File"),
        help_text=_("A local TOSCA template file to upload."),
        widget=forms.FileInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'source',
                'data-source-file': _('TOSCA Template File')
            }),
        required=False)

    direct_input = forms.CharField(
        label=_('TOSCA YAML'),
        help_text=_('The YAML formatted contents of a TOSCA template.'),
        widget=forms.widgets.Textarea(
            attrs={
                'class': 'switched',
                'data-switch-on': 'source',
                'data-source-raw': _('TOSCA YAML')
            }),
        required=False)

    def __init__(self, request, *args, **kwargs):
        super(OnBoardVNF, self).__init__(request, *args, **kwargs)

    def clean(self):
        data = super(OnBoardVNF, self).clean()

        # The key can be missing based on particular upload
        # conditions. Code defensively for it here...
        toscal_file = data.get('toscal_file', None)
        toscal_raw = data.get('direct_input', None)
        source_type = data.get("source_type")
        if source_type == "file" and not toscal_file:
            raise ValidationError(_("No TOSCA template file selected."))
        if source_type == "raw" and not toscal_raw:
            raise ValidationError(_("No direct input specified."))

        if toscal_file and not toscal_file.name.endswith(('.yaml', '.csar')):
            raise ValidationError(
                _("Only .yaml or .csar file uploads \
                                    are supported"))

        try:
            if toscal_file:
                toscal_str = self.files['toscal_file'].read()
            else:
                toscal_str = data['direct_input']
            # toscal = yaml.loads(toscal_str)
            data['tosca'] = toscal_str
        except Exception as e:
            msg = _('There was a problem loading the namespace: %s.') % e
            raise forms.ValidationError(msg)

        return data

    def handle(self, request, data):
        try:
            toscal = data['tosca']
            vnfd_name = data['name']
            vnfd_description = data['description']
            tosca_arg = {
                'vnfd': {
                    'name': vnfd_name,
                    'description': vnfd_description,
                    'attributes': {
                        'vnfd': toscal
                    }
                }
            }
            vnfd_instance = api.tacker.create_vnfd(request, tosca_arg)
            messages.success(
                request,
                _('VNF Catalog entry %s has been created.') %
                vnfd_instance['vnfd']['name'])
            return toscal
        except Exception as e:
            msg = _('Unable to create TOSCA. %s')
            msg %= e.message.split('Failed validating', 1)[0]
            exceptions.handle(request, message=msg)
            return False
Exemple #25
0
class CreateImageForm(forms.SelfHandlingForm):
    name = forms.CharField(max_length="255", label=_("Name"), required=True)
    description = forms.CharField(widget=forms.widgets.Textarea(),
                                  label=_("Description"),
                                  required=False)

    source_type = forms.ChoiceField(
        label=_('Image Source'),
        choices=[('url', _('Image Location')), ('file', _('Image File'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'source'
        }))

    copy_from = forms.CharField(max_length="255",
                                label=_("Image Location"),
                                help_text=_("An external (HTTP) URL to load "
                                            "the image from."),
                                widget=forms.TextInput(
                                    attrs={
                                        'class': 'switched',
                                        'data-switch-on': 'source',
                                        'data-source-url': _('Image Location')
                                    }),
                                required=False)
    image_file = forms.FileField(label=_("Image File"),
                                 help_text=_("A local image to upload."),
                                 widget=forms.FileInput(
                                     attrs={
                                         'class': 'switched',
                                         'data-switch-on': 'source',
                                         'data-source-file': _('Image File')
                                     }),
                                 required=False)
    disk_format = forms.ChoiceField(
        label=_('Format'),
        required=True,
        choices=[('', ''), ('aki', _('AKI - Amazon Kernel '
                                     'Image')),
                 ('ami', _('AMI - Amazon Machine '
                           'Image')),
                 ('ari', _('ARI - Amazon Ramdisk '
                           'Image')), ('iso', _('ISO - Optical Disk Image')),
                 ('qcow2', _('QCOW2 - QEMU Emulator')), ('raw', 'Raw'),
                 ('vdi', 'VDI'), ('vhd', 'VHD'), ('vmdk', 'VMDK')],
        widget=forms.Select(attrs={'class': 'switchable'}))
    minimum_disk = forms.IntegerField(label=_("Minimum Disk (GB)"),
                                      help_text=_(
                                          'The minimum disk size'
                                          ' required to boot the'
                                          ' image. If unspecified, this'
                                          ' value defaults to 0'
                                          ' (no minimum).'),
                                      required=False)
    minimum_ram = forms.IntegerField(label=_("Minimum Ram (MB)"),
                                     help_text=_('The minimum disk size'
                                                 ' required to boot the'
                                                 ' image. If unspecified, this'
                                                 ' value defaults to 0 (no'
                                                 ' minimum).'),
                                     required=False)
    is_public = forms.BooleanField(label=_("Public"), required=False)
    protected = forms.BooleanField(label=_("Protected"), required=False)

    def __init__(self, *args, **kwargs):
        super(CreateImageForm, self).__init__(*args, **kwargs)
        if not settings.HORIZON_IMAGES_ALLOW_UPLOAD:
            self.fields['image_file'].widget = HiddenInput()

    def clean(self):
        data = super(CreateImageForm, self).clean()
        if not data['copy_from'] and not data['image_file']:
            raise ValidationError(
                _("A image or external image location must be specified."))
        elif data['copy_from'] and data['image_file']:
            raise ValidationError(
                _("Can not specify both image and external image location."))
        else:
            return data

    def handle(self, request, data):
        # Glance does not really do anything with container_format at the
        # moment. It requires it is set to the same disk_format for the three
        # Amazon image types, otherwise it just treats them as 'bare.' As such
        # we will just set that to be that here instead of bothering the user
        # with asking them for information we can already determine.
        if data['disk_format'] in (
                'ami',
                'aki',
                'ari',
        ):
            container_format = data['disk_format']
        else:
            container_format = 'bare'

        meta = {
            'is_public': data['is_public'],
            'protected': data['protected'],
            'disk_format': data['disk_format'],
            'container_format': container_format,
            'min_disk': (data['minimum_disk'] or 0),
            'min_ram': (data['minimum_ram'] or 0),
            'name': data['name'],
            'properties': {}
        }

        if data['description']:
            meta['properties']['description'] = data['description']
        if settings.HORIZON_IMAGES_ALLOW_UPLOAD and data['image_file']:
            meta['data'] = self.files['image_file']
        else:
            meta['copy_from'] = data['copy_from']

        try:
            image = api.glance.image_create(request, **meta)
            messages.success(
                request,
                _('Your image %s has been queued for creation.' %
                  data['name']))
            return image
        except:
            exceptions.handle(request, _('Unable to create new image.'))
Exemple #26
0
class CreateImageForm(forms.SelfHandlingForm):
    name = forms.CharField(max_length="255", label=_("Name"), required=True)
    description = forms.CharField(widget=forms.widgets.Textarea(
        attrs={'class': 'modal-body-fixed-width'}),
        label=_("Description"),
        required=False)

    source_type = forms.ChoiceField(
        label=_('Image Source'),
        required=False,
        choices=[('url', _('Image Location')),
                 ('file', _('Image File'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'source'}))

    copy_from = forms.CharField(max_length="255",
                                label=_("Image Location"),
                                help_text=_("An external (HTTP) URL to load "
                                            "the image from."),
                                widget=forms.TextInput(attrs={
                                    'class': 'switched',
                                    'data-switch-on': 'source',
                                    'data-source-url': _('Image Location')}),
                                required=False)
    image_file = forms.FileField(label=_("Image File"),
                                 help_text=_("A local image to upload."),
                                 widget=forms.FileInput(attrs={
                                     'class': 'switched',
                                     'data-switch-on': 'source',
                                     'data-source-file': _('Image File')}),
                                 required=False)
    disk_format = forms.ChoiceField(label=_('Format'),
                                    required=True,
                                    choices=[],
                                    widget=forms.Select(attrs={'class':
                                                               'switchable'}))
    architecture = forms.CharField(max_length="255", label=_("Architecture"),
                                   required=False)
    minimum_disk = forms.IntegerField(label=_("Minimum Disk (GB)"),
                                    help_text=_('The minimum disk size'
                                            ' required to boot the'
                                            ' image. If unspecified, this'
                                            ' value defaults to 0'
                                            ' (no minimum).'),
                                    required=False)
    minimum_ram = forms.IntegerField(label=_("Minimum Ram (MB)"),
                                    help_text=_('The minimum memory size'
                                            ' required to boot the'
                                            ' image. If unspecified, this'
                                            ' value defaults to 0 (no'
                                            ' minimum).'),
                                    required=False)
    is_public = forms.BooleanField(label=_("Public"), required=False)
    protected = forms.BooleanField(label=_("Protected"), required=False)

    def __init__(self, request, *args, **kwargs):
        super(CreateImageForm, self).__init__(request, *args, **kwargs)
        if (not settings.HORIZON_IMAGES_ALLOW_UPLOAD or
                not policy.check((("image", "upload_image"),), request)):
            self._hide_file_source_type()
        if not policy.check((("image", "set_image_location"),), request):
            self._hide_url_source_type()
        if not policy.check((("image", "publicize_image"),), request):
            self._hide_is_public()
        self.fields['disk_format'].choices = IMAGE_FORMAT_CHOICES

    def _hide_file_source_type(self):
        self.fields['image_file'].widget = HiddenInput()
        source_type = self.fields['source_type']
        source_type.choices = [choice for choice in source_type.choices
                               if choice[0] != 'file']
        if len(source_type.choices) == 1:
            source_type.widget = HiddenInput()

    def _hide_url_source_type(self):
        self.fields['copy_from'].widget = HiddenInput()
        source_type = self.fields['source_type']
        source_type.choices = [choice for choice in source_type.choices
                               if choice[0] != 'url']
        if len(source_type.choices) == 1:
            source_type.widget = HiddenInput()

    def _hide_is_public(self):
        self.fields['is_public'].widget = HiddenInput()
        self.fields['is_public'].initial = False

    def clean(self):
        data = super(CreateImageForm, self).clean()

        # The image_file key can be missing based on particular upload
        # conditions. Code defensively for it here...
        image_file = data.get('image_file', None)
        image_url = data.get('copy_from', None)

        if not image_url and not image_file:
            raise ValidationError(
                _("A image or external image location must be specified."))
        elif image_url and image_file:
            raise ValidationError(
                _("Can not specify both image and external image location."))
        else:
            return data

    def handle(self, request, data):
        # Glance does not really do anything with container_format at the
        # moment. It requires it is set to the same disk_format for the three
        # Amazon image types, otherwise it just treats them as 'bare.' As such
        # we will just set that to be that here instead of bothering the user
        # with asking them for information we can already determine.
        if data['disk_format'] in ('ami', 'aki', 'ari',):
            container_format = data['disk_format']
        else:
            container_format = 'bare'

        meta = {'is_public': data['is_public'],
                'protected': data['protected'],
                'disk_format': data['disk_format'],
                'container_format': container_format,
                'min_disk': (data['minimum_disk'] or 0),
                'min_ram': (data['minimum_ram'] or 0),
                'name': data['name'],
                'properties': {}}

        if data['description']:
            meta['properties']['description'] = data['description']
        if data['architecture']:
            meta['properties']['architecture'] = data['architecture']
        if (settings.HORIZON_IMAGES_ALLOW_UPLOAD and
                policy.check((("image", "upload_image"),), request) and
                data.get('image_file', None)):
            meta['data'] = self.files['image_file']
        else:
            meta['copy_from'] = data['copy_from']

        try:
            image = api.glance.image_create(request, **meta)
            messages.success(request,
                _('Your image %s has been queued for creation.') %
                data['name'])
            return image
        except Exception:
            exceptions.handle(request, _('Unable to create new image.'))
Exemple #27
0
class CreateForm(forms.SelfHandlingForm):
    source = forms.ChoiceField(label=_('Source'),
                               choices=[('app_file', _('App File')),
                                        ('input', _('Input'))],
                               widget=forms.Select(attrs={
                                   'class': 'switchable',
                                   'data-slug': 'source'
                               }))
    app_file = forms.FileField(
        label=_("Local app file location"),
        required=False,
        widget=forms.FileInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'source',
                'data-source-app_file': _('Local app file location')
            }))
    name = forms.CharField(label=_("Application Name"),
                           required=False,
                           max_length=100)
    languagepack = forms.CharField(label=_("Languagepack"), required=False)
    git_url = forms.URLField(label=_("Source repository"), required=False)
    run_cmd = forms.CharField(label=_("Application entry point"),
                              required=False)
    unittest_cmd = forms.CharField(label=_("Command to execute unit tests"),
                                   required=False)
    port = forms.IntegerField(label=_("The port your application listens on"),
                              min_value=0,
                              required=False)
    param_file = forms.FileField(
        label=_("A yaml file containing custom parameters"), required=False)

    def clean(self):
        cleaned_data = super(CreateForm, self).clean()
        import_type = cleaned_data.get('source')
        if import_type == 'app_file' and not cleaned_data.get('app_file'):
            msg = _('Please supply an app file')
            raise forms.ValidationError(msg)
        elif import_type == 'input':
            if not (cleaned_data.get('name')):
                msg = _('Please supply a name')
                raise forms.ValidationError(msg)
            elif not cleaned_data.get('languagepack'):
                msg = _('Please supply a languagepack')
                raise forms.ValidationError(msg)
            elif not cleaned_data.get('git_url'):
                msg = _('Please supply a github url')
                raise forms.ValidationError(msg)
            elif not cleaned_data.get('run_cmd'):
                msg = _('Please supply a run command')
                raise forms.ValidationError(msg)
        return cleaned_data

    def handle(self, request, data):
        LOG.info('CreateApplication %s' % data)
        solum = solumclient(request)

        app_data = None
        if data['source'] == 'app_file':
            inf = data['app_file'].read()
            app_data = yaml.load(inf)
            if 'repo_token' not in app_data:
                app_data['repo_token'] = ''
        else:
            app_data = {
                'version': 1,
                'description': 'default app description',
                'source': {
                    'repository': '',
                    'revision': 'master',
                    'repo_token': ''
                },
                'workflow_config': {
                    'test_cmd': '',
                    'run_cmd': ''
                }
            }

        if data['name']:
            app_data['name'] = data['name']

        if data['languagepack']:
            app_data['languagepack'] = data['languagepack']

        if data['git_url']:
            app_data['source'] = dict()
            app_data['source']['repository'] = data['git_url']
            app_data['source']['revision'] = 'master'

        if data['run_cmd']:
            if app_data.get('workflow_config') is None:
                app_data['workflow_config'] = dict()
            if not app_data['workflow_config']['run_cmd']:
                app_data['workflow_config']['run_cmd'] = data['run_cmd']

        if data['unittest_cmd']:
            if app_data.get('workflow_config') is None:
                app_data['workflow_config'] = dict()
            if not app_data['workflow_config']['test_cmd']:
                app_data['workflow_config']['test_cmd'] = data['unittest_cmd']

        if not app_data.get('ports'):
            app_data['ports'] = []
            if data['port']:
                app_data['ports'].append(data['port'])
            else:
                app_data['ports'].append(80)

        if data['param_file']:
            param_def = data['param_file'].read()
            app_data['parameters'] = yaml.load(param_def)

        try:
            solum.apps.create(**app_data)
            messages.success(request,
                             _('Application was successfully created.'))
            return True
        except Exception:
            msg = _('Unable to create application.')
            redirect = reverse("horizon:solum:applications:index")
            exceptions.handle(request, msg, redirect=redirect)
            return False
class CustomizeAction(workflows.Action):
    class Meta(object):
        name = _("Post-Creation")
        help_text_template = ("project/instances/"
                              "_launch_customize_help.html")

    source_choices = [('', _('Select Script Source')),
                      ('raw', _('Direct Input')), ('file', _('File'))]

    attributes = {'class': 'switchable', 'data-slug': 'scriptsource'}
    script_source = forms.ChoiceField(label=_('Customization Script Source'),
                                      choices=source_choices,
                                      widget=forms.Select(attrs=attributes),
                                      required=False)

    script_help = _("A script or set of commands to be executed after the "
                    "instance has been built (max 16kb).")

    script_upload = forms.FileField(
        label=_('Script File'),
        help_text=script_help,
        widget=forms.FileInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'scriptsource',
                'data-scriptsource-file': _('Script File')
            }),
        required=False)

    script_data = forms.CharField(
        label=_('Script Data'),
        help_text=script_help,
        widget=forms.widgets.Textarea(
            attrs={
                'class': 'switched',
                'data-switch-on': 'scriptsource',
                'data-scriptsource-raw': _('Script Data')
            }),
        required=False)

    def __init__(self, *args):
        super(CustomizeAction, self).__init__(*args)

    def clean(self):
        cleaned = super(CustomizeAction, self).clean()

        files = self.request.FILES
        script = self.clean_uploaded_files('script', files)

        if script is not None:
            cleaned['script_data'] = script

        return cleaned

    def clean_uploaded_files(self, prefix, files):
        upload_str = prefix + "_upload"

        has_upload = upload_str in files
        if has_upload:
            upload_file = files[upload_str]
            log_script_name = upload_file.name
            LOG.info('got upload %s' % log_script_name)

            if upload_file._size > 16 * units.Ki:  # 16kb
                msg = _('File exceeds maximum size (16kb)')
                raise forms.ValidationError(msg)
            else:
                script = upload_file.read()
                if script != "":
                    try:
                        normalize_newlines(script)
                    except Exception as e:
                        msg = _('There was a problem parsing the'
                                ' %(prefix)s: %(error)s')
                        msg = msg % {
                            'prefix': prefix,
                            'error': six.text_type(e)
                        }
                        raise forms.ValidationError(msg)
                return script
        else:
            return None
Exemple #29
0
class TemplateForm(forms.SelfHandlingForm):
    class Meta(object):
        name = _('Select Template')
        help_text = _('Select a template to launch a stack.')

    # TODO(jomara) - update URL choice for template & environment files
    # w/ client side download when applicable
    base_choices = [('file', _('File')), ('raw', _('Direct Input'))]
    url_choice = [('url', _('URL'))]
    attributes = {'class': 'switchable', 'data-slug': 'templatesource'}
    template_source = forms.ChoiceField(label=_('Template Source'),
                                        choices=base_choices + url_choice,
                                        widget=forms.Select(attrs=attributes))

    attributes = create_upload_form_attributes('template', 'file',
                                               _('Template File'))
    template_upload = forms.FileField(
        label=_('Template File'),
        help_text=_('A local template to upload.'),
        widget=forms.FileInput(attrs=attributes),
        required=False)

    attributes = create_upload_form_attributes('template', 'url',
                                               _('Template URL'))
    template_url = forms.URLField(
        label=_('Template URL'),
        help_text=_('An external (HTTP) URL to load the template from.'),
        widget=forms.TextInput(attrs=attributes),
        required=False)

    picklist = getattr(settings, 'OPENSTACK_HEAT_STACK_LIST', None)
    if (picklist != None):
        choices = [('', '')]
        base = (picklist)
        try:
            html_page = urllib2.urlopen(base)
            soup = BeautifulSoup(html_page, "html.parser")
            for link in soup.findAll('a'):
                choices.append(
                    [urlparse.urljoin(base, link.get('href')), link.text])
            template_url = forms.ChoiceField(
                label=_('Template URL'),
                choices=choices,
                widget=forms.Select(attrs=attributes),
                required=False)
        except:
            pass

    attributes = create_upload_form_attributes('template', 'raw',
                                               _('Template Data'))
    template_data = forms.CharField(
        label=_('Template Data'),
        help_text=_('The raw contents of the template.'),
        widget=forms.widgets.Textarea(attrs=attributes),
        required=False)

    attributes = {'data-slug': 'envsource', 'class': 'switchable'}
    environment_source = forms.ChoiceField(
        label=_('Environment Source'),
        choices=base_choices,
        widget=forms.Select(attrs=attributes),
        required=False)

    attributes = create_upload_form_attributes('env', 'file',
                                               _('Environment File'))
    environment_upload = forms.FileField(
        label=_('Environment File'),
        help_text=_('A local environment to upload.'),
        widget=forms.FileInput(attrs=attributes),
        required=False)

    attributes = create_upload_form_attributes('env', 'raw',
                                               _('Environment Data'))
    environment_data = forms.CharField(
        label=_('Environment Data'),
        help_text=_('The raw contents of the environment file.'),
        widget=forms.widgets.Textarea(attrs=attributes),
        required=False)

    if django.VERSION >= (1, 9):
        # Note(Itxaka): On django>=1.9 Charfield has an strip option that
        # we need to set to False as to not hit
        # https://bugs.launchpad.net/python-heatclient/+bug/1546166
        environment_data.strip = False
        template_data.strip = False

    def __init__(self, *args, **kwargs):
        self.next_view = kwargs.pop('next_view')
        super(TemplateForm, self).__init__(*args, **kwargs)

    def clean(self):
        cleaned = super(TemplateForm, self).clean()

        files = self.request.FILES
        self.clean_uploaded_files('template', _('template'), cleaned, files)
        self.clean_uploaded_files('environment', _('environment'), cleaned,
                                  files)

        # Validate the template and get back the params.
        kwargs = {}
        if cleaned['environment_data']:
            kwargs['environment'] = cleaned['environment_data']
        try:
            files, tpl =\
                api.heat.get_template_files(cleaned.get('template_data'),
                                            cleaned.get('template_url'))
            kwargs['files'] = files
            kwargs['template'] = tpl
            validated = api.heat.template_validate(self.request, **kwargs)
            cleaned['template_validate'] = validated
            cleaned['template_validate']['files'] = files
            cleaned['template_validate']['template'] = tpl
        except Exception as e:
            raise forms.ValidationError(six.text_type(e))

        return cleaned

    def clean_uploaded_files(self, prefix, field_label, cleaned, files):
        """Cleans Template & Environment data from form upload.

        Does some of the crunchy bits for processing uploads vs raw
        data depending on what the user specified. Identical process
        for environment data & template data.

        :type prefix: str
        :param prefix: prefix (environment, template) of field
        :type field_label: str
        :param field_label: translated prefix str for messages
        :type input_type: dict
        :param prefix: existing cleaned fields from form
        :rtype: dict
        :return: cleaned dict including environment & template data
        """

        upload_str = prefix + "_upload"
        data_str = prefix + "_data"
        url = cleaned.get(prefix + '_url')
        data = cleaned.get(prefix + '_data')

        has_upload = upload_str in files
        # Uploaded file handler
        if has_upload and not url:
            log_template_name = files[upload_str].name
            LOG.info('got upload %s' % log_template_name)

            tpl = files[upload_str].read()
            if tpl.startswith('{'):
                try:
                    json.loads(tpl)
                except Exception as e:
                    msg = _('There was a problem parsing the'
                            ' %(prefix)s: %(error)s')
                    msg = msg % {'prefix': prefix, 'error': six.text_type(e)}
                    raise forms.ValidationError(msg)
            cleaned[data_str] = tpl

        # URL handler
        elif url and (has_upload or data):
            msg = _('Please specify a %s using only one source method.')
            msg = msg % field_label
            raise forms.ValidationError(msg)

        elif prefix == 'template':
            # Check for raw template input - blank environment allowed
            if not url and not data:
                msg = _('You must specify a template via one of the '
                        'available sources.')
                raise forms.ValidationError(msg)

    def create_kwargs(self, data):
        kwargs = {
            'parameters': data['template_validate'],
            'environment_data': data['environment_data']
        }
        if data.get('stack_id'):
            kwargs['stack_id'] = data['stack_id']
        return kwargs

    def handle(self, request, data):
        kwargs = self.create_kwargs(data)
        # NOTE (gabriel): This is a bit of a hack, essentially rewriting this
        # request so that we can chain it as an input to the next view...
        # but hey, it totally works.
        request.method = 'GET'

        return self.next_view.as_view()(request, **kwargs)