Exemplo n.º 1
0
class GeneralConfigAction(workflows.Action):
    job_name = forms.CharField(label=_("Name"))

    job_type = forms.ChoiceField(label=_("Job Type"),
                                 widget=forms.Select(attrs={
                                     'class': 'switchable',
                                     'data-slug': 'jobtype'
                                 }))

    main_binary = forms.DynamicChoiceField(
        label=_("Choose a main binary"),
        required=False,
        help_text=_("Choose the binary which "
                    "should be used in this Job."),
        add_item_link=JOB_BINARY_CREATE_URL,
        widget=fields.DynamicSelectWidget(
            attrs={
                'class': 'switched',
                'data-switch-on': 'jobtype',
                'data-jobtype-pig': _("Choose a main binary"),
                'data-jobtype-hive': _("Choose a main binary"),
                'data-jobtype-shell': _("Choose a shell script"),
                'data-jobtype-spark': _("Choose a main binary"),
                'data-jobtype-storm': _("Choose a main binary"),
                'data-jobtype-mapreduce.streaming': _("Choose a main binary")
            }))

    job_description = forms.CharField(label=_("Description"),
                                      required=False,
                                      widget=forms.Textarea(attrs={'rows': 4}))

    def __init__(self, request, context, *args, **kwargs):
        super(GeneralConfigAction, self).__init__(request, context, *args,
                                                  **kwargs)
        if request.REQUEST.get("guide_job_type"):
            self.fields["job_type"].initial = (
                request.REQUEST.get("guide_job_type").lower())

    def populate_job_type_choices(self, request, context):
        choices = []
        choices_list = saharaclient.job_types_list(request)

        for choice in choices_list:
            job_type = choice.name.lower()
            if job_type in helpers.JOB_TYPE_MAP:
                choices.append((job_type, helpers.JOB_TYPE_MAP[job_type][0]))
        return choices

    def populate_main_binary_choices(self, request, context):
        job_binaries = saharaclient.job_binary_list(request)

        choices = [(job_binary.id, job_binary.name)
                   for job_binary in job_binaries]
        choices.insert(0, ('', _("-- not selected --")))
        return choices

    def clean(self):
        cleaned_data = super(workflows.Action, self).clean()
        job_type = cleaned_data.get("job_type", "")

        if job_type in ["Java", "MapReduce"]:
            cleaned_data['main_binary'] = None

        return cleaned_data

    class Meta(object):
        name = _("Create Job Template")
        help_text_template = (
            "project/data_processing.jobs/_create_job_help.html")
Exemplo n.º 2
0
class CreatePartition(forms.SelfHandlingForm):
    host_id = forms.CharField(label=_("host_id"),
                              initial='host_id',
                              widget=forms.widgets.HiddenInput)

    ihost_uuid = forms.CharField(label=_("ihost_uuid"),
                                 initial='ihost_uuid',
                                 widget=forms.widgets.HiddenInput)

    idisk_uuid = forms.CharField(label=_("idisk_uuid"),
                                 initial='idisk_uuid',
                                 widget=forms.widgets.HiddenInput)

    hostname = forms.CharField(
        label=_("Hostname"),
        initial='hostname',
        widget=forms.TextInput(attrs={'readonly': 'readonly'}))

    disks = forms.ChoiceField(label=_("Disks"),
                              required=True,
                              widget=forms.Select(attrs={
                                  'class': 'switchable',
                                  'data-slug': 'disk'
                              }),
                              help_text=_("Disk to create partition on."))

    size_mib = forms.IntegerField(
        label=_("Partition Size MiB"),
        required=True,
        initial=1024,
        widget=forms.TextInput(attrs={'data-slug': 'size_mib'}),
        help_text=_("Size in MiB for the new "
                    "partition."))

    type_guid = forms.CharField(
        label=_("Partition Type"),
        initial='LVM Physical Volume',
        widget=forms.TextInput(attrs={'readonly': 'readonly'}))

    failure_url = 'horizon:admin:inventory:detail'

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

        # Populate disk choices.
        host_uuid = kwargs['initial']['ihost_uuid']
        avail_disk_list = api.sysinv.host_disk_list(self.request, host_uuid)
        disk_tuple_list = []
        for d in avail_disk_list:
            disk_model = d.get_model_num()
            if disk_model is not None and "floppy" in disk_model.lower():
                continue
            if d.available_mib == 0:
                continue
            disk_tuple_list.append(
                (d.uuid, "%s (path: %s size:%s available_mib:%s type: %s)" %
                 (d.device_node, d.device_path, str(
                     d.size_mib), str(d.available_mib), d.device_type)))

        self.fields['disks'].choices = disk_tuple_list

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

    def handle(self, request, data):
        host_id = data['host_id']
        disks = data['disks'][:]
        data['idisk_uuid'] = disks

        try:
            del data['host_id']
            del data['disks']
            del data['hostname']
            data['type_guid'] = sysinv.USER_PARTITION_PHYS_VOL
            # The REST API takes care of creating the partition.
            partition = api.sysinv.host_disk_partition_create(request, **data)

            msg = _('Partition was successfully created.')
            LOG.debug(msg)
            messages.success(request, msg)

            return partition
        except exc.ClientException as ce:
            msg = _('Failed to create partition.')
            LOG.info(msg)
            LOG.error(ce)

            # Allow REST API error message to appear on UI
            messages.error(request, ce)

            # Redirect to host details pg
            redirect = reverse(self.failure_url, args=[host_id])
            return shortcuts.redirect(redirect)
        except Exception as e:
            msg = _('Failed to create partition.')
            LOG.info(msg)
            LOG.error(e)

            # If not a REST API error, throw default.
            redirect = reverse(self.failure_url, args=[host_id])
            return exceptions.handle(request, message=e, redirect=redirect)
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': e}
                        raise forms.ValidationError(msg)
                return script
        else:
            return None
Exemplo n.º 4
0
class AddStorageVolume(forms.SelfHandlingForm):
    # Only allowed to choose 'osd'
    FUNCTION_CHOICES = (
        ('osd', _("osd")),
        ('journal', _("journal")),
        # ('monitor', _("monitor")),
    )

    host_id = forms.CharField(label=_("host_id"),
                              initial='host_id',
                              widget=forms.widgets.HiddenInput)

    ihost_uuid = forms.CharField(label=_("ihost_uuid"),
                                 initial='ihost_uuid',
                                 widget=forms.widgets.HiddenInput)

    idisk_uuid = forms.CharField(label=_("idisk_uuid"),
                                 initial='idisk_uuid',
                                 widget=forms.widgets.HiddenInput)

    tier_uuid = forms.CharField(label=_("tier_uuid"),
                                initial='tier_uuid',
                                widget=forms.widgets.HiddenInput)

    hostname = forms.CharField(
        label=_("Hostname"),
        initial='hostname',
        widget=forms.TextInput(attrs={'readonly': 'readonly'}))

    function = forms.ChoiceField(
        label=_("Function"),
        required=False,
        choices=FUNCTION_CHOICES,
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'function'
        }))

    disks = forms.ChoiceField(label=_("Disks"),
                              required=True,
                              widget=forms.Select(attrs={
                                  'class': 'switchable',
                                  'data-slug': 'disk'
                              }),
                              help_text=_("Assign disk to a storage volume."))

    journal_locations = forms.ChoiceField(
        label=_("Journal"),
        required=False,
        widget=forms.Select(
            attrs={
                'class': 'switched',
                'data-switch-on': 'function',
                'data-function-osd': _("Journal")
            }),
        help_text=_("Assign disk to a "
                    "journal storage "
                    "volume."))

    journal_size_mib = forms.CharField(
        label=_("Journal Size MiB"),
        required=False,
        initial=sysinv.JOURNAL_DEFAULT_SIZE,
        widget=forms.TextInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'function',
                'data-function-osd': _("Journal Size MiB")
            }),
        help_text=_("Journal's size for the"
                    "current OSD."))

    tiers = forms.ChoiceField(label=_("Storage Tier"),
                              required=False,
                              widget=forms.Select(
                                  attrs={
                                      'class': 'switched',
                                      'data-switch-on': 'function',
                                      'data-function-osd': _("Storage Tier")
                                  }),
                              help_text=_("Assign OSD to a storage tier."))

    failure_url = 'horizon:admin:inventory:detail'

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

        # Populate available disk choices
        this_stor_uuid = 0
        host_uuid = kwargs['initial']['ihost_uuid']

        ihost = api.sysinv.host_get(self.request, host_uuid)
        ceph_caching = ((ihost.capabilities.get('pers_subtype') ==
                         sysinv.PERSONALITY_SUBTYPE_CEPH_CACHING))

        avail_disk_list = api.sysinv.host_disk_list(self.request, host_uuid)
        disk_tuple_list = []
        for d in avail_disk_list:
            if d.istor_uuid and d.istor_uuid != this_stor_uuid:
                continue
            is_rootfs_device = \
                (('stor_function' in d.capabilities)
                 and (d.capabilities['stor_function'] == 'rootfs'))
            if is_rootfs_device:
                continue
            disk_model = d.get_model_num()
            if disk_model is not None and "floppy" in disk_model.lower():
                continue
            if (ceph_caching and d.device_type != 'SSD'
                    and d.device_type != 'NVME'):
                continue
            disk_tuple_list.append(
                (d.uuid, "%s (path: %s size:%s model:%s type: %s)" %
                 (d.device_node, d.device_path, str(
                     d.size_mib), disk_model, d.device_type)))

        # Get the cluster
        cluster_list = api.sysinv.cluster_list(self.request)
        cluster_uuid = cluster_list[0].uuid

        # Populate the available tiers for OSD assignment
        avail_tier_list = api.sysinv.storage_tier_list(self.request,
                                                       cluster_uuid)
        tier_tuple_list = [(t.uuid, t.name) for t in avail_tier_list]

        # Populate available journal choices. If no journal is available,
        # then the journal is collocated.
        if ceph_caching:
            avail_journal_list = []
        else:
            avail_journal_list = api.sysinv.host_stor_get_by_function(
                self.request, host_uuid, 'journal')

        journal_tuple_list = []
        if avail_journal_list:
            for j in avail_journal_list:
                journal_tuple_list.append((j.uuid, "%s " % j.uuid))
        else:
            journal_tuple_list.append((None, "Collocated with OSD"))
            self.fields['journal_size_mib'].widget.attrs['disabled'] = \
                'disabled'

        if ceph_caching:
            self.fields['function'].choices = (
                AddStorageVolume.FUNCTION_CHOICES[:1])

        self.fields['disks'].choices = disk_tuple_list
        self.fields['journal_locations'].choices = journal_tuple_list
        self.fields['tiers'].choices = tier_tuple_list

    def clean(self):
        cleaned_data = super(AddStorageVolume, self).clean()
        # host_id = cleaned_data.get('host_id')
        # ihost_uuid = cleaned_data.get('ihost_uuid')

        # disks = cleaned_data.get('disks')

        return cleaned_data

    def handle(self, request, data):
        host_id = data['host_id']
        # host_uuid = data['ihost_uuid']
        disks = data['disks'][:]  # copy
        tiers = data['tiers'][:]  # copy

        # GUI only allows one disk to be picked
        data['idisk_uuid'] = disks

        # GUI only allows one tier to be picked
        data['tier_uuid'] = tiers

        # Obtain journal information.
        journal = data['journal_locations'][:]

        if journal:
            data['journal_location'] = journal
        else:
            data['journal_location'] = None
            data['journal_size_mib'] = sysinv.JOURNAL_DEFAULT_SIZE

        try:
            del data['host_id']
            del data['disks']
            del data['tiers']
            del data['hostname']
            del data['journal_locations']

            # The REST API takes care of creating the stor
            # and updating disk.foristorid
            stor = api.sysinv.host_stor_create(request, **data)

            msg = _('Storage volume was successfully created.')
            LOG.debug(msg)
            messages.success(request, msg)

            return stor
        except exc.ClientException as ce:
            msg = _('Failed to create storage volume.')
            LOG.info(msg)
            LOG.error(ce)

            # Allow REST API error message to appear on UI
            messages.error(request, ce)

            # Redirect to host details pg
            redirect = reverse(self.failure_url, args=[host_id])
            return shortcuts.redirect(redirect)
        except Exception as e:
            msg = _('Failed to create storage volume.')
            LOG.info(msg)
            LOG.error(e)

            # if not a rest API error, throw default
            redirect = reverse(self.failure_url, args=[host_id])
            return exceptions.handle(request, message=e, redirect=redirect)
Exemplo n.º 5
0
class AddPhysicalVolume(forms.SelfHandlingForm):

    PV_TYPE_CHOICES = (
        ('disk', _("Disk")),
        ('partition', _("Partition")),
    )

    host_id = forms.CharField(label=_("host_id"),
                              initial='host_id',
                              widget=forms.widgets.HiddenInput)

    ihost_uuid = forms.CharField(label=_("ihost_uuid"),
                                 initial='ihost_uuid',
                                 widget=forms.widgets.HiddenInput)

    disk_or_part_uuid = forms.CharField(label=_("disk_or_part_uuid"),
                                        initial='disk_or_part_uuid',
                                        widget=forms.widgets.HiddenInput)

    hostname = forms.CharField(
        label=_("Hostname"),
        initial='hostname',
        widget=forms.TextInput(attrs={'readonly': 'readonly'}))

    lvg = forms.ChoiceField(label=_("Local Volume Group"),
                            required=True,
                            widget=forms.Select(attrs={
                                'class': 'switchable',
                                'data-slug': 'lvg'
                            }),
                            help_text=_("Associate this physical volume to a "
                                        "volume group "))

    pv_type = forms.ChoiceField(
        label=_("PV Type"),
        required=False,
        choices=PV_TYPE_CHOICES,
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'pv_type',
            'initial': 'Disk'
        }))

    disks = forms.ChoiceField(label=_("Disks"),
                              required=False,
                              widget=forms.Select(
                                  attrs={
                                      'class': 'switched',
                                      'data-switch-on': 'pv_type',
                                      'data-pv_type-disk': _("Disks")
                                  }),
                              help_text=_("Assign disk to physical volume."))

    partitions = forms.ChoiceField(
        label=_("Partitions"),
        required=False,
        widget=forms.Select(
            attrs={
                'class': 'switched',
                'data-switch-on': 'pv_type',
                'data-pv_type-partition': _("Partitions")
            }),
        help_text=_("Assign partition to physical "
                    "volume."))

    failure_url = 'horizon:admin:inventory:detail'

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

        # Populate available partition, disk, and volume group choices
        host_uuid = kwargs['initial']['ihost_uuid']
        host_id = kwargs['initial']['host_id']

        host = api.sysinv.host_get(self.request, host_id)
        subfunctions = host.subfunctions

        compatible_lvgs = []
        if host.personality.lower().startswith(
                api.sysinv.PERSONALITY_CONTROLLER):
            compatible_lvgs += [
                api.sysinv.LVG_CGTS_VG, api.sysinv.LVG_CINDER_VOLUMES
            ]

        if api.sysinv.SUBFUNCTIONS_COMPUTE in subfunctions:
            compatible_lvgs += [api.sysinv.LVG_NOVA_LOCAL]

        avail_disk_list = api.sysinv.host_disk_list(self.request, host_uuid)
        ilvg_list = api.sysinv.host_lvg_list(self.request, host_uuid)
        partitions = api.sysinv.host_disk_partition_list(
            self.request, host_uuid)
        ipv_list = api.sysinv.host_pv_list(self.request, host_uuid)
        disk_tuple_list = []
        partitions_tuple_list = []
        ilvg_tuple_list = []

        pv_cinder_volumes = next(
            (pv for pv in ipv_list
             if pv.lvm_vg_name == api.sysinv.LVG_CINDER_VOLUMES), None)

        for lvg in ilvg_list:
            if (lvg.lvm_vg_name in compatible_lvgs and lvg.vg_state
                    in [api.sysinv.LVG_ADD, api.sysinv.LVG_PROV]):
                if (lvg.lvm_vg_name == api.sysinv.LVG_CINDER_VOLUMES
                        and pv_cinder_volumes):
                    continue
                ilvg_tuple_list.append((lvg.uuid, lvg.lvm_vg_name))

        for disk in avail_disk_list:
            capabilities = disk.capabilities

            if capabilities.get('stor_function') == 'rootfs':
                continue
            # TODO(rchurch): re-factor
            elif capabilities.get('device_function') == 'cinder_device':
                continue
            else:
                break

        for d in avail_disk_list:
            disk_cap = d.capabilities
            # TODO(rchurch): re-factor
            is_cinder_device = \
                (('device_function' in disk_cap)
                 and (disk_cap['device_function'] == 'cinder_device'))

            is_rootfs_device = \
                (('stor_function' in disk_cap)
                 and (disk_cap['stor_function'] == 'rootfs'))

            disk_model = d.get_model_num()
            # TODO(rchurch): re-factor
            if not d.ipv_uuid and is_cinder_device:
                continue

            if is_rootfs_device or d.ipv_uuid:
                continue

            if disk_model is not None and "floppy" in disk_model.lower():
                continue

            disk_tuple_list.append(
                (d.uuid, "%s (path:%s size:%s model:%s)" %
                 (d.device_node, d.device_path, str(d.size_mib), disk_model)))

        for p in partitions:
            if p.type_guid != api.sysinv.USER_PARTITION_PHYS_VOL:
                continue
            if p.ipv_uuid:
                continue
            if p.status == api.sysinv.PARTITION_IN_USE_STATUS:
                # If partition is in use, but the PV it is attached to
                # is in a "removing" state, we should allow the partition
                # to be listed as a possible option.
                for pv in ipv_list:
                    if (pv.disk_or_part_device_path == p.device_path
                            and pv.pv_state == api.sysinv.PV_DEL):
                        break
                else:
                    continue

            partitions_tuple_list.append(
                (p.uuid, "%s (size:%s)" % (p.device_path, str(p.size_mib))))

        self.fields['disks'].choices = disk_tuple_list
        self.fields['lvg'].choices = ilvg_tuple_list
        self.fields['partitions'].choices = partitions_tuple_list

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

    def handle(self, request, data):
        host_id = data['host_id']

        lvgs = data['lvg'][:]

        # GUI only allows one disk to be picked
        if data['pv_type'] == 'disk':
            data['disk_or_part_uuid'] = data['disks'][:]
        else:
            data['disk_or_part_uuid'] = data['partitions'][:]

        data['ilvg_uuid'] = lvgs

        try:
            del data['host_id']
            del data['disks']
            del data['hostname']
            del data['lvg']
            del data['partitions']

            stor = api.sysinv.host_pv_create(request, **data)

            msg = _('Physical volume was successfully created.')
            messages.success(request, msg)
            return stor
        except exc.ClientException as ce:
            msg = _('Failed to create physical volume.')

            # Allow REST API error message to appear on UI
            w_msg = str(ce)
            if ('Warning:' in w_msg):
                LOG.info(ce)
                messages.warning(request, w_msg.split(':', 1)[-1])
            else:
                LOG.error(ce)
                messages.error(request, w_msg)

            # Redirect to host details pg
            redirect = reverse(self.failure_url, args=[host_id])
            return shortcuts.redirect(redirect)
        except Exception as e:
            msg = _('Failed to create physical volume.')
            LOG.error(e)

            # if not a rest API error, throw default
            redirect = reverse(self.failure_url, args=[host_id])
            return exceptions.handle(request, message=e, redirect=redirect)
Exemplo n.º 6
0
class UpdateMemory(forms.SelfHandlingForm):
    VSWITCH_HP_SIZE_CHOICES = (('2', _("2 MB")), ('1024', _("1 GB")))

    APP_HP_SETTING_CHOICES = (('percent', _('Percent Value')),
                              ('integer', _('Integer Value')))

    memtotal_mib = forms.CharField(label=_("memtotal_mib"),
                                   required=False,
                                   widget=forms.widgets.HiddenInput)

    memtotal_mib_two = forms.CharField(label=_("memtotal_mib_two"),
                                       required=False,
                                       widget=forms.widgets.HiddenInput)

    memtotal_mib_three = forms.CharField(label=_("memtotal_mib_three"),
                                         required=False,
                                         widget=forms.widgets.HiddenInput)

    memtotal_mib_four = forms.CharField(label=_("memtotal_mib_four"),
                                        required=False,
                                        widget=forms.widgets.HiddenInput)

    size_mib_2M = forms.CharField(label=_("size_mib_2M"),
                                  required=False,
                                  widget=forms.widgets.HiddenInput,
                                  initial=constants.MIB_2M)

    size_mib_1G = forms.CharField(label=_("size_mib_1G"),
                                  required=False,
                                  widget=forms.widgets.HiddenInput,
                                  initial=constants.MIB_1G)

    host = forms.CharField(label=_("host"),
                           required=False,
                           widget=forms.widgets.HiddenInput)

    host_id = forms.CharField(label=_("host_id"),
                              required=False,
                              widget=forms.widgets.HiddenInput)

    platform_memory = forms.CharField(
        label=_("#(MiB) of Platform Memory for Node 0"), required=False)

    vm_hugepages_nr_percentage = forms.ChoiceField(
        label=_("Application Huge Pages 1G/2M Setting Type"),
        required=False,
        choices=APP_HP_SETTING_CHOICES,
        help_text="Take Application Hugepages as a Percentage or Integer.",
        widget=forms.ThemableSelectWidget(
            attrs={
                'class': 'switchable',
                'data-slug': 'vm_hugepages_nr_percentage'
            }))

    vm_hugepages_nr_2M = forms.CharField(
        label=_("% of Application 2M Hugepages Node 0"),
        required=False,
        widget=forms.TextInput(
            attrs={
                'class':
                'switched',
                'data-switch-on':
                'vm_hugepages_nr_percentage',
                'data-vm_hugepages_nr_percentage-percent':
                '% of Application 2M Hugepages Node 0',
                'data-vm_hugepages_nr_percentage-integer':
                '# of Application 2M Hugepages Node 0'
            }))

    vm_hugepages_nr_1G = forms.CharField(
        label=_("# of Application 1G Hugepages Node 0"),
        required=False,
        widget=forms.TextInput(
            attrs={
                'class':
                'switched',
                'data-switch-on':
                'vm_hugepages_nr_percentage',
                'data-vm_hugepages_nr_percentage-percent':
                '% of Application 1G Hugepages Node 0',
                'data-vm_hugepages_nr_percentage-integer':
                '# of Application 1G Hugepages Node 0'
            }))

    vswitch_hugepages_reqd = forms.CharField(
        label=_("# of vSwitch 1G Hugepages Node 0"), required=False)

    vswitch_hugepages_size_mib = forms.ChoiceField(
        label=_("vSwitch Hugepage Size Node 0"),
        required=False,
        choices=VSWITCH_HP_SIZE_CHOICES,
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'vswitch_hugepages_size_mib'
        }))

    platform_memory_two = forms.CharField(
        label=_("#(MiB) of Platform Memory for Node 1"), required=False)

    vm_hugepages_nr_2M_two = forms.CharField(
        label=_("# of Application 2M Hugepages Node 1"),
        required=False,
        widget=forms.TextInput(
            attrs={
                'class':
                'switched',
                'data-switch-on':
                'vm_hugepages_nr_percentage',
                'data-vm_hugepages_nr_percentage-percent':
                '% of Application 2M Hugepages Node 1',
                'data-vm_hugepages_nr_percentage-integer':
                '# of Application 2M Hugepages Node 1'
            }))

    vm_hugepages_nr_1G_two = forms.CharField(
        label=_("# of Application 1G Hugepages Node 1"),
        required=False,
        widget=forms.TextInput(
            attrs={
                'class':
                'switched',
                'data-switch-on':
                'vm_hugepages_nr_percentage',
                'data-vm_hugepages_nr_percentage-percent':
                '% of Application 1G Hugepages Node 1',
                'data-vm_hugepages_nr_percentage-integer':
                '# of Application 1G Hugepages Node 1'
            }))

    vswitch_hugepages_reqd_two = forms.CharField(
        label=_("# of vSwitch 1G Hugepages Node 1"), required=False)

    vswitch_hugepages_size_mib_two = forms.ChoiceField(
        label=_("vSwitch Hugepage Size Node 1"),
        required=False,
        choices=VSWITCH_HP_SIZE_CHOICES,
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'vswitch_hugepages_size_mib'
        }))

    platform_memory_three = forms.CharField(
        label=_("#(MiB) of Platform Memory for Node 2"), required=False)

    vm_hugepages_nr_2M_three = forms.CharField(
        label=_("# of Application 2M Hugepages Node 2"),
        required=False,
        widget=forms.TextInput(
            attrs={
                'class':
                'switched',
                'data-switch-on':
                'vm_hugepages_nr_percentage',
                'data-vm_hugepages_nr_percentage-percent':
                '% of Application 2M Hugepages Node 2',
                'data-vm_hugepages_nr_percentage-integer':
                '# of Application 2M Hugepages Node 2'
            }))

    vm_hugepages_nr_1G_three = forms.CharField(
        label=_("# of Application 1G Hugepages Node 2"),
        required=False,
        widget=forms.TextInput(
            attrs={
                'class':
                'switched',
                'data-switch-on':
                'vm_hugepages_nr_percentage',
                'data-vm_hugepages_nr_percentage-percent':
                '% of Application 1G Hugepages Node 2',
                'data-vm_hugepages_nr_percentage-integer':
                '# of Application 1G Hugepages Node 2'
            }))

    vswitch_hugepages_reqd_three = forms.CharField(
        label=_("# of vSwitch 1G Hugepages Node 2"), required=False)

    vswitch_hugepages_size_mib_three = forms.ChoiceField(
        label=_("vSwitch Hugepage Size Node 2"),
        required=False,
        choices=VSWITCH_HP_SIZE_CHOICES,
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'vswitch_hugepages_size_mib'
        }))

    platform_memory_four = forms.CharField(
        label=_("#(MiB) of Platform Memory for Node 3"), required=False)

    vm_hugepages_nr_2M_four = forms.CharField(
        label=_("# of Application 2M Hugepages Node 3"),
        required=False,
        widget=forms.TextInput(
            attrs={
                'class':
                'switched',
                'data-switch-on':
                'vm_hugepages_nr_percentage',
                'data-vm_hugepages_nr_percentage-percent':
                '% of Application 2M Hugepages Node 3',
                'data-vm_hugepages_nr_percentage-integer':
                '# of Application 2M Hugepages Node 3'
            }))

    vm_hugepages_nr_1G_four = forms.CharField(
        label=_("# of Application 1G Hugepages Node 3"),
        required=False,
        widget=forms.TextInput(
            attrs={
                'class':
                'switched',
                'data-switch-on':
                'vm_hugepages_nr_percentage',
                'data-vm_hugepages_nr_percentage-percent':
                '% of Application 1G Hugepages Node 3',
                'data-vm_hugepages_nr_percentage-integer':
                '# of Application 1G Hugepages Node 3'
            }))

    vswitch_hugepages_reqd_four = forms.CharField(
        label=_("# of vSwitch 1G Hugepages Node 3"), required=False)

    vswitch_hugepages_size_mib_four = forms.ChoiceField(
        label=_("vSwitch Hugepage Size Node 3"),
        required=False,
        choices=VSWITCH_HP_SIZE_CHOICES,
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'vswitch_hugepages_size_mib'
        }))

    failure_url = 'horizon:admin:inventory:detail'

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

        self.host = kwargs['initial']['host']
        self.vswitch_type = stx_api.sysinv.get_vswitch_type(request)
        LOG.debug("vswitch_type is %s", self.vswitch_type)

        memory_fieldsets = [{
            'platform_memory':
            self.fields['platform_memory'],
            'vm_hugepages_nr_2M':
            self.fields['vm_hugepages_nr_2M'],
            'vm_hugepages_nr_1G':
            self.fields['vm_hugepages_nr_1G'],
            'vswitch_hugepages_size_mib':
            self.fields['vswitch_hugepages_size_mib'],
            'vswitch_hugepages_reqd':
            self.fields['vswitch_hugepages_reqd'],
            'memtotal_mib':
            self.fields['memtotal_mib']
        }, {
            'platform_memory':
            self.fields['platform_memory_two'],
            'vm_hugepages_nr_2M':
            self.fields['vm_hugepages_nr_2M_two'],
            'vm_hugepages_nr_1G':
            self.fields['vm_hugepages_nr_1G_two'],
            'vswitch_hugepages_size_mib':
            self.fields['vswitch_hugepages_size_mib_two'],
            'vswitch_hugepages_reqd':
            self.fields['vswitch_hugepages_reqd_two'],
            'memtotal_mib':
            self.fields['memtotal_mib_two']
        }, {
            'platform_memory':
            self.fields['platform_memory_three'],
            'vm_hugepages_nr_2M':
            self.fields['vm_hugepages_nr_2M_three'],
            'vm_hugepages_nr_1G':
            self.fields['vm_hugepages_nr_1G_three'],
            'vswitch_hugepages_size_mib':
            self.fields['vswitch_hugepages_size_mib_three'],
            'vswitch_hugepages_reqd':
            self.fields['vswitch_hugepages_reqd_three'],
            'memtotal_mib':
            self.fields['memtotal_mib_three']
        }, {
            'platform_memory':
            self.fields['platform_memory_four'],
            'vm_hugepages_nr_2M':
            self.fields['vm_hugepages_nr_2M_four'],
            'vm_hugepages_nr_1G':
            self.fields['vm_hugepages_nr_1G_four'],
            'vswitch_hugepages_size_mib':
            self.fields['vswitch_hugepages_size_mib_four'],
            'vswitch_hugepages_reqd':
            self.fields['vswitch_hugepages_reqd_four'],
            'memtotal_mib':
            self.fields['memtotal_mib_four']
        }]

        count = 0
        for m in self.host.memorys:
            count = count + 1
            for n in self.host.nodes:
                if m.inode_uuid == n.uuid:
                    field_set = memory_fieldsets[int(n.numa_node)]
                    platform_field = field_set['platform_memory']
                    platform_field.help_text = \
                        'Minimum platform memory(MiB): ' + \
                        str(m.minimum_platform_reserved_mib)

                    platform_field.initial = str(m.platform_reserved_mib)

                    field_set['memtotal_mib'].initial = m.memtotal_mib

                    vm_hugepages_nr_percentage_field = \
                        self.fields['vm_hugepages_nr_percentage']

                    if (m.vm_pending_as_percentage == "True"):
                        vm_hugepages_nr_percentage_field.initial = "percent"
                    else:
                        vm_hugepages_nr_percentage_field.initial = "integer"

                    vm_2M_field = field_set['vm_hugepages_nr_2M']
                    vm_2M_field.help_text = \
                        'Maximum 2M pages: ' + \
                        str(m.vm_hugepages_possible_2M)

                    if m.vm_hugepages_nr_2M_pending or \
                            m.vm_hugepages_nr_2M_pending == 0:
                        vm_2M_field.initial = str(m.vm_hugepages_nr_2M_pending)
                    elif m.vm_hugepages_nr_2M:
                        if (m.vm_pending_as_percentage == "True"):
                            vm_2M_field.initial = str(
                                round(m.vm_hugepages_nr_2M * 100 /
                                      m.vm_hugepages_possible_2M))
                        else:
                            vm_2M_field.initial = str(m.vm_hugepages_nr_2M)
                    else:
                        vm_2M_field.initial = '0'

                    vm_1G_field = field_set['vm_hugepages_nr_1G']
                    vm_1g_supported = m.vm_hugepages_use_1G != 'False'
                    if vm_1g_supported:
                        help_msg = 'Maximum 1G pages: ' + \
                                   str(m.vm_hugepages_possible_1G)
                    else:
                        help_msg = 'This node does not support 1G hugepages'

                    vm_1G_field.help_text = help_msg

                    if m.vm_hugepages_nr_1G_pending or \
                            m.vm_hugepages_nr_1G_pending == 0:
                        vm_1G_field.initial = str(m.vm_hugepages_nr_1G_pending)
                    elif m.vm_hugepages_nr_1G:
                        if (m.vm_pending_as_percentage == "True"):
                            vm_1G_field.initial = \
                                str(int(m.vm_hugepages_nr_1G
                                    * 100 / m.vm_hugepages_possible_1G))
                        else:
                            vm_1G_field.initial = str(m.vm_hugepages_nr_1G)
                    elif vm_1g_supported:
                        vm_1G_field.initial = '0'
                    else:
                        vm_1G_field.initial = ''

                    if not vm_1g_supported:
                        vm_1G_field.widget.attrs['disabled'] = 'disabled'

                    vswitch_hp_reqd_field = field_set['vswitch_hugepages_reqd']
                    vswitch_hp_reqd_field.help_text = \
                        'Maximum vSwitch pages'

                    vswitch_hp_size_mib_field = \
                        field_set['vswitch_hugepages_size_mib']
                    vswitch_hp_size_mib_field.help_text = \
                        'vSwitch hugepage size'

                    if m.vswitch_hugepages_reqd:
                        vswitch_hp_reqd_field.initial = \
                            str(m.vswitch_hugepages_reqd)
                    elif m.vswitch_hugepages_nr:
                        vswitch_hp_reqd_field.initial = \
                            str(m.vswitch_hugepages_nr)

                    if m.vswitch_hugepages_size_mib:
                        vswitch_hp_size_mib_field.initial = \
                            str(m.vswitch_hugepages_size_mib)
                    if self.vswitch_type is None:
                        LOG.debug("vswitch_hp field is hidden")
                        vswitch_hp_size_mib_field.widget = \
                            forms.widgets.HiddenInput()
                        vswitch_hp_reqd_field.widget = \
                            forms.widgets.HiddenInput()
                    break

        while count < 4:
            field_set = memory_fieldsets[count]
            field_set['platform_memory'].widget = \
                forms.widgets.HiddenInput()
            field_set['vm_hugepages_nr_2M'].widget = \
                forms.widgets.HiddenInput()
            field_set['vm_hugepages_nr_1G'].widget = \
                forms.widgets.HiddenInput()
            field_set['vswitch_hugepages_reqd'].widget = \
                forms.widgets.HiddenInput()
            field_set['vswitch_hugepages_size_mib'].widget = \
                forms.widgets.HiddenInput()
            count += 1

    def clean(self):
        cleaned_data = super(UpdateMemory, self).clean()
        # host_id = cleaned_data.get('host_id')
        return cleaned_data

    def handle(self, request, data):

        host_id = data['host_id']
        del data['host_id']
        del data['host']

        node = []
        node.append('node0')

        if data['platform_memory_two'] or \
           data['vm_hugepages_nr_2M_two'] or \
           data['vm_hugepages_nr_1G_two'] or \
           data['vswitch_hugepages_size_mib_two'] or \
           data['vswitch_hugepages_reqd_two']:
            node.append('node1')

        if data['platform_memory_three'] or \
           data['vm_hugepages_nr_2M_three'] or \
           data['vm_hugepages_nr_1G_three'] or \
           data['vswitch_hugepages_size_mib_three'] or \
           data['vswitch_hugepages_reqd_three']:
            node.append('node2')

        if data['platform_memory_four'] or \
           data['vm_hugepages_nr_2M_four'] or \
           data['vm_hugepages_nr_1G_four'] or \
           data['vswitch_hugepages_size_mib_four'] or \
           data['vswitch_hugepages_reqd_four']:
            node.append('node3')

        # host = api.sysinv.host_get(request, host_id)
        pages_1G = {}
        pages_2M = {}
        plat_mem = {}
        pages_vs_size = {}
        pages_vs_reqd = {}

        # Node 0 arguments
        if not data['platform_memory']:
            del data['platform_memory']
        else:
            plat_mem['node0'] = data['platform_memory']

        if not data['vm_hugepages_nr_2M']:
            del data['vm_hugepages_nr_2M']
        else:
            pages_2M['node0'] = data['vm_hugepages_nr_2M']

        if not data['vm_hugepages_nr_1G']:
            del data['vm_hugepages_nr_1G']
        else:
            pages_1G['node0'] = data['vm_hugepages_nr_1G']

        if self.vswitch_type:
            if not data['vswitch_hugepages_size_mib']:
                del data['vswitch_hugepages_size_mib']
            else:
                pages_vs_size['node0'] = data['vswitch_hugepages_size_mib']

            if not data['vswitch_hugepages_reqd']:
                del data['vswitch_hugepages_reqd']
            else:
                pages_vs_reqd['node0'] = data['vswitch_hugepages_reqd']

        # Node 1 arguments
        if not data['platform_memory_two']:
            del data['platform_memory_two']
        else:
            plat_mem['node1'] = data['platform_memory_two']

        if not data['vm_hugepages_nr_2M_two']:
            del data['vm_hugepages_nr_2M_two']
        else:
            pages_2M['node1'] = data['vm_hugepages_nr_2M_two']

        if not data['vm_hugepages_nr_1G_two']:
            del data['vm_hugepages_nr_1G_two']
        else:
            pages_1G['node1'] = data['vm_hugepages_nr_1G_two']

        if self.vswitch_type:
            if not data['vswitch_hugepages_size_mib_two']:
                del data['vswitch_hugepages_size_mib_two']
            else:
                pages_vs_size['node1'] = data['vswitch_hugepages_size_mib_two']

            if not data['vswitch_hugepages_reqd_two']:
                del data['vswitch_hugepages_reqd_two']
            else:
                pages_vs_reqd['node1'] = data['vswitch_hugepages_reqd_two']

        # Node 2 arguments
        if not data['platform_memory_three']:
            del data['platform_memory_three']
        else:
            plat_mem['node2'] = data['platform_memory_three']

        if not data['vm_hugepages_nr_2M_three']:
            del data['vm_hugepages_nr_2M_three']
        else:
            pages_2M['node2'] = data['vm_hugepages_nr_2M_three']

        if not data['vm_hugepages_nr_1G_three']:
            del data['vm_hugepages_nr_1G_three']
        else:
            pages_1G['node2'] = data['vm_hugepages_nr_1G_three']

        if self.vswitch_type:
            if not data['vswitch_hugepages_size_mib_three']:
                del data['vswitch_hugepages_size_mib_three']
            else:
                pages_vs_size['node2'] = \
                    data['vswitch_hugepages_size_mib_three']

            if not data['vswitch_hugepages_reqd']:
                del data['vswitch_hugepages_reqd']
            else:
                pages_vs_reqd['node2'] = \
                    data['vswitch_hugepages_reqd_three']

        # Node 3 arguments
        if not data['platform_memory_four']:
            del data['platform_memory_four']
        else:
            plat_mem['node3'] = data['platform_memory_four']

        if not data['vm_hugepages_nr_2M_four']:
            del data['vm_hugepages_nr_2M_four']
        else:
            pages_2M['node3'] = data['vm_hugepages_nr_2M_four']

        if not data['vm_hugepages_nr_1G_four']:
            del data['vm_hugepages_nr_1G_four']
        else:
            pages_1G['node3'] = data['vm_hugepages_nr_1G_four']

        if self.vswitch_type:
            if not data['vswitch_hugepages_size_mib_four']:
                del data['vswitch_hugepages_size_mib_four']
            else:
                pages_vs_size['node3'] = \
                    data['vswitch_hugepages_size_mib_four']

            if not data['vswitch_hugepages_reqd_four']:
                del data['vswitch_hugepages_reqd_four']
            else:
                pages_vs_reqd['node3'] = data['vswitch_hugepages_reqd_four']

        try:
            for nd in node:
                node_found = False
                memory = None
                for m in self.host.memorys:
                    for n in self.host.nodes:
                        if m.inode_uuid == n.uuid:
                            if int(n.numa_node) == int(node.index(nd)):
                                memory = m
                                node_found = True
                            break
                    if node_found:
                        break

                if node_found:
                    new_data = {}
                    new_data["vm_pending_as_percentage"] = ("True" if str(
                        data["vm_hugepages_nr_percentage"]) == "percent" else
                                                            "False")
                    if nd in plat_mem:
                        new_data['platform_reserved_mib'] = plat_mem[nd]
                    if nd in pages_2M:
                        new_data['vm_hugepages_nr_2M_pending'] = pages_2M[nd]
                    if nd in pages_1G:
                        new_data['vm_hugepages_nr_1G_pending'] = pages_1G[nd]
                    if self.vswitch_type:
                        if nd in pages_vs_size:
                            new_data['vswitch_hugepages_size_mib'] = \
                                pages_vs_size[nd]
                        if nd in pages_vs_reqd:
                            new_data['vswitch_hugepages_reqd'] = \
                                pages_vs_reqd[nd]

                    if new_data:
                        stx_api.sysinv.host_memory_update(
                            request, memory.uuid, **new_data)

                else:
                    msg = _('Failed to find %s') % nd
                    messages.error(request, msg)
                    LOG.error(msg)
                    # Redirect to failure pg
                    redirect = reverse(self.failure_url, args=[host_id])
                    return shortcuts.redirect(redirect)

            msg = _('Memory allocation has been successfully ' 'updated.')
            LOG.debug(msg)
            messages.success(request, msg)
            return self.host.memorys
        except exc.ClientException as ce:
            # Allow REST API error message to appear on UI
            messages.error(request, ce)
            LOG.error(ce)

            # Redirect to failure pg
            redirect = reverse(self.failure_url, args=[host_id])
            return shortcuts.redirect(redirect)

        except Exception:
            msg = _('Failed to update memory allocation')
            LOG.info(msg)
            redirect = reverse(self.failure_url, args=[host_id])
            exceptions.handle(request, msg, redirect=redirect)
Exemplo n.º 7
0
class AddResourceForm(forms.SelfHandlingForm):
    label = forms.CharField(label=_("Label"), max_length=255, required=True)
    rackid = forms.CharField(label=_("Rack ID"), widget=forms.HiddenInput())
    rack_label = forms.CharField(label=_("Rack"),
                                 max_length=255,
                                 required=True)
    eiaLocation = forms.CharField(label=_("EIA Location"),
                                  max_length=3,
                                  required=False)
    ip_address = forms.CharField(
        label=_("Host Name or IP Address"),
        max_length=255,
        required=True,
        help_text=_("Specify the fully qualified host name or IP V4 address "
                    "used by Operational Management to access the "
                    " resource."))
    auth_method = forms.ChoiceField(
        label=_('Authentication Method'),
        choices=[(AUTH_METHOD_USER_PWD, _('User ID and Password')),
                 (AUTH_METHOD_USER_KEY, _('User ID and SSH Key'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'auth'
        }),
        help_text=_("Indicates the type of credential information "
                    "used by Operational Management to access the resource."))
    userID = forms.CharField(label=_("User ID"), max_length=255, required=True)
    password = forms.CharField(label=_("password"),
                               required=True,
                               widget=forms.PasswordInput(attrs={
                                   'class':
                                   'switched',
                                   'data-switch-on':
                                   'auth',
                                   'data-auth-0':
                                   _("Password")
                               },
                                                          render_value=False))
    sshKey = forms.CharField(widget=forms.widgets.Textarea(
        attrs={
            'class': 'switched',
            'data-switch-on': 'auth',
            'data-auth-1': _("SSH Key"),
            'rows': 4
        }),
                             required=True,
                             help_text=_(
                                 "Paste the private SSH key for the specified"
                                 " resource."))
    passphrase = forms.CharField(label=_("passphrase"),
                                 required=False,
                                 widget=forms.PasswordInput(
                                     attrs={
                                         'class': 'switched',
                                         'data-switch-on': 'auth',
                                         'data-auth-1': _("Passphrase")
                                     },
                                     render_value=False))

    def __init__(self, request, *args, **kwargs):
        super(AddResourceForm, self).__init__(request, *args, **kwargs)
        # User should only be allowed to add to the rack being displayed
        self.fields["rack_label"].widget = forms.TextInput(
            attrs={'readonly': 'readonly'})

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

    def _clean_auth_ids(self, data):
        auth_method = data.get('auth_method')

        # if User ID + SSH Key was chosen, we can ignore any 'password' errors
        if (auth_method == AUTH_METHOD_USER_KEY) and ('password'
                                                      in self._errors):
            del self._errors['password']
        # if User ID + Password was chosen, we can ignore any 'sshKey' errors
        if (auth_method == AUTH_METHOD_USER_PWD) and ('sshKey'
                                                      in self._errors):
            del self._errors['sshKey']

    def handle(self, request, data):
        __method__ = 'forms.AddResourceForm.handle'
        try:
            # Need to ensure we pass along the correct password (either
            # password or phassphrase), and that we don't accidently pass
            # the SSH key
            password_value = None
            if data['auth_method'] != AUTH_METHOD_USER_KEY:
                data['sshKey'] = None
                if 'password' in data:
                    password_value = data['password']
            else:
                if 'passphrase' in data:
                    password_value = data['passphrase']

            logging.debug(
                "%s: Attempting to add a resource to rack: %s, using"
                " label: %s, address: %s, user id: %s, eia location"
                " %s, and authentication method: %s", __method__,
                self.initial['rackid'], data['label'], data['ip_address'],
                data['userID'], data['eiaLocation'], data['auth_method'])

            # pass in "None" for resource type in add_resource -- so that the
            # API will determine type for us
            (rc, result_dict) = resource_mgr.add_resource(
                data['label'], None, data['ip_address'],
                data['userID'].strip(), password_value, self.initial['rackid'],
                data['eiaLocation'], data['sshKey'])

            if rc is not 0:
                # Log details of the unsuccessful attempt.
                logging.error(
                    "%s: Attempt to add a resource to rack: %s, "
                    "using label: %s, address: %s, user id: %s, "
                    "eia location %s, and authentication method:"
                    " %s failed.", __method__, self.initial['rackid'],
                    data['label'], data['ip_address'], data['userID'],
                    data['eiaLocation'], data['auth_method'])

                logging.error(
                    "%s: Unable to add resource %s to rack %s. A Non-0 "
                    " return code returned from resource_mgr.add_resource."
                    " The return code is: %s. Details of the attempt: "
                    " %s", __method__, data['label'], self.initial['rackid'],
                    rc, result_dict)
                msg = str('Attempt to add resource ' + data['label'] +
                          ' was ' +
                          'not successful. Details of the attempt: ' +
                          result_dict)
                messages.error(request, msg)
                # Return false in this case so that the dialog is not
                # dismissed.  This gives the end-user a chance to
                # update the dialog w/o having to re-enter all the
                # information a second time.
                return False
            else:
                msg = str('Resource ' + data['label'] + ' successfully' +
                          ' added.')
                messages.success(request, msg)
                return True
        except Exception as e:
            logging.error(
                "%s: Exception received trying to add a resource.  "
                "Exception is: %s", __method__, e)
            exceptions.handle(request, _('Unable to add resource.'))
            # In this case, return True so that the dialog closes.
            # In theory, there are no values the end-user could change
            # to the dialog inputs that would allow us to proceed.
            return True
Exemplo n.º 8
0
class CreateForm(forms.SelfHandlingForm):
    name = forms.CharField(max_length=255,
                           label=_("Volume Name"),
                           required=False)
    description = forms.CharField(max_length=255,
                                  widget=forms.Textarea(attrs={
                                      'class': 'modal-body-fixed-width',
                                      'rows': 4
                                  }),
                                  label=_("Description"),
                                  required=False)
    volume_source_type = forms.ChoiceField(
        label=_("Volume Source"),
        required=False,
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'source'
        }))
    snapshot_source = forms.ChoiceField(
        label=_("Use snapshot as a source"),
        widget=forms.SelectWidget(attrs={'class': 'snapshot-selector'},
                                  data_attrs=('size', 'name'),
                                  transform=lambda x: "%s (%sGB)" %
                                  (x.name, x.size)),
        required=False)
    image_source = forms.ChoiceField(
        label=_("Use image as a source"),
        widget=forms.SelectWidget(attrs={'class': 'image-selector'},
                                  data_attrs=('size', 'name', 'min_disk'),
                                  transform=lambda x: "%s (%s)" %
                                  (x.name, filesizeformat(x.bytes))),
        required=False)
    volume_source = forms.ChoiceField(
        label=_("Use a volume as source"),
        widget=forms.SelectWidget(
            attrs={'class': 'image-selector'},
            data_attrs=('size', 'name'),
            transform=lambda x: "%s (%s)" %
            (x.name, filesizeformat(x.size * 1024 * 1024 * 1024))),
        required=False)
    type = forms.ChoiceField(label=_("Type"),
                             required=False,
                             widget=forms.Select(
                                 attrs={
                                     'class': 'switched',
                                     'data-switch-on': 'source',
                                     'data-source-no_source_type': _('Type'),
                                     'data-source-image_source': _('Type')
                                 }))
    size = forms.IntegerField(min_value=1, initial=1, label=_("Size (GB)"))
    availability_zone = forms.ChoiceField(
        label=_("Availability Zone"),
        required=False,
        widget=forms.Select(
            attrs={
                'class': 'switched',
                'data-switch-on': 'source',
                'data-source-no_source_type': _('Availability Zone'),
                'data-source-image_source': _('Availability Zone')
            }))

    def prepare_source_fields_if_snapshot_specified(self, request):
        try:
            snapshot = self.get_snapshot(request, request.GET["snapshot_id"])
            self.fields['name'].initial = snapshot.name
            self.fields['size'].initial = snapshot.size
            self.fields['snapshot_source'].choices = ((snapshot.id,
                                                       snapshot), )
            try:
                # Set the volume type from the original volume
                orig_volume = cinder.volume_get(request, snapshot.volume_id)
                self.fields['type'].initial = orig_volume.volume_type
            except Exception:
                pass
            self.fields['size'].help_text = (
                _('Volume size must be equal to or greater than the '
                  'snapshot size (%sGB)') % snapshot.size)
            del self.fields['image_source']
            del self.fields['volume_source']
            del self.fields['volume_source_type']
            del self.fields['availability_zone']
        except Exception:
            exceptions.handle(request,
                              _('Unable to load the specified snapshot.'))

    def prepare_source_fields_if_image_specified(self, request):
        self.fields['availability_zone'].choices = \
            availability_zones(request)
        try:
            image = self.get_image(request, request.GET["image_id"])
            image.bytes = image.size
            self.fields['name'].initial = image.name
            min_vol_size = functions.bytes_to_gigabytes(image.size)
            size_help_text = (_('Volume size must be equal to or greater '
                                'than the image size (%s)') %
                              filesizeformat(image.size))
            properties = getattr(image, 'properties', {})
            min_disk_size = (getattr(image, 'min_disk', 0)
                             or properties.get('min_disk', 0))
            if (min_disk_size > min_vol_size):
                min_vol_size = min_disk_size
                size_help_text = (_('Volume size must be equal to or '
                                    'greater than the image minimum '
                                    'disk size (%sGB)') % min_disk_size)
            self.fields['size'].initial = min_vol_size
            self.fields['size'].help_text = size_help_text
            self.fields['image_source'].choices = ((image.id, image), )
            del self.fields['snapshot_source']
            del self.fields['volume_source']
            del self.fields['volume_source_type']
        except Exception:
            msg = _('Unable to load the specified image. %s')
            exceptions.handle(request, msg % request.GET['image_id'])

    def prepare_source_fields_if_volume_specified(self, request):
        self.fields['availability_zone'].choices = \
            availability_zones(request)
        volume = None
        try:
            volume = self.get_volume(request, request.GET["volume_id"])
        except Exception:
            msg = _('Unable to load the specified volume. %s')
            exceptions.handle(request, msg % request.GET['volume_id'])

        if volume is not None:
            self.fields['name'].initial = volume.name
            self.fields['description'].initial = volume.description
            min_vol_size = volume.size
            size_help_text = (_('Volume size must be equal to or greater '
                                'than the origin volume size (%s)') %
                              filesizeformat(volume.size))
            self.fields['size'].initial = min_vol_size
            self.fields['size'].help_text = size_help_text
            self.fields['volume_source'].choices = ((volume.id, volume), )
            self.fields['type'].initial = volume.type
            del self.fields['snapshot_source']
            del self.fields['image_source']
            del self.fields['volume_source_type']

    def prepare_source_fields_default(self, request):
        source_type_choices = []
        self.fields['availability_zone'].choices = \
            availability_zones(request)

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

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

        volumes = self.get_volumes(request)
        if volumes:
            source_type_choices.append(("volume_source", _("Volume")))
            choices = [('', _("Choose a volume"))]
            for volume in volumes:
                choices.append((volume.id, volume))
            self.fields['volume_source'].choices = choices
        else:
            del self.fields['volume_source']

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

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

        if "snapshot_id" in request.GET:
            self.prepare_source_fields_if_snapshot_specified(request)
        elif 'image_id' in request.GET:
            self.prepare_source_fields_if_image_specified(request)
        elif 'volume_id' in request.GET:
            self.prepare_source_fields_if_volume_specified(request)
        else:
            self.prepare_source_fields_default(request)

    def clean(self):
        cleaned_data = super(CreateForm, self).clean()
        source_type = self.cleaned_data.get('volume_source_type')
        if (source_type == 'image_source'
                and not cleaned_data.get('image_source')):
            msg = _('Image source must be specified')
            self._errors['image_source'] = self.error_class([msg])
        elif (source_type == 'snapshot_source'
              and not cleaned_data.get('snapshot_source')):
            msg = _('Snapshot source must be specified')
            self._errors['snapshot_source'] = self.error_class([msg])
        elif (source_type == 'volume_source'
              and not cleaned_data.get('volume_source')):
            msg = _('Volume source must be specified')
            self._errors['volume_source'] = self.error_class([msg])
        return cleaned_data

    def get_volumes(self, request):
        volumes = []
        try:
            available = api.cinder.VOLUME_STATE_AVAILABLE
            volumes = cinder.volume_list(self.request,
                                         search_opts=dict(status=available))
        except Exception:
            exceptions.handle(request,
                              _('Unable to retrieve list of volumes.'))
        return volumes

    def handle(self, request, data):
        try:
            usages = quotas.tenant_limit_usages(self.request)
            availableGB = usages['maxTotalVolumeGigabytes'] - \
                usages['gigabytesUsed']
            availableVol = usages['maxTotalVolumes'] - usages['volumesUsed']

            snapshot_id = None
            image_id = None
            volume_id = None
            source_type = data.get('volume_source_type', None)
            az = data.get('availability_zone', None) or None
            if (data.get("snapshot_source", None)
                    and source_type in [None, 'snapshot_source']):
                # Create from Snapshot
                snapshot = self.get_snapshot(request, data["snapshot_source"])
                snapshot_id = snapshot.id
                if (data['size'] < snapshot.size):
                    error_message = (_('The volume size cannot be less than '
                                       'the snapshot size (%sGB)') %
                                     snapshot.size)
                    raise ValidationError(error_message)
                az = None
            elif (data.get("image_source", None)
                  and source_type in [None, 'image_source']):
                # Create from Snapshot
                image = self.get_image(request, data["image_source"])
                image_id = image.id
                image_size = functions.bytes_to_gigabytes(image.size)
                if (data['size'] < image_size):
                    error_message = (_('The volume size cannot be less than '
                                       'the image size (%s)') %
                                     filesizeformat(image.size))
                    raise ValidationError(error_message)
                properties = getattr(image, 'properties', {})
                min_disk_size = (getattr(image, 'min_disk', 0)
                                 or properties.get('min_disk', 0))
                if (min_disk_size > 0 and data['size'] < min_disk_size):
                    error_message = (_('The volume size cannot be less than '
                                       'the image minimum disk size (%sGB)') %
                                     min_disk_size)
                    raise ValidationError(error_message)
            elif (data.get("volume_source", None)
                  and source_type in [None, 'volume_source']):
                # Create from volume
                volume = self.get_volume(request, data["volume_source"])
                volume_id = volume.id

                if data['size'] < volume.size:
                    error_message = (_('The volume size cannot be less than '
                                       'the source volume size (%sGB)') %
                                     volume.size)
                    raise ValidationError(error_message)
            else:
                if type(data['size']) is str:
                    data['size'] = int(data['size'])

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

            metadata = {}

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

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

    @memoized
    def get_image(self, request, id):
        return glance.image_get(request, id)

    @memoized
    def get_volume(self, request, id):
        return cinder.volume_get(request, id)
Exemplo n.º 9
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)
    copy_from = forms.CharField(max_length="255",
                                label=_("Image Location"),
                                help_text=_("An external (HTTP) URL to load "
                                            "the image from."),
                                required=False)
    image_file = forms.FileField(label=_("Image File"),
                                 help_text=("A local image to upload."),
                                 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.'))
Exemplo n.º 10
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)
Exemplo n.º 11
0
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"),
                                   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

    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:
            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']
        elif data['is_copying']:
            meta['copy_from'] = data['image_url']
        else:
            meta['location'] = data['image_url']

        if data['geoTag']:
            geoTag = json.loads(data['geoTag'])
            if geoTag.has_key('trust'):
                meta['properties']['trust'] = geoTag['trust']
            if geoTag.has_key('tags'):
                meta['properties']['tags'] = simplejson.dumps(geoTag['tags'])

        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
Exemplo n.º 12
0
    def __init__(self, request, *args, **kwargs):
        super(CreateForm, self).__init__(request, *args, **kwargs)
        # NOTE(vkmc): choose only those share protocols that are enabled
        # FIXME(vkmc): this should be better implemented by having a
        # capabilities endpoint on the control plane.
        manila_features = getattr(settings, 'OPENSTACK_MANILA_FEATURES', {})
        self.enabled_share_protocols = manila_features.get(
            'enabled_share_protocols',
            ['NFS', 'CIFS', 'GlusterFS', 'HDFS', 'CephFS', 'MapRFS'])
        self.enable_public_shares = manila_features.get(
            'enable_public_shares', True)
        share_networks = manila.share_network_list(request)
        share_types = manila.share_type_list(request)
        self.fields['share_type'].choices = ([("", "")] +
                                             [(st.name, st.name)
                                              for st in share_types])

        availability_zones = manila.availability_zone_list(request)
        self.fields['availability_zone'].choices = (
            [("", "")] + [(az.name, az.name) for az in availability_zones])

        self.sn_field_name_prefix = 'share-network-choices-'
        for st in share_types:
            extra_specs = st.get_keys()
            dhss = extra_specs.get('driver_handles_share_servers')
            # NOTE(vponomaryov): Set and tie share-network field only for
            # share types with enabled handling of share servers.
            if (isinstance(dhss, six.string_types)
                    and dhss.lower() in ['true', '1']):
                sn_choices = ([('', '')] + [(sn.id, sn.name or sn.id)
                                            for sn in share_networks])
                sn_field_name = self.sn_field_name_prefix + st.name
                sn_field = forms.ChoiceField(
                    label=_("Share Network"),
                    required=True,
                    choices=sn_choices,
                    widget=forms.Select(
                        attrs={
                            'class': 'switched',
                            'data-switch-on': 'sharetype',
                            'data-sharetype-%s' % st.name: _("Share Network"),
                        }))
                self.fields[sn_field_name] = sn_field

        self.fields['share_source_type'] = forms.ChoiceField(
            label=_("Share Source"),
            required=False,
            widget=forms.Select(attrs={
                'class': 'switchable',
                'data-slug': 'source'
            }))
        self.fields['snapshot'] = forms.ChoiceField(
            label=_("Use snapshot as a source"),
            widget=forms.fields.SelectWidget(attrs={
                'class':
                'switched',
                'data-switch-on':
                'source',
                'data-source-snapshot':
                _('Snapshot')
            },
                                             data_attrs=('size', 'name'),
                                             transform=lambda x: "%s (%sGiB)" %
                                             (x.name, x.size)),
            required=False)
        self.fields['metadata'] = forms.CharField(
            label=_("Metadata"),
            required=False,
            widget=forms.Textarea(attrs={'rows': 4}))

        if self.enable_public_shares:
            self.fields['is_public'] = forms.BooleanField(
                label=_("Make visible for all"),
                required=False,
                help_text=(
                    "If set then all tenants will be able to see this share."))

        self.fields['share_proto'].choices = [
            (sp, sp) for sp in self.enabled_share_protocols
        ]
        if ("snapshot_id" in request.GET
                or kwargs.get("data", {}).get("snapshot")):
            try:
                snapshot = self.get_snapshot(
                    request,
                    request.GET.get("snapshot_id",
                                    kwargs.get("data", {}).get("snapshot")))
                self.fields['name'].initial = snapshot.name
                self.fields['size'].initial = snapshot.size
                self.fields['snapshot'].choices = ((snapshot.id, snapshot), )
                try:
                    # Set the share type from the original share
                    orig_share = manila.share_get(request, snapshot.share_id)
                    # NOTE(vponomaryov): we should use share type name, not ID,
                    # because we use names in our choices above.
                    self.fields['share_type'].initial = (
                        orig_share.share_type_name)
                except Exception:
                    pass
                self.fields['size'].help_text = _(
                    'Share size must be equal to or greater than the snapshot '
                    'size (%sGiB)') % snapshot.size
                del self.fields['share_source_type']
            except Exception:
                exceptions.handle(request,
                                  _('Unable to load the specified snapshot.'))
        else:
            source_type_choices = []

            try:
                snapshot_list = manila.share_snapshot_list(request)
                snapshots = [
                    s for s in snapshot_list if s.status == 'available'
                ]
                if snapshots:
                    source_type_choices.append(("snapshot", _("Snapshot")))
                    choices = [('', _("Choose a snapshot"))] + \
                              [(s.id, s) for s in snapshots]
                    self.fields['snapshot'].choices = choices
                else:
                    del self.fields['snapshot']
            except Exception:
                exceptions.handle(request,
                                  _("Unable to retrieve "
                                    "share snapshots."))

            if source_type_choices:
                choices = ([('no_source_type', _("No source, empty share"))] +
                           source_type_choices)
                self.fields['share_source_type'].choices = choices
            else:
                del self.fields['share_source_type']
Exemplo n.º 13
0
class CreateForm(forms.SelfHandlingForm):
    name = forms.CharField(max_length="255", label=_("Share Name"))
    description = forms.CharField(label=_("Description"),
                                  required=False,
                                  widget=forms.Textarea(attrs={'rows': 3}))
    share_proto = forms.ChoiceField(label=_("Share Protocol"), required=True)
    size = forms.IntegerField(min_value=1, label=_("Size (GiB)"))
    share_type = forms.ChoiceField(
        label=_("Share Type"),
        required=True,
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'sharetype'
        }))
    availability_zone = forms.ChoiceField(label=_("Availability Zone"),
                                          required=False)

    def __init__(self, request, *args, **kwargs):
        super(CreateForm, self).__init__(request, *args, **kwargs)
        # NOTE(vkmc): choose only those share protocols that are enabled
        # FIXME(vkmc): this should be better implemented by having a
        # capabilities endpoint on the control plane.
        manila_features = getattr(settings, 'OPENSTACK_MANILA_FEATURES', {})
        self.enabled_share_protocols = manila_features.get(
            'enabled_share_protocols',
            ['NFS', 'CIFS', 'GlusterFS', 'HDFS', 'CephFS', 'MapRFS'])
        self.enable_public_shares = manila_features.get(
            'enable_public_shares', True)
        share_networks = manila.share_network_list(request)
        share_types = manila.share_type_list(request)
        self.fields['share_type'].choices = ([("", "")] +
                                             [(st.name, st.name)
                                              for st in share_types])

        availability_zones = manila.availability_zone_list(request)
        self.fields['availability_zone'].choices = (
            [("", "")] + [(az.name, az.name) for az in availability_zones])

        self.sn_field_name_prefix = 'share-network-choices-'
        for st in share_types:
            extra_specs = st.get_keys()
            dhss = extra_specs.get('driver_handles_share_servers')
            # NOTE(vponomaryov): Set and tie share-network field only for
            # share types with enabled handling of share servers.
            if (isinstance(dhss, six.string_types)
                    and dhss.lower() in ['true', '1']):
                sn_choices = ([('', '')] + [(sn.id, sn.name or sn.id)
                                            for sn in share_networks])
                sn_field_name = self.sn_field_name_prefix + st.name
                sn_field = forms.ChoiceField(
                    label=_("Share Network"),
                    required=True,
                    choices=sn_choices,
                    widget=forms.Select(
                        attrs={
                            'class': 'switched',
                            'data-switch-on': 'sharetype',
                            'data-sharetype-%s' % st.name: _("Share Network"),
                        }))
                self.fields[sn_field_name] = sn_field

        self.fields['share_source_type'] = forms.ChoiceField(
            label=_("Share Source"),
            required=False,
            widget=forms.Select(attrs={
                'class': 'switchable',
                'data-slug': 'source'
            }))
        self.fields['snapshot'] = forms.ChoiceField(
            label=_("Use snapshot as a source"),
            widget=forms.fields.SelectWidget(attrs={
                'class':
                'switched',
                'data-switch-on':
                'source',
                'data-source-snapshot':
                _('Snapshot')
            },
                                             data_attrs=('size', 'name'),
                                             transform=lambda x: "%s (%sGiB)" %
                                             (x.name, x.size)),
            required=False)
        self.fields['metadata'] = forms.CharField(
            label=_("Metadata"),
            required=False,
            widget=forms.Textarea(attrs={'rows': 4}))

        if self.enable_public_shares:
            self.fields['is_public'] = forms.BooleanField(
                label=_("Make visible for all"),
                required=False,
                help_text=(
                    "If set then all tenants will be able to see this share."))

        self.fields['share_proto'].choices = [
            (sp, sp) for sp in self.enabled_share_protocols
        ]
        if ("snapshot_id" in request.GET
                or kwargs.get("data", {}).get("snapshot")):
            try:
                snapshot = self.get_snapshot(
                    request,
                    request.GET.get("snapshot_id",
                                    kwargs.get("data", {}).get("snapshot")))
                self.fields['name'].initial = snapshot.name
                self.fields['size'].initial = snapshot.size
                self.fields['snapshot'].choices = ((snapshot.id, snapshot), )
                try:
                    # Set the share type from the original share
                    orig_share = manila.share_get(request, snapshot.share_id)
                    # NOTE(vponomaryov): we should use share type name, not ID,
                    # because we use names in our choices above.
                    self.fields['share_type'].initial = (
                        orig_share.share_type_name)
                except Exception:
                    pass
                self.fields['size'].help_text = _(
                    'Share size must be equal to or greater than the snapshot '
                    'size (%sGiB)') % snapshot.size
                del self.fields['share_source_type']
            except Exception:
                exceptions.handle(request,
                                  _('Unable to load the specified snapshot.'))
        else:
            source_type_choices = []

            try:
                snapshot_list = manila.share_snapshot_list(request)
                snapshots = [
                    s for s in snapshot_list if s.status == 'available'
                ]
                if snapshots:
                    source_type_choices.append(("snapshot", _("Snapshot")))
                    choices = [('', _("Choose a snapshot"))] + \
                              [(s.id, s) for s in snapshots]
                    self.fields['snapshot'].choices = choices
                else:
                    del self.fields['snapshot']
            except Exception:
                exceptions.handle(request,
                                  _("Unable to retrieve "
                                    "share snapshots."))

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

    def clean(self):
        cleaned_data = super(CreateForm, self).clean()
        errors = [k for k in self.errors.viewkeys()]

        # NOTE(vponomaryov): skip errors for share-network fields that are not
        # related to chosen share type.
        for k in errors:
            st_name = k.split(self.sn_field_name_prefix)[-1]
            chosen_st = cleaned_data.get('share_type')
            if (k.startswith(self.sn_field_name_prefix)
                    and st_name != chosen_st):
                cleaned_data[k] = 'Not set'
                self.errors.pop(k, None)

        share_type = cleaned_data.get('share_type')
        if share_type:
            cleaned_data['share_network'] = cleaned_data.get(
                self.sn_field_name_prefix + share_type)

        return cleaned_data

    def handle(self, request, data):
        try:
            snapshot_id = None
            source_type = data.get('share_source_type', None)
            share_network = data.get('share_network', None)
            if (data.get("snapshot", None)
                    and source_type in [None, 'snapshot']):
                # Create from Snapshot
                snapshot = self.get_snapshot(request, data["snapshot"])
                snapshot_id = snapshot.id
                if (data['size'] < snapshot.size):
                    error_message = _('The share size cannot be less than the '
                                      'snapshot size (%sGiB)') % snapshot.size
                    raise ValidationError(error_message)
            else:
                data['size'] = int(data['size'])

            metadata = {}
            try:
                set_dict, unset_list = utils.parse_str_meta(data['metadata'])
                if unset_list:
                    msg = _("Expected only pairs of key=value.")
                    raise ValidationError(message=msg)
                metadata = set_dict
            except ValidationError as e:
                self.api_error(e.messages[0])
                return False
            is_public = self.enable_public_shares and data['is_public']
            share = manila.share_create(
                request,
                size=data['size'],
                name=data['name'],
                description=data['description'],
                proto=data['share_proto'],
                share_network=share_network,
                snapshot_id=snapshot_id,
                share_type=data['share_type'],
                is_public=is_public,
                metadata=metadata,
                availability_zone=data['availability_zone'])
            message = _('Creating share "%s"') % data['name']
            messages.success(request, message)
            return share
        except ValidationError as e:
            self.api_error(e.messages[0])
            return False
        except Exception:
            exceptions.handle(request, ignore=True)
            self.api_error(_("Unable to create share."))
            return False

    @memoized
    def get_snapshot(self, request, id):
        return manila.share_snapshot_get(request, id)
Exemplo n.º 14
0
class CreateImageForm(forms.SelfHandlingForm):
    name = forms.CharField(max_length=255, label=_("Name"))
    description = forms.CharField(max_length=255,
                                  widget=forms.Textarea(attrs={'rows': 4}),
                                  label=_("Description"),
                                  required=False)
    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"),
        help_text=_('CPU architecture of the image.'),
        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"),
        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(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)

        # 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.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
Exemplo n.º 15
0
class UpdateHostInfoAction(workflows.Action):
    host_id = forms.CharField(widget=forms.widgets.HiddenInput)

    personality = forms.ChoiceField(
        label=_("Personality"),
        choices=PERSONALITY_CHOICES,
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'personality'
        }))

    subfunctions = forms.ChoiceField(
        label=FIELD_LABEL_PERFORMANCE_PROFILE,
        choices=PERFORMANCE_CHOICES,
        widget=forms.Select(
            attrs={
                'class':
                'switched',
                'data-switch-on':
                'personality',
                'data-personality-' + stx_api.sysinv.PERSONALITY_COMPUTE:
                _("Performance Profile")
            }))

    hostname = forms.RegexField(
        label=_("Host Name"),
        max_length=255,
        required=False,
        regex=r'^[\w\.\-]+$',
        error_messages={
            'invalid':
            _('Name may only contain letters,'
              ' numbers, underscores, '
              'periods and hyphens.')
        },
        widget=forms.TextInput(
            attrs={
                'class':
                'switched',
                'data-switch-on':
                'personality',
                'data-personality-' + stx_api.sysinv.PERSONALITY_COMPUTE:
                _("Host Name")
            }))

    location = forms.CharField(label=_("Location"),
                               initial='location',
                               required=False,
                               help_text=_("Physical location of Host."))

    cpuProfile = forms.ChoiceField(label=_("CPU Profile"), required=False)

    interfaceProfile = forms.ChoiceField(label=_("Interface Profile"),
                                         required=False)

    diskProfile = forms.ChoiceField(label=_("Storage Profile"), required=False)

    memoryProfile = forms.ChoiceField(label=_("Memory Profile"),
                                      required=False)

    ttys_dcd = forms.BooleanField(
        label=_("Serial Console Data Carrier Detect"),
        required=False,
        help_text=_("Enable serial line data carrier detection. "
                    "When selected, dropping carrier detect on the serial "
                    "port revoke any active session and a new login "
                    "process is initiated when a new connection is detected."))

    class Meta(object):
        name = _("Host Info")
        help_text = _(
            "From here you can update the configuration of the current host.\n"
            "Note: this will not affect the resources allocated to any"
            " existing"
            " instances using this host until the host is rebooted.")

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

        # pesonality cannot be storage if ceph is not configured
        cinder_backend = stx_api.sysinv.get_cinder_backend(request)
        if stx_api.sysinv.CINDER_BACKEND_CEPH not in cinder_backend:
            self.fields['personality'].choices = \
                PERSONALITY_CHOICES_WITHOUT_STORAGE

        # All-in-one system, personality can only be controller.
        systems = stx_api.sysinv.system_list(request)
        self.system_mode = systems[0].to_dict().get('system_mode')
        self.system_type = systems[0].to_dict().get('system_type')
        if self.system_type == constants.TS_AIO:
            self.fields['personality'].choices = \
                PERSONALITY_CHOICE_CONTROLLER
            self.fields['personality'].widget.attrs['disabled'] = 'disabled'

        # Remove compute personality if in DC mode and region
        if getattr(self.request.user, 'services_region', None) == 'RegionOne' \
                and getattr(settings, 'DC_MODE', False):
            self.fields['personality'].choices = \
                [choice for choice in self.fields['personality'].choices
                 if choice[0] != stx_api.sysinv.PERSONALITY_COMPUTE]

        # hostname cannot be modified once it is set
        if self.initial['hostname']:
            self.fields['hostname'].widget.attrs['readonly'] = 'readonly'
            self.fields['hostname'].required = False

        # subfunctions cannot be modified once it is set
        if self.initial['subfunctions']:
            self.fields['subfunctions'].widget.attrs['disabled'] = 'disabled'
            self.fields['subfunctions'].required = False

        # personality cannot be modified once it is set
        host_id = self.initial['host_id']
        personality = self.initial['personality']

        mem_profile_configurable = False

        if personality and self.system_mode != constants.SYSTEM_MODE_SIMPLEX:
            self.fields['personality'].widget.attrs['disabled'] = 'disabled'
            self.fields['personality'].required = False
            self._personality = personality

            host = stx_api.sysinv.host_get(self.request, host_id)
            host.nodes = stx_api.sysinv.host_node_list(self.request, host.uuid)
            host.cpus = stx_api.sysinv.host_cpu_list(self.request, host.uuid)
            host.ports = stx_api.sysinv.host_port_list(self.request, host.uuid)
            host.disks = stx_api.sysinv.host_disk_list(self.request, host.uuid)

            if 'compute' in host.subfunctions:
                mem_profile_configurable = True
                host.memory = stx_api.sysinv.host_memory_list(
                    self.request, host.uuid)
            else:
                del self.fields['memoryProfile']

            if host.nodes and host.cpus and host.ports:
                # Populate Available Cpu Profile Choices
                try:
                    avail_cpu_profile_list = stx_api.sysinv.host_cpuprofile_list(
                        self.request)

                    host_profile = icpu_utils.HostCpuProfile(
                        host.subfunctions, host.cpus, host.nodes)

                    cpu_profile_tuple_list = [
                        ('', _("Copy from an available cpu profile."))
                    ]
                    for ip in avail_cpu_profile_list:
                        nodes = stx_api.sysinv.host_node_list(
                            self.request, ip.uuid)
                        cpu_profile = icpu_utils.CpuProfile(ip.cpus, nodes)
                        if host_profile.profile_applicable(cpu_profile):
                            cpu_profile_tuple_list.append(
                                (ip.profilename, ip.profilename))

                except Exception:
                    exceptions.handle(
                        self.request,
                        _('Unable to retrieve list of cpu profiles.'))
                    cpu_profile_tuple_list = []

                self.fields['cpuProfile'].choices = cpu_profile_tuple_list

                # Populate Available Interface Profile Choices
                try:
                    avail_interface_profile_list = \
                        stx_api.sysinv.host_interfaceprofile_list(self.request)

                    interface_profile_tuple_list = [
                        ('', _("Copy from an available interface profile."))
                    ]
                    for ip in avail_interface_profile_list:
                        if ifprofile_applicable(request, host, ip):
                            interface_profile_tuple_list.append(
                                (ip.profilename, ip.profilename))

                except Exception:
                    exceptions.handle(
                        self.request,
                        _('Unable to retrieve list of interface profiles.'))
                    interface_profile_tuple_list = []

                self.fields[
                    'interfaceProfile'].choices = interface_profile_tuple_list
            else:
                self.fields['cpuProfile'].widget = forms.widgets.HiddenInput()
                self.fields[
                    'interfaceProfile'].widget = forms.widgets.HiddenInput()

            if ((personality == 'storage' or 'compute' in host._subfunctions)
                    and host.disks):
                # Populate Available Disk Profile Choices
                try:
                    disk_profile_tuple_list = [
                        ('', _("Copy from an available storage profile."))
                    ]
                    avail_disk_profile_list = \
                        stx_api.sysinv.host_diskprofile_list(self.request)
                    for dp in avail_disk_profile_list:
                        if diskprofile_applicable(host, dp):
                            disk_profile_tuple_list.append(
                                (dp.profilename, dp.profilename))

                except Exception as e:
                    LOG.exception(e)
                    exceptions.handle(
                        self.request,
                        _('Unable to retrieve list of storage profiles.'))
                    disk_profile_tuple_list = []

                self.fields['diskProfile'].choices = disk_profile_tuple_list
            else:
                self.fields['diskProfile'].widget = forms.widgets.HiddenInput()

            if mem_profile_configurable and host.nodes and host.memory:
                # Populate Available Memory Profile Choices
                try:
                    avail_memory_profile_list = \
                        stx_api.sysinv.host_memprofile_list(self.request)
                    memory_profile_tuple_list = [
                        ('', _("Copy from an available memory profile."))
                    ]
                    for mp in avail_memory_profile_list:
                        if memoryprofile_applicable(host, host._subfunctions,
                                                    mp):
                            memory_profile_tuple_list.append(
                                (mp.profilename, mp.profilename))

                except Exception:
                    exceptions.handle(
                        self.request,
                        _('Unable to retrieve list of memory profiles.'))
                    memory_profile_tuple_list = []

                self.fields[
                    'memoryProfile'].choices = memory_profile_tuple_list

        else:
            self.fields['cpuProfile'].widget = forms.widgets.HiddenInput()
            self.fields['interfaceProfile'].widget = forms.widgets.HiddenInput(
            )
            self.fields['diskProfile'].widget = forms.widgets.HiddenInput()
            self.fields['memoryProfile'].widget = forms.widgets.HiddenInput()

    def clean_location(self):
        try:
            host_id = self.cleaned_data['host_id']
            host = stx_api.sysinv.host_get(self.request, host_id)
            location = host._location
            location['locn'] = self.cleaned_data.get('location')
            return location
        except Exception:
            msg = _('Unable to get host data')
            exceptions.check_message(["Connection", "refused"], msg)
            raise

    def clean(self):
        cleaned_data = super(UpdateHostInfoAction, self).clean()
        disabled = self.fields['personality'].widget.attrs.get('disabled')
        if disabled == 'disabled':
            if self.system_type == constants.TS_AIO:
                self._personality = 'controller'
            cleaned_data['personality'] = self._personality

        if cleaned_data['personality'] == stx_api.sysinv.PERSONALITY_STORAGE:
            self._subfunctions = stx_api.sysinv.PERSONALITY_STORAGE
            cleaned_data['subfunctions'] = self._subfunctions
        elif cleaned_data[
                'personality'] == stx_api.sysinv.PERSONALITY_CONTROLLER:
            if self.system_type == constants.TS_AIO:
                self._subfunctions = (stx_api.sysinv.PERSONALITY_CONTROLLER +
                                      ',' + stx_api.sysinv.PERSONALITY_COMPUTE)
            else:
                self._subfunctions = stx_api.sysinv.PERSONALITY_CONTROLLER
            cleaned_data['subfunctions'] = self._subfunctions

        return cleaned_data
Exemplo n.º 16
0
    def __init__(self, request, *args, **kwargs):

        super(RegistrForm, self).__init__(request, *args, **kwargs)

        self.registr_err = None

        initial = kwargs['initial'] if 'initial' in kwargs else dict()

        self.fields['username'] = forms.CharField(
            label=_('User name'),
            max_length=OS_LNAME_LEN,
            widget=forms.HiddenInput
            if 'username' in initial else forms.TextInput)

        self.fields['federated'] = forms.CharField(max_length=OS_LNAME_LEN,
                                                   widget=forms.HiddenInput)

        self.fields['givenname'] = forms.CharField(
            label=_('First name'),
            max_length=OS_LNAME_LEN,
            widget=forms.HiddenInput
            if 'givenname' in initial else forms.TextInput)

        self.fields['sn'] = forms.CharField(
            label=_('Last name'),
            max_length=OS_LNAME_LEN,
            widget=forms.HiddenInput if 'sn' in initial else forms.TextInput)

        if initial['needpwd']:
            self.fields['pwd'] = forms.RegexField(
                label=_("Password"),
                max_length=PWD_LEN,
                widget=forms.PasswordInput(render_value=False),
                regex=validators.password_validator(),
                error_messages={
                    'invalid': validators.password_validator_msg()
                })

            self.fields['repwd'] = forms.CharField(
                label=_("Confirm Password"),
                max_length=PWD_LEN,
                widget=forms.PasswordInput(render_value=False))

        self.fields['email'] = forms.EmailField(
            label=_('Email Address'),
            max_length=EMAIL_LEN,
            widget=forms.HiddenInput
            if 'email' in initial else forms.TextInput)

        self.fields['prjaction'] = forms.ChoiceField(
            label=_('Project action'),
            #choices = <see later>
            widget=forms.Select(attrs={
                'class': 'switchable',
                'data-slug': 'actsource'
            }))

        self.fields['newprj'] = forms.CharField(
            label=_('Personal project'),
            max_length=OS_SNAME_LEN,
            required=False,
            widget=forms.TextInput(
                attrs={
                    'class': 'switched',
                    'data-switch-on': 'actsource',
                    'data-actsource-newprj': _('Project name')
                }))

        self.fields['prjdescr'] = forms.CharField(
            label=_("Project description"),
            required=False,
            widget=forms.widgets.Textarea(
                attrs={
                    'class': 'switched',
                    'data-switch-on': 'actsource',
                    'data-actsource-newprj': _('Project description')
                }))

        self.fields['prjpriv'] = forms.BooleanField(
            label=_("Private project"),
            required=False,
            initial=False,
            widget=forms.widgets.CheckboxInput(
                attrs={
                    'class': 'switched',
                    'data-switch-on': 'actsource',
                    'data-actsource-newprj': _('Private project')
                }))

        self.fields['selprj'] = forms.MultipleChoiceField(
            label=_('Available projects'),
            required=False,
            widget=forms.SelectMultiple(
                attrs={
                    'class': 'switched',
                    'data-switch-on': 'actsource',
                    'data-actsource-selprj': _('Select existing project')
                }),
        )

        self.fields['organization'] = forms.CharField(
            label=_('Organization'),
            required=True,
            widget=forms.HiddenInput
            if 'organization' in initial else forms.TextInput)

        phone_regex = settings.HORIZON_CONFIG.get(
            'phone_regex', '^\s*\+*[0-9]+[0-9\s.]+\s*$')
        self.fields['phone'] = forms.RegexField(
            label=_('Phone number'),
            required=True,
            regex=phone_regex,
            error_messages={'invalid': _("Wrong phone format")})

        self.fields['contactper'] = forms.CharField(label=_('Contact person'),
                                                    required=False)

        self.fields['notes'] = forms.CharField(label=_('Notes'),
                                               required=False,
                                               widget=forms.widgets.Textarea())

        self.fields['aupok'] = forms.CharField(widget=forms.HiddenInput,
                                               initial='reject')

        import_guest_project()

        missing_guest = True
        avail_prjs = list()
        for prj_entry in Project.objects.exclude(status=PRJ_PRIVATE):
            if prj_entry.status == PRJ_GUEST:
                missing_guest = False
            elif prj_entry.projectid:
                avail_prjs.append(
                    (prj_entry.projectname, prj_entry.projectname))

        self.fields['selprj'].choices = avail_prjs

        if missing_guest:
            p_choices = [('selprj', _('Select existing projects')),
                         ('newprj', _('Create new project'))]
        else:
            p_choices = [('selprj', _('Select existing projects')),
                         ('newprj', _('Create new project')),
                         ('guestprj', _('Use guest project'))]

        self.fields['prjaction'].choices = p_choices
Exemplo n.º 17
0
class BoardManagementAction(workflows.Action):

    FIELD_LABEL_BM_IP = _("Board Management Controller IP Address")
    FIELD_LABEL_BM_USERNAME = _("Board Management Controller User Name")
    FIELD_LABEL_BM_PASSWORD = _("Board Management Controller Password")
    FIELD_LABEL_BM_CONFIRM_PASSWORD = _("Confirm Password")

    bm_type = forms.ChoiceField(label=_("Board Management Controller Type "),
                                choices=BM_TYPES_CHOICES,
                                required=False,
                                widget=forms.Select(attrs={
                                    'class': 'switchable',
                                    'data-slug': 'bm_type'
                                }))

    bm_ip = forms.IPField(
        label=FIELD_LABEL_BM_IP,
        required=False,
        help_text=_("IP address of the Board Management Controller"
                    " (e.g. 172.25.0.0)"),
        version=forms.IPv4 | forms.IPv6,
        mask=False,
        widget=forms.TextInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'bm_type',
                'data-bm_type-' + stx_api.sysinv.BM_TYPE_GENERIC:
                FIELD_LABEL_BM_IP
            }))

    bm_username = forms.CharField(
        label=FIELD_LABEL_BM_USERNAME,
        required=False,
        widget=forms.TextInput(
            attrs={
                'autocomplete':
                'off',
                'class':
                'switched',
                'data-switch-on':
                'bm_type',
                'data-bm_type-' + stx_api.sysinv.BM_TYPE_GENERIC:
                FIELD_LABEL_BM_USERNAME
            }))

    bm_password = forms.RegexField(
        label=FIELD_LABEL_BM_PASSWORD,
        widget=forms.PasswordInput(
            render_value=False,
            attrs={
                'autocomplete':
                'off',
                'class':
                'switched',
                'data-switch-on':
                'bm_type',
                'data-bm_type-' + stx_api.sysinv.BM_TYPE_GENERIC:
                FIELD_LABEL_BM_PASSWORD
            }),
        regex=validators.password_validator(),
        required=False,
        error_messages={'invalid': validators.password_validator_msg()})

    bm_confirm_password = forms.CharField(
        label=FIELD_LABEL_BM_CONFIRM_PASSWORD,
        widget=forms.PasswordInput(
            render_value=False,
            attrs={
                'autocomplete':
                'off',
                'class':
                'switched',
                'data-switch-on':
                'bm_type',
                'data-bm_type-' + stx_api.sysinv.BM_TYPE_GENERIC:
                FIELD_LABEL_BM_CONFIRM_PASSWORD
            }),
        required=False)

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

        if cleaned_data.get('bm_type'):
            if 'bm_ip' not in cleaned_data or not cleaned_data['bm_ip']:
                raise forms.ValidationError(
                    _('Board management IP address is required.'))
                raise forms.ValidationError(
                    _('Board management MAC address is required.'))

            if 'bm_username' not in cleaned_data or not \
                    cleaned_data['bm_username']:
                raise forms.ValidationError(
                    _('Board management user name is required.'))

            if 'bm_password' in cleaned_data:
                if cleaned_data['bm_password'] != cleaned_data.get(
                        'bm_confirm_password', None):
                    raise forms.ValidationError(
                        _('Board management passwords do not match.'))
        else:
            cleaned_data.pop('bm_ip')
            cleaned_data.pop('bm_username')

        return cleaned_data

    # We have to protect the entire "data" dict because it contains the
    # password and confirm_password strings.
    @sensitive_variables('data')
    def handle(self, request, data):
        # Throw away the password confirmation, we're done with it.
        data.pop('bm_confirm_password', None)
Exemplo n.º 18
0
class CreateForm(forms.SelfHandlingForm):
    tenantP = forms.ChoiceField(label=_("Project"), required=True)
    name = forms.CharField(max_length="255", label=_("Server Group Name"))
    policy = forms.ChoiceField(label=_("Policy"),
                               required=False,
                               widget=forms.Select(attrs={
                                   'class': 'switchable',
                                   'data-slug': 'policy_ht'
                               }))

    is_best_effort = forms.BooleanField(label=_("Best Effort"), required=False)

    group_size = forms.IntegerField(
        min_value=1,
        label=_("Max Group Size (Instances)"),
        required=False,
        widget=forms.TextInput(
            attrs={
                'class': 'switchable switched',
                'data-switch-on': 'policy_ht',
                'data-policy_ht-anti-affinity': 'Max Group Size (Instances)',
                'data-policy_ht-affinity': 'Max Group Size (Instances)'
            }))

    group_size_ht = forms.IntegerField(
        label=_("Max Group Size (Instances)"),
        required=False,
        widget=forms.TextInput(
            attrs={
                'readonly': 'readonly',
                'class': 'switchable switched',
                'data-switch-on': 'policy_ht',
                'data-policy_ht-affinity-hyperthread':
                'Max Group Size (Instances)'
            }))

    def __init__(self, request, *args, **kwargs):
        super(CreateForm, self).__init__(request, *args, **kwargs)
        self.fields['policy'].choices = [("anti-affinity", "anti-affinity"),
                                         ("affinity", "affinity")]

        # Populate available project_id/name choices
        all_projects = []
        try:
            # Get list of available projects.
            all_projects, has_more = api.keystone.tenant_list(request)

            projects_list = [(project.id, project.name)
                             for project in all_projects]

        except Exception:
            projects_list = []
            exceptions.handle(self.request,
                              _('Unable to retrieve list of tenants.'))

        self.fields['tenantP'].choices = projects_list

    def handle(self, request, data):
        try:
            policy = data['policy']
            policies = []
            if policy:
                policies.append(policy)
            metadata = {}
            if data['is_best_effort']:
                metadata['wrs-sg:best_effort'] = "true"
            group_size = data['group_size']
            group_size_ht = data['group_size_ht']
            if group_size:
                metadata['wrs-sg:group_size'] = str(group_size)
            elif group_size_ht:
                metadata['wrs-sg:group_size'] = str(group_size_ht)

            project_id = None
            if data['tenantP']:
                project_id = data['tenantP']

            server_group = stx_nova.server_group_create(
                request, data['name'], project_id, metadata, policies)
            return server_group

        except ValidationError as e:
            self.api_error(e.messages[0])
            return False
        except Exception as e:
            exceptions.handle(request, ignore=True)
            self.api_error(_("Unable to create server group."))
            return False
Exemplo n.º 19
0
class EditResourceForm(forms.SelfHandlingForm):
    label = forms.CharField(label=_("Label"), max_length=255, required=True)
    rackid = forms.ChoiceField(label=_("Rack"), required=True)
    eiaLocation = forms.CharField(label=_("EIA Location"),
                                  max_length=3,
                                  required=False)
    ip_address = forms.CharField(
        label=_("Host Name or IP Address"),
        max_length=255,
        required=True,
        help_text=_("Specify the fully qualified host name or IP V4"
                    " address used by Operational Management to access"
                    " the resource."))
    auth_method = forms.ChoiceField(
        label=_('Authentication Method'),
        choices=[(AUTH_METHOD_USER_PWD, _('User ID and Password')),
                 (AUTH_METHOD_USER_KEY, _('User ID and SSH Key'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'auth'
        }),
        help_text=_("Indicates the type of credential information used "
                    "by Operational Management to access the resource."))
    userID = forms.CharField(label=_("User ID"), max_length=255, required=True)
    password = forms.CharField(
        label=_("password"),
        widget=forms.PasswordInput(attrs={
            'class': 'switched',
            'data-switch-on': 'auth',
            'data-auth-0': _("Password")
        },
                                   render_value=False),
        help_text=_(
            "This is the password that Operational Management should"
            " use when accessing the resource.  Specifying a value here does"
            " not change the password of the user on the resource."))
    sshKey = forms.CharField(
        widget=forms.widgets.Textarea(
            attrs={
                'class': 'switched',
                'data-switch-on': 'auth',
                'data-auth-1': _("SSH Key"),
                'rows': 4
            }),
        help_text=_("Paste the private SSH key for the specified resource."))
    passphrase = forms.CharField(label=_("passphrase"),
                                 widget=forms.PasswordInput(
                                     attrs={
                                         'class': 'switched',
                                         'data-switch-on': 'auth',
                                         'data-auth-1': _("Passphrase")
                                     },
                                     render_value=False),
                                 required=False)

    def __init__(self, request, *args, **kwargs):
        super(EditResourceForm, self).__init__(request, *args, **kwargs)
        self.fields['rackid'].choices = create_rack_choices(request)

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

    def _clean_auth_ids(self, data):
        auth_method = data.get('auth_method')
        auth_method_changed = int(auth_method) != self.initial['auth_method']

        # if we have an sshKey value (but it's empty), or we don't
        # have an sshKey value at all
        if (('sshKey' in data and data['sshKey'] == u'')
                or ('sshKey' not in data)):
            # and if the auth method has changed to user/key
            if auth_method_changed and (auth_method == AUTH_METHOD_USER_KEY):
                # we really do have an error
                self._errors['sshKey'] = [
                    "Because you are changing the authentication"
                    " method for this resource to 'User ID and"
                    " SSH Key', you must supply an SSH Key value."
                ]
            # else if the auth method is user/key, and the
            # user id value has changed from its initial value
            elif ((auth_method == AUTH_METHOD_USER_KEY)
                  and (self.initial['userID'] != data['userID'])):
                # we really do have an error
                self._errors['sshKey'] = [
                    "Because you are using the authentication"
                    " method 'User ID and SSH Key' for this "
                    " resource and are changing the User ID,"
                    " you must supply an SSH Key value."
                ]
            # else we don't have an sshKey (and) we don't need an ssh key
            # (no error needed)
            else:
                del self._errors['sshKey']
        else:
            # we have an ssh key -- no error needed
            if 'sshKey' in self._errors:
                del self._errors['sshKey']

        # if we have a password value (but it's empty), or we don't
        # have a password value at all
        if (('password' in data and data['password'] == u'')
                or ('password' not in data)):
            # and if the auth method has changed to user/password
            if auth_method_changed and (auth_method == AUTH_METHOD_USER_PWD):
                # we really do have an error
                self._errors['password'] = [
                    "Because you are changing the authentication"
                    " method for this resource to 'User ID and"
                    " Password', you must supply a password value."
                ]
            # else if the auth method is user/password, and the user id
            # value has changed from its initial value
            elif ((auth_method == AUTH_METHOD_USER_PWD)
                  and (self.initial['userID'] != data['userID'])):
                # we really do have an error
                self._errors['password'] = [
                    "Because you are using the authentication"
                    " method 'User ID and Password' for this"
                    " resource and are changing the User ID,"
                    " you must supply password value."
                ]
            # else we don't have a password (and) we don't need a password
            # (no error needed)
            else:
                del self._errors['password']
        else:
            # we have have a password -- no error needed
            if 'password' in self._errors:
                del self._errors['password']

    def handle(self, request, data):
        __method__ = 'forms.EditResourceForm.handle'
        try:
            # We only want to pass the changed fields to the API.
            # Determine what fields have changed (we will process
            # authentication-related fields after this block)
            new_label = None
            if ('label' in data) and (self.initial['label'] != data['label']):
                new_label = data['label']
            new_user_id = None
            if ('userID'
                    in data) and (self.initial['userID'] != data['userID']):
                new_user_id = data['userID']
            new_ip_address = None
            if ('ip_address' in data) and (self.initial['ip_address'] !=
                                           data['ip_address']):
                new_ip_address = data['ip_address']
            new_rackid = None
            if ('rackid' in data) and (self.initial['rackid'] != int(
                    data['rackid'])):
                new_rackid = data['rackid']
            new_eia_location = None
            if ('eiaLocation' in data) and (self.initial['eiaLocation'] !=
                                            data['eiaLocation']):
                new_eia_location = data['eiaLocation']

            # Need to ensure we pass correct authentication-related fields
            new_password = None
            new_ssh_key = None
            if data['auth_method'] != AUTH_METHOD_USER_KEY:
                # user id and password authentication
                if 'password' in data and data['password'] is not None:
                    new_password = data['password']
            else:
                # user id and SSH key (and passphrase) authentication
                if 'sshKey' in data and data['sshKey'] is not None:
                    new_ssh_key = data['sshKey']
                    # only specify a passphrase if we are setting the sshKey
                    if 'passphrase' in data and data['passphrase'] is not None:
                        new_password = data['passphrase']
            # pass in "None" for original resource label; also, we will
            # pass in the resource ID so the API knows which resource is
            # being edited
            logging.debug(
                "%s: Attempting to edit resource %s on rack: %s, "
                "using label: %s, address: %s, user id: %s, eia "
                "location %s, new rack %s, and authentication "
                " method: %s", __method__, self.initial['label'],
                self.initial['rackid'], new_label, new_ip_address, new_user_id,
                new_eia_location, new_rackid, data['auth_method'])

            (rc, result_dict) = resource_mgr.change_resource_properties(
                None, self.initial['resourceId'], new_label, new_user_id,
                new_password, new_ip_address, new_rackid, new_eia_location,
                new_ssh_key)
            if rc is not 0:
                # Log details of the unsuccessful attempt.
                logging.error(
                    "%s: Attempt to edit resource %s on rack: %s,"
                    " using new label: %s, address: %s, user id:"
                    " %s, eia location %s, new rack %s, and"
                    " authentication method: %s failed.", __method__,
                    self.initial['label'], self.initial['rackid'], new_label,
                    new_ip_address, new_user_id, new_eia_location, new_rackid,
                    data['auth_method'])

                logging.error(
                    "%s: Unable to edit resource %s to rack %s.  A Non-0"
                    " return code returned from resource_mgr.edit_resource."
                    " The return code is: %s.  Details of the attempt: "
                    " %s", __method__, self.initial['label'],
                    self.initial['rackid'], rc, result_dict)
                # failure case -- so use the initial label for logging/message
                msg = str('Attempt to edit resource ' + self.initial['label'] +
                          " was not successful." +
                          ' Details of the attempt: ' + result_dict)
                messages.error(request, msg)

                # Return false in this case so that the dialog is not
                # dismissed.  This gives the end-user a chance to
                # update the dialog w/o having to re-enter all the
                # information a second time.
                return False
            else:
                # must have a 0 rc -- display completion msg -- use current
                # label for message
                msg = str('Resource ' + data['label'] +
                          ' successfully edited.')
                messages.success(request, msg)
                return True
        except Exception as e:
            logging.error(
                "%s: Exception received trying to edit resource."
                " Exception is: %s", __method__, e)
            exceptions.handle(request, _('Unable to edit selected resource.'))
            # In this case, return True so that the dialog closes.
            # In theory, there are no values the end-user could change
            # to the dialog inputs that would allow us to proceed.
            return True
Exemplo n.º 20
0
class AddSensorGroup(forms.SelfHandlingForm):

    DATA_TYPE_CHOICES = (
        (None, _("<Select Sensor Data type>")),
        ('analog', _("Analog Sensor")),
        ('discrete', _("Discrete Sensor")),
    )

    host_uuid = forms.CharField(label=_("host_uuid"),
                                initial='host_uuid',
                                widget=forms.widgets.HiddenInput)

    hostname = forms.CharField(
        label=_("Hostname"),
        initial='hostname',
        widget=forms.TextInput(attrs={'readonly': 'readonly'}))

    sensorgroup_name = forms.CharField(
        label=_("Sensor Group Name"),
        required=True,
        widget=forms.TextInput(attrs={'readonly': 'readonly'}))

    sensorgroup_datatype = forms.ChoiceField(
        label=_("Sensor Group Data Type"),
        required=True,
        choices=DATA_TYPE_CHOICES,
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'datatype'
        }))

    sensortype = forms.CharField(
        label=_("Sensor Type"),
        required=True,
        widget=forms.TextInput(attrs={'readonly': 'readonly'}))

    failure_url = 'horizon:admin:inventory:detail'

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

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

    def handle(self, request, data):
        host_id = data['host_id']

        try:
            del data['host_id']
            del data['hostname']

            # The REST API takes care of creating the sensorgroup and assoc
            sensorgroup = stx_api.sysinv.host_sensorgroup_create(
                request, **data)

            msg = _('Sensor group was successfully created.')
            LOG.debug(msg)
            messages.success(request, msg)

            return sensorgroup
        except exc.ClientException as ce:
            msg = _('Failed to create sensor group.')
            LOG.info(msg)
            LOG.error(ce)

            # Allow REST API error message to appear on UI
            messages.error(request, ce)

            # Redirect to host details pg
            redirect = reverse(self.failure_url, args=[host_id])
            return shortcuts.redirect(redirect)
        except Exception as e:
            msg = _('Failed to create sensor group.')
            LOG.info(msg)
            LOG.error(e)

            # if not a rest API error, throw default
            redirect = reverse(self.failure_url, args=[host_id])
            return exceptions.handle(request, message=e, redirect=redirect)
Exemplo n.º 21
0
class CreateForm(forms.SelfHandlingForm):
    name = forms.CharField(max_length="255", label=_("Server Group Name"))
    policy = forms.ChoiceField(label=_("Policy"),
                               required=False,
                               widget=forms.Select(attrs={
                                   'class': 'switchable',
                                   'data-slug': 'policy_ht'
                               }))

    is_best_effort = forms.BooleanField(label=_("Best Effort"), required=False)

    group_size = forms.IntegerField(
        min_value=1,
        label=_("Max Group Size (Instances)"),
        required=False,
        widget=forms.TextInput(
            attrs={
                'class': 'switchable switched',
                'data-switch-on': 'policy_ht',
                'data-policy_ht-anti-affinity': 'Max Group Size (Instances)',
                'data-policy_ht-affinity': 'Max Group Size (Instances)'
            }))

    group_size_ht = forms.IntegerField(
        label=_("Max Group Size (Instances)"),
        required=False,
        widget=forms.TextInput(
            attrs={
                'readonly': 'readonly',
                'class': 'switchable switched',
                'data-switch-on': 'policy_ht',
                'data-policy_ht-affinity-hyperthread':
                'Max Group Size (Instances)'
            }))

    def __init__(self, request, *args, **kwargs):
        super(CreateForm, self).__init__(request, *args, **kwargs)
        self.fields['policy'].choices = [("anti-affinity", "anti-affinity"),
                                         ("affinity", "affinity")]

    def handle(self, request, data):
        try:
            project_id = self.request.user.tenant_id
            policy = data['policy']
            policies = []
            if policy:
                policies.append(policy)
            metadata = {}
            if data['is_best_effort']:
                metadata['wrs-sg:best_effort'] = "true"
            group_size = data['group_size']
            group_size_ht = data['group_size_ht']
            if group_size:
                metadata['wrs-sg:group_size'] = str(group_size)
            elif group_size_ht:
                metadata['wrs-sg:group_size'] = str(group_size_ht)

            kwargs = {
                'name': data['name'],
                'policies': policies,
                'metadata': metadata,
                'project_id': project_id
            }

            server_group = stx_nova.server_group_create(request, **kwargs)
            return server_group

        except ValidationError as e:
            self.api_error(e.messages[0])
            return False
        except Exception:
            exceptions.handle(request, ignore=True)
            self.api_error(_("Unable to create server group."))
            return False
Exemplo n.º 22
0
class CreateNetworkProfile(forms.SelfHandlingForm):
    """Create Network Profile form."""

    name = forms.CharField(max_length=255, label=_("Name"))
    segment_type = forms.ChoiceField(
        label=_('Segment Type'),
        choices=[('vlan', _('VLAN')), ('overlay', _('Overlay')),
                 ('trunk', _('Trunk'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'segtype'
        }))
    # Sub type options available for Overlay segment type
    sub_type = forms.ChoiceField(label=_('Sub Type'),
                                 choices=[('native_vxlan', _('Native VXLAN')),
                                          ('enhanced', _('Enhanced VXLAN')),
                                          ('other', _('Other'))],
                                 required=False,
                                 widget=forms.Select(
                                     attrs={
                                         'class': 'switchable switched',
                                         'data-slug': 'subtype',
                                         'data-switch-on': 'segtype',
                                         'data-segtype-overlay': _("Sub Type")
                                     }))
    # Sub type options available for Trunk segment type
    sub_type_trunk = forms.ChoiceField(
        label=_('Sub Type'),
        choices=[('vlan', _('VLAN'))],
        required=False,
        widget=forms.Select(
            attrs={
                'class': 'switched',
                'data-switch-on': 'segtype',
                'data-segtype-trunk': _("Sub Type")
            }))
    segment_range = forms.CharField(
        max_length=255,
        label=_("Segment Range"),
        required=False,
        widget=forms.TextInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'segtype',
                'data-segtype-vlan': _("Segment Range"),
                'data-segtype-overlay': _("Segment Range")
            }),
        help_text=_("1-4093 for VLAN; "
                    "5000-10000 for Overlay"))
    multicast_ip_range = forms.CharField(
        max_length=30,
        label=_("Multicast IP Range"),
        required=False,
        widget=forms.TextInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'subtype',
                'data-subtype-native_vxlan': _("Multicast IP Range")
            }),
        help_text=_("Multicast IPv4 range"
                    "(e.g. 224.0.0.0-"
                    "224.0.0.100)"))
    other_subtype = forms.CharField(
        max_length=255,
        label=_("Sub Type Value (Manual Input)"),
        required=False,
        widget=forms.TextInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'subtype',
                'data-subtype-other': _("Sub Type Value "
                                        "(Manual Input)")
            }),
        help_text=_("Enter parameter (e.g. GRE)"))
    physical_network = forms.CharField(
        max_length=255,
        label=_("Physical Network"),
        required=False,
        widget=forms.TextInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'segtype',
                'data-segtype-vlan': _("Physical Network")
            }))
    project = forms.ChoiceField(label=_("Project"), required=False)

    def __init__(self, request, *args, **kwargs):
        super(CreateNetworkProfile, self).__init__(request, *args, **kwargs)
        self.fields['project'].choices = get_tenant_choices(request)

    def clean(self):
        # If sub_type is 'other' or 'trunk' then
        # assign this new value for sub_type
        cleaned_data = super(CreateNetworkProfile, self).clean()

        segment_type = cleaned_data.get('segment_type')
        if segment_type == 'overlay':
            sub_type = cleaned_data.get('sub_type')
            if sub_type == 'other':
                other_subtype = cleaned_data.get('other_subtype')
                cleaned_data['sub_type'] = other_subtype
                LOG.debug('subtype is now %(params)s',
                          {'params': other_subtype})
        elif segment_type == 'trunk':
            sub_type_trunk = cleaned_data.get('sub_type_trunk')
            cleaned_data['sub_type'] = sub_type_trunk
            LOG.debug('subtype is now %(params)s', {'params': sub_type_trunk})

        return cleaned_data

    def handle(self, request, data):
        try:
            LOG.debug('request = %(req)s, params = %(params)s', {
                'req': request,
                'params': data
            })
            params = {
                'name': data['name'],
                'segment_type': data['segment_type'],
                'sub_type': data['sub_type'],
                'segment_range': data['segment_range'],
                'physical_network': data['physical_network'],
                'multicast_ip_range': data['multicast_ip_range'],
                'tenant_id': data['project']
            }
            profile = api.neutron.profile_create(request, **params)
            msg = _('Network Profile %s '
                    'was successfully created.') % data['name']
            LOG.debug(msg)
            messages.success(request, msg)
            return profile
        except Exception:
            redirect = reverse('horizon:router:nexus1000v:index')
            msg = _('Failed to create network profile %s') % data['name']
            LOG.error(msg)
            exceptions.handle(request, msg, redirect=redirect)
Exemplo n.º 23
0
class AddLocalVolumeGroup(forms.SelfHandlingForm):

    host_id = forms.CharField(label=_("host_id"),
                              initial='host_id',
                              widget=forms.widgets.HiddenInput)

    ihost_uuid = forms.CharField(label=_("ihost_uuid"),
                                 initial='ihost_uuid',
                                 widget=forms.widgets.HiddenInput)

    hostname = forms.CharField(
        label=_("Hostname"),
        initial='hostname',
        widget=forms.TextInput(attrs={'readonly': 'readonly'}))

    lvm_vg_name = forms.ChoiceField(
        label=_("Local Volume Group Name"),
        required=True,
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'lvm_vg_name'
        }))

    failure_url = 'horizon:admin:inventory:detail'

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

        # Populate available volume group choices
        host_uuid = kwargs['initial']['ihost_uuid']
        host_id = kwargs['initial']['host_id']

        host = api.sysinv.host_get(self.request, host_id)
        subfunctions = host.subfunctions

        # LVGs that are considered as "present" in the system are those
        # in an adding or provisioned state.
        ilvg_list = api.sysinv.host_lvg_list(self.request, host_uuid)
        current_lvg_states = [api.sysinv.LVG_ADD, api.sysinv.LVG_PROV]
        current_lvgs = [
            lvg.lvm_vg_name for lvg in ilvg_list
            if lvg.vg_state in current_lvg_states
        ]

        compatible_lvgs = []
        if host.personality.lower().startswith(
                api.sysinv.PERSONALITY_CONTROLLER):
            compatible_lvgs += [api.sysinv.LVG_CINDER_VOLUMES]

        if api.sysinv.SUBFUNCTIONS_COMPUTE in subfunctions:
            compatible_lvgs += [api.sysinv.LVG_NOVA_LOCAL]

        allowed_lvgs = set(compatible_lvgs) - set(current_lvgs)

        ilvg_tuple_list = []
        for lvg in allowed_lvgs:
            ilvg_tuple_list.append((lvg, lvg))

        self.fields['lvm_vg_name'].choices = ilvg_tuple_list

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

    def handle(self, request, data):
        host_id = data['host_id']

        try:
            del data['host_id']
            del data['hostname']

            # The REST API takes care of creating the stor
            # and updating disk.foristorid
            lvg = api.sysinv.host_lvg_create(request, **data)

            msg = _('Local volume group was successfully created.')
            LOG.debug(msg)
            messages.success(request, msg)

            return lvg
        except exc.ClientException as ce:
            msg = _('Failed to create local volume group.')
            LOG.info(msg)
            LOG.error(ce)

            # Allow REST API error message to appear on UI
            w_msg = str(ce)
            if ('Warning' in w_msg):
                LOG.info(ce)
                messages.warning(request, w_msg.split(':', 1)[-1])
            else:
                LOG.error(ce)
                messages.error(request, w_msg)

            # Redirect to host details pg
            redirect = reverse(self.failure_url, args=[host_id])
            return shortcuts.redirect(redirect)
        except Exception as e:
            msg = _('Failed to create local volume group.')
            LOG.info(msg)
            LOG.error(e)

            # if not a rest API error, throw default
            redirect = reverse(self.failure_url, args=[host_id])
            return exceptions.handle(request, message=e, redirect=redirect)
Exemplo n.º 24
0
class AddRule(forms.SelfHandlingForm):
    id = forms.CharField(widget=forms.HiddenInput())
    ip_protocol = forms.ChoiceField(label=_('Rule'),
                                    widget=forms.Select(attrs={
                                            'class': 'switchable',
                                            'data-slug': 'protocol'}))

    port_or_range = forms.ChoiceField(label=_('Open'),
                                      choices=[('port', _('Port')),
                                               ('range', _('Port Range'))],
                                      widget=forms.Select(attrs={
                                            'class': 'switchable switched',
                                            'data-slug': 'range',
                                            'data-switch-on': 'protocol',
                                            'data-protocol-tcp': _('Open'),
                                            'data-protocol-udp': _('Open')}))

    port = forms.IntegerField(label=_("Port"),
                              required=False,
                              help_text=_("Enter an integer value "
                                          "between 1 and 65535."),
                              widget=forms.TextInput(attrs={
                                   'class': 'switched',
                                   'data-switch-on': 'range',
                                   'data-range-port': _('Port')}),
                              validators=[validate_port_range])

    from_port = forms.IntegerField(label=_("From Port"),
                                   required=False,
                                   help_text=_("Enter an integer value "
                                               "between 1 and 65535."),
                                   widget=forms.TextInput(attrs={
                                        'class': 'switched',
                                        'data-switch-on': 'range',
                                        'data-range-range': _('From Port')}),
                                   validators=[validate_port_range])

    to_port = forms.IntegerField(label=_("To Port"),
                                 required=False,
                                 help_text=_("Enter an integer value "
                                             "between 1 and 65535."),
                                 widget=forms.TextInput(attrs={
                                        'class': 'switched',
                                        'data-switch-on': 'range',
                                        'data-range-range': _('To Port')}),
                                 validators=[validate_port_range])

    icmp_type = forms.IntegerField(label=_("Type"),
                                   required=False,
                                   help_text=_("Enter a value for ICMP type "
                                               "in the range (-1: 255)"),
                                   widget=forms.TextInput(attrs={
                                        'class': 'switched',
                                        'data-switch-on': 'protocol',
                                        'data-protocol-icmp': _('Type')}),
                                   validators=[validate_port_range])

    icmp_code = forms.IntegerField(label=_("Code"),
                                   required=False,
                                   help_text=_("Enter a value for ICMP code "
                                               "in the range (-1: 255)"),
                                   widget=forms.TextInput(attrs={
                                          'class': 'switched',
                                          'data-switch-on': 'protocol',
                                          'data-protocol-icmp': _('Code')}),
                                   validators=[validate_port_range])

    source = forms.ChoiceField(label=_('Source'),
                               choices=[('cidr', _('CIDR')),
                                        ('sg', _('Security Group'))],
                               help_text=_('To specify an allowed IP '
                                           'range, select "CIDR". To '
                                           'allow access from all '
                                           'members of another security '
                                           'group select "Security '
                                           'Group".'),
                               widget=forms.Select(attrs={
                                      'class': 'switchable',
                                      'data-slug': 'source'}))

    cidr = fields.IPField(label=_("CIDR"),
                          required=False,
                          initial="0.0.0.0/0",
                          help_text=_("Classless Inter-Domain Routing "
                                      "(e.g. 192.168.0.0/24)"),
                          version=fields.IPv4 | fields.IPv6,
                          mask=True,
                          widget=forms.TextInput(
                                attrs={'class': 'switched',
                                       'data-switch-on': 'source',
                                       'data-source-cidr': _('CIDR')}))

    security_group = forms.ChoiceField(label=_('Security Group'),
                                       required=False,
                                       widget=forms.Select(attrs={
                                          'class': 'switched',
                                          'data-switch-on': 'source',
                                          'data-source-sg': _('Security '
                                                              'Group')}))

    def __init__(self, *args, **kwargs):
        sg_list = kwargs.pop('sg_list', [])
        super(AddRule, self).__init__(*args, **kwargs)
        # Determine if there are security groups available for the
        # source group option; add the choices and enable the option if so.
        if sg_list:
            security_groups_choices = sg_list
        else:
            security_groups_choices = [("", _("No security groups available"))]
        self.fields['security_group'].choices = security_groups_choices

        rules_dict = getattr(settings, 'SECURITY_GROUP_RULES', {})
        common_rules = [(k, _(rules_dict[k]['name']))
                         for k in rules_dict]
        common_rules.sort()
        custom_rules = [('tcp', _('Custom TCP Rule')),
                        ('udp', _('Custom UDP Rule')),
                        ('icmp', _('Custom ICMP Rule'))]
        self.fields['ip_protocol'].choices = custom_rules + common_rules
        self.rules = rules_dict

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

        ip_proto = cleaned_data.get('ip_protocol')
        port_or_range = cleaned_data.get("port_or_range")
        source = cleaned_data.get("source")

        icmp_type = cleaned_data.get("icmp_type", None)
        icmp_code = cleaned_data.get("icmp_code", None)

        from_port = cleaned_data.get("from_port", None)
        to_port = cleaned_data.get("to_port", None)
        port = cleaned_data.get("port", None)

        if ip_proto == 'icmp':
            if icmp_type is None:
                msg = _('The ICMP type is invalid.')
                raise ValidationError(msg)
            if icmp_code is None:
                msg = _('The ICMP code is invalid.')
                raise ValidationError(msg)
            if icmp_type not in xrange(-1, 256):
                msg = _('The ICMP type not in range (-1, 255)')
                raise ValidationError(msg)
            if icmp_code not in xrange(-1, 256):
                msg = _('The ICMP code not in range (-1, 255)')
                raise ValidationError(msg)
            cleaned_data['from_port'] = icmp_type
            cleaned_data['to_port'] = icmp_code
        elif ip_proto == 'tcp' or ip_proto == 'udp':
            if port_or_range == "port":
                cleaned_data["from_port"] = port
                cleaned_data["to_port"] = port
                if port is None:
                    msg = _('The specified port is invalid.')
                    raise ValidationError(msg)
            else:
                if from_port is None:
                    msg = _('The "from" port number is invalid.')
                    raise ValidationError(msg)
                if to_port is None:
                    msg = _('The "to" port number is invalid.')
                    raise ValidationError(msg)
                if to_port < from_port:
                    msg = _('The "to" port number must be greater than '
                            'or equal to the "from" port number.')
                    raise ValidationError(msg)
        else:
            cleaned_data['ip_protocol'] = self.rules[ip_proto]['ip_protocol']
            cleaned_data['from_port'] = int(self.rules[ip_proto]['from_port'])
            cleaned_data['to_port'] = int(self.rules[ip_proto]['to_port'])

        if source == "cidr":
            cleaned_data['security_group'] = None
        else:
            cleaned_data['cidr'] = None

        return cleaned_data

    def handle(self, request, data):
        try:
            rule = api.nova.security_group_rule_create(
                        request,
                        get_int_or_uuid(data['id']),
                        data['ip_protocol'],
                        data['from_port'],
                        data['to_port'],
                        data['cidr'],
                        data['security_group'])
            messages.success(request,
                             _('Successfully added rule: %s') % unicode(rule))
            return rule
        except:
            redirect = reverse("horizon:project:access_and_security:"
                               "security_groups:detail", args=[data['id']])
            exceptions.handle(request,
                              _('Unable to add rule to security group.'),
                              redirect=redirect)
Exemplo n.º 25
0
class EditStorageVolume(forms.SelfHandlingForm):
    id = forms.CharField(widget=forms.widgets.HiddenInput)

    journal_locations = forms.ChoiceField(
        label=_("Journal"),
        required=False,
        widget=forms.Select(attrs={'data-slug': 'journal_locations'}),
        help_text=_("Assign disk to journal "
                    "storage volume."))

    journal_size_mib = forms.CharField(
        label=_("Journal Size MiB"),
        required=False,
        initial=sysinv.JOURNAL_DEFAULT_SIZE,
        widget=forms.TextInput(attrs={'data-slug': 'journal_size_mib'}),
        help_text=_("Journal's size for the "
                    "current OSD."))

    failure_url = 'horizon:admin:inventory:detail'

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

        stor = api.sysinv.host_stor_get(self.request,
                                        kwargs['initial']['uuid'])

        initial_journal_location = kwargs['initial']['journal_location']
        host_uuid = kwargs['initial']['host_uuid']

        # Populate available journal choices. If no journal is available,
        # then the journal is collocated.
        avail_journal_list = api.sysinv.host_stor_get_by_function(
            self.request, host_uuid, 'journal')

        journal_tuple_list = []

        if stor.uuid == initial_journal_location:
            journal_tuple_list.append((stor.uuid, "Collocated with OSD"))
        else:
            journal_tuple_list.append(
                (initial_journal_location, "%s " % initial_journal_location))

        if avail_journal_list:
            for j in avail_journal_list:
                if j.uuid != initial_journal_location:
                    journal_tuple_list.append((j.uuid, "%s " % j.uuid))

        if stor.uuid != initial_journal_location:
            journal_tuple_list.append((stor.uuid, "Collocated with OSD"))

        self.fields['journal_locations'].choices = journal_tuple_list

    def handle(self, request, data):
        stor_id = data['id']

        try:
            # Obtain journal information.
            journal = data['journal_locations'][:]

            if journal:
                data['journal_location'] = journal
            else:
                data['journal_location'] = None
                data['journal_size_mib'] = sysinv.JOURNAL_DEFAULT_SIZE

            del data['journal_locations']
            del data['id']

            # The REST API takes care of updating the stor journal information.
            stor = api.sysinv.host_stor_update(request, stor_id, **data)

            msg = _('Storage volume was successfully updated.')
            LOG.debug(msg)
            messages.success(request, msg)

            return stor
        except exc.ClientException as ce:
            msg = _('Failed to update storage volume.')
            LOG.info(msg)
            LOG.error(ce)

            # Allow REST API error message to appear on UI.
            messages.error(request, ce)

            # Redirect to host details pg.
            redirect = reverse(self.failure_url, args=[stor_id])
            return shortcuts.redirect(redirect)
        except Exception as e:
            msg = _('Failed to update storage volume.')
            LOG.info(msg)
            LOG.error(e)

            # if not a rest API error, throw default
            redirect = reverse(self.failure_url, args=[stor_id])
            return exceptions.handle(request, message=e, redirect=redirect)
Exemplo n.º 26
0
class GeneralConfigAction(workflows.Action):
    data_source_name = forms.CharField(label=_("Name"))

    data_source_type = forms.ChoiceField(
        label=_("Data Source Type"),
        widget=forms.Select(attrs={
            "class": "switchable",
            "data-slug": "ds_type"
        }))

    data_source_manila_share = forms.ChoiceField(
        label=_("Manila share"),
        required=False,
        widget=forms.Select(
            attrs={
                "class": "switched",
                "data-switch-on": "ds_type",
                "data-ds_type-manila": _("Manila share")
            }))

    data_source_url = forms.CharField(
        label=_("URL"),
        widget=forms.TextInput(
            attrs={
                "class": "switched",
                "data-switch-on": "ds_type",
                "data-ds_type-manila": _("Path on share"),
                "data-ds_type-swift": _("URL"),
                "data-ds_type-hdfs": _("URL"),
                "data-ds_type-maprfs": _("URL")
            }))

    data_source_credential_user = forms.CharField(
        label=_("Source username"),
        required=False,
        widget=forms.TextInput(
            attrs={
                "class": "switched",
                "data-switch-on": "ds_type",
                "data-ds_type-swift": _("Source username")
            }))

    data_source_credential_pass = forms.CharField(widget=forms.PasswordInput(
        attrs={
            'class': 'switched',
            'data-switch-on': 'ds_type',
            'data-ds_type-swift': _("Source password"),
            'autocomplete': 'off'
        }),
                                                  label=_("Source password"),
                                                  required=False)

    data_source_description = forms.CharField(
        label=_("Description"),
        required=False,
        widget=forms.Textarea(attrs={'rows': 4}))

    is_public = acl_utils.get_is_public_form(_("data source"))
    is_protected = acl_utils.get_is_protected_form(_("data source"))

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

        self.fields["data_source_type"].choices = [("swift", "Swift"),
                                                   ("hdfs", "HDFS"),
                                                   ("maprfs", "MapR FS")]
        # If Manila is running, enable it as a choice for a data source
        if saharaclient.base.is_service_enabled(request, 'share'):
            self.fields["data_source_type"].choices.append(
                ("manila", "Manila"))
            self.fields["data_source_manila_share"].choices = (
                self.populate_manila_share_choices(request))

    def populate_manila_share_choices(self, request):
        try:
            shares = manilaclient.share_list(request)
            choices = [(s.id, s.name) for s in shares]
        except Exception:
            exceptions.handle(request, _("Failed to get list of shares"))
            choices = []
        return choices

    class Meta(object):
        name = _("Create Data Source")
        help_text_template = "data_sources/_create_data_source_help.html"
Exemplo n.º 27
0
class AddRule(forms.SelfHandlingForm):
    id = forms.CharField(widget=forms.HiddenInput())
    rule_menu = forms.ChoiceField(
        label=_('Rule'),
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'rule_menu'
        }))

    # "direction" field is enabled only when custom mode.
    # It is because most common rules in local_settings.py is meaningful
    # when its direction is 'ingress'.
    direction = forms.ChoiceField(
        label=_('Direction'),
        required=False,
        widget=forms.Select(
            attrs={
                'class': 'switched',
                'data-switch-on': 'rule_menu',
                'data-rule_menu-tcp': _('Direction'),
                'data-rule_menu-udp': _('Direction'),
                'data-rule_menu-icmp': _('Direction'),
                'data-rule_menu-custom': _('Direction'),
                'data-rule_menu-all_tcp': _('Direction'),
                'data-rule_menu-all_udp': _('Direction'),
                'data-rule_menu-all_icmp': _('Direction'),
            }))

    ip_protocol = forms.IntegerField(
        label=_('IP Protocol'),
        required=False,
        help_text=_("Enter an integer value between 0 and 255 "
                    "(or -1 which means wildcard)."),
        validators=[utils_validators.validate_ip_protocol],
        widget=forms.TextInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'rule_menu',
                'data-rule_menu-custom': _('IP Protocol')
            }))

    port_or_range = forms.ChoiceField(
        label=_('Open Port'),
        choices=[('port', _('Port')), ('range', _('Port Range'))],
        widget=forms.Select(
            attrs={
                'class': 'switchable switched',
                'data-slug': 'range',
                'data-switch-on': 'rule_menu',
                'data-rule_menu-tcp': _('Open Port'),
                'data-rule_menu-udp': _('Open Port')
            }))

    port = forms.IntegerField(
        label=_("Port"),
        required=False,
        help_text=_("Enter an integer value "
                    "between 1 and 65535."),
        widget=forms.TextInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'range',
                'data-range-port': _('Port')
            }),
        validators=[utils_validators.validate_port_range])

    from_port = forms.IntegerField(
        label=_("From Port"),
        required=False,
        help_text=_("Enter an integer value "
                    "between 1 and 65535."),
        widget=forms.TextInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'range',
                'data-range-range': _('From Port')
            }),
        validators=[utils_validators.validate_port_range])

    to_port = forms.IntegerField(
        label=_("To Port"),
        required=False,
        help_text=_("Enter an integer value "
                    "between 1 and 65535."),
        widget=forms.TextInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'range',
                'data-range-range': _('To Port')
            }),
        validators=[utils_validators.validate_port_range])

    icmp_type = forms.IntegerField(
        label=_("Type"),
        required=False,
        help_text=_("Enter a value for ICMP type "
                    "in the range (-1: 255)"),
        widget=forms.TextInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'rule_menu',
                'data-rule_menu-icmp': _('Type')
            }),
        validators=[utils_validators.validate_port_range])

    icmp_code = forms.IntegerField(
        label=_("Code"),
        required=False,
        help_text=_("Enter a value for ICMP code "
                    "in the range (-1: 255)"),
        widget=forms.TextInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'rule_menu',
                'data-rule_menu-icmp': _('Code')
            }),
        validators=[utils_validators.validate_port_range])

    remote = forms.ChoiceField(label=_('Remote'),
                               choices=[('cidr', _('CIDR')),
                                        ('sg', _('Security Group'))],
                               help_text=_('To specify an allowed IP '
                                           'range, select "CIDR". To '
                                           'allow access from all '
                                           'members of another security '
                                           'group select "Security '
                                           'Group".'),
                               widget=forms.Select(attrs={
                                   'class': 'switchable',
                                   'data-slug': 'remote'
                               }))

    cidr = fields.IPField(label=_("CIDR"),
                          required=False,
                          initial="0.0.0.0/0",
                          help_text=_("Classless Inter-Domain Routing "
                                      "(e.g. 192.168.0.0/24)"),
                          version=fields.IPv4 | fields.IPv6,
                          mask=True,
                          widget=forms.TextInput(
                              attrs={
                                  'class': 'switched',
                                  'data-switch-on': 'remote',
                                  'data-remote-cidr': _('CIDR')
                              }))

    security_group = forms.ChoiceField(
        label=_('Security Group'),
        required=False,
        widget=forms.Select(
            attrs={
                'class': 'switched',
                'data-switch-on': 'remote',
                'data-remote-sg': _('Security '
                                    'Group')
            }))
    # When cidr is used ethertype is determined from IP version of cidr.
    # When source group, ethertype needs to be specified explicitly.
    ethertype = forms.ChoiceField(label=_('Ether Type'),
                                  required=False,
                                  choices=[('IPv4', _('IPv4')),
                                           ('IPv6', _('IPv6'))],
                                  widget=forms.Select(
                                      attrs={
                                          'class': 'switched',
                                          'data-slug': 'ethertype',
                                          'data-switch-on': 'remote',
                                          'data-remote-sg': _('Ether Type')
                                      }))

    def __init__(self, *args, **kwargs):
        sg_list = kwargs.pop('sg_list', [])
        super(AddRule, self).__init__(*args, **kwargs)
        # Determine if there are security groups available for the
        # remote group option; add the choices and enable the option if so.
        if sg_list:
            security_groups_choices = sg_list
        else:
            security_groups_choices = [("", _("No security groups available"))]
        self.fields['security_group'].choices = security_groups_choices

        backend = api.network.security_group_backend(self.request)

        rules_dict = getattr(settings, 'SECURITY_GROUP_RULES', [])
        common_rules = [(k, _(rules_dict[k]['name'])) for k in rules_dict
                        if rules_dict[k].get('backend', backend) == backend]
        common_rules.sort()
        custom_rules = [('tcp', _('Custom TCP Rule')),
                        ('udp', _('Custom UDP Rule')),
                        ('icmp', _('Custom ICMP Rule'))]
        if backend == 'neutron':
            custom_rules.append(('custom', _('Other Protocol')))
        self.fields['rule_menu'].choices = custom_rules + common_rules
        self.rules = rules_dict

        if backend == 'neutron':
            self.fields['direction'].choices = [('ingress', _('Ingress')),
                                                ('egress', _('Egress'))]
        else:
            # direction and ethertype are not supported in Nova secgroup.
            self.fields['direction'].widget = forms.HiddenInput()
            self.fields['ethertype'].widget = forms.HiddenInput()
            # ip_protocol field is to specify arbitrary protocol number
            # and it is available only for neutron security group.
            self.fields['ip_protocol'].widget = forms.HiddenInput()

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

        rule_menu = cleaned_data.get('rule_menu')
        port_or_range = cleaned_data.get("port_or_range")
        remote = cleaned_data.get("remote")

        icmp_type = cleaned_data.get("icmp_type", None)
        icmp_code = cleaned_data.get("icmp_code", None)

        from_port = cleaned_data.get("from_port", None)
        to_port = cleaned_data.get("to_port", None)
        port = cleaned_data.get("port", None)

        if rule_menu == 'icmp':
            cleaned_data['ip_protocol'] = rule_menu
            if icmp_type is None:
                msg = _('The ICMP type is invalid.')
                raise ValidationError(msg)
            if icmp_code is None:
                msg = _('The ICMP code is invalid.')
                raise ValidationError(msg)
            if icmp_type not in xrange(-1, 256):
                msg = _('The ICMP type not in range (-1, 255)')
                raise ValidationError(msg)
            if icmp_code not in xrange(-1, 256):
                msg = _('The ICMP code not in range (-1, 255)')
                raise ValidationError(msg)
            cleaned_data['from_port'] = icmp_type
            cleaned_data['to_port'] = icmp_code
        elif rule_menu == 'tcp' or rule_menu == 'udp':
            cleaned_data['ip_protocol'] = rule_menu
            if port_or_range == "port":
                cleaned_data["from_port"] = port
                cleaned_data["to_port"] = port
                if port is None:
                    msg = _('The specified port is invalid.')
                    raise ValidationError(msg)
            else:
                if from_port is None:
                    msg = _('The "from" port number is invalid.')
                    raise ValidationError(msg)
                if to_port is None:
                    msg = _('The "to" port number is invalid.')
                    raise ValidationError(msg)
                if to_port < from_port:
                    msg = _('The "to" port number must be greater than '
                            'or equal to the "from" port number.')
                    raise ValidationError(msg)
        elif rule_menu == 'custom':
            pass
        else:
            cleaned_data['ip_protocol'] = self.rules[rule_menu]['ip_protocol']
            cleaned_data['from_port'] = int(self.rules[rule_menu]['from_port'])
            cleaned_data['to_port'] = int(self.rules[rule_menu]['to_port'])
            cleaned_data['direction'] = self.rules[rule_menu].get('direction')

        # NOTE(amotoki): There are two cases where cleaned_data['direction']
        # is empty: (1) Nova Security Group is used. Since "direction" is
        # HiddenInput, direction field exists but its value is ''.
        # (2) Template is used. In this case, the default value is None.
        # To make sure 'direction' field has 'ingress' or 'egress',
        # fill this field here if it is not specified.
        if not cleaned_data['direction']:
            cleaned_data['direction'] = 'ingress'

        if remote == "cidr":
            cleaned_data['security_group'] = None
        else:
            cleaned_data['cidr'] = None

        # If cleaned_data does not contain cidr, cidr is already marked
        # as invalid, so skip the further validation for cidr.
        # In addition cleaned_data['cidr'] is None means source_group is used.
        if 'cidr' in cleaned_data and cleaned_data['cidr'] is not None:
            cidr = cleaned_data['cidr']
            if not cidr:
                msg = _('CIDR must be specified.')
                self._errors['cidr'] = self.error_class([msg])
            else:
                # If cidr is specified, ethertype is determined from IP address
                # version. It is used only when Neutron is enabled.
                ip_ver = netaddr.IPNetwork(cidr).version
                cleaned_data['ethertype'] = 'IPv6' if ip_ver == 6 else 'IPv4'

        return cleaned_data

    def handle(self, request, data):
        try:
            rule = api.network.security_group_rule_create(
                request, filters.get_int_or_uuid(data['id']),
                data['direction'], data['ethertype'], data['ip_protocol'],
                data['from_port'], data['to_port'], data['cidr'],
                data['security_group'])
            messages.success(request,
                             _('Successfully added rule: %s') % unicode(rule))
            return rule
        except Exception:
            redirect = reverse(
                "horizon:project:access_and_security:"
                "security_groups:detail",
                args=[data['id']])
            exceptions.handle(request,
                              _('Unable to add rule to security group.'),
                              redirect=redirect)
Exemplo n.º 28
0
class AddHostInfoAction(workflows.Action):
    FIELD_LABEL_PERSONALITY = _("Personality")
    FIELD_LABEL_HOSTNAME = _("Host Name")
    FIELD_LABEL_MGMT_MAC = _("Management MAC Address")
    FIELD_LABEL_MGMT_IP = _("Management IP Address")

    personality = forms.ChoiceField(
        label=FIELD_LABEL_PERSONALITY,
        help_text=_("Host Personality"),
        choices=PERSONALITY_CHOICES,
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'personality'
        }))

    subfunctions = forms.ChoiceField(
        label=FIELD_LABEL_PERFORMANCE_PROFILE,
        choices=PERFORMANCE_CHOICES,
        widget=forms.Select(
            attrs={
                'class':
                'switched',
                'data-switch-on':
                'personality',
                'data-personality-' + stx_api.sysinv.PERSONALITY_COMPUTE:
                _("Personality Sub-Type")
            }))

    hostname = forms.RegexField(
        label=FIELD_LABEL_HOSTNAME,
        max_length=255,
        required=False,
        regex=r'^[\w\.\-]+$',
        error_messages={
            'invalid':
            _('Name may only contain letters,'
              ' numbers, underscores, '
              'periods and hyphens.')
        },
        widget=forms.TextInput(
            attrs={
                'class':
                'switched',
                'data-switch-on':
                'personality',
                'data-personality-' + stx_api.sysinv.PERSONALITY_COMPUTE:
                FIELD_LABEL_HOSTNAME,
            }))

    mgmt_mac = forms.MACAddressField(
        label=FIELD_LABEL_MGMT_MAC,
        widget=forms.TextInput(
            attrs={
                'class':
                'switched',
                'data-switch-on':
                'personality',
                'data-personality-' + stx_api.sysinv.PERSONALITY_COMPUTE:
                FIELD_LABEL_MGMT_MAC,
                'data-personality-' + stx_api.sysinv.PERSONALITY_CONTROLLER:
                FIELD_LABEL_MGMT_MAC,
                'data-personality-' + stx_api.sysinv.PERSONALITY_STORAGE:
                FIELD_LABEL_MGMT_MAC,
            }))

    class Meta(object):
        name = _("Host Info")
        help_text = _(
            "From here you can add the configuration for a new host.")

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

        # pesonality cannot be storage if ceph is not configured
        cinder_backend = stx_api.sysinv.get_cinder_backend(request)
        if stx_api.sysinv.CINDER_BACKEND_CEPH not in cinder_backend:
            self.fields['personality'].choices = \
                PERSONALITY_CHOICES_WITHOUT_STORAGE

        # All-in-one system, personality can only be controller.
        systems = stx_api.sysinv.system_list(request)
        system_type = systems[0].to_dict().get('system_type')
        if system_type == constants.TS_AIO:
            self.fields['personality'].choices = \
                PERSONALITY_CHOICE_CONTROLLER
            self.fields['personality'].widget.attrs['disabled'] = 'disabled'

        # Remove compute personality if in DC mode and region
        if getattr(self.request.user, 'services_region', None) == 'RegionOne' \
                and getattr(settings, 'DC_MODE', False):
            self.fields['personality'].choices = \
                [choice for choice in self.fields['personality'].choices
                 if choice[0] != stx_api.sysinv.PERSONALITY_COMPUTE]

    def clean(self):
        cleaned_data = super(AddHostInfoAction, self).clean()
        return cleaned_data
Exemplo n.º 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)

    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['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': 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)
Exemplo n.º 30
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': 2
    }),
                                  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'),
                'ng-model': 'copyFrom',
                'ng-change': 'selectImageFormat(copyFrom)'
            }),
        required=False)

    image_file = forms.FileField(
        label=_("Load File"),
        help_text=_("A local image to upload."),
        widget=forms.FileInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'source',
                'data-source-file': _('Load 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"),
        widget=forms.TextInput(attrs={'readonly': 'readonly'}),
        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_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
        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()
        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_url = data.get('copy_from', None)
        image_file = data.get('image_file', 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'
        data['is_public'] = 'public'
        properties = {}
        if data.get('description'):
            properties['description'] = data['description']
        if data.get('kernel'):
            properties['kernel_id'] = data['kernel']
        if data.get('ramdisk'):
            properties['ramdisk_id'] = data['ramdisk']
        if data.get('architecture'):
            properties['architecture'] = data['architecture']

        meta = {
            'visibility': data['is_public'],
            'protected': False,
            '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']
        }
        meta.update(properties)
        if (api.glance.get_image_upload_mode() != 'off' 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'])
            if request.session.has_key('last_activity'):
                request.session['last_activity'] = int(time.time())
            return image
        except Exception:
            exceptions.handle(request, _('Unable to create new image.'))