Exemple #1
0
class JobBinaryCreateForm(forms.SelfHandlingForm):
    NEW_SCRIPT = "newscript"
    UPLOAD_BIN = "uploadfile"

    job_binary_name = forms.CharField(label=_("Name"))

    job_binary_type = forms.ChoiceField(
        label=_("Storage type"),
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'jb_type'
        }))

    job_binary_url = forms.CharField(label=_("URL"),
                                     required=False,
                                     widget=LabeledInput(
                                         attrs={
                                             'class': 'switched',
                                             'data-switch-on': 'jb_type',
                                             'data-jb_type-swift': _('URL')
                                         }))

    job_binary_internal = forms.ChoiceField(
        label=_("Internal binary"),
        required=False,
        widget=forms.Select(
            attrs={
                'class': 'switched switchable',
                'data-slug': 'jb_internal',
                'data-switch-on': 'jb_type',
                'data-jb_type-internal-db': _('Internal Binary')
            }))

    job_binary_file = forms.FileField(
        label=_("Upload File"),
        required=False,
        widget=forms.ClearableFileInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'jb_internal',
                'data-jb_internal-uploadfile': _("Upload File")
            }))

    job_binary_script_name = forms.CharField(
        label=_("Script name"),
        required=False,
        widget=forms.TextInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'jb_internal',
                'data-jb_internal-newscript': _("Script name")
            }))

    job_binary_script = forms.CharField(
        label=_("Script text"),
        required=False,
        widget=forms.Textarea(
            attrs={
                'rows': 4,
                'class': 'switched',
                'data-switch-on': 'jb_internal',
                'data-jb_internal-newscript': _("Script text")
            }))

    job_binary_username = forms.CharField(
        label=_("Username"),
        required=False,
        widget=forms.TextInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'jb_type',
                'data-jb_type-swift': _('Username')
            }))

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

    job_binary_description = forms.CharField(label=_("Description"),
                                             required=False,
                                             widget=forms.Textarea())

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

        self.help_text_template = ("project/data_processing.job_binaries/"
                                   "_create_job_binary_help.html")

        self.fields["job_binary_type"].choices =\
            [("internal-db", "Internal database"),
             ("swift", "Swift")]

        self.fields["job_binary_internal"].choices =\
            self.populate_job_binary_internal_choices(request)

    def populate_job_binary_internal_choices(self, request):
        try:
            job_binaries = saharaclient.job_binary_internal_list(request)
        except Exception:
            exceptions.handle(request,
                              _("Failed to get list of internal binaries."))
            job_binaries = []

        choices = [(job_binary.id, job_binary.name)
                   for job_binary in job_binaries]
        choices.insert(0, (self.NEW_SCRIPT, '*Create a script'))
        choices.insert(0, (self.UPLOAD_BIN, '*Upload a new file'))

        return choices

    def handle(self, request, context):
        try:
            extra = {}
            bin_url = "%s://%s" % (context["job_binary_type"],
                                   context["job_binary_url"])
            if (context["job_binary_type"] == "internal-db"):
                bin_url = self.handle_internal(request, context)
            elif (context["job_binary_type"] == "swift"):
                extra = self.handle_swift(request, context)

            bin_object = saharaclient.job_binary_create(
                request, context["job_binary_name"], bin_url,
                context["job_binary_description"], extra)
            messages.success(request, "Successfully created job binary")
            return bin_object
        except Exception:
            exceptions.handle(request, _("Unable to create job binary"))
            return False

    def get_help_text(self, extra_context=None):
        text = ""
        extra_context = extra_context or {}
        if self.help_text_template:
            tmpl = template.loader.get_template(self.help_text_template)
            context = template.RequestContext(self.request, extra_context)
            text += tmpl.render(context)
        else:
            text += defaultfilters.linebreaks(force_text(self.help_text))
        return defaultfilters.safe(text)

    class Meta(object):
        name = _("Create Job Binary")
        help_text_template = ("project/data_processing.job_binaries/"
                              "_create_job_binary_help.html")

    def handle_internal(self, request, context):
        result = ""

        bin_id = context["job_binary_internal"]
        if (bin_id == self.UPLOAD_BIN):
            try:
                result = saharaclient.job_binary_internal_create(
                    request,
                    self.get_unique_binary_name(
                        request, request.FILES["job_binary_file"].name),
                    request.FILES["job_binary_file"].read())
                bin_id = result.id
            except Exception:
                exceptions.handle(request, _("Unable to upload job binary"))
                return None
        elif (bin_id == self.NEW_SCRIPT):
            try:
                result = saharaclient.job_binary_internal_create(
                    request,
                    self.get_unique_binary_name(
                        request, context["job_binary_script_name"]),
                    context["job_binary_script"])
                bin_id = result.id
            except Exception:
                exceptions.handle(request, _("Unable to create job binary"))
                return None

        return "internal-db://%s" % bin_id

    def handle_swift(self, request, context):
        username = context["job_binary_username"]
        password = context["job_binary_password"]

        extra = {"user": username, "password": password}
        return extra

    def get_unique_binary_name(self, request, base_name):
        try:
            internals = saharaclient.job_binary_internal_list(request)
        except Exception:
            internals = []
            exceptions.handle(request,
                              _("Failed to fetch internal binary list"))
        names = [internal.name for internal in internals]
        if base_name in names:
            return "%s_%s" % (base_name, uuid.uuid1())
        return base_name
class StopPluginForm(forms.SelfHandlingForm):

    uuid = forms.CharField(label=_("Plugin ID"), widget=forms.HiddenInput)

    name = forms.CharField(
        label=_('Plugin Name'),
        widget=forms.TextInput(attrs={'readonly': 'readonly'})
    )

    delay = forms.IntegerField(
        label=_("Delay in secs"),
        required=False,
        help_text=_("OPTIONAL: seconds to wait before stopping the plugin")
    )

    board_list = forms.MultipleChoiceField(
        label=_("Boards List"),
        widget=forms.SelectMultiple(
            attrs={'class': 'switchable', 'data-slug': 'slug-stop-boards'}),
        help_text=_("Select boards in this pool ")
    )

    def __init__(self, *args, **kwargs):

        super(StopPluginForm, self).__init__(*args, **kwargs)
        # input=kwargs.get('initial',{})

        boardslist_length = len(kwargs["initial"]["board_list"])

        self.fields["board_list"].choices = kwargs["initial"]["board_list"]
        self.fields["board_list"].max_length = boardslist_length

    def handle(self, request, data):

        counter = 0

        if not data["delay"]:
            data["delay"] = {}
        else:
            data["delay"] = {"delay": data["delay"]}

        for board in data["board_list"]:
            for key, value in self.fields["board_list"].choices:
                if key == board:

                    try:
                        plugin = None
                        plugin = iotronic.plugin_action(request, key,
                                                        data["uuid"],
                                                        "PluginStop",
                                                        data["delay"])
                        # LOG.debug("API: %s %s", plugin, request)
                        message_text = "Plugin stopped successfully on board "\
                                       + str(value) + "."
                        messages.success(request, _(message_text))

                        if counter != len(data["board_list"]) - 1:
                            counter += 1
                        else:
                            return plugin
                    except Exception:
                        message_text = "Unable to stop plugin on board " \
                                       + str(value) + "."
                        exceptions.handle(request, _(message_text))

                    break
Exemple #3
0
class CreatePort(forms.SelfHandlingForm):
    name = forms.CharField(max_length=255, label=_("Name"), required=False)
    admin_state = forms.BooleanField(label=_("Enable Admin State"),
                                     initial=True,
                                     required=False)
    device_id = forms.CharField(max_length=100,
                                label=_("Device ID"),
                                help_text=_("Device ID attached to the port"),
                                required=False)
    device_owner = forms.CharField(
        max_length=100,
        label=_("Device Owner"),
        help_text=_("Owner of the device attached to the port"),
        required=False)
    specify_ip = forms.ThemableChoiceField(
        label=_("Specify IP address or subnet"),
        help_text=_("To specify a subnet or a fixed IP, select any options."),
        initial=False,
        required=False,
        choices=[('', _("Unspecified")), ('subnet_id', _("Subnet")),
                 ('fixed_ip', _("Fixed IP Address"))],
        widget=forms.ThemableSelectWidget(attrs={
            'class': 'switchable',
            'data-slug': 'specify_ip',
        }))
    subnet_id = forms.ThemableChoiceField(
        label=_("Subnet"),
        required=False,
        widget=forms.ThemableSelectWidget(
            attrs={
                'class': 'switched',
                'data-switch-on': 'specify_ip',
                'data-specify_ip-subnet_id': _('Subnet'),
            }))
    fixed_ip = forms.IPField(
        label=_("Fixed IP Address"),
        required=False,
        help_text=_("Specify the subnet IP address for the new port"),
        version=forms.IPv4 | forms.IPv6,
        widget=forms.TextInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'specify_ip',
                'data-specify_ip-fixed_ip': _('Fixed IP Address'),
            }))
    mac_address = forms.MACAddressField(
        label=_("MAC Address"),
        required=False,
        help_text=_("Specify the MAC address for the new port"))
    failure_url = 'horizon:project:networks:detail'

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

        # prepare subnet choices and input area for each subnet
        subnet_choices = self._get_subnet_choices(kwargs['initial'])
        if subnet_choices:
            subnet_choices.insert(0, ('', _("Select a subnet")))
            self.fields['subnet_id'].choices = subnet_choices
        else:
            self.fields['specify_ip'].widget = forms.HiddenInput()
            self.fields['subnet_id'].widget = forms.HiddenInput()
            self.fields['fixed_ip'].widget = forms.HiddenInput()

        if api.neutron.is_extension_supported(request, 'mac-learning'):
            self.fields['mac_state'] = forms.BooleanField(
                label=_("MAC Learning State"), initial=False, required=False)

        try:
            if api.neutron.is_extension_supported(request, 'port-security'):
                self.fields['port_security_enabled'] = forms.BooleanField(
                    label=_("Port Security"),
                    help_text=_("Enable anti-spoofing rules for the port"),
                    initial=True,
                    required=False)
        except Exception:
            msg = _("Unable to retrieve port security state")
            exceptions.handle(self.request, msg)

    def _get_subnet_choices(self, kwargs):
        try:
            network_id = kwargs['network_id']
            network = api.neutron.network_get(self.request, network_id)
        except Exception:
            return []

        return [(subnet.id, '%s %s' % (subnet.name_or_id, subnet.cidr))
                for subnet in network.subnets]

    def handle(self, request, data):
        try:
            params = {
                'network_id': self.initial['network_id'],
                'admin_state_up': data['admin_state'],
                'name': data['name'],
                'device_id': data['device_id'],
                'device_owner': data['device_owner']
            }

            if data.get('specify_ip') == 'subnet_id':
                if data.get('subnet_id'):
                    params['fixed_ips'] = [{"subnet_id": data['subnet_id']}]
            elif data.get('specify_ip') == 'fixed_ip':
                if data.get('fixed_ip'):
                    params['fixed_ips'] = [{"ip_address": data['fixed_ip']}]

            if data.get('mac_state'):
                params['mac_learning_enabled'] = data['mac_state']
            if 'port_security_enabled' in data:
                params['port_security_enabled'] = data['port_security_enabled']

            # Send mac_address only when it is specified.
            if data['mac_address']:
                params['mac_address'] = data['mac_address']

            port = api.neutron.port_create(request, **params)
            if port['name']:
                msg = _('Port %s was successfully created.') % port['name']
            else:
                msg = _('Port %s was successfully created.') % port['id']
            messages.success(request, msg)
            return port
        except Exception as e:
            LOG.info('Failed to create a port for network %(id)s: %(exc)s', {
                'id': self.initial['network_id'],
                'exc': e
            })
            msg = (_('Failed to create a port for network %s') %
                   self.initial['network_id'])
            redirect = reverse(self.failure_url,
                               args=(self.initial['network_id'], ))
            exceptions.handle(request, msg, redirect=redirect)
Exemple #4
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.ThemableSelectWidget(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.ThemableSelectWidget(attrs=attributes),
        required=False)

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

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

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

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

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

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

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

        return cleaned

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

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

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

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

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

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

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

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

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

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

        return self.next_view.as_view()(request, **kwargs)
Exemple #5
0
class TemplateForm(forms.SelfHandlingForm):
    class Meta:
        name = _('Select Template')
        help_text = _('From here you can select a template to launch '
                      'a stack.')

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

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

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

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

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

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

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

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

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

        return cleaned

    def handle(self, request, data):
        kwargs = {
            'parameters': data['template_validate'],
            'template_data': data['template_data'],
            'template_url': data['template_url']
        }
        # NOTE (gabriel): This is a bit of a hack, essentially rewriting this
        # request so that we can chain it as an input to the next view...
        # but hey, it totally works.
        request.method = 'GET'
        return self.next_view.as_view()(request, **kwargs)
Exemple #6
0
class UpdatePort(forms.SelfHandlingForm):
    network_id = forms.CharField(widget=forms.HiddenInput())
    port_id = forms.CharField(
        label=_("ID"), widget=forms.TextInput(attrs={'readonly': 'readonly'}))
    name = forms.CharField(max_length=255, label=_("Name"), required=False)
    admin_state = forms.BooleanField(label=_("Enable Admin State"),
                                     required=False)
    failure_url = 'horizon:project:networks:detail'

    def __init__(self, request, *args, **kwargs):
        super(UpdatePort, self).__init__(request, *args, **kwargs)
        try:
            if api.neutron.is_extension_supported(request, 'binding'):
                neutron_settings = getattr(settings,
                                           'OPENSTACK_NEUTRON_NETWORK', {})
                supported_vnic_types = neutron_settings.get(
                    'supported_vnic_types', ['*'])
                if supported_vnic_types:
                    if supported_vnic_types == ['*']:
                        vnic_type_choices = VNIC_TYPES
                    else:
                        vnic_type_choices = [
                            vnic_type for vnic_type in VNIC_TYPES
                            if vnic_type[0] in supported_vnic_types
                        ]

                    self.fields['binding__vnic_type'] = forms.ChoiceField(
                        choices=vnic_type_choices,
                        label=_("Binding: VNIC Type"),
                        help_text=_(
                            "The VNIC type that is bound to the neutron port"),
                        required=False)
        except Exception:
            msg = _("Unable to verify the VNIC types extension in Neutron")
            exceptions.handle(self.request, msg)

        try:
            if api.neutron.is_extension_supported(request, 'mac-learning'):
                self.fields['mac_state'] = forms.BooleanField(
                    label=_("MAC Learning State"),
                    initial=False,
                    required=False)
        except Exception:
            msg = _("Unable to retrieve MAC learning state")
            exceptions.handle(self.request, msg)

        try:
            if api.neutron.is_extension_supported(request, 'port-security'):
                self.fields['port_security_enabled'] = forms.BooleanField(
                    label=_("Port Security"),
                    help_text=_("Enable anti-spoofing rules for the port"),
                    required=False)
        except Exception:
            msg = _("Unable to retrieve port security state")
            exceptions.handle(self.request, msg)

    def handle(self, request, data):
        try:
            LOG.debug('params = %s', data)
            extension_kwargs = {}
            if 'binding__vnic_type' in data:
                extension_kwargs['binding__vnic_type'] = \
                    data['binding__vnic_type']
            if 'mac_state' in data:
                extension_kwargs['mac_learning_enabled'] = data['mac_state']
            if 'port_security_enabled' in data:
                extension_kwargs['port_security_enabled'] = \
                    data['port_security_enabled']

            port = api.neutron.port_update(request,
                                           data['port_id'],
                                           name=data['name'],
                                           admin_state_up=data['admin_state'],
                                           **extension_kwargs)
            msg = _('Port %s was successfully updated.') % data['port_id']
            messages.success(request, msg)
            return port
        except Exception as e:
            LOG.info('Failed to update port %(id)s: %(exc)s', {
                'id': data['port_id'],
                'exc': e
            })
            msg = _('Failed to update port %s') % data['port_id']
            redirect = reverse(self.failure_url, args=[data['network_id']])
            exceptions.handle(request, msg, redirect=redirect)
Exemple #7
0
    def __init__(self, request, *args, **kwargs):
        super(JobBinaryCreateForm, self).__init__(request, *args, **kwargs)

        self.help_text_template = ("project/data_processing.job_binaries/"
                                   "_create_job_binary_help.html")

        self.fields["job_binary_name"] = forms.CharField(label=_("Name"))

        self.fields["job_binary_type"] = forms.ChoiceField(
            label=_("Storage type"),
            widget=forms.Select(
                attrs={
                    'class': 'switchable',
                    'data-slug': 'jb_type'
                }))

        self.fields["job_binary_url"] = forms.CharField(
            label=_("URL"),
            required=False,
            widget=LabeledInput(
                attrs={
                    'class': 'switched',
                    'data-switch-on': 'jb_type',
                    'data-jb_type-swift': _('URL')
                }))

        self.fields["job_binary_internal"] = forms.ChoiceField(
            label=_("Internal binary"),
            required=False,
            widget=forms.Select(
                attrs={
                    'class': 'switched switchable',
                    'data-slug': 'jb_internal',
                    'data-switch-on': 'jb_type',
                    'data-jb_type-internal-db': _('Internal Binary')
                }))

        self.fields["job_binary_file"] = forms.FileField(
            label=_("Upload File"),
            required=False,
            widget=forms.ClearableFileInput(
                attrs={
                    'class': 'switched',
                    'data-switch-on': 'jb_internal',
                    'data-jb_internal-uploadfile': _("Upload File")
                }))

        self.fields["job_binary_script_name"] = forms.CharField(
            label=_("Script name"),
            required=False,
            widget=forms.TextInput(
                attrs={
                    'class': 'switched',
                    'data-switch-on': 'jb_internal',
                    'data-jb_internal-newscript': _("Script name")
                }))

        self.fields["job_binary_script"] = forms.CharField(
            label=_("Script text"),
            required=False,
            widget=forms.Textarea(
                attrs={
                    'rows': 4,
                    'class': 'switched',
                    'data-switch-on': 'jb_internal',
                    'data-jb_internal-newscript': _("Script text")
                }))

        self.fields["job_binary_username"] = forms.CharField(
            label=_("Username"),
            required=False,
            widget=forms.TextInput(
                attrs={
                    'class': 'switched',
                    'data-switch-on': 'jb_type',
                    'data-jb_type-swift': _('Username')
                }))

        self.fields["job_binary_password"] = forms.CharField(
            label=_("Password"),
            required=False,
            widget=forms.PasswordInput(
                attrs={
                    'autocomplete': 'off',
                    'class': 'switched',
                    'data-switch-on': 'jb_type',
                    'data-jb_type-swift': _('Password')
                }))

        self.fields["job_binary_description"] = (
            forms.CharField(label=_("Description"),
                            required=False,
                            widget=forms.Textarea()))

        self.fields["job_binary_type"].choices =\
            [("internal-db", "Internal database"),
             ("swift", "Swift")]

        self.fields["job_binary_internal"].choices =\
            self.populate_job_binary_internal_choices(request)

        self.load_form_values()
Exemple #8
0
class AddInterface(forms.SelfHandlingForm):
    subnet_id = forms.ChoiceField(label=_("Subnet"))
    ip_address = forms.IPField(label=_("IP Address (optional)"),
                               required=False,
                               initial="",
                               help_text=_(
                                   "Specify an IP address for the interface "
                                   "created (e.g. 192.168.0.254)."),
                               version=forms.IPv4 | forms.IPv6,
                               mask=False)
    router_name = forms.CharField(
        label=_("Router Name"),
        widget=forms.TextInput(attrs={'readonly': 'readonly'}))
    router_id = forms.CharField(
        label=_("Router ID"),
        widget=forms.TextInput(attrs={'readonly': 'readonly'}))
    failure_url = 'horizon:project:routers:detail'

    def __init__(self, request, *args, **kwargs):
        super(AddInterface, self).__init__(request, *args, **kwargs)
        c = self.populate_subnet_id_choices(request)
        self.fields['subnet_id'].choices = c

    def populate_subnet_id_choices(self, request):
        tenant_id = self.request.user.tenant_id
        networks = []
        router_subnet_ids = []
        router_id = request.REQUEST.get('router_id',
                                        self.initial.get('router_id'))

        try:
            networks = api.neutron.network_list_for_tenant(request, tenant_id)
            if router_id:
                ports = api.neutron.port_list(request, device_id=router_id)
                router_subnet_ids = [
                    fixed_ip["subnet_id"] for port in ports
                    for fixed_ip in port.fixed_ips
                ]
        except Exception as e:
            msg = _('Failed to get network list %s') % e
            LOG.info(msg)
            messages.error(request, msg)
            if router_id:
                redirect = reverse(self.failure_url, args=[router_id])
            else:
                redirect = reverse('horizon:project:routers:index')
            exceptions.handle(request, msg, redirect=redirect)
            return

        choices = []
        for n in networks:
            net_name = n.name + ': ' if n.name else ''
            choices += [(subnet.id, '%s%s (%s)' %
                         (net_name, subnet.cidr, subnet.name or subnet.id))
                        for subnet in n['subnets']
                        if subnet.id not in router_subnet_ids]
        if choices:
            choices.insert(0, ("", _("Select Subnet")))
        else:
            choices.insert(0, ("", _("No subnets available")))
        return choices

    def handle(self, request, data):
        if data['ip_address']:
            port = self._add_interface_by_port(request, data)
        else:
            port = self._add_interface_by_subnet(request, data)
        msg = _('Interface added')
        if port:
            msg += ' ' + port.fixed_ips[0]['ip_address']
        LOG.debug(msg)
        messages.success(request, msg)
        return True

    def _add_interface_by_subnet(self, request, data):
        router_id = data['router_id']
        try:
            router_inf = api.neutron.router_add_interface(
                request, router_id, subnet_id=data['subnet_id'])
        except Exception as e:
            self._handle_error(request, router_id, e)
        try:
            port = api.neutron.port_get(request, router_inf['port_id'])
        except Exception:
            # Ignore an error when port_get() since it is just
            # to get an IP address for the interface.
            port = None
        return port

    def _add_interface_by_port(self, request, data):
        router_id = data['router_id']
        subnet_id = data['subnet_id']
        try:
            subnet = api.neutron.subnet_get(request, subnet_id)
        except Exception:
            msg = _('Unable to get subnet "%s"') % subnet_id
            self._handle_error(request, router_id, msg)
        try:
            ip_address = data['ip_address']
            body = {
                'network_id': subnet.network_id,
                'fixed_ips': [{
                    'subnet_id': subnet.id,
                    'ip_address': ip_address
                }]
            }
            port = api.neutron.port_create(request, **body)
        except Exception as e:
            self._handle_error(request, router_id, e)
        try:
            api.neutron.router_add_interface(request,
                                             router_id,
                                             port_id=port.id)
        except Exception as e:
            self._delete_port(request, port)
            self._handle_error(request, router_id, e)
        return port

    def _handle_error(self, request, router_id, reason):
        msg = _('Failed to add_interface: %s') % reason
        LOG.info(msg)
        redirect = reverse(self.failure_url, args=[router_id])
        exceptions.handle(request, msg, redirect=redirect)

    def _delete_port(self, request, port):
        try:
            api.neutron.port_delete(request, port.id)
        except Exception:
            msg = _('Failed to delete port %s') % port.id
            LOG.info(msg)
            exceptions.handle(request, msg)
Exemple #9
0
class UpdateProviderNetworkRange(forms.SelfHandlingForm):
    failure_url = 'horizon:admin:datanets:datanets:detail'
    providernet_id = forms.CharField(widget=forms.HiddenInput())
    providernet_range_id = forms.CharField(widget=forms.HiddenInput())
    name = forms.CharField(
        max_length=255,
        label=_("Name"),
        required=False,
        widget=forms.TextInput(attrs={'readonly': 'readonly'}))
    description = forms.CharField(max_length=255,
                                  label=_("Description"),
                                  required=False)
    minimum = forms.IntegerField(label=_("Minimum"), min_value=1)
    maximum = forms.IntegerField(label=_("Maximum"), min_value=1)
    shared = forms.BooleanField(widget=forms.HiddenInput(), required=False)
    tenant_id = forms.CharField(widget=forms.HiddenInput(), required=False)

    # VXLAN specific fields
    mode_widget = forms.TextInput(attrs={'readonly': 'readonly'})
    mode = forms.CharField(label=_("mode"), required=False, widget=mode_widget)
    group_widget = forms.TextInput(attrs={'readonly': 'readonly'})
    group = forms.CharField(max_length=255,
                            label=_("Multicast Group Address"),
                            required=False,
                            widget=group_widget)
    port_widget = forms.RadioSelect(attrs={'disabled': 'disabled'})
    port_choices = [('4789', _('IANA Assigned VXLAN UDP port (4789)')),
                    ('4790', _('IANA Assigned VXLAN-GPE UDP port (4790)')),
                    ('8472', _('Legacy VXLAN UDP port (8472)'))]
    port = forms.ChoiceField(label=_("UDP Port"),
                             required=False,
                             widget=port_widget,
                             choices=port_choices)
    ttl_widget = forms.TextInput(attrs={'readonly': 'readonly'})
    ttl = forms.IntegerField(label=_("TTL"), required=False, widget=ttl_widget)

    def __init__(self, request, *args, **kwargs):
        super(UpdateProviderNetworkRange,
              self).__init__(request, *args, **kwargs)
        initial = kwargs['initial']
        if 'mode' not in initial:
            del self.fields["mode"]
        if 'group' not in initial or initial.get('mode') == 'static':
            del self.fields["group"]
        if 'port' not in initial:
            del self.fields["port"]
        if 'ttl' not in initial:
            del self.fields["ttl"]

    def handle(self, request, data):
        try:
            params = {
                'description': data['description'],
                'minimum': data['minimum'],
                'maximum': data['maximum']
            }

            providernet_range = stx_api.neutron.provider_network_range_modify(
                request, data['providernet_range_id'], **params)
            msg = (_('Provider network range %s was successfully updated.') %
                   data['providernet_range_id'])
            LOG.debug(msg)
            messages.success(request, msg)
            return providernet_range
        except neutron_exceptions.NeutronClientException as e:
            LOG.info(str(e))
            redirect = reverse('horizon:admin:datanets:datanets:'
                               'detail',
                               args=(data['providernet_id'], ))
            exceptions.handle(request, str(e), redirect=redirect)
        except Exception:
            msg = (_('Failed to update provider network range %s') %
                   data['providernet_range_id'])
            LOG.info(msg)
            redirect = reverse(self.failure_url, args=[data['providernet_id']])
            exceptions.handle(request, msg, redirect=redirect)
Exemple #10
0
class UpdateIpam(forms.SelfHandlingForm):
    id = forms.CharField(widget=forms.HiddenInput())
    name = forms.CharField(label=_("Name"),
                           widget=forms.TextInput(
                                      attrs={'readonly': 'readonly'}),
                           validators=[validators.validate_slug])

    dnsmethod = forms.ChoiceField(label=_('DNS Method'),
                               choices=[('default', _('Default')),
                                        ('vdns', _('Virtual DNS')),
                                        ('tenantdns', _('Tenant DNS')),
                                        ('none', _('None'))],
                               widget=forms.Select(attrs={
                                   'class': 'switchable',
                                   'data-slug': 'dnsmethod'}))

    vdns = forms.CharField(label=_("Virtual DNS"),
                          required=False,
                          help_text=_("FQ Name of Virtual DNS i.e. default-domain:vdns"),
                          widget=forms.TextInput(
                              attrs={'class': 'switched',
                                     'data-switch-on': 'dnsmethod',
                                     'data-dnsmethod-vdns': _('Virtual DNS')}))

    tenantdns = fields.IPField(label=_("Tenant DNS Server IP"),
                          required=False,
                          help_text=_("Tenant managed DNS Server's IP Address"),
                          version=fields.IPv4,
                          mask=False,
                          widget=forms.TextInput(
                              attrs={'class': 'switched',
                                     'data-switch-on': 'dnsmethod',
                                     'data-dnsmethod-tenantdns': _('Tenant DNS Server IP')}))

    ntpip = fields.IPField(label=_("NTP Server IP"),
                          required=False,
                          help_text=_("IP Address of the NTP Server"),
                          version=fields.IPv4,
                          mask=False,
                          widget=forms.TextInput())

    domainname = forms.CharField(label=_("Domain Name"),
                          required=False,
                          help_text=_("Domain Name i.e. openstack.org"),
                          widget=forms.TextInput())

    def __init__(self, *args, **kwargs):
        ipam_obj = kwargs.pop('ipam_obj', {})
        mgmt = ipam_obj.__dict__['_apidict']['mgmt']
        super(UpdateIpam, self).__init__(*args, **kwargs)
        if mgmt['ipam_dns_method'] == 'default-dns-server':
            self.fields['dnsmethod'].initial = 'default'

        if mgmt['ipam_dns_method'] == 'tenant-dns-server':
            self.fields['dnsmethod'].initial = 'tenantdns'
            if 'ipam_dns_server' in mgmt and \
                'tenant_dns_server_address' in mgmt['ipam_dns_server'] and \
                'ip_address' in mgmt['ipam_dns_server']['tenant_dns_server_address'] :
                for ip in mgmt['ipam_dns_server']['tenant_dns_server_address']['ip_address']:
                    self.fields['tenantdns'].initial = ip

        if mgmt['ipam_dns_method'] == 'virtual-dns-server':
            self.fields['dnsmethod'].initial = 'vdns'
            if 'ipam_dns_server' in mgmt and \
                'virtual_dns_server_name' in mgmt['ipam_dns_server'] and \
                mgmt['ipam_dns_server']['virtual_dns_server_name'] != None :
                self.fields['vdns'].initial = mgmt['ipam_dns_server']['virtual_dns_server_name'] 

        if mgmt['ipam_dns_method'] == 'none':
            self.fields['dnsmethod'].initial = 'none'

        if 'dhcp_option_list' in mgmt:
            dhcp_list = mgmt['dhcp_option_list']
            if dhcp_list and 'dhcp_option' in dhcp_list:
                for entry in mgmt['dhcp_option_list']['dhcp_option']:
                    if entry['dhcp_option_name'] == '4':
                        self.fields['ntpip'].initial = entry['dhcp_option_value']
                    if entry['dhcp_option_name'] == '15':
                        self.fields['domainname'].initial = entry['dhcp_option_value']

    def clean(self):
        cleaned_data = super(UpdateIpam, self).clean()
        name       = cleaned_data.get("name")
        dnsmethod  = cleaned_data.get("dnsmethod")
        vdns       = cleaned_data.get("vdns")
        tenantdns  = cleaned_data.get("tenantdns")
        ntpip      = cleaned_data.get("ntpip")
        domainname = cleaned_data.get("domainname")

        if dnsmethod == 'vdns' and not len(vdns):
            msg = _('Virtual DNS : Enter a valid Virtual DNS in FQN format')
            raise ValidationError(msg)

        if dnsmethod == 'tenantdns':
            if not tenantdns:
                msg = _('Tenant DNS Server IP : Enter Tenant DNS Server IP address')
                raise ValidationError(msg)
            elif not len(tenantdns):
                msg = _('Tenant DNS Server IP : Enter Tenant DNS Server IP address')
                raise ValidationError(msg)

        return cleaned_data

    def handle(self, request, data):
        params = {'mgmt': {'ipam_method': None,
                           'dhcp_option_list': {'dhcp_option':[]}}}

        if data['domainname']:
            params['mgmt']['dhcp_option_list']['dhcp_option'].append(
                                                {'dhcp_option_name': '15',
                                                 'dhcp_option_value':
                                                  data['domainname']})

        if data['ntpip']:
            params['mgmt']['dhcp_option_list']['dhcp_option'].append(
                                                {'dhcp_option_name': '4',
                                                 'dhcp_option_value':
                                                  data['ntpip']})

        params['mgmt']['ipam_dns_server'] = {}
        params['mgmt']['ipam_dns_server']['tenant_dns_server_address'] = {}
        params['mgmt']['ipam_dns_server']['virtual_dns_server_name'] = None

        if data['dnsmethod'] == 'default':
            params['mgmt']['ipam_dns_method'] = 'default-dns-server'

        if data['dnsmethod'] == 'none':
            params['mgmt']['ipam_dns_method'] = 'none'

        if data['dnsmethod'] == 'tenantdns':
            params['mgmt']['ipam_dns_method'] = 'tenant-dns-server'
            if data['tenantdns']:
                params['mgmt']['ipam_dns_server']['tenant_dns_server_address']['ip_address'] = []
                params['mgmt']['ipam_dns_server']['tenant_dns_server_address']['ip_address'].append(data['tenantdns'])
            
        if data['dnsmethod'] == 'vdns':
            params['mgmt']['ipam_dns_method'] = 'virtual-dns-server'
            params['mgmt']['ipam_dns_server']['virtual_dns_server_name'] = data['vdns']

        try:
            ipam = ipam_modify(request, ipam_id=data['id'], **params)
            messages.success(request,
                             _('Successfully updated network ipam: %s')
                               % data['name'])
            return ipam 
        except Exception:
            redirect = reverse("horizon:project:networking:index")
            exceptions.handle(request,
                              _('Unable to update network ipam.'),
                              redirect=redirect)
Exemple #11
0
class CreateNetworkIpam(forms.SelfHandlingForm):
    name = forms.CharField(label=_("Name"),
                           error_messages={
                               'required': _('This field is required.'),
                               'invalid': _("The string may only contain"
                                            " ASCII characters and numbers.")},
                           validators=[validators.validate_slug])

    dnsmethod = forms.ChoiceField(label=_('DNS Method'),
                               choices=[('default', _('Default')),
                                        ('vdns', _('Virtual DNS')),
                                        ('tenantdns', _('Tenant DNS')),
                                        ('none', _('None'))],
                               widget=forms.Select(attrs={
                                   'class': 'switchable',
                                   'data-slug': 'dnsmethod'}))

    vdns = forms.CharField(label=_("Virtual DNS"),
                          required=False,
                          help_text=_("FQ Name of Virtual DNS i.e. default-domain:vdns"),
                          widget=forms.TextInput(
                              attrs={'class': 'switched',
                                     'data-switch-on': 'dnsmethod',
                                     'data-dnsmethod-vdns': _('Virtual DNS')}))

    tenantdns = fields.IPField(label=_("Tenant DNS Server IP"),
                          required=False,
                          help_text=_("Tenant managed DNS Server's IP Address"),
                          version=fields.IPv4,
                          mask=False,
                          widget=forms.TextInput(
                              attrs={'class': 'switched',
                                     'data-switch-on': 'dnsmethod',
                                     'data-dnsmethod-tenantdns': _('Tenant DNS Server IP')}))

    ntpip = fields.IPField(label=_("NTP Server IP"),
                          required=False,
                          help_text=_("IP Address of the NTP Server"),
                          version=fields.IPv4,
                          mask=False,
                          widget=forms.TextInput())

    domainname = forms.CharField(label=_("Domain Name"),
                          required=False,
                          help_text=_("Domain Name i.e. openstack.org"),
                          widget=forms.TextInput())

    def clean(self):
        cleaned_data = super(CreateNetworkIpam, self).clean()
        name       = cleaned_data.get("name")
        dnsmethod  = cleaned_data.get("dnsmethod")
        vdns       = cleaned_data.get("vdns")
        tenantdns  = cleaned_data.get("tenantdns")
        ntpip      = cleaned_data.get("ntpip")
        domainname = cleaned_data.get("domainname")

        if dnsmethod == 'vdns' and not len(vdns):
            msg = _('Virtual DNS : Enter a valid Virtual DNS in FQN format')
            raise ValidationError(msg)

        if dnsmethod == 'tenantdns':
            if not tenantdns:
                msg = _('Tenant DNS Server IP : Enter Tenant DNS Server IP address')
                raise ValidationError(msg)
            elif not len(tenantdns):
                msg = _('Tenant DNS Server IP : Enter Tenant DNS Server IP address')
                raise ValidationError(msg)

        return cleaned_data

    def handle(self, request, data):
        params = {'name': data['name'],
                  'mgmt': {'ipam_method': None,
                           'dhcp_option_list': {'dhcp_option':[]}}}

        if data['domainname']:
            params['mgmt']['dhcp_option_list']['dhcp_option'].append(
                                                {'dhcp_option_name': '15',
                                                 'dhcp_option_value':
                                                  data['domainname']})

        if data['ntpip']:
            params['mgmt']['dhcp_option_list']['dhcp_option'].append(
                                                {'dhcp_option_name': '4',
                                                 'dhcp_option_value':
                                                  data['ntpip']})

        params['mgmt']['ipam_dns_server'] = {}
        params['mgmt']['ipam_dns_server']['tenant_dns_server_address'] = {}
        params['mgmt']['ipam_dns_server']['virtual_dns_server_name'] = None

        if data['dnsmethod'] == 'default':
            params['mgmt']['ipam_dns_method'] = 'default-dns-server'

        if data['dnsmethod'] == 'none':
            params['mgmt']['ipam_dns_method'] = 'none'

        if data['dnsmethod'] == 'tenantdns':
            params['mgmt']['ipam_dns_method'] = 'tenant-dns-server'
            if data['tenantdns']:
                params['mgmt']['ipam_dns_server']['tenant_dns_server_address']['ip_address'] = []
                params['mgmt']['ipam_dns_server']['tenant_dns_server_address']['ip_address'].append(data['tenantdns'])
            
        if data['dnsmethod'] == 'vdns':
            params['mgmt']['ipam_dns_method'] = 'virtual-dns-server'
            params['mgmt']['ipam_dns_server']['virtual_dns_server_name'] = data['vdns']
        try:
            ipam = ipam_create(request, **params)
            messages.success(request,
                             _('Successfully created network ipam: %s')
                               % data['name'])
            return ipam 
        except Exception:
            redirect = reverse("horizon:project:networking:index")
            exceptions.handle(request,
                              _('Unable to create network ipam.'),
                              redirect=redirect)
class AddMonitorAction(workflows.Action):
    type = forms.ChoiceField(label=_("Type"),
                             choices=[('ping', _('PING')), ('tcp', _('TCP')),
                                      ('http', _('HTTP')),
                                      ('https', _('HTTPS'))],
                             widget=forms.Select(attrs={
                                 'class': 'switchable',
                                 'data-slug': 'type'
                             }))
    delay = forms.IntegerField(
        min_value=1,
        label=_("Delay"),
        help_text=_("The minimum time in seconds between regular checks "
                    "of a member"))
    timeout = forms.IntegerField(
        min_value=1,
        label=_("Timeout"),
        help_text=_("The maximum time in seconds for a monitor to wait "
                    "for a reply"))
    max_retries = forms.IntegerField(
        max_value=10,
        min_value=1,
        label=_("Max Retries (1~10)"),
        help_text=_("Number of permissible failures before changing "
                    "the status of member to inactive"))
    http_method = forms.ChoiceField(
        initial="GET",
        required=False,
        choices=[('GET', _('GET'))],
        label=_("HTTP Method"),
        help_text=_("HTTP method used to check health status of a member"),
        widget=forms.Select(
            attrs={
                'class': 'switched',
                'data-switch-on': 'type',
                'data-type-http': _('HTTP Method'),
                'data-type-https': _('HTTP Method')
            }))
    url_path = forms.CharField(initial="/",
                               required=False,
                               max_length=80,
                               label=_("URL"),
                               widget=forms.TextInput(
                                   attrs={
                                       'class': 'switched',
                                       'data-switch-on': 'type',
                                       'data-type-http': _('URL'),
                                       'data-type-https': _('URL')
                                   }))
    expected_codes = forms.RegexField(
        initial="200",
        required=False,
        max_length=80,
        regex=r'^(\d{3}(\s*,\s*\d{3})*)$|^(\d{3}-\d{3})$',
        label=_("Expected HTTP Status Codes"),
        help_text=_("Expected code may be a single value (e.g. 200), "
                    "a list of values (e.g. 200, 202), "
                    "or range of values (e.g. 200-204)"),
        widget=forms.TextInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'type',
                'data-type-http': _('Expected HTTP Status Codes'),
                'data-type-https': _('Expected HTTP Status Codes')
            }))
    admin_state_up = forms.BooleanField(label=_("Admin State"),
                                        initial=True,
                                        required=False)

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

    def clean(self):
        cleaned_data = super(AddMonitorAction, self).clean()
        type_opt = cleaned_data.get('type')

        if type_opt in ['http', 'https']:
            http_method_opt = cleaned_data.get('http_method')
            url_path = cleaned_data.get('url_path')
            expected_codes = cleaned_data.get('expected_codes')

            if not http_method_opt:
                msg = _('Please choose a HTTP method')
                self._errors['http_method'] = self.error_class([msg])
            if not url_path:
                msg = _('Please specify an URL')
                self._errors['url_path'] = self.error_class([msg])
            if not expected_codes:
                msg = _('Please enter a single value (e.g. 200), '
                        'a list of values (e.g. 200, 202), '
                        'or range of values (e.g. 200-204)')
                self._errors['expected_codes'] = self.error_class([msg])
        return cleaned_data

    class Meta:
        name = _("Add New Monitor")
        permissions = ('openstack.services.network', )
        help_text = _("Create a monitor template.\n\n"
                      "Select type of monitoring. "
                      "Specify delay, timeout, and retry limits "
                      "required by the monitor. "
                      "Specify method, URL path, and expected "
                      "HTTP codes upon success.")
Exemple #13
0
class CreateECStoragePolicy(forms.SelfHandlingForm):
    name = forms.CharField(max_length=255,
                           label=_("Name"),
                           help_text=_("The name of the new policy."),
                           widget=forms.TextInput(attrs={
                               "ng-model": "name",
                               "not-blank": ""
                           }))

    partition_power = forms.CharField(
        max_length=255,
        label=_("Partiton Power"),
        help_text=_("If the value is x the num of partitions will be 2^x"),
        initial=10)

    time = forms.CharField(
        max_length=255,
        label=_("Time"),
        help_text=_(
            "Time between moving a partition more than once. In hours"),
        initial=1)

    ec_type = forms.CharField(
        max_length=255,
        label=_("EC Type"),
        required=True,
        help_text=_(
            "Is chosen from the list of EC backends supported by PyECLib"),
        initial='liberasurecode_rs_vand')

    ec_num_data_fragments = forms.CharField(
        max_length=255,
        label=_("Num. Data Fragments"),
        required=True,
        help_text=_(
            "The total number of fragments that will be comprised of data."),
        initial=10)

    ec_num_parity_fragments = forms.CharField(
        max_length=255,
        label=_("Num. Parity Fragments"),
        required=True,
        help_text=_(
            "The total number of fragments that will be comprised of parity."),
        initial=4)

    ec_object_segment_size = forms.CharField(
        max_length=255,
        label=_("Object Segment Size"),
        required=True,
        help_text=
        _("The amount of data that will be buffered up before feeding a segment into the encoder/decoder."
          ),
        initial=1048576)

    ec_duplication_factor = forms.CharField(
        max_length=255,
        label=_("Duplication Factor"),
        required=True,
        help_text=
        _("EC Duplication enables Swift to make duplicated copies of fragments of erasure coded objects."
          ),
        initial=1)

    policy_type = forms.CharField(widget=forms.HiddenInput(), initial='EC')

    deprecated = forms.CharField(widget=forms.HiddenInput(), initial='False')

    deployed = forms.CharField(widget=forms.HiddenInput(), initial='False')

    devices = forms.CharField(widget=forms.HiddenInput(), initial='[]')

    default = forms.CharField(widget=forms.HiddenInput(), initial='False')

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

    def handle(self, request, data):
        try:
            response = api.swift_new_storage_policy(request, data)
            if 200 <= response.status_code < 300:
                messages.success(request,
                                 _("Storage policy successfully created."))
                return data
            else:
                raise sdsexception.SdsException(response.text)
        except Exception as ex:
            redirect = reverse("horizon:crystal:rings:index")
            error_message = "Unable to create storage policy.\t %s" % ex.message
            exceptions.handle(request, _(error_message), redirect=redirect)
Exemple #14
0
class CreateNetworkProfile(forms.SelfHandlingForm):
    """ Create Network Profile form."""

    name = forms.CharField(max_length=255, label=_("Name"), required=True)
    segment_type = forms.ChoiceField(
        label=_('Segment Type'),
        choices=[('vlan', _('VLAN')), ('vxlan', _('VXLAN'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'segtype'
        }))
    segment_range = forms.CharField(max_length=255,
                                    label=_("Segment Range"),
                                    required=True,
                                    help_text=_("1-4093 for VLAN"))
    # TODO(absubram): Update help text for VXLAN segment range value.
    multicast_ip_range = forms.CharField(
        max_length=30,
        label=_("Multicast IP Range"),
        required=False,
        widget=forms.TextInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'segtype',
                'data-segtype-vxlan': _("Multicast IP Range")
            }))
    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_id = forms.ChoiceField(label=_("Project"), required=False)

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

    def handle(self, request, data):
        try:
            LOG.debug(_('request = %(req)s, params = %(params)s'), {
                'req': request,
                'params': data
            })
            profile = api.neutron.profile_create(
                request,
                name=data['name'],
                segment_type=data['segment_type'],
                segment_range=data['segment_range'],
                physical_network=data['physical_network'],
                multicast_ip_range=data['multicast_ip_range'],
                tenant_id=data['project_id'])
            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)
Exemple #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_WORKER:
                _("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_WORKER:
                _("Host Name")
            }))

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

    clock_synchronization = forms.ChoiceField(
        label=_("Clock Synchronization"),
        choices=stx_api.sysinv.CLOCK_SYNCHRONIZATION_CHOICES)

    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
        storage_backend = stx_api.sysinv.get_storage_backend(request)
        if stx_api.sysinv.STORAGE_BACKEND_CEPH not in storage_backend:
            self.fields['personality'].choices = \
                PERSONALITY_CHOICES_WITHOUT_STORAGE

        # All-in-one system, personality can only be controller or worker.
        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_CHOICES_WITHOUT_STORAGE

        # 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['readonly'] = 'readonly'
            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
        cpu_profile_configurable = False

        if personality and self.system_mode != constants.SYSTEM_MODE_SIMPLEX:
            self.fields['personality'].widget.attrs['readonly'] = 'readonly'
            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 'worker' in host.subfunctions:
                mem_profile_configurable = True
                cpu_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 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[
                    'interfaceProfile'].widget = forms.widgets.HiddenInput()

            stor_model = sysinv.get_ceph_storage_model(request)
            if ((personality == 'storage' or
                 (personality == 'controller'
                  and stor_model == sysinv_const.CEPH_CONTROLLER_MODEL)
                 or 'worker' 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()

            # Populate Available Cpu Profile Choices
            if cpu_profile_configurable and host.nodes and host.memory:
                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

            else:
                self.fields['cpuProfile'].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_WORKER)
            else:
                self._subfunctions = stx_api.sysinv.PERSONALITY_CONTROLLER
            cleaned_data['subfunctions'] = self._subfunctions

        return cleaned_data
Exemple #16
0
class CreateProviderNetworkRange(forms.SelfHandlingForm):
    providernet_id = forms.CharField(widget=forms.HiddenInput())
    name = forms.CharField(max_length=255, label=_("Name"), required=False)
    description = forms.CharField(max_length=255,
                                  label=_("Description"),
                                  required=False)
    shared = forms.BooleanField(label=_("Shared"),
                                initial=False,
                                required=False,
                                widget=forms.CheckboxInput(
                                    attrs={
                                        'class': 'switchable',
                                        'data-hide-on-checked': 'true',
                                        'data-slug': 'is_shared'
                                    }))

    tenant_id = forms.ChoiceField(
        label=_("Project"),
        required=False,
        widget=forms.Select(attrs={
            'class': 'switched',
            'data-switch-on': 'is_shared'
        }))

    minimum = forms.IntegerField(label=_("Minimum"), min_value=1)
    maximum = forms.IntegerField(label=_("Maximum"), min_value=1)
    # VXLAN specific fields
    mode_choices = [('dynamic', _('Multicast VXLAN')),
                    ('static', _('Static VXLAN'))]
    mode = forms.ChoiceField(label=_("Mode"),
                             initial='dynamic',
                             required=False,
                             choices=mode_choices,
                             widget=forms.Select(attrs={
                                 'class': 'switchable',
                                 'data-slug': 'vxlan_mode'
                             }))
    group_help = (_("Specify the IPv4 or IPv6 multicast address for these "
                    "VXLAN instances"))
    group = forms.CharField(
        max_length=255,
        label=_("Multicast Group Address"),
        initial="239.0.0.1",
        required=False,
        help_text=group_help,
        widget=forms.TextInput(
            attrs={
                'class': 'switchable switched',
                'data-slug': 'vxlan_group',
                'data-switch-on': 'vxlan_mode',
                'data-vxlan_mode-dynamic': 'Multicast Group Address'
            }))
    port_choices = [('4789', _('IANA Assigned VXLAN UDP port (4789)')),
                    ('4790', _('IANA Assigned VXLAN-GPE UDP port (4790)')),
                    ('8472', _('Legacy VXLAN UDP port (8472)'))]
    port = forms.ChoiceField(label=_("UDP Port"),
                             required=True,
                             widget=forms.RadioSelect(),
                             choices=port_choices)
    ttl = forms.IntegerField(
        label=_("TTL"),
        required=False,
        initial=1,
        min_value=1,
        max_value=255,
        help_text=(
            _("Specify the time-to-live value for these VXLAN instances")))

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

        tenant_choices = [('', _("Select a project"))]
        tenants, has_more = api.keystone.tenant_list(request)  # noqa pylint: disable=unused-variable
        for tenant in tenants:
            if tenant.enabled:
                tenant_choices.append((tenant.id, tenant.name))
        self.fields['tenant_id'].choices = tenant_choices
        initial = kwargs['initial']
        if 'providernet_type' in initial:
            providernet_type = initial['providernet_type']
            if providernet_type != "vxlan":
                del self.fields["mode"]
                del self.fields["group"]
                del self.fields["port"]
                del self.fields["ttl"]

    def handle(self, request, data):
        try:
            params = {
                'providernet_id': data['providernet_id'],
                'name': data['name'],
                'description': data['description'],
                'minimum': data['minimum'],
                'maximum': data['maximum'],
                'shared': data['shared'],
                'tenant_id': data['tenant_id']
            }

            if not data['tenant_id']:
                params['shared'] = True

            if self.initial['providernet_type'] == "vxlan":
                params['mode'] = data['mode']
                if params['mode'] == 'dynamic':
                    params['group'] = data['group']
                params['port'] = int(data['port'])
                params['ttl'] = int(data['ttl'])

            providernet_range = stx_api.neutron.provider_network_range_create(
                request, **params)
            msg = (_('Provider network range %s was successfully created.') %
                   providernet_range['id'])
            LOG.debug(msg)
            messages.success(request, msg)
            return providernet_range
        except neutron_exceptions.NeutronClientException as e:
            LOG.info(str(e))
            redirect = reverse('horizon:admin:datanets:datanets:'
                               'detail',
                               args=(data['providernet_id'], ))
            exceptions.handle(request, str(e), redirect=redirect)
        except Exception:
            msg = _('Failed to create a provider'
                    ' network range for network %s') \
                % data['providernet_id']
            LOG.info(msg)
            redirect = reverse('horizon:admin:datanets:datanets:'
                               'detail',
                               args=(data['providernet_id'], ))
            exceptions.handle(request, msg, redirect=redirect)

    def clean(self):
        cleaned_data = super(CreateProviderNetworkRange, self).clean()
        if not cleaned_data["shared"] and not cleaned_data["tenant_id"]:
            msg = "Project must be specified for non-shared Segmentation Range"
            raise forms.ValidationError(msg)
        if cleaned_data["shared"]:
            cleaned_data["tenant_id"] = ""
Exemple #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-' + sysinv.HOST_BM_TYPE_DYNAMIC:
                FIELD_LABEL_BM_IP,
                'data-bm_type-' + sysinv.HOST_BM_TYPE_IPMI: FIELD_LABEL_BM_IP,
                'data-bm_type-' + sysinv.HOST_BM_TYPE_REDFISH:
                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-' + sysinv.HOST_BM_TYPE_DYNAMIC:
                FIELD_LABEL_BM_USERNAME,
                'data-bm_type-' + sysinv.HOST_BM_TYPE_IPMI:
                FIELD_LABEL_BM_USERNAME,
                'data-bm_type-' + sysinv.HOST_BM_TYPE_REDFISH:
                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-' + sysinv.HOST_BM_TYPE_DYNAMIC:
                FIELD_LABEL_BM_PASSWORD,
                'data-bm_type-' + sysinv.HOST_BM_TYPE_IPMI:
                FIELD_LABEL_BM_PASSWORD,
                'data-bm_type-' + sysinv.HOST_BM_TYPE_REDFISH:
                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-' + sysinv.HOST_BM_TYPE_DYNAMIC:
                FIELD_LABEL_BM_CONFIRM_PASSWORD,
                'data-bm_type-' + sysinv.HOST_BM_TYPE_IPMI:
                FIELD_LABEL_BM_CONFIRM_PASSWORD,
                'data-bm_type-' + sysinv.HOST_BM_TYPE_REDFISH:
                FIELD_LABEL_BM_CONFIRM_PASSWORD
            }),
        required=False)

    def clean(self):
        cleaned_data = super(BoardManagementAction, self).clean()
        if cleaned_data.get('bm_type') != \
                sysinv_const.HOST_BM_TYPE_DEPROVISIONED:
            if 'bm_ip' not in cleaned_data or not cleaned_data['bm_ip']:
                raise forms.ValidationError(
                    _('Board management IP 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)
Exemple #18
0
class AddRule(forms.SelfHandlingForm):
    id = forms.CharField(widget=forms.HiddenInput())
    rule_menu = forms.ChoiceField(
        label=_('Rule'),
        widget=forms.ThemableSelectWidget(attrs={
            'class': 'switchable',
            'data-slug': 'rule_menu'
        }))
    description = forms.CharField(
        label=_('Description'),
        required=False,
        max_length=255,
        widget=forms.Textarea(attrs={'rows': 2}),
        help_text=_('A brief description of the security group rule '
                    'you are adding'))

    # "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.ThemableSelectWidget(
            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."),
        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.ThemableSelectWidget(
            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-required-when-shown': 'true',
                '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-required-when-shown': 'true',
                '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-required-when-shown': 'true',
                '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_icmp_type_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_icmp_code_range])

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

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

    security_group = forms.ChoiceField(
        label=_('Security Group'),
        required=False,
        widget=forms.ThemableSelectWidget(
            attrs={
                'class': 'switched',
                'data-required-when-shown': 'true',
                '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.ThemableSelectWidget(
                                      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

        # TODO(amotoki): settings.SECURITY_GROUP_RULES may contains 'backend'
        # parameter. If 'backend' is used, error message should be emitted.
        backend = 'neutron'

        rules_dict = 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')),
                        ('custom', _('Other Protocol'))]
        self.fields['rule_menu'].choices = custom_rules + common_rules
        self.rules = rules_dict

        self.fields['direction'].choices = [('ingress', _('Ingress')),
                                            ('egress', _('Egress'))]
        self.fields['ip_protocol'].help_text = _(
            "Enter an integer value between -1 and 255 "
            "(-1 means wild card).")

        self.fields['port_or_range'].choices = [
            ('port', _('Port')),
            ('range', _('Port Range')),
            ('all', _('All ports')),
        ]

        if not setting_utils.get_dict_config('OPENSTACK_NEUTRON_NETWORK',
                                             'enable_ipv6'):
            self.fields['cidr'].version = forms.IPv4
            self.fields['ethertype'].widget = forms.TextInput(
                attrs={'readonly': 'readonly'})
            self.fields['ethertype'].initial = 'IPv4'

        try:
            is_desc_supported = api.neutron.is_extension_supported(
                self.request, 'standard-attr-description')
        except Exception:
            exceptions.handle(
                self.request,
                _('Failed to check if description field is supported.'))
            is_desc_supported = False
        if not is_desc_supported:
            del self.fields['description']

    def _update_and_pop_error(self, cleaned_data, key, value):
        cleaned_data[key] = value
        self.errors.pop(key, None)

    def _clean_rule_icmp(self, cleaned_data, rule_menu):
        icmp_type = cleaned_data.get("icmp_type", None)
        icmp_code = cleaned_data.get("icmp_code", None)

        self._update_and_pop_error(cleaned_data, 'ip_protocol', rule_menu)
        if icmp_type == -1 and icmp_code != -1:
            msg = _('ICMP code is provided but ICMP type is missing.')
            raise ValidationError(msg)
        if self.errors.get('icmp_type'):
            msg = _('The ICMP type not in range (-1, 255)')
            raise ValidationError(msg)
        if self.errors.get('icmp_code'):
            msg = _('The ICMP code not in range (-1, 255)')
            raise ValidationError(msg)

        self._update_and_pop_error(cleaned_data, 'from_port', icmp_type)
        self._update_and_pop_error(cleaned_data, 'to_port', icmp_code)
        self._update_and_pop_error(cleaned_data, 'port', None)

    def _clean_rule_tcp_udp(self, cleaned_data, rule_menu):
        port_or_range = cleaned_data.get("port_or_range")
        from_port = cleaned_data.get("from_port", None)
        to_port = cleaned_data.get("to_port", None)
        port = cleaned_data.get("port", None)

        self._update_and_pop_error(cleaned_data, 'ip_protocol', rule_menu)
        self._update_and_pop_error(cleaned_data, 'icmp_code', None)
        self._update_and_pop_error(cleaned_data, 'icmp_type', None)
        if port_or_range == 'all':
            self._update_and_pop_error(cleaned_data, 'port', None)
            self._update_and_pop_error(cleaned_data, 'from_port', None)
            self._update_and_pop_error(cleaned_data, 'to_port', None)
        elif port_or_range == "port":
            self._update_and_pop_error(cleaned_data, 'from_port', port)
            self._update_and_pop_error(cleaned_data, 'to_port', port)
            if port is None:
                msg = _('The specified port is invalid.')
                raise ValidationError(msg)
        else:
            self._update_and_pop_error(cleaned_data, 'port', None)
            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)

    def _clean_rule_custom(self, cleaned_data, rule_menu):
        # custom IP protocol rule so we need to fill unused fields so
        # the validation works
        unused_fields = [
            'icmp_code', 'icmp_type', 'from_port', 'to_port', 'port'
        ]
        for unused_field in unused_fields:
            self._update_and_pop_error(cleaned_data, unused_field, None)

    def _apply_rule_menu(self, cleaned_data, rule_menu):
        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'])
        self._update_and_pop_error(cleaned_data, 'icmp_code', None)
        self._update_and_pop_error(cleaned_data, 'icmp_type', None)
        if rule_menu not in ['all_tcp', 'all_udp', 'all_icmp']:
            direction = self.rules[rule_menu].get('direction')
            cleaned_data['direction'] = direction

    def _clean_rule_menu(self, cleaned_data):
        rule_menu = cleaned_data.get('rule_menu')
        if rule_menu == 'icmp':
            self._clean_rule_icmp(cleaned_data, rule_menu)
        elif rule_menu in ('tcp', 'udp'):
            self._clean_rule_tcp_udp(cleaned_data, rule_menu)
        elif rule_menu == 'custom':
            self._clean_rule_custom(cleaned_data, rule_menu)
        else:
            self._apply_rule_menu(cleaned_data, rule_menu)

    def _adjust_ip_protocol_of_icmp(self, data):
        # Note that this needs to be called after IPv4/IPv6 is determined.
        try:
            ip_protocol = int(data['ip_protocol'])
        except ValueError:
            # string representation of IP protocol
            ip_protocol = data['ip_protocol']
        is_ipv6 = data['ethertype'] == 'IPv6'

        if isinstance(ip_protocol, int):
            # When IP protocol number is specified, we assume a user
            # knows more detail on IP protocol number,
            # so a warning message on a mismatch between IP proto number
            # and IP version is displayed.
            if is_ipv6 and ip_protocol == 1:
                msg = _('58 (ipv6-icmp) should be specified for IPv6 '
                        'instead of 1.')
                self._errors['ip_protocol'] = self.error_class([msg])
            elif not is_ipv6 and ip_protocol == 58:
                msg = _('1 (icmp) should be specified for IPv4 '
                        'instead of 58.')
                self._errors['ip_protocol'] = self.error_class([msg])
        else:
            # ICMPv6 uses different an IP protocol name and number.
            # To allow 'icmp' for both IPv4 and IPv6 in the form,
            # we need to replace 'icmp' with 'ipv6-icmp' based on IP version.
            if is_ipv6 and ip_protocol == 'icmp':
                data['ip_protocol'] = 'ipv6-icmp'

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

        self._clean_rule_menu(cleaned_data)

        # 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 except all_* 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'

        remote = cleaned_data.get("remote")
        if remote == "cidr":
            self._update_and_pop_error(cleaned_data, 'security_group', None)
        else:
            self._update_and_pop_error(cleaned_data, 'cidr', None)

        # If cleaned_data does not contain a non-empty value, IPField already
        # has validated it, 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'

        self._adjust_ip_protocol_of_icmp(cleaned_data)

        return cleaned_data

    def handle(self, request, data):
        redirect = reverse("horizon:project:security_groups:detail",
                           args=[data['id']])
        params = {}
        if 'description' in data:
            params['description'] = data['description']
        try:
            rule = api.neutron.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'], **params)
            messages.success(request, _('Successfully added rule: %s') % rule)
            return rule
        except exceptions.Conflict as error:
            exceptions.handle(request, error, redirect=redirect)
        except Exception:
            exceptions.handle(request,
                              _('Unable to add rule to security group.'),
                              redirect=redirect)
Exemple #19
0
class CreateNetwork(forms.SelfHandlingForm):
    name = forms.CharField(max_length=255,
                           label=_("Name"),
                           required=False)
    tenant_id = forms.ChoiceField(label=_("Project"))
    if api.neutron.is_port_profiles_supported():
        widget = None
    else:
        widget = forms.HiddenInput()
    net_profile_id = forms.ChoiceField(label=_("Network Profile"),
                                       required=False,
                                       widget=widget)
    network_type = forms.ChoiceField(
        label=_("Provider Network Type"),
        help_text=_("The physical mechanism by which the virtual "
                    "network is implemented."),
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'network_type'
        }))
    physical_network = forms.CharField(
        max_length=255,
        label=_("Physical Network"),
        help_text=_("The name of the physical network over which the "
                    "virtual network is implemented."),
        initial='default',
        widget=forms.TextInput(attrs={
            'class': 'switched',
            'data-switch-on': 'network_type',
        }))
    segmentation_id = forms.IntegerField(
        label=_("Segmentation ID"),
        widget=forms.TextInput(attrs={
            'class': 'switched',
            'data-switch-on': 'network_type',
        }))
    admin_state = forms.ChoiceField(choices=[(True, _('UP')),
                                             (False, _('DOWN'))],
                                    label=_("Admin State"))
    shared = forms.BooleanField(label=_("Shared"),
                                initial=False, required=False)
    external = forms.BooleanField(label=_("External Network"),
                                  initial=False, required=False)

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

    def __init__(self, request, *args, **kwargs):
        super(CreateNetwork, self).__init__(request, *args, **kwargs)
        tenant_choices = [('', _("Select a project"))]
        tenants, has_more = api.keystone.tenant_list(request)
        for tenant in tenants:
            if tenant.enabled:
                tenant_choices.append((tenant.id, tenant.name))
        self.fields['tenant_id'].choices = tenant_choices

        if api.neutron.is_port_profiles_supported():
            self.fields['net_profile_id'].choices = (
                self.get_network_profile_choices(request))

        if api.neutron.is_extension_supported(request, 'provider'):
            neutron_settings = getattr(settings,
                                       'OPENSTACK_NEUTRON_NETWORK', {})
            self.seg_id_range = SEGMENTATION_ID_RANGE.copy()
            seg_id_range = neutron_settings.get('segmentation_id_range')
            if seg_id_range:
                self.seg_id_range.update(seg_id_range)

            self.provider_types = PROVIDER_TYPES.copy()
            extra_provider_types = neutron_settings.get('extra_provider_types')
            if extra_provider_types:
                self.provider_types.update(extra_provider_types)

            self.nettypes_with_seg_id = [
                net_type for net_type in self.provider_types
                if self.provider_types[net_type]['require_segmentation_id']]
            self.nettypes_with_physnet = [
                net_type for net_type in self.provider_types
                if self.provider_types[net_type]['require_physical_network']]

            supported_provider_types = neutron_settings.get(
                'supported_provider_types', DEFAULT_PROVIDER_TYPES)
            if supported_provider_types == ['*']:
                supported_provider_types = DEFAULT_PROVIDER_TYPES

            undefined_provider_types = [
                net_type for net_type in supported_provider_types
                if net_type not in self.provider_types]
            if undefined_provider_types:
                LOG.error('Undefined provider network types are found: %s',
                          undefined_provider_types)

            seg_id_help = [
                _("For %(type)s networks, valid IDs are %(min)s to %(max)s.")
                % {'type': net_type,
                   'min': self.seg_id_range[net_type][0],
                   'max': self.seg_id_range[net_type][1]}
                for net_type in self.nettypes_with_seg_id]
            self.fields['segmentation_id'].help_text = ' '.join(seg_id_help)

            # Register network types which require segmentation ID
            attrs = dict(('data-network_type-%s' % network_type,
                          _('Segmentation ID'))
                         for network_type in self.nettypes_with_seg_id)
            self.fields['segmentation_id'].widget.attrs.update(attrs)

            # Register network types which require physical network
            attrs = dict(('data-network_type-%s' % network_type,
                          _('Physical Network'))
                         for network_type in self.nettypes_with_physnet)
            self.fields['physical_network'].widget.attrs.update(attrs)

            network_type_choices = [
                (net_type, self.provider_types[net_type]['display_name'])
                for net_type in supported_provider_types]
            if len(network_type_choices) == 0:
                self._hide_provider_network_type()
            else:
                self.fields['network_type'].choices = network_type_choices
        else:
            self._hide_provider_network_type()

    def get_network_profile_choices(self, request):
        profile_choices = [('', _("Select a profile"))]
        for profile in self._get_profiles(request, 'network'):
            profile_choices.append((profile.id, profile.name))
        return profile_choices

    def _get_profiles(self, request, type_p):
        profiles = []
        try:
            profiles = api.neutron.profile_list(request, type_p)
        except Exception:
            msg = _('Network Profiles could not be retrieved.')
            exceptions.handle(request, msg)
        return profiles

    def _hide_provider_network_type(self):
        self.fields['network_type'].widget = forms.HiddenInput()
        self.fields['physical_network'].widget = forms.HiddenInput()
        self.fields['segmentation_id'].widget = forms.HiddenInput()
        self.fields['network_type'].required = False
        self.fields['physical_network'].required = False
        self.fields['segmentation_id'].required = False

    def handle(self, request, data):
        try:
            params = {'name': data['name'],
                      'tenant_id': data['tenant_id'],
                      'admin_state_up': (data['admin_state'] == 'True'),
                      'shared': data['shared'],
                      'router:external': data['external']}
            if api.neutron.is_port_profiles_supported():
                params['net_profile_id'] = data['net_profile_id']
            if api.neutron.is_extension_supported(request, 'provider'):
                network_type = data['network_type']
                params['provider:network_type'] = network_type
                if network_type in self.nettypes_with_physnet:
                    params['provider:physical_network'] = (
                        data['physical_network'])
                if network_type in self.nettypes_with_seg_id:
                    params['provider:segmentation_id'] = (
                        data['segmentation_id'])
            network = api.neutron.network_create(request, **params)
            msg = _('Network %s was successfully created.') % data['name']
            LOG.debug(msg)
            messages.success(request, msg)
            return network
        except Exception:
            redirect = reverse('horizon:admin:networks:index')
            msg = _('Failed to create network %s') % data['name']
            exceptions.handle(request, msg, redirect=redirect)

    def clean(self):
        cleaned_data = super(CreateNetwork, self).clean()
        if api.neutron.is_extension_supported(self.request, 'provider'):
            self._clean_physical_network(cleaned_data)
            self._clean_segmentation_id(cleaned_data)
        return cleaned_data

    def _clean_physical_network(self, data):
        network_type = data.get('network_type')
        if ('physical_network' in self._errors and
                network_type not in self.nettypes_with_physnet):
            # In this case the physical network is not required, so we can
            # ignore any errors.
            del self._errors['physical_network']

    def _clean_segmentation_id(self, data):
        network_type = data.get('network_type')
        if 'segmentation_id' in self._errors:
            if network_type not in self.nettypes_with_seg_id:
                # In this case the segmentation ID is not required, so we can
                # ignore any errors.
                del self._errors['segmentation_id']
        elif network_type in self.nettypes_with_seg_id:
            seg_id = data.get('segmentation_id')
            seg_id_range = {'min': self.seg_id_range[network_type][0],
                            'max': self.seg_id_range[network_type][1]}
            if seg_id < seg_id_range['min'] or seg_id > seg_id_range['max']:
                msg = (_('For a %(network_type)s network, valid segmentation '
                         'IDs are %(min)s through %(max)s.')
                       % {'network_type': network_type,
                          'min': seg_id_range['min'],
                          'max': seg_id_range['max']})
                self._errors['segmentation_id'] = self.error_class([msg])
Exemple #20
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 &quot;CIDR&quot;. '
                                           'To allow access from all '
                                           'members of another security '
                                           'group select &quot;Security '
                                           'Group&quot;.'),
                               widget=forms.Select(attrs={
                                   'class': 'switchable',
                                   'data-slug': 'remote'
                               }))

    cidr = forms.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=forms.IPv4 | forms.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 _update_and_pop_error(self, cleaned_data, key, value):
        cleaned_data[key] = value
        self.errors.pop(key, None)

    def _clean_rule_icmp(self, cleaned_data, rule_menu):
        icmp_type = cleaned_data.get("icmp_type", None)
        icmp_code = cleaned_data.get("icmp_code", None)

        self._update_and_pop_error(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 range(-1, 256):
            msg = _('The ICMP type not in range (-1, 255)')
            raise ValidationError(msg)
        if icmp_code not in range(-1, 256):
            msg = _('The ICMP code not in range (-1, 255)')
            raise ValidationError(msg)
        self._update_and_pop_error(cleaned_data, 'from_port', icmp_type)
        self._update_and_pop_error(cleaned_data, 'to_port', icmp_code)
        self._update_and_pop_error(cleaned_data, 'port', None)

    def _clean_rule_tcp_udp(self, cleaned_data, rule_menu):
        port_or_range = cleaned_data.get("port_or_range")
        from_port = cleaned_data.get("from_port", None)
        to_port = cleaned_data.get("to_port", None)
        port = cleaned_data.get("port", None)

        self._update_and_pop_error(cleaned_data, 'ip_protocol', rule_menu)
        self._update_and_pop_error(cleaned_data, 'icmp_code', None)
        self._update_and_pop_error(cleaned_data, 'icmp_type', None)
        if port_or_range == "port":
            self._update_and_pop_error(cleaned_data, 'from_port', port)
            self._update_and_pop_error(cleaned_data, 'to_port', port)
            if port is None:
                msg = _('The specified port is invalid.')
                raise ValidationError(msg)
        else:
            self._update_and_pop_error(cleaned_data, 'port', None)
            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)

    def _apply_rule_menu(self, cleaned_data, rule_menu):
        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'])
        if rule_menu not in ['all_tcp', 'all_udp', 'all_icmp']:
            direction = self.rules[rule_menu].get('direction')
            cleaned_data['direction'] = direction

    def _clean_rule_menu(self, cleaned_data):
        rule_menu = cleaned_data.get('rule_menu')
        if rule_menu == 'icmp':
            self._clean_rule_icmp(cleaned_data, rule_menu)
        elif rule_menu == 'tcp' or rule_menu == 'udp':
            self._clean_rule_tcp_udp(cleaned_data, rule_menu)
        elif rule_menu == 'custom':
            pass
        else:
            self._apply_rule_menu(cleaned_data, rule_menu)

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

        self._clean_rule_menu(cleaned_data)

        # 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 except all_* 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'

        remote = cleaned_data.get("remote")
        if remote == "cidr":
            self._update_and_pop_error(cleaned_data, 'security_group', None)
        else:
            self._update_and_pop_error(cleaned_data, 'cidr', None)

        # If cleaned_data does not contain a non-empty value, IPField already
        # has validated it, 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') % six.text_type(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)
Exemple #21
0
class CreateNetwork(forms.SelfHandlingForm):
    name = forms.CharField(max_length=255, label=_("Name"), required=False)
    tenant_id = forms.ThemableChoiceField(label=_("Project"))
    network_type = forms.ChoiceField(
        label=_("Provider Network Type"),
        help_text=_("The physical mechanism by which the virtual "
                    "network is implemented."),
        widget=forms.ThemableSelectWidget(attrs={
            'class': 'switchable',
            'data-slug': 'network_type'
        }))
    physical_network = forms.CharField(
        max_length=255,
        label=_("Physical Network"),
        help_text=_("The name of the physical network over which the "
                    "virtual network is implemented. Specify one of the "
                    "physical networks defined in your neutron deployment."),
        widget=forms.TextInput(attrs={
            'class': 'switched',
            'data-switch-on': 'network_type',
        }))
    segmentation_id = forms.IntegerField(
        label=_("Segmentation ID"),
        widget=forms.TextInput(attrs={
            'class': 'switched',
            'data-switch-on': 'network_type',
        }))
    admin_state = forms.BooleanField(label=_("Enable Admin State"),
                                     initial=True,
                                     required=False)
    shared = forms.BooleanField(label=_("Shared"),
                                initial=False,
                                required=False)
    external = forms.BooleanField(label=_("External Network"),
                                  initial=False,
                                  required=False)
    with_subnet = forms.BooleanField(label=_("Create Subnet"),
                                     widget=forms.CheckboxInput(
                                         attrs={
                                             'class':
                                             'switchable',
                                             'data-slug':
                                             'with_subnet',
                                             'data-hide-tab':
                                             'create_network__'
                                             'createsubnetinfo'
                                             'action,'
                                             'create_network__'
                                             'createsubnetdetail'
                                             'action',
                                             'data-hide-on-checked':
                                             'false'
                                         }),
                                     initial=True,
                                     required=False)
    az_hints = forms.MultipleChoiceField(
        label=_("Availability Zone Hints"),
        required=False,
        help_text=_("Availability zones where the DHCP agents may be "
                    "scheduled. Leaving this unset is equivalent to "
                    "selecting all availability zones"))

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

    def __init__(self, request, *args, **kwargs):
        super(CreateNetwork, self).__init__(request, *args, **kwargs)
        tenant_choices = [('', _("Select a project"))]
        tenants, has_more = api.keystone.tenant_list(request)
        for tenant in tenants:
            if tenant.enabled:
                tenant_choices.append((tenant.id, tenant.name))
        self.fields['tenant_id'].choices = tenant_choices

        try:
            is_extension_supported = \
                api.neutron.is_extension_supported(request, 'provider')
        except Exception:
            msg = _("Unable to verify Neutron service providers")
            exceptions.handle(self.request, msg)
            self._hide_provider_network_type()
            is_extension_supported = False

        if is_extension_supported:
            neutron_settings = getattr(settings, 'OPENSTACK_NEUTRON_NETWORK',
                                       {})
            self.seg_id_range = SEGMENTATION_ID_RANGE.copy()
            seg_id_range = neutron_settings.get('segmentation_id_range')
            if seg_id_range:
                self.seg_id_range.update(seg_id_range)

            self.provider_types = PROVIDER_TYPES.copy()
            extra_provider_types = neutron_settings.get('extra_provider_types')
            if extra_provider_types:
                self.provider_types.update(extra_provider_types)

            self.nettypes_with_seg_id = [
                net_type for net_type in self.provider_types
                if self.provider_types[net_type]['require_segmentation_id']
            ]
            self.nettypes_with_physnet = [
                net_type for net_type in self.provider_types
                if self.provider_types[net_type]['require_physical_network']
            ]

            supported_provider_types = neutron_settings.get(
                'supported_provider_types', DEFAULT_PROVIDER_TYPES)
            if supported_provider_types == ['*']:
                supported_provider_types = DEFAULT_PROVIDER_TYPES

            undefined_provider_types = [
                net_type for net_type in supported_provider_types
                if net_type not in self.provider_types
            ]
            if undefined_provider_types:
                LOG.error('Undefined provider network types are found: %s',
                          undefined_provider_types)

            seg_id_help = [
                _("For %(type)s networks, valid IDs are %(min)s to %(max)s.") %
                {
                    'type': net_type,
                    'min': self.seg_id_range[net_type][0],
                    'max': self.seg_id_range[net_type][1]
                } for net_type in self.nettypes_with_seg_id
            ]
            self.fields['segmentation_id'].help_text = ' '.join(seg_id_help)

            # Register network types which require segmentation ID
            attrs = dict(
                ('data-network_type-%s' % network_type, _('Segmentation ID'))
                for network_type in self.nettypes_with_seg_id)
            self.fields['segmentation_id'].widget.attrs.update(attrs)

            physical_networks = getattr(settings, 'OPENSTACK_NEUTRON_NETWORK',
                                        {}).get('physical_networks', [])

            if physical_networks:
                self.fields['physical_network'] = forms.ThemableChoiceField(
                    label=_("Physical Network"),
                    choices=[(net, net) for net in physical_networks],
                    widget=forms.ThemableSelectWidget(
                        attrs={
                            'class': 'switched',
                            'data-switch-on': 'network_type',
                        }),
                    help_text=_("The name of the physical network over "
                                "which the virtual network is implemented."),
                )

            # Register network types which require physical network
            attrs = dict(
                ('data-network_type-%s' % network_type, _('Physical Network'))
                for network_type in self.nettypes_with_physnet)
            self.fields['physical_network'].widget.attrs.update(attrs)

            network_type_choices = [
                (net_type, self.provider_types[net_type]['display_name'])
                for net_type in supported_provider_types
            ]
            if not network_type_choices:
                self._hide_provider_network_type()
            else:
                self.fields['network_type'].choices = network_type_choices

        try:
            if api.neutron.is_extension_supported(request,
                                                  'network_availability_zone'):
                zones = api.neutron.list_availability_zones(
                    self.request, 'network', 'available')
                self.fields['az_hints'].choices = [(zone['name'], zone['name'])
                                                   for zone in zones]
            else:
                del self.fields['az_hints']
        except Exception:
            msg = _('Failed to get availability zone list.')
            messages.warning(request, msg)
            del self.fields['az_hints']

    def _hide_provider_network_type(self):
        self.fields['network_type'].widget = forms.HiddenInput()
        self.fields['physical_network'].widget = forms.HiddenInput()
        self.fields['segmentation_id'].widget = forms.HiddenInput()
        self.fields['network_type'].required = False
        self.fields['physical_network'].required = False
        self.fields['segmentation_id'].required = False

    def handle(self, request, data):
        try:
            params = {
                'name': data['name'],
                'tenant_id': data['tenant_id'],
                'admin_state_up': data['admin_state'],
                'shared': data['shared'],
                'router:external': data['external']
            }
            if api.neutron.is_extension_supported(request, 'provider'):
                network_type = data['network_type']
                params['provider:network_type'] = network_type
                if network_type in self.nettypes_with_physnet:
                    params['provider:physical_network'] = (
                        data['physical_network'])
                if network_type in self.nettypes_with_seg_id:
                    params['provider:segmentation_id'] = (
                        data['segmentation_id'])
            if 'az_hints' in data and data['az_hints']:
                params['availability_zone_hints'] = data['az_hints']
            network = api.neutron.network_create(request, **params)
            LOG.debug('Network %s was successfully created.', data['name'])
            return network
        except Exception:
            redirect = reverse('horizon:admin:networks:index')
            msg = _('Failed to create network %s') % data['name']
            exceptions.handle(request, msg, redirect=redirect)

    def clean(self):
        cleaned_data = super(CreateNetwork, self).clean()
        if api.neutron.is_extension_supported(self.request, 'provider'):
            self._clean_physical_network(cleaned_data)
            self._clean_segmentation_id(cleaned_data)
        return cleaned_data

    def _clean_physical_network(self, data):
        network_type = data.get('network_type')
        if ('physical_network' in self._errors
                and network_type not in self.nettypes_with_physnet):
            # In this case the physical network is not required, so we can
            # ignore any errors.
            del self._errors['physical_network']

    def _clean_segmentation_id(self, data):
        network_type = data.get('network_type')
        if 'segmentation_id' in self._errors:
            if (network_type not in self.nettypes_with_seg_id
                    and not self.data.get("segmentation_id")):
                # In this case the segmentation ID is not required, so we can
                # ignore the field is required error.
                del self._errors['segmentation_id']
        elif network_type in self.nettypes_with_seg_id:
            seg_id = data.get('segmentation_id')
            seg_id_range = {
                'min': self.seg_id_range[network_type][0],
                'max': self.seg_id_range[network_type][1]
            }
            if seg_id < seg_id_range['min'] or seg_id > seg_id_range['max']:
                msg = (_('For a %(network_type)s network, valid segmentation '
                         'IDs are %(min)s through %(max)s.') % {
                             'network_type': network_type,
                             'min': seg_id_range['min'],
                             'max': seg_id_range['max']
                         })
                self._errors['segmentation_id'] = self.error_class([msg])
Exemple #22
0
class UpdateIPSecSiteConnection(forms.SelfHandlingForm):
    name = forms.CharField(max_length=80, label=_("Name"), required=False)
    ipsecsiteconnection_id = forms.CharField(
        label=_("ID"), widget=forms.TextInput(attrs={'readonly': 'readonly'}))
    description = forms.CharField(required=False,
                                  max_length=80,
                                  label=_("Description"))
    peer_address = forms.IPField(
        label=_("Peer gateway public IPv4/IPv6 Address or FQDN"),
        help_text=_("Peer gateway public IPv4/IPv6 address or FQDN for "
                    "the VPN Connection"),
        version=forms.IPv4 | forms.IPv6,
        mask=False)
    peer_id = forms.IPField(
        label=_("Peer router identity for authentication (Peer ID)"),
        help_text=_("Peer router identity for authentication. "
                    "Can be IPv4/IPv6 address, e-mail, key ID, or FQDN"),
        version=forms.IPv4 | forms.IPv6,
        mask=False)
    peer_cidrs = forms.MultiIPField(label=_("Remote peer subnet(s)"),
                                    help_text=_(
                                        "Remote peer subnet(s) address(es) "
                                        "with mask(s) in CIDR format "
                                        "separated with commas if needed "
                                        "(e.g. 20.1.0.0/24, 21.1.0.0/24)"),
                                    version=forms.IPv4 | forms.IPv6,
                                    mask=True)
    psk = forms.CharField(widget=forms.PasswordInput(render_value=True),
                          max_length=80,
                          label=_("Pre-Shared Key (PSK) string"))
    mtu = forms.IntegerField(
        min_value=68,
        required=False,
        label=_("Maximum Transmission Unit size for the connection"),
        help_text=_("Equal to or greater than 68 if the local subnet is IPv4. "
                    "Equal to or greater than 1280 if the local subnet "
                    "is IPv6."))
    dpd_action = forms.ChoiceField(label=_("Dead peer detection actions"),
                                   required=False,
                                   choices=[('hold', _('hold')),
                                            ('clear', _('clear')),
                                            ('disabled', _('disabled')),
                                            ('restart', _('restart')),
                                            ('restart-by-peer',
                                             _('restart-by-peer'))])
    dpd_interval = forms.IntegerField(
        min_value=1,
        required=False,
        label=_("Dead peer detection interval"),
        help_text=_("Valid integer lesser than the DPD timeout"))
    dpd_timeout = forms.IntegerField(
        min_value=1,
        required=False,
        label=_("Dead peer detection timeout"),
        help_text=_("Valid integer greater than the DPD interval"))
    initiator = forms.ChoiceField(label=_("Initiator state"),
                                  required=False,
                                  choices=[
                                      ('bi-directional', _('bi-directional')),
                                      ('response-only', _('response-only'))
                                  ])
    admin_state_up = forms.BooleanField(label=_("Enable Admin State"),
                                        required=False)

    failure_url = 'horizon:project:vpn:index'

    def clean(self):
        cleaned_data = super(UpdateIPSecSiteConnection, self).clean()
        interval = cleaned_data.get('dpd_interval')
        timeout = cleaned_data.get('dpd_timeout')

        if not interval < timeout:
            msg = _("DPD Timeout must be greater than DPD Interval")
            self._errors['dpd_timeout'] = self.error_class([msg])
        return cleaned_data

    def handle(self, request, context):
        try:
            data = {
                'ipsec_site_connection': {
                    'name': context['name'],
                    'description': context['description'],
                    'peer_address': context['peer_address'],
                    'peer_id': context['peer_id'],
                    'peer_cidrs': context['peer_cidrs'].replace(" ",
                                                                "").split(","),
                    'psk': context['psk'],
                    'mtu': context['mtu'],
                    'dpd': {
                        'action': context['dpd_action'],
                        'interval': context['dpd_interval'],
                        'timeout': context['dpd_timeout']
                    },
                    'initiator': context['initiator'],
                    'admin_state_up': context['admin_state_up'],
                }
            }
            ipsecsiteconnection = api.vpn.ipsecsiteconnection_update(
                request, context['ipsecsiteconnection_id'], **data)
            msg = (_('IPSec Site Connection %s was successfully updated.') %
                   context['name'])
            messages.success(request, msg)
            return ipsecsiteconnection
        except Exception as e:
            LOG.info('Failed to update IPSec Site Connection %(id)s: %(exc)s',
                     {
                         'id': context['ipsecsiteconnection_id'],
                         'exc': e
                     })
            msg = (_('Failed to update IPSec Site Connection %s') %
                   context['name'])
            redirect = reverse(self.failure_url)
            exceptions.handle(request, msg, redirect=redirect)
class CreateSubnetInfoAction(workflows.Action):
    subnet_name = forms.CharField(max_length=255,
                                  widget=forms.TextInput(attrs={}),
                                  label=_("Subnet Name"),
                                  required=False)

    address_source = forms.ChoiceField(
        required=False,
        label=_('Network Address Source'),
        choices=[('manual', _('Enter Network Address manually')),
                 ('subnetpool', _('Allocate Network Address from a pool'))],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'source',
        }))

    subnetpool = forms.ChoiceField(
        label=_("Address pool"),
        widget=forms.SelectWidget(attrs={
            'class': 'switched switchable',
            'data-slug': 'subnetpool',
            'data-switch-on': 'source',
            'data-source-subnetpool': _('Address pool')
        },
                                  data_attrs=('name', 'prefixes', 'ip_version',
                                              'min_prefixlen', 'max_prefixlen',
                                              'default_prefixlen'),
                                  transform=lambda x: "%s (%s)" %
                                  (x.name, ", ".join(x.prefixes))
                                  if 'prefixes' in x else "%s" % (x.name)),
        required=False)

    prefixlen = forms.ChoiceField(
        widget=forms.Select(attrs={
            'class': 'switched',
            'data-switch-on': 'subnetpool',
        }),
        label=_('Network Mask'),
        required=False)

    cidr = forms.IPField(label=_("Network Address"),
                         required=False,
                         initial="",
                         widget=forms.TextInput(
                             attrs={
                                 'class': 'switched',
                                 'data-switch-on': 'source',
                                 'data-source-manual': _("Network Address"),
                             }),
                         help_text=_("Network address in CIDR format "
                                     "(e.g. 192.168.0.0/24, 2001:DB8::/48)"),
                         version=forms.IPv4 | forms.IPv6,
                         mask=True)
    ip_version = forms.ChoiceField(
        choices=[(4, 'IPv4'), (6, 'IPv6')],
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'ipversion',
        }),
        label=_("IP Version"),
        required=False)
    gateway_ip = forms.IPField(
        label=_("Gateway IP"),
        widget=forms.TextInput(
            attrs={
                'class': 'switched',
                'data-switch-on': 'gateway_ip',
                'data-source-manual': _("Gateway IP")
            }),
        required=False,
        initial="",
        help_text=_("IP address of Gateway (e.g. 192.168.0.254) "
                    "The default value is the first IP of the "
                    "network address "
                    "(e.g. 192.168.0.1 for 192.168.0.0/24, "
                    "2001:DB8::1 for 2001:DB8::/48). "
                    "If you use the default, leave blank. "
                    "If you do not want to use a gateway, "
                    "check 'Disable Gateway' below."),
        version=forms.IPv4 | forms.IPv6,
        mask=False)
    no_gateway = forms.BooleanField(label=_("Disable Gateway"),
                                    widget=forms.CheckboxInput(
                                        attrs={
                                            'class': 'switchable',
                                            'data-slug': 'gateway_ip',
                                            'data-hide-on-checked': 'true'
                                        }),
                                    initial=False,
                                    required=False)

    class Meta(object):
        name = _("Subnet")
        help_text = _('Creates a subnet associated with the network.'
                      ' You need to enter a valid "Network Address"'
                      ' and "Gateway IP". If you did not enter the'
                      ' "Gateway IP", the first value of a network'
                      ' will be assigned by default. If you do not want'
                      ' gateway please check the "Disable Gateway" checkbox.'
                      ' Advanced configuration is available by clicking on'
                      ' the "Subnet Details" tab.')

    def __init__(self, request, context, *args, **kwargs):
        super(CreateSubnetInfoAction, self).__init__(request, context, *args,
                                                     **kwargs)
        if 'with_subnet' in context:
            self.fields['with_subnet'] = forms.BooleanField(
                initial=context['with_subnet'],
                required=False,
                widget=forms.HiddenInput())

        if not getattr(settings, 'OPENSTACK_NEUTRON_NETWORK', {}).get(
                'enable_ipv6', True):
            self.fields['ip_version'].widget = forms.HiddenInput()
            self.fields['ip_version'].initial = 4

        try:
            if api.neutron.is_extension_supported(request,
                                                  'subnet_allocation'):
                self.fields['subnetpool'].choices = \
                    self.get_subnetpool_choices(request)
            else:
                self.hide_subnetpool_choices()
        except Exception:
            self.hide_subnetpool_choices()
            msg = _('Unable to initialize subnetpools')
            exceptions.handle(request, msg)
        if len(self.fields['subnetpool'].choices) > 1:
            # Pre-populate prefixlen choices to satisfy Django
            # ChoiceField Validation. This is overridden w/data from
            # subnetpool on select.
            self.fields['prefixlen'].choices = \
                zip(list(range(0, 128 + 1)),
                    list(range(0, 128 + 1)))
            # Populate data-fields for switching the prefixlen field
            # when user selects a subnetpool other than
            # "Provider default pool"
            for (id, name) in self.fields['subnetpool'].choices:
                if not len(id):
                    continue
                key = 'data-subnetpool-' + id
                self.fields['prefixlen'].widget.attrs[key] = \
                    _('Network Mask')
        else:
            self.hide_subnetpool_choices()

    def get_subnetpool_choices(self, request):
        subnetpool_choices = [('', _('Select a pool'))]

        for subnetpool in api.neutron.subnetpool_list(request):
            subnetpool_choices.append((subnetpool.id, subnetpool))
        return subnetpool_choices

    def hide_subnetpool_choices(self):
        self.fields['address_source'].widget = forms.HiddenInput()
        self.fields['subnetpool'].choices = []
        self.fields['subnetpool'].widget = forms.HiddenInput()
        self.fields['prefixlen'].widget = forms.HiddenInput()

    def _check_subnet_data(self, cleaned_data, is_create=True):
        cidr = cleaned_data.get('cidr')
        ip_version = int(cleaned_data.get('ip_version'))
        gateway_ip = cleaned_data.get('gateway_ip')
        no_gateway = cleaned_data.get('no_gateway')
        address_source = cleaned_data.get('address_source')
        subnetpool = cleaned_data.get('subnetpool')

        if not subnetpool and address_source == 'subnetpool':
            msg = _('Specify "Address pool" or select '
                    '"Enter Network Address manually" and specify '
                    '"Network Address".')
            raise forms.ValidationError(msg)
        if not cidr and address_source != 'subnetpool':
            msg = _('Specify "Network Address" or '
                    'clear "Create Subnet" checkbox in previous step.')
            raise forms.ValidationError(msg)
        if cidr:
            subnet = netaddr.IPNetwork(cidr)
            if subnet.version != ip_version:
                msg = _('Network Address and IP version are inconsistent.')
                raise forms.ValidationError(msg)
            if (ip_version == 4 and subnet.prefixlen == 32) or \
                    (ip_version == 6 and subnet.prefixlen == 128):
                msg = _("The subnet in the Network Address is "
                        "too small (/%s).") % subnet.prefixlen
                self._errors['cidr'] = self.error_class([msg])
        if not no_gateway and gateway_ip:
            if netaddr.IPAddress(gateway_ip).version is not ip_version:
                msg = _('Gateway IP and IP version are inconsistent.')
                raise forms.ValidationError(msg)
        if not is_create and not no_gateway and not gateway_ip:
            msg = _('Specify IP address of gateway or '
                    'check "Disable Gateway" checkbox.')
            raise forms.ValidationError(msg)

    def clean(self):
        cleaned_data = super(CreateSubnetInfoAction, self).clean()
        with_subnet = cleaned_data.get('with_subnet')
        if not with_subnet:
            return cleaned_data
        self._check_subnet_data(cleaned_data)
        return cleaned_data
Exemple #24
0
class UpdateIKEPolicy(forms.SelfHandlingForm):
    name = forms.CharField(max_length=80, label=_("Name"), required=False)
    ikepolicy_id = forms.CharField(
        label=_("ID"), widget=forms.TextInput(attrs={'readonly': 'readonly'}))
    description = forms.CharField(required=False,
                                  max_length=80,
                                  label=_("Description"))
    # Currently this field has only one choice, so mark it as readonly.
    auth_algorithm = forms.ChoiceField(
        label=_("Authorization algorithm"),
        choices=[('sha1', _('sha1'))],
        widget=forms.ThemableSelectWidget(attrs={'readonly': 'readonly'}),
        required=False)
    encryption_algorithm = forms.ChoiceField(label=_("Encryption algorithm"),
                                             choices=[
                                                 ('3des', _('3des')),
                                                 ('aes-128', _('aes-128')),
                                                 ('aes-192', _('aes-192')),
                                                 ('aes-256', _('aes-256'))
                                             ],
                                             required=False)
    ike_version = forms.ChoiceField(label=_("IKE version"),
                                    choices=[('v1', _('v1')), ('v2', _('v2'))],
                                    required=False)
    # Currently this field has only one choice, so mark it as readonly.
    lifetime_units = forms.ChoiceField(
        label=_("Lifetime units for IKE keys"),
        choices=[('seconds', _('seconds'))],
        widget=forms.ThemableSelectWidget(attrs={'readonly': 'readonly'}),
        required=False)
    lifetime_value = forms.IntegerField(
        min_value=60,
        label=_("Lifetime value for IKE keys"),
        help_text=_("Equal to or greater than 60"),
        required=False)
    pfs = forms.ChoiceField(label=_("Perfect Forward Secrecy"),
                            choices=[('group2', _('group2')),
                                     ('group5', _('group5')),
                                     ('group14', _('group14'))],
                            required=False)
    # Currently this field has only one choice, so mark it as readonly.
    phase1_negotiation_mode = forms.ChoiceField(
        label=_("IKE Phase1 negotiation mode"),
        choices=[('main', 'main')],
        widget=forms.ThemableSelectWidget(attrs={'readonly': 'readonly'}),
        required=False)

    failure_url = 'horizon:project:vpn:index'

    def handle(self, request, context):
        try:
            data = {
                'ikepolicy': {
                    'name': context['name'],
                    'description': context['description'],
                    'auth_algorithm': context['auth_algorithm'],
                    'encryption_algorithm': context['encryption_algorithm'],
                    'ike_version': context['ike_version'],
                    'lifetime': {
                        'units': context['lifetime_units'],
                        'value': context['lifetime_value']
                    },
                    'pfs': context['pfs'],
                    'phase1_negotiation_mode':
                    context['phase1_negotiation_mode'],
                }
            }
            ikepolicy = api.vpn.ikepolicy_update(request,
                                                 context['ikepolicy_id'],
                                                 **data)
            msg = (_('IKE Policy %s was successfully updated.') %
                   context['name'])
            messages.success(request, msg)
            return ikepolicy
        except Exception as e:
            LOG.info('Failed to update IKE Policy %(id)s: %(exc)s', {
                'id': context['ikepolicy_id'],
                'exc': e
            })
            msg = _('Failed to update IKE Policy %s') % context['name']
            redirect = reverse(self.failure_url)
            exceptions.handle(request, msg, redirect=redirect)
Exemple #25
0
class LaunchForm(forms.SelfHandlingForm):
    name = forms.CharField(label=_("Cluster Name"), max_length=80)
    datastore = forms.ChoiceField(
        label=_("Datastore"),
        help_text=_("Type and version of datastore."),
        widget=forms.Select(attrs={
            'class': 'switchable',
            'data-slug': 'datastore'
        }))
    network = forms.ChoiceField(label=_("Network"),
                                help_text=_("Network attached to instance."),
                                required=False)
    volume = forms.IntegerField(label=_("Volume Size"),
                                min_value=0,
                                initial=1,
                                help_text=_("Size of the volume in GB."))
    locality = forms.ChoiceField(
        label=_("Locality"),
        choices=[("", "None"), ("affinity", "affinity"),
                 ("anti-affinity", "anti-affinity")],
        required=False,
        help_text=_("Specify whether instances in the cluster will "
                    "be created on the same hypervisor (affinity) or on "
                    "different hypervisors (anti-affinity)."))
    root_password = forms.CharField(
        label=_("Root Password"),
        required=False,
        help_text=_("Password for root user."),
        widget=forms.PasswordInput(attrs={
            'class': 'switched',
            'data-switch-on': 'datastore',
        }))
    num_instances_vertica = forms.IntegerField(
        label=_("Number of Instances"),
        min_value=3,
        initial=3,
        required=False,
        help_text=_("Number of instances in the cluster. (Read only)"),
        widget=forms.TextInput(
            attrs={
                'readonly': 'readonly',
                'class': 'switched',
                'data-switch-on': 'datastore',
            }))
    num_shards = forms.IntegerField(
        label=_("Number of Shards"),
        min_value=1,
        initial=1,
        required=False,
        help_text=_("Number of shards. (Read only)"),
        widget=forms.TextInput(
            attrs={
                'readonly': 'readonly',
                'class': 'switched',
                'data-switch-on': 'datastore',
            }))
    num_instances = forms.IntegerField(
        label=_("Number of Instances"),
        initial=3,
        required=False,
        help_text=_("Number of instances in the cluster."),
        widget=forms.TextInput(attrs={
            'class': 'switched',
            'data-switch-on': 'datastore',
        }))

    # (name of field variable, label)
    default_fields = [('num_instances', _('Number of Instances'))]
    mongodb_fields = default_fields + [
        ('num_shards', _('Number of Shards')),
    ]
    vertica_fields = [
        ('num_instances_vertica', ('Number of Instances')),
        ('root_password', _('Root Password')),
    ]

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

        self.fields['datastore'].choices = self.populate_datastore_choices(
            request)
        self.fields['network'].choices = self.populate_network_choices(request)

    def clean(self):
        datastore_field_value = self.data.get("datastore", None)
        if datastore_field_value:
            datastore, datastore_version = (
                create_instance.parse_datastore_and_version_text(
                    common_utils.unhexlify(datastore_field_value)))

            flavor_field_name = self._build_widget_field_name(
                datastore, datastore_version)
            if not self.data.get(flavor_field_name, None):
                msg = _("The flavor must be specified.")
                self._errors[flavor_field_name] = self.error_class([msg])

            if db_capability.is_vertica_datastore(datastore):
                if not self.data.get("root_password", None):
                    msg = _("Password for root user must be specified.")
                    self._errors["root_password"] = self.error_class([msg])
            else:
                if int(self.data.get("num_instances", 0)) < 1:
                    msg = _("The number of instances must be greater than 1.")
                    self._errors["num_instances"] = self.error_class([msg])

                if db_capability.is_mongodb_datastore(datastore):
                    if int(self.data.get("num_shards", 0)) < 1:
                        msg = _("The number of shards must be greater than 1.")
                        self._errors["num_shards"] = self.error_class([msg])

        if not self.data.get("locality", None):
            self.cleaned_data["locality"] = None

        return self.cleaned_data

    @memoized.memoized_method
    def datastore_flavors(self, request, datastore_name, datastore_version):
        try:
            return trove_api.trove.datastore_flavors(request, datastore_name,
                                                     datastore_version)
        except Exception:
            LOG.exception("Exception while obtaining flavors list")
            self._flavors = []
            redirect = reverse('horizon:project:database_clusters:index')
            exceptions.handle(request,
                              _('Unable to obtain flavors.'),
                              redirect=redirect)

    @memoized.memoized_method
    def populate_network_choices(self, request):
        network_list = []
        try:
            if api.base.is_service_enabled(request, 'network'):
                tenant_id = self.request.user.tenant_id
                networks = api.neutron.network_list_for_tenant(
                    request, tenant_id)
                network_list = [(network.id, network.name_or_id)
                                for network in networks]
            else:
                self.fields['network'].widget = forms.HiddenInput()
        except exceptions.ServiceCatalogException:
            network_list = []
            redirect = reverse('horizon:project:database_clusters:index')
            exceptions.handle(request,
                              _('Unable to retrieve networks.'),
                              redirect=redirect)
        return network_list

    @memoized.memoized_method
    def datastores(self, request):
        try:
            return trove_api.trove.datastore_list(request)
        except Exception:
            LOG.exception("Exception while obtaining datastores list")
            self._datastores = []
            redirect = reverse('horizon:project:database_clusters:index')
            exceptions.handle(request,
                              _('Unable to obtain datastores.'),
                              redirect=redirect)

    def filter_cluster_datastores(self, request):
        datastores = []
        for ds in self.datastores(request):
            # TODO(michayu): until capabilities lands
            if db_capability.is_cluster_capable_datastore(ds.name):
                datastores.append(ds)
        return datastores

    @memoized.memoized_method
    def datastore_versions(self, request, datastore):
        try:
            return trove_api.trove.datastore_version_list(request, datastore)
        except Exception:
            LOG.exception("Exception while obtaining datastore version list")
            self._datastore_versions = []
            redirect = reverse('horizon:project:database_clusters:index')
            exceptions.handle(request,
                              _('Unable to obtain datastore versions.'),
                              redirect=redirect)

    def populate_datastore_choices(self, request):
        choices = ()
        datastores = self.filter_cluster_datastores(request)
        if datastores is not None:
            datastore_flavor_fields = {}
            for ds in datastores:
                versions = self.datastore_versions(request, ds.name)
                if versions:
                    # only add to choices if datastore has at least one version
                    version_choices = ()
                    for v in versions:
                        # NOTE(zhaochao): troveclient API resources are lazy
                        # loading objects. When an attribute is not found, the
                        # get() method of the Manager object will be called
                        # with the ID of the resource. However for
                        # datastore_versions, the get() method is expecting two
                        # arguments: datastore and datastore_version(name), so
                        # TypeError will be raised as not enough arguments are
                        # passed. In Python 2.x, hasattr() won't reraise the
                        # exception(which is not correct), but reraise under
                        # Python 3(which should be correct).
                        # Use v.to_dict() to verify the 'active' info instead.
                        if not v.to_dict().get('active', True):
                            continue
                        selection_text = self._build_datastore_display_text(
                            ds.name, v.name)
                        widget_text = self._build_widget_field_name(
                            ds.name, v.name)
                        version_choices = (version_choices +
                                           ((widget_text, selection_text), ))
                        k, v = self._add_datastore_flavor_field(
                            request, ds.name, v.name)
                        datastore_flavor_fields[k] = v
                        self._add_attr_to_optional_fields(ds.name, widget_text)

                    choices = choices + version_choices
            self._insert_datastore_version_fields(datastore_flavor_fields)
        return choices

    def _add_datastore_flavor_field(self, request, datastore,
                                    datastore_version):
        name = self._build_widget_field_name(datastore, datastore_version)
        attr_key = 'data-datastore-' + name
        field = forms.ChoiceField(label=_("Flavor"),
                                  help_text=_("Size of image to launch."),
                                  required=False,
                                  widget=forms.Select(
                                      attrs={
                                          'class': 'switched',
                                          'data-switch-on': 'datastore',
                                          attr_key: _("Flavor")
                                      }))
        valid_flavors = self.datastore_flavors(request, datastore,
                                               datastore_version)
        if valid_flavors:
            field.choices = instance_utils.sort_flavor_list(
                request, valid_flavors)

        return name, field

    def _build_datastore_display_text(self, datastore, datastore_version):
        return datastore + ' - ' + datastore_version

    def _build_widget_field_name(self, datastore, datastore_version):
        # Since the fieldnames cannot contain an uppercase character
        # we generate a hex encoded string representation of the
        # datastore and version as the fieldname
        return common_utils.hexlify(
            self._build_datastore_display_text(datastore, datastore_version))

    def _insert_datastore_version_fields(self, datastore_flavor_fields):
        fields_to_restore_at_the_end = collections.OrderedDict()
        while True:
            k, v = self.fields.popitem()
            if k == 'datastore':
                self.fields[k] = v
                break
            else:
                fields_to_restore_at_the_end[k] = v

        for k, v in datastore_flavor_fields.items():
            self.fields[k] = v

        for k in reversed(list(fields_to_restore_at_the_end.keys())):
            self.fields[k] = fields_to_restore_at_the_end[k]

    def _add_attr_to_optional_fields(self, datastore, selection_text):
        if db_capability.is_mongodb_datastore(datastore):
            fields = self.mongodb_fields
        elif db_capability.is_vertica_datastore(datastore):
            fields = self.vertica_fields
        else:
            fields = self.default_fields

        for field in fields:
            attr_key = 'data-datastore-' + selection_text
            widget = self.fields[field[0]].widget
            if attr_key not in widget.attrs:
                widget.attrs[attr_key] = field[1]

    def _get_locality(self, data):
        locality = None
        if data.get('locality'):
            locality = data['locality']
        return locality

    @sensitive_variables('data')
    def handle(self, request, data):
        try:
            datastore, datastore_version = (
                create_instance.parse_datastore_and_version_text(
                    common_utils.unhexlify(data['datastore'])))

            flavor_field_name = self._build_widget_field_name(
                datastore, datastore_version)
            flavor = data[flavor_field_name]
            num_instances = data['num_instances']
            root_password = None
            if db_capability.is_vertica_datastore(datastore):
                root_password = data['root_password']
                num_instances = data['num_instances_vertica']
            LOG.info(
                "Launching cluster with parameters "
                "{name=%s, volume=%s, flavor=%s, "
                "datastore=%s, datastore_version=%s", "locality=%s",
                data['name'], data['volume'], flavor, datastore,
                datastore_version, self._get_locality(data))

            trove_api.trove.cluster_create(request,
                                           data['name'],
                                           data['volume'],
                                           flavor,
                                           num_instances,
                                           datastore=datastore,
                                           datastore_version=datastore_version,
                                           nics=data['network'],
                                           root_password=root_password,
                                           locality=self._get_locality(data))
            messages.success(request,
                             _('Launched cluster "%s"') % data['name'])
            return True
        except Exception:
            redirect = reverse("horizon:project:database_clusters:index")
            exceptions.handle(request,
                              _('Unable to launch cluster.'),
                              redirect=redirect)
Exemple #26
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)

            server_group = 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:
            exceptions.handle(request, ignore=True)
            self.api_error(_("Unable to create server group."))
            return False
class CallPluginForm(forms.SelfHandlingForm):

    uuid = forms.CharField(label=_("Plugin ID"), widget=forms.HiddenInput)

    name = forms.CharField(
        label=_('Plugin Name'),
        widget=forms.TextInput(attrs={'readonly': 'readonly'})
    )

    board_list = forms.MultipleChoiceField(
        label=_("Boards List"),
        widget=forms.SelectMultiple(
            attrs={'class': 'switchable', 'data-slug': 'slug-call-boards'}),
        help_text=_("Select boards in this pool ")
    )

    parameters = forms.CharField(
        label=_("Parameters"),
        required=False,
        widget=forms.Textarea(
            attrs={'class': 'switchable',
                   'data-slug': 'slug-callplugin-json'}),
        help_text=_("Plugin parameters")
    )

    def __init__(self, *args, **kwargs):

        super(CallPluginForm, self).__init__(*args, **kwargs)
        # input=kwargs.get('initial',{})

        boardslist_length = len(kwargs["initial"]["board_list"])

        self.fields["board_list"].choices = kwargs["initial"]["board_list"]
        self.fields["board_list"].max_length = boardslist_length

    def handle(self, request, data):

        counter = 0

        if not data["parameters"]:
            data["parameters"] = {}
        else:
            data["parameters"] = json.loads(data["parameters"])

        for board in data["board_list"]:
            for key, value in self.fields["board_list"].choices:
                if key == board:

                    try:
                        plugin = None
                        plugin = iotronic.plugin_action(request, key,
                                                        data["uuid"],
                                                        "PluginCall",
                                                        data["parameters"])
                        # LOG.debug("API: %s %s", plugin, request)
                        message_text = "Plugin called successfully on board " \
                                       + str(value) + "."
                        messages.success(request, _(message_text))

                        if counter != len(data["board_list"]) - 1:
                            counter += 2
                        else:
                            return plugin
                    except Exception:
                        message_text = "Unable to call plugin on board " \
                                       + str(value) + "."
                        exceptions.handle(request, _(message_text))

                    break
Exemple #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_WORKER:
                _("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_WORKER:
                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_WORKER:
                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
        storage_backend = stx_api.sysinv.get_storage_backend(request)
        if stx_api.sysinv.STORAGE_BACKEND_CEPH not in storage_backend:
            self.fields['personality'].choices = \
                PERSONALITY_CHOICES_WITHOUT_STORAGE

        # All-in-one system, personality can be controller or worker.
        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_CHOICES_WITHOUT_STORAGE

    def clean(self):
        cleaned_data = super(AddHostInfoAction, self).clean()
        return cleaned_data
Exemple #29
0
class UpdateIPSecPolicy(forms.SelfHandlingForm):
    name = forms.CharField(max_length=80, label=_("Name"), required=False)
    ipsecpolicy_id = forms.CharField(
        label=_("ID"),
        widget=forms.TextInput(attrs={'readonly': 'readonly'}))
    description = forms.CharField(
        required=False, max_length=80, label=_("Description"))
    # Currently this field has only one choice, so mark it as readonly.
    auth_algorithm = forms.ChoiceField(
        label=_("Authorization algorithm"),
        choices=[('sha1', _('sha1'))],
        widget=forms.TextInput(attrs={'readonly': 'readonly'}))
    encapsulation_mode = forms.ChoiceField(
        label=_("Encapsulation mode"),
        choices=[('tunnel', _('tunnel')),
                 ('transport', _('transport'))])
    encryption_algorithm = forms.ChoiceField(
        label=_("Encryption algorithm"),
        choices=[('3des', _('3des')),
                 ('aes-128', _('aes-128')),
                 ('aes-192', _('aes-192')),
                 ('aes-256', _('aes-256'))])
    # Currently this field has only one choice, so mark it as readonly.
    lifetime_units = forms.ChoiceField(
        label=_("Lifetime units"),
        choices=[('seconds', _('seconds'))],
        widget=forms.Select(attrs={'readonly': 'readonly'}))
    lifetime_value = forms.IntegerField(
        min_value=60,
        label=_("Lifetime value"),
        help_text=_("Equal to or greater than 60"))
    pfs = forms.ChoiceField(
        label=_("Perfect Forward Secrecy"),
        choices=[('group2', _('group2')),
                 ('group5', _('group5')),
                 ('group14', _('group14'))])
    transform_protocol = forms.ChoiceField(
        label=_("Transform Protocol"),
        choices=[('esp', _('esp')),
                 ('ah', _('ah')),
                 ('ah-esp', _('ah-esp'))])

    failure_url = 'horizon:project:vpn:index'

    def handle(self, request, context):
        try:
            data = {'ipsecpolicy':
                {'name': context['name'],
                 'description': context['description'],
                 'auth_algorithm': context['auth_algorithm'],
                 'encapsulation_mode': context['encapsulation_mode'],
                 'encryption_algorithm': context['encryption_algorithm'],
                 'lifetime': {'units': context['lifetime_units'],
                              'value': context['lifetime_value']},
                 'pfs': context['pfs'],
                 'transform_protocol': context['transform_protocol'],
                 }}
            ipsecpolicy = api.vpn.ipsecpolicy_update(
                request, context['ipsecpolicy_id'], **data)
            msg = (_('IPSec Policy %s was successfully updated.')
                   % context['name'])
            LOG.debug(msg)
            messages.success(request, msg)
            return ipsecpolicy
        except Exception as e:
            msg = _('Failed to update IPSec Policy %s') % context['name']
            LOG.info('%s: %s' % (msg, e))
            redirect = reverse(self.failure_url)
            exceptions.handle(request, msg, redirect=redirect)
Exemple #30
0
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

from django.utils.functional import cached_property  # noqa
from django.utils.translation import ugettext_lazy as _  # noqa

from horizon import exceptions
from horizon import forms
from horizon import messages

from monitoring import api
from monitoring.notifications import constants

READONLY_TEXTINPUT = forms.TextInput(attrs={'readonly': 'readonly'})


class BaseNotificationMethodForm(forms.SelfHandlingForm):
    @classmethod
    def _instantiate(cls, request, *args, **kwargs):
        return cls(request, *args, **kwargs)

    def _init_fields(self, readOnly=False, create=False):
        required = True
        textWidget = None
        selectWidget = None
        readOnlyTextInput = READONLY_TEXTINPUT
        readOnlySelectInput = forms.Select(attrs={'disabled': 'disabled'})
        if readOnly:
            required = False