Example #1
0
class AddProtocolForm(forms.SelfHandlingForm):
    idp_id = forms.CharField(
        label=_("Identity Provider ID"),
        widget=forms.TextInput(attrs={'readonly': 'readonly'}))
    id = forms.CharField(label=_("Protocol ID"))
    mapping_id = forms.ThemableChoiceField(label=_("Mapping ID"))

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

    def populate_mapping_id_choices(self, request):
        try:
            mappings = api.keystone.mapping_list(request)
        except Exception as e:
            LOG.info('Failed to get mapping list %s', e)
            msg = _('Failed to get mapping list %s') % e
            messages.error(request, msg)

        choices = [(m.id, m.id) for m in mappings]
        choices.sort()

        if choices:
            choices.insert(0, ("", _("Select Mapping")))
        else:
            choices.insert(0, ("", _("No mappings available")))

        self.fields['mapping_id'].choices = choices

    def handle(self, request, data):
        try:
            new_mapping = api.keystone.protocol_create(request, data["id"],
                                                       data["idp_id"],
                                                       data["mapping_id"])
            messages.success(
                request, _("Identity provider protocol created successfully."))
            return new_mapping
        except exceptions.Conflict:
            msg = _('Protocol ID "%s" is already used.') % data["id"]
            messages.error(request, msg)
        except Exception:
            exceptions.handle(
                request, _("Unable to create identity provider protocol."))
Example #2
0
class SetFlavorChoiceAction(workflows.Action):
    old_flavor_id = forms.CharField(required=False, widget=forms.HiddenInput())
    old_flavor_name = forms.CharField(
        label=_("Old Flavor"),
        widget=forms.TextInput(attrs={'readonly': 'readonly'}),
        required=False,
    )
    flavor = forms.ThemableChoiceField(
        label=_("New Flavor"), help_text=_("Choose the flavor to launch."))

    class Meta(object):
        name = _("Flavor Choice")
        slug = 'flavor_choice'
        help_text_template = ("admin/vgpu/" "_flavors_and_quotas.html")

    def populate_flavor_choices(self, request, context):
        old_flavor_id = context.get('old_flavor_id')
        flavors = context.get('flavors').values()

        # Remove current flavor from the list of flavor choices
        flavors = [flavor for flavor in flavors if flavor.id != old_flavor_id]
        if len(flavors) > 1:
            flavors = instance_utils.sort_flavor_list(request, flavors)
        if flavors:
            flavors.insert(0, ("", _("Select a New Flavor")))
        else:
            flavors.insert(0, ("", _("No flavors available")))
        return flavors

    def get_help_text(self, extra_context=None):
        extra = {} if extra_context is None else dict(extra_context)
        try:
            extra['usages'] = api.nova.tenant_absolute_limits(self.request,
                                                              reserved=True)
            extra['usages_json'] = json.dumps(extra['usages'])
            flavors = json.dumps(
                [f._info for f in instance_utils.flavor_list(self.request)])
            extra['flavors'] = flavors
            extra['resize_instance'] = True
        except Exception:
            exceptions.handle(self.request,
                              _("Unable to retrieve quota information."))
        return super(SetFlavorChoiceAction, self).get_help_text(extra)
Example #3
0
class CreateVolumeTypeEncryption(forms.SelfHandlingForm):
    name = forms.CharField(
        label=_("Name"),
        required=False,
        widget=forms.TextInput(attrs={'readonly': 'readonly'}))
    provider = forms.CharField(max_length=255, label=_("Provider"))
    control_location = forms.ThemableChoiceField(label=_("Control Location"),
                                                 choices=(('front-end',
                                                           _('front-end')),
                                                          ('back-end',
                                                           _('back-end'))))
    cipher = forms.CharField(label=_("Cipher"), required=False)
    key_size = forms.IntegerField(label=_("Key Size (bits)"),
                                  required=False,
                                  min_value=1)
    volume_type_id = forms.CharField(widget=forms.HiddenInput())

    def handle(self, request, data):
        try:
            # Set Cipher to None if empty
            if data['cipher'] == u'':
                data['cipher'] = None

            volume_type_id = data.pop('volume_type_id')
            volume_type_name = data.pop('name')

            # Create encryption for the volume type
            volume_type = cinder.\
                volume_encryption_type_create(request,
                                              volume_type_id,
                                              data)
            messages.success(
                request,
                _('Successfully created encryption for '
                  'volume type: %s') % volume_type_name)
            return volume_type
        except Exception as ex:
            redirect = reverse("horizon:admin:volume_types:index")
            exceptions.handle(request,
                              _('Unable to create encrypted volume type: %s') %
                              ex,
                              redirect=redirect)
Example #4
0
class SetGatewayForm(forms.SelfHandlingForm):
    network_id = forms.ThemableChoiceField(label=_("External Network"))
    failure_url = 'horizon:project:routers:index'

    def __init__(self, request, *args, **kwargs):
        super(SetGatewayForm, self).__init__(request, *args, **kwargs)
        c = self.populate_network_id_choices(request)
        self.fields['network_id'].choices = c

    def populate_network_id_choices(self, request):
        search_opts = {'router:external': True}
        try:
            networks = api.neutron.network_list(request, **search_opts)
        except Exception as e:
            LOG.info('Faield to get network list: %s', e)
            msg = _('Failed to get network list: %s') % e
            messages.error(request, msg)
            redirect = reverse(self.failure_url)
            exceptions.handle(request, msg, redirect=redirect)
            return
        choices = [(network.id, network.name or network.id)
                   for network in networks]
        if choices:
            choices.insert(0, ("", _("Select network")))
        else:
            choices.insert(0, ("", _("No networks available")))
        return choices

    def handle(self, request, data):
        try:
            api.neutron.router_add_gateway(request,
                                           self.initial['router_id'],
                                           data['network_id'])
            msg = _('Gateway interface is added')
            messages.success(request, msg)
            return True
        except Exception as e:
            LOG.info('Failed to set gateway to router %(id)s: %(exc)s',
                     {'id': self.initial['router_id'], 'exc': e})
            msg = _('Failed to set gateway: %s') % e
            redirect = reverse(self.failure_url)
            exceptions.handle(request, msg, redirect=redirect)
class AddPort(forms.SelfHandlingForm):
    failure_url = 'horizon:project:firewalls_v2:index'
    port_id = forms.ThemableChoiceField(
        label=_("Ports"), required=False)

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

        try:
            tenant_id = self.request.user.tenant_id
            ports = api_fwaas_v2.fwg_port_list_for_tenant(request, tenant_id)
            initial_ports = self.initial['ports']
            filtered_ports = [port for port in ports
                              if port.id not in initial_ports]
            filtered_ports = sorted(filtered_ports, key=attrgetter('name'))
        except Exception:
            exceptions.handle(request, _('Unable to retrieve port list.'))
            ports = []

        current_choices = [(p.id, p.name_or_id) for p in filtered_ports]
        self.fields['port_id'].choices = current_choices

    def handle(self, request, context):
        firewallgroup_id = self.initial['firewallgroup_id']
        name_or_id = context.get('name') or firewallgroup_id
        body = _get_request_body(context, self.initial)
        add_port = context['port_id']
        if add_port:
            ports = self.initial['ports']
            ports.append(add_port)
            body['ports'] = ports
        try:
            firewallgroup = api_fwaas_v2.firewall_update(
                request, firewallgroup_id, **body)
            msg = _('FirewallGroup %s was successfully updated.') % name_or_id
            messages.success(request, msg)
            return firewallgroup
        except Exception as e:
            msg = (_('Failed to update firewallgroup %(name)s: %(reason)s') %
                   {'name': name_or_id, 'reason': e})
            redirect = reverse(self.failure_url)
            exceptions.handle(request, msg, redirect=redirect)
Example #6
0
class CreateInstance(forms.SelfHandlingForm):

    controller = forms.ThemableChoiceField(label=_("Controller"))

    parameters = forms.CharField(
        widget=forms.widgets.Textarea(attrs={'rows': 2}),
        label=_("Parameters"),
        required=False)

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

    status = forms.CharField(
        max_length=255,
        label=_("Status"),
        initial='Stopped',
        widget=forms.HiddenInput(  # hidden
            attrs={"ng-model": "status"}))

    def __init__(self, request, *args, **kwargs):
        super(CreateInstance, self).__init__(request, *args, **kwargs)
        controllers = json.loads(api.get_all_controllers(self.request).text)
        self.fields['controller'].choices = [(controller['id'],
                                              controller['controller_name'])
                                             for controller in controllers]

    @staticmethod
    def handle(request, data):
        try:
            response = api.add_instance(request, data)
            if 200 <= response.status_code < 300:
                messages.success(request, _("Instance successfully created."))
                return data
            else:
                raise sdsexception.SdsException(response.text)
        except Exception as ex:
            redirect = reverse("horizon:crystal:controllers:index")
            error_message = "Unable to create instance.\t %s" % ex.message
            exceptions.handle(request, _(error_message), redirect=redirect)
Example #7
0
class UpdateNetwork(forms.SelfHandlingForm):
    name = forms.CharField(label=_("Name"), required=False)
    tenant_id = forms.CharField(widget=forms.HiddenInput)
    network_id = forms.CharField(
        label=_("ID"), widget=forms.TextInput(attrs={'readonly': 'readonly'}))
    admin_state = forms.ThemableChoiceField(choices=[(True, _('UP')),
                                                     (False, _('DOWN'))],
                                            label=_("Admin State"))
    shared = forms.BooleanField(label=_("Shared"), required=False)
    external = forms.BooleanField(label=_("External Network"), required=False)
    failure_url = 'horizon:admin:networks:index'

    def handle(self, request, data):
        try:
            params = {
                'name': data['name'],
                'admin_state_up': (data['admin_state'] == 'True'),
                'shared': data['shared'],
                'router:external': data['external']
            }
            network = api.neutron.network_update(request,
                                                 self.initial['network_id'],
                                                 **params)
            msg = _('Network %s was successfully updated.') % data['name']
            LOG.debug(msg)
            api.nova.systemlogs_create(request,
                                       data['name'],
                                       record_action.UPDATENETWORK,
                                       detail=msg)
            messages.success(request, msg)
            return network
        except Exception:
            msg = _('Failed to update network %s') % data['name']
            LOG.info(msg)
            api.nova.systemlogs_create(request,
                                       data['name'],
                                       record_action.UPDATENETWORK,
                                       result=False,
                                       detail=msg)
            redirect = reverse(self.failure_url)
            exceptions.handle(request, msg, redirect=redirect)
Example #8
0
class UpdateNetwork(forms.SelfHandlingForm):
    name = forms.CharField(label=_("Name"), required=False)
    tenant_id = forms.CharField(widget=forms.HiddenInput)
    network_id = forms.CharField(label=_("ID"),
                                 widget=forms.TextInput(
                                     attrs={'readonly': 'readonly'}))
    admin_state = forms.ThemableChoiceField(
        choices=[('True', _('UP')),
                 ('False', _('DOWN'))],
        required=False,
        label=_("Admin State"))
    shared = forms.BooleanField(label=_("Shared"), required=False)
    failure_url = 'horizon:project:networks:index'

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

        if not policy.check((("network", "create_network:shared"),), request):
            self.fields['shared'].widget = forms.HiddenInput()

    def handle(self, request, data):
        try:
            params = {'admin_state_up': (data['admin_state'] == 'True'),
                      'name': data['name']}
            # Make sure we are not sending shared data when the user
            # doesnt'have admin rights because even if the user doesn't
            # change it neutron sends back a 403 error
            if policy.check((("network", "update_network:shared"),), request):
                params['shared'] = data['shared']
            network = api.neutron.network_update(request,
                                                 data['network_id'],
                                                 **params)
            msg = _('Network %s was successfully updated.') % data['name']
            LOG.debug(msg)
            messages.success(request, msg)
            return network
        except Exception:
            msg = _('Failed to update network %s') % data['name']
            LOG.info(msg)
            redirect = reverse(self.failure_url)
            exceptions.handle(request, msg, redirect=redirect)
Example #9
0
class DetachInterface(forms.SelfHandlingForm):
    instance_id = forms.CharField(widget=forms.HiddenInput())
    port = forms.ThemableChoiceField(label=_("Port"))

    def __init__(self, request, *args, **kwargs):
        super(DetachInterface, self).__init__(request, *args, **kwargs)
        instance_id = self.initial.get("instance_id", None)

        ports = []
        try:
            ports = api.neutron.port_list(request, device_id=instance_id)
        except Exception:
            exceptions.handle(request, _('Unable to retrieve ports '
                                         'information.'))
        choices = []
        for port in ports:
            ips = []
            for ip in port.fixed_ips:
                ips.append(ip['ip_address'])
            choices.append((port.id, ','.join(ips) or port.id))
        if choices:
            choices.insert(0, ("", _("Select Port")))
        else:
            choices.insert(0, ("", _("No Ports available")))
        self.fields['port'].choices = choices

    def handle(self, request, data):
        instance_id = data['instance_id']
        port = data.get('port')
        try:
            api.nova.interface_detach(request, instance_id, port)
            msg = _('Detached interface %(port)s for instance '
                    '%(instance)s.') % {'port': port, 'instance': instance_id}
            messages.success(request, msg)
        except Exception:
            redirect = reverse('horizon:project:instances:index')
            exceptions.handle(request, _("Unable to detach interface."),
                              redirect=redirect)
        return True
Example #10
0
class CreateQosSpec(forms.SelfHandlingForm):
    name = forms.CharField(max_length=255, label=_("Name"))
    consumer = forms.ThemableChoiceField(label=_("Consumer"),
                                         choices=cinder.CONSUMER_CHOICES)

    def handle(self, request, data):
        try:
            qos_spec = cinder.qos_spec_create(request, data['name'],
                                              {'consumer': data['consumer']})
            messages.success(
                request,
                _('Successfully created QoS Spec: %s') % data['name'])
            return qos_spec
        except Exception as ex:
            if getattr(ex, 'code', None) == 409:
                msg = _('QoS Spec name "%s" already ' 'exists.') % data['name']
                self._errors['name'] = self.error_class([msg])
            else:
                redirect = reverse("horizon:admin:volumes:index")
                exceptions.handle(request,
                                  _('Unable to create QoS Spec.'),
                                  redirect=redirect)
Example #11
0
class UpdateNetwork(forms.SelfHandlingForm):
    name = forms.CharField(label=_("Name"), required=False)
    tenant_id = forms.CharField(widget=forms.HiddenInput)
    network_id = forms.CharField(
        label=_("ID"), widget=forms.TextInput(attrs={'readonly': 'readonly'}))
    admin_state = forms.ThemableChoiceField(choices=[(True, _('UP')),
                                                     (False, _('DOWN'))],
                                            required=False,
                                            label=_("Admin State"))
    shared = forms.BooleanField(label=_("Shared"), required=False)
    failure_url = 'horizon:project:networks:index'

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

        if not policy.check((("network", "create_network:shared"), ), request):
            self.fields['shared'].widget = forms.CheckboxInput(
                attrs={'disabled': True})
            self.fields['shared'].help_text = _(
                'Non admin users are not allowed to set shared option.')

    def handle(self, request, data):
        try:
            params = {
                'admin_state_up': (data['admin_state'] == 'True'),
                'name': data['name'],
                'shared': data['shared']
            }
            network = api.neutron.network_update(request, data['network_id'],
                                                 **params)
            msg = _('Network %s was successfully updated.') % data['name']
            LOG.debug(msg)
            messages.success(request, msg)
            return network
        except Exception:
            msg = _('Failed to update network %s') % data['name']
            LOG.info(msg)
            redirect = reverse(self.failure_url)
            exceptions.handle(request, msg, redirect=redirect)
Example #12
0
class AttachInterface(forms.SelfHandlingForm):
    instance_id = forms.CharField(widget=forms.HiddenInput())
    network = forms.ThemableChoiceField(label=_("Network"))

    def __init__(self, request, *args, **kwargs):
        super(AttachInterface, self).__init__(request, *args, **kwargs)
        networks = instance_utils.network_field_data(request,
                                                     include_empty_option=True)
        self.fields['network'].choices = networks

    def handle(self, request, data):
        instance_id = data['instance_id']
        network = data.get('network')
        try:
            api.nova.interface_attach(request, instance_id, net_id=network)
            msg = _('Attaching interface for instance %s.') % instance_id
            messages.success(request, msg)
        except Exception:
            redirect = reverse('horizon:project:instances:index')
            exceptions.handle(request, _("Unable to attach interface."),
                              redirect=redirect)
        return True
Example #13
0
class UpdateZone(forms.SelfHandlingForm):

    name = forms.CharField(max_length=255,
                           label=_("Name"),
                           help_text=_("The name of the new zone."))

    regions = forms.ThemableChoiceField(label=_("Region"))

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

    zone_id = forms.CharField(max_length=255,
                              label=_("Zone ID"),
                              widget=forms.HiddenInput())

    def __init__(self, request, *args, **kwargs):
        super(UpdateZone, self).__init__(request, *args, **kwargs)
        self.fields['regions'].choices = [
            (region['id'], region['name']) for region in json.loads(
                api.swift_list_regions(self.request).text)
        ]

    def handle(self, request, data):
        try:
            response = api.update_zone(request, data)
            if 200 <= response.status_code < 300:
                messages.success(
                    request,
                    _('Successfully updated node: %s') % data['zone_id'])
                return data
            else:
                raise sdsexception.SdsException(response.text)
        except Exception as ex:
            redirect = reverse("horizon:crystal:zones:index")
            error_message = "Unable to update zone.\t %s" % ex.message
            exceptions.handle(request, _(error_message), redirect=redirect)
Example #14
0
    def __init__(self, request, *args, **kwargs):
        super(CreatePort, 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.ThemableChoiceField(
                            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)
Example #15
0
class UpdateStatus(forms.SelfHandlingForm):
    status = forms.ThemableChoiceField(label=_("Status"))

    def __init__(self, request, *args, **kwargs):
        # Obtain the localized status to use as initial value, has to be done
        # before super() otherwise the initial value will get overwritten back
        # to the raw value
        current_status = kwargs['initial']['status']
        choices = dict(STATUS_CHOICES)
        kwargs['initial']['status'] = choices[current_status]

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

        self.fields['status'].choices = populate_status_choices(
            current_status, STATUS_CHOICES)

    def handle(self, request, data):
        # Obtain the localized status for including in the message
        for choice in self.fields['status'].choices:
            if choice[0] == data['status']:
                new_status = choice[1]
                break
        else:
            new_status = data['status']

        try:
            cinder.volume_reset_state(request,
                                      self.initial['volume_id'],
                                      data['status'])
            messages.success(request,
                             _('Successfully updated volume status to "%s".') %
                             new_status)
            return True
        except Exception:
            redirect = reverse("horizon:admin:volumes:index")
            exceptions.handle(request,
                              _('Unable to update volume status to "%s".') %
                              new_status, redirect=redirect)
Example #16
0
class EditQosSpecConsumer(forms.SelfHandlingForm):
    current_consumer = forms.CharField(
        label=_("Current consumer"),
        widget=forms.TextInput(attrs={'readonly': 'readonly'}),
        required=False)
    consumer_choice = forms.ThemableChoiceField(
        label=_("New QoS Spec Consumer"),
        choices=cinder.CONSUMER_CHOICES,
        help_text=_("Choose consumer for this QoS Spec."))

    def __init__(self, request, *args, **kwargs):
        super(EditQosSpecConsumer, self).__init__(request, *args, **kwargs)
        consumer_field = self.fields['consumer_choice']
        qos_spec = self.initial["qos_spec"]
        self.fields['current_consumer'].initial = qos_spec.consumer
        choices = [
            choice for choice in cinder.CONSUMER_CHOICES
            if choice[0] != qos_spec.consumer
        ]
        choices.insert(0, ("", _("Select a new consumer")))
        consumer_field.choices = choices

    def handle(self, request, data):
        qos_spec_id = self.initial['qos_spec_id']
        new_consumer = data['consumer_choice']

        # Update QOS Spec consumer information
        try:
            cinder.qos_spec_set_keys(request, qos_spec_id,
                                     {'consumer': new_consumer})
            messages.success(request,
                             _('Successfully modified QoS Spec consumer.'))
            return True
        except Exception:
            redirect = reverse("horizon:admin:volumes:index")
            exceptions.handle(request,
                              _('Error editing QoS Spec consumer.'),
                              redirect=redirect)
Example #17
0
class RemovePort(forms.SelfHandlingForm):
    failure_url = 'horizon:project:firewalls_v2:index'
    port_id = forms.ThemableChoiceField(label=_("Ports"), required=False)

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

        try:
            ports = self.initial['ports']
        except Exception:
            exceptions.handle(request, _('Unable to retrieve port list.'))
            ports = []

        current_choices = [(p, p) for p in ports]
        self.fields['port_id'].choices = current_choices

    def handle(self, request, context):
        firewallgroup_id = self.initial['id']
        name_or_id = context.get('name') or firewallgroup_id
        body = _get_request_body(context, self.initial)
        remove_port = context['port_id']
        if remove_port:
            ports = self.initial['ports']
            ports.remove(remove_port)
            body['ports'] = ports
        try:
            firewallgroup = api_fwaas_v2.firewall_update(
                request, firewallgroup_id, **body)
            msg = _('FirewallGroup %s was successfully updated.') % name_or_id
            messages.success(request, msg)
            return firewallgroup
        except Exception as e:
            msg = (_('Failed to update firewallgroup %(name)s: %(reason)s') % {
                'name': name_or_id,
                'reason': e
            })
            redirect = reverse(self.failure_url)
            exceptions.handle(request, msg, redirect=redirect)
Example #18
0
class ThemableChoiceFieldForm(forms.SelfHandlingForm):
    # It's POSSIBLE to combine this with the test helper form above, but
    # I fear we'd run into collisions where one test's desired output is
    # actually within a separate widget's output.

    title_dic = {
        "label1": {
            "title": "This is choice 1"
        },
        "label2": {
            "title": "This is choice 2"
        },
        "label3": {
            "title": "This is choice 3"
        }
    }
    name = forms.CharField(max_length=255,
                           label="Test Name",
                           help_text="Please enter a name")
    test_choices = forms.ThemableChoiceField(
        label="Test Choices",
        required=False,
        help_text="Testing drop down choices",
        widget=forms.fields.ThemableSelectWidget(
            attrs={
                'class': 'switchable',
                'data-slug': 'source'
            },
            transform_html_attrs=title_dic.get))

    def __init__(self, request, *args, **kwargs):
        super(ThemableChoiceFieldForm, self).__init__(request, *args, **kwargs)
        choices = ([('choice1', 'label1'), ('choice2', 'label2')])
        self.fields['test_choices'].choices = choices

    def handle(self, request, data):
        return True
Example #19
0
class CreateContainer(forms.SelfHandlingForm):
    ACCESS_CHOICES = (
        ("private", _("Private")),
        ("public", _("Public")),
    )

    parent = forms.CharField(max_length=255,
                             required=False,
                             widget=forms.HiddenInput)
    name = forms.CharField(max_length=255,
                           label=_("Container Name"),
                           validators=[no_slash_validator])
    access = forms.ThemableChoiceField(label=_("Container Access"),
                                       choices=ACCESS_CHOICES)

    def handle(self, request, data):
        try:
            if not data['parent']:
                is_public = data["access"] == "public"
                metadata = ({'is_public': is_public})
                # Create a container
                api.swift.swift_create_container(request,
                                                 data["name"],
                                                 metadata=metadata)
                messages.success(request, _("Container created successfully."))
            else:
                # Create a pseudo-folder
                container, slash, remainder = data['parent'].partition("/")
                remainder = remainder.rstrip("/")
                subfolder_name = "/".join(
                    [bit for bit in (remainder, data['name']) if bit])
                api.swift.swift_create_subfolder(request, container,
                                                 subfolder_name)
                messages.success(request, _("Folder created successfully."))
            return True
        except Exception:
            exceptions.handle(request, _('Unable to create container.'))
Example #20
0
class ManagePoliciesForm(forms.SelfHandlingForm):
    cluster_id = forms.CharField(widget=forms.HiddenInput())
    policies = forms.ThemableChoiceField(label=_("Policies"))
    enabled = forms.BooleanField(
        label=_("Enabled"),
        initial=True,
        required=False,
        help_text=_("Whether the policy should be enabled once attached. "
                    "Default to enabled."))

    def __init__(self, request, *args, **kwargs):
        super(ManagePoliciesForm, self).__init__(request, *args, **kwargs)
        cluster_policies = senlin.cluster_policy_list(
            self.request, kwargs['initial']['cluster_id'], {})
        cluster_policies_ids = [policy.id for policy in cluster_policies]
        policies = senlin.policy_list(self.request)[0]
        available_policies = [(policy.id, policy.name) for policy in policies
                              if policy.id not in cluster_policies_ids]
        self.fields['policies'].choices = (
            [("", _("Select Policy"))] + available_policies)

    def handle(self, request, data):
        try:
            params = {"enabled": data.pop('enabled')}
            attach = senlin.cluster_attach_policy(
                request, data["cluster_id"], data['policies'], params)
            msg = _('Attaching policy %(policy)s to cluster '
                    '%(cluster)s.') % {"policy": data['policies'],
                                       "cluster": data['cluster_id']}
            messages.success(request, msg)
            return attach
        except Exception:
            redirect = reverse(INDEX_URL)
            exceptions.handle(request,
                              _("Unable to attach policy."),
                              redirect=redirect)
Example #21
0
class AddFirewallAction(workflows.Action):
    name = forms.CharField(max_length=80, label=_("Name"), required=False)
    description = forms.CharField(max_length=80,
                                  label=_("Description"),
                                  required=False)
    firewall_policy_id = forms.ThemableChoiceField(label=_("Policy"))
    admin_state_up = forms.BooleanField(label=_("Enable Admin State"),
                                        initial=True,
                                        required=False)

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

        firewall_policy_id_choices = [('', _("Select a Policy"))]
        try:
            tenant_id = self.request.user.tenant_id
            policies = api.fwaas.policy_list_for_tenant(request, tenant_id)
            policies = sorted(policies, key=lambda policy: policy.name)
        except Exception as e:
            exceptions.handle(
                request,
                _('Unable to retrieve policy list (%(error)s).') %
                {'error': str(e)})
            policies = []
        for p in policies:
            firewall_policy_id_choices.append((p.id, p.name_or_id))
        self.fields['firewall_policy_id'].choices = firewall_policy_id_choices

    class Meta(object):
        name = _("Firewall")
        permissions = ('openstack.services.network', )
        help_text = _("Create a firewall based on a policy.\n\n"
                      "A firewall represents a logical firewall resource that "
                      "a tenant can instantiate and manage. A firewall must "
                      "be associated with one policy, all other fields are "
                      "optional.")
Example #22
0
class UpdateUserForm(BaseUserForm, AddExtraColumnMixIn):
    # Hide the domain_id and domain_name by default
    domain_id = forms.CharField(label=_("Domain ID"),
                                required=False,
                                widget=forms.HiddenInput())
    domain_name = forms.CharField(label=_("Domain Name"),
                                  required=False,
                                  widget=forms.HiddenInput())
    id = forms.CharField(label=_("ID"), widget=forms.HiddenInput)
    name = forms.CharField(max_length=255, label=_("User Name"))
    description = forms.CharField(
        widget=forms.widgets.Textarea(attrs={'rows': 4}),
        label=_("Description"),
        required=False)
    email = forms.EmailField(label=_("Email"), required=False)
    project = forms.ThemableChoiceField(label=_("Primary Project"),
                                        required=PROJECT_REQUIRED)

    def __init__(self, request, *args, **kwargs):
        super(UpdateUserForm, self).__init__(request, *args, **kwargs)
        self.add_extra_fields()
        if api.keystone.keystone_can_edit_user() is False:
            for field in ('name', 'email'):
                self.fields.pop(field)
        # For keystone V3, display the two fields in read-only
        if api.keystone.VERSIONS.active >= 3:
            readonlyInput = forms.TextInput(attrs={'readonly': 'readonly'})
            self.fields["domain_id"].widget = readonlyInput
            self.fields["domain_name"].widget = readonlyInput
        # For keystone V2.0, hide description field
        else:
            self.fields["description"].widget = forms.HiddenInput()

    def handle(self, request, data):
        user = data.pop('id')

        data.pop('domain_id')
        data.pop('domain_name')

        if not PROJECT_REQUIRED and 'project' not in self.changed_data:
            data.pop('project')

        if 'description' not in self.changed_data:
            data.pop('description')
        try:
            if "email" in data:
                data['email'] = data['email'] or None
            response = api.keystone.user_update(request, user, **data)
            messages.success(request, _('User has been updated successfully.'))
        except exceptions.Conflict:
            msg = _('User name "%s" is already used.') % data['name']
            messages.error(request, msg)
            return False
        except Exception:
            response = exceptions.handle(request, ignore=True)
            messages.error(request, _('Unable to update the user.'))

        if isinstance(response, http.HttpResponse):
            return response
        else:
            return True
Example #23
0
class CreateUserForm(PasswordMixin, BaseUserForm, AddExtraColumnMixIn):
    # Hide the domain_id and domain_name by default
    domain_id = forms.CharField(label=_("Domain ID"),
                                required=False,
                                widget=forms.HiddenInput())
    domain_name = forms.CharField(label=_("Domain Name"),
                                  required=False,
                                  widget=forms.HiddenInput())
    name = forms.CharField(max_length=255, label=_("User Name"))
    description = forms.CharField(
        widget=forms.widgets.Textarea(attrs={'rows': 4}),
        label=_("Description"),
        required=False)
    email = forms.EmailField(label=_("Email"), required=False)
    project = forms.ThemableDynamicChoiceField(label=_("Primary Project"),
                                               required=PROJECT_REQUIRED,
                                               add_item_link=ADD_PROJECT_URL)
    role_id = forms.ThemableChoiceField(label=_("Role"),
                                        required=PROJECT_REQUIRED)
    enabled = forms.BooleanField(label=_("Enabled"),
                                 required=False,
                                 initial=True)

    def __init__(self, *args, **kwargs):
        roles = kwargs.pop('roles')
        super(CreateUserForm, self).__init__(*args, **kwargs)
        # Reorder form fields from multiple inheritance
        ordering = [
            "domain_id", "domain_name", "name", "description", "email",
            "password", "confirm_password", "project", "role_id", "enabled"
        ]
        self.add_extra_fields(ordering)
        self.fields = collections.OrderedDict(
            (key, self.fields[key]) for key in ordering)
        role_choices = [(role.id, role.name) for role in roles]
        self.fields['role_id'].choices = role_choices

        # For keystone V3, display the two fields in read-only
        if api.keystone.VERSIONS.active >= 3:
            readonlyInput = forms.TextInput(attrs={'readonly': 'readonly'})
            self.fields["domain_id"].widget = readonlyInput
            self.fields["domain_name"].widget = readonlyInput
        # For keystone V2.0, hide description field
        else:
            self.fields["description"].widget = forms.HiddenInput()

    # 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):
        domain = api.keystone.get_default_domain(self.request, False)
        try:
            LOG.info('Creating user with name "%s"' % data['name'])
            desc = data["description"]
            if "email" in data:
                data['email'] = data['email'] or None

            # add extra information
            if api.keystone.VERSIONS.active >= 3:
                EXTRA_INFO = getattr(settings, 'USER_TABLE_EXTRA_INFO', {})
                kwargs = dict((key, data.get(key)) for key in EXTRA_INFO)
            else:
                kwargs = {}

            new_user = \
                api.keystone.user_create(request,
                                         name=data['name'],
                                         email=data['email'],
                                         description=desc or None,
                                         password=data['password'],
                                         project=data['project'] or None,
                                         enabled=data['enabled'],
                                         domain=domain.id,
                                         **kwargs)
            messages.success(
                request,
                _('User "%s" was successfully created.') % data['name'])
            if data['project'] and data['role_id']:
                roles = api.keystone.roles_for_user(request, new_user.id,
                                                    data['project']) or []
                assigned = [
                    role for role in roles if role.id == str(data['role_id'])
                ]
                if not assigned:
                    try:
                        api.keystone.add_tenant_user_role(
                            request, data['project'], new_user.id,
                            data['role_id'])
                    except Exception:
                        exceptions.handle(
                            request,
                            _('Unable to add user '
                              'to primary project.'))
            return new_user
        except exceptions.Conflict:
            msg = _('User name "%s" is already used.') % data['name']
            messages.error(request, msg)
        except Exception:
            exceptions.handle(request, _('Unable to create user.'))
Example #24
0
class CreateForm(forms.SelfHandlingForm):
    name = forms.CharField(max_length=255, label=_("Cluster Name"))
    profile_id = forms.ThemableChoiceField(label=_("Profile"))
    min_size = forms.IntegerField(
        label=_("Min Size"),
        required=False,
        initial=0,
        help_text=_("Min size of the cluster. Default to 0."))
    max_size = forms.IntegerField(
        label=_("Max Size"),
        required=False,
        initial=-1,
        help_text=_("Max size of the cluster. Default to -1, "
                    "means unlimited."))
    desired_capacity = forms.IntegerField(
        label=_("Desired Capacity"),
        initial=0,
        help_text=_("Desired capacity of the cluster. Default to 0."))
    # Hide the parent field
    parent = forms.ThemableChoiceField(
        label=_("Parent Cluster"),
        required=False,
        widget=forms.HiddenInput())
    timeout = forms.IntegerField(
        label=_("Timeout"),
        required=False,
        help_text=_("Cluster creation timeout in seconds."))
    metadata = forms.CharField(
        max_length=255,
        label=_("Metadata"),
        required=False,
        help_text=_("YAML formated metadata"),
        widget=forms.Textarea(attrs={'rows': 4}))

    def __init__(self, request, *args, **kwargs):
        super(CreateForm, self).__init__(request, *args, **kwargs)
        profiles = senlin.profile_list(request)[0]
        self.fields['profile_id'].choices = (
            [("", _("Select Profile"))] + [(profile.id, profile.name)
                                           for profile in profiles])

    def handle(self, request, data):
        try:
            # As we hide the parent field, use None here
            data['parent'] = None

            if not data['metadata']:
                metadata = {}
            else:
                try:
                    metadata = yaml.safe_load(data['metadata'])
                except Exception as ex:
                    raise Exception(_('The specified metadata is not a valid '
                                      'YAML format: %s') % ex)
            data['metadata'] = metadata

            cluster = senlin.cluster_create(request, **data)
            msg = _('Creating cluster "%s" successfully') % data['name']
            messages.success(request, msg)
            return cluster
        except Exception:
            redirect = reverse(INDEX_URL)
            exceptions.handle(request,
                              _("Unable to create cluster."),
                              redirect=redirect)
class SetInstanceDetailsAction(workflows.Action):
    availability_zone = forms.ThemableChoiceField(label=_("Availability Zone"),
                                                  required=False)

    name = forms.CharField(label=_("Instance Name"),
                           max_length=255)

    flavor = forms.ThemableChoiceField(label=_("Flavor"),
                                       help_text=_("Size of image to launch."))

    count = forms.IntegerField(label=_("Number of Instances"),
                               min_value=1,
                               initial=1)

    source_type = forms.ThemableChoiceField(
        label=_("Instance Boot Source"),
        help_text=_("Choose Your Boot Source "
                    "Type."))

    instance_snapshot_id = forms.ThemableChoiceField(
        label=_("Instance Snapshot"),
        required=False)

    volume_id = forms.ThemableChoiceField(label=_("Volume"), required=False)

    volume_snapshot_id = forms.ThemableChoiceField(label=_("Volume Snapshot"),
                                                   required=False)

    image_id = forms.ChoiceField(
        label=_("Image Name"),
        required=False,
        widget=forms.ThemableSelectWidget(
            data_attrs=('volume_size',),
            transform=lambda x: ("%s (%s)" % (x.name,
                                              filesizeformat(x.bytes)))))

    volume_size = forms.IntegerField(label=_("Device size (GB)"),
                                     initial=1,
                                     min_value=0,
                                     required=False,
                                     help_text=_("Volume size in gigabytes "
                                                 "(integer value)."))

    device_name = forms.CharField(label=_("Device Name"),
                                  required=False,
                                  initial="vda",
                                  help_text=_("Volume mount point (e.g. 'vda' "
                                              "mounts at '/dev/vda'). Leave "
                                              "this field blank to let the "
                                              "system choose a device name "
                                              "for you."))

    vol_delete_on_instance_delete = forms.BooleanField(
        label=_("Delete Volume on Instance Delete"),
        initial=False,
        required=False,
        help_text=_("Delete volume when the instance is deleted"))

    class Meta(object):
        name = _("Details")
        help_text_template = ("project/instances/"
                              "_launch_details_help.html")

    def __init__(self, request, context, *args, **kwargs):
        self._init_images_cache()
        self.request = request
        self.context = context
        super(SetInstanceDetailsAction, self).__init__(
            request, context, *args, **kwargs)

        # Hide the device field if the hypervisor doesn't support it.
        if not nova.can_set_mount_point():
            self.fields['device_name'].widget = forms.widgets.HiddenInput()

        source_type_choices = [
            ('', _("Select source")),
            ("image_id", _("Boot from image")),
            ("instance_snapshot_id", _("Boot from snapshot")),
        ]
        if cinder.is_volume_service_enabled(request):
            source_type_choices.append(("volume_id", _("Boot from volume")))

            try:
                if api.nova.extension_supported("BlockDeviceMappingV2Boot",
                                                request):
                    source_type_choices.append(
                        ("volume_image_id",
                         _("Boot from image (creates a new volume)")))
            except Exception:
                exceptions.handle(request, _('Unable to retrieve extensions '
                                             'information.'))

            source_type_choices.append(
                ("volume_snapshot_id",
                 _("Boot from volume snapshot (creates a new volume)")))
        self.fields['source_type'].choices = source_type_choices

    @memoized.memoized_method
    def _get_flavor(self, flavor_id):
        try:
            # We want to retrieve details for a given flavor,
            # however flavor_list uses a memoized decorator
            # so it is used instead of flavor_get to reduce the number
            # of API calls.
            flavors = instance_utils.flavor_list(self.request)
            flavor = [x for x in flavors if x.id == flavor_id][0]
        except IndexError:
            flavor = None
        return flavor

    @memoized.memoized_method
    def _get_image(self, image_id):
        try:
            # We want to retrieve details for a given image,
            # however get_available_images uses a cache of image list,
            # so it is used instead of image_get to reduce the number
            # of API calls.
            images = image_utils.get_available_images(
                self.request,
                self.context.get('project_id'),
                self._images_cache)
            image = [x for x in images if x.id == image_id][0]
        except IndexError:
            image = None
        return image

    def _check_quotas(self, cleaned_data):
        count = cleaned_data.get('count', 1)

        # Prevent launching more instances than the quota allows
        usages = quotas.tenant_quota_usages(
            self.request,
            targets=('instances', 'cores', 'ram', 'volumes', ))
        available_count = usages['instances']['available']
        if available_count < count:
            msg = (_('The requested instance(s) cannot be launched '
                     'as your quota will be exceeded: Available: '
                     '%(avail)s, Requested: %(req)s.')
                   % {'avail': available_count, 'req': count})
            raise forms.ValidationError(msg)

        source_type = cleaned_data.get('source_type')
        if source_type in ('volume_image_id', 'volume_snapshot_id'):
            available_volume = usages['volumes']['available']
            if available_volume < count:
                msg = (_('The requested instance cannot be launched. '
                         'Requested volume exceeds quota: Available: '
                         '%(avail)s, Requested: %(req)s.')
                       % {'avail': available_volume, 'req': count})
                raise forms.ValidationError(msg)

        flavor_id = cleaned_data.get('flavor')
        flavor = self._get_flavor(flavor_id)

        count_error = []
        # Validate cores and ram.
        available_cores = usages['cores']['available']
        if flavor and available_cores < count * flavor.vcpus:
            count_error.append(_("Cores(Available: %(avail)s, "
                                 "Requested: %(req)s)")
                               % {'avail': available_cores,
                                  'req': count * flavor.vcpus})

        available_ram = usages['ram']['available']
        if flavor and available_ram < count * flavor.ram:
            count_error.append(_("RAM(Available: %(avail)s, "
                                 "Requested: %(req)s)")
                               % {'avail': available_ram,
                                  'req': count * flavor.ram})

        if count_error:
            value_str = ", ".join(count_error)
            msg = (_('The requested instance cannot be launched. '
                     'The following requested resource(s) exceed '
                     'quota(s): %s.') % value_str)
            if count == 1:
                self._errors['flavor'] = self.error_class([msg])
            else:
                self._errors['count'] = self.error_class([msg])

    def _check_flavor_for_image(self, cleaned_data):
        # Prevents trying to launch an image needing more resources.
        image_id = cleaned_data.get('image_id')
        image = self._get_image(image_id)
        flavor_id = cleaned_data.get('flavor')
        flavor = self._get_flavor(flavor_id)
        if not image or not flavor:
            return
        props_mapping = (("min_ram", "ram"), ("min_disk", "disk"))
        for iprop, fprop in props_mapping:
            if (getattr(image, iprop) > 0 and
                    getattr(flavor, fprop) > 0 and
                    getattr(image, iprop) > getattr(flavor, fprop)):
                msg = (_("The flavor '%(flavor)s' is too small "
                         "for requested image.\n"
                         "Minimum requirements: "
                         "%(min_ram)s MB of RAM and "
                         "%(min_disk)s GB of Root Disk.") %
                       {'flavor': flavor.name,
                        'min_ram': image.min_ram,
                        'min_disk': image.min_disk})
                self._errors['image_id'] = self.error_class([msg])
                break  # Not necessary to continue the tests.

    def _check_volume_for_image(self, cleaned_data):
        image_id = cleaned_data.get('image_id')
        image = self._get_image(image_id)
        volume_size = cleaned_data.get('volume_size')
        if not image or not volume_size:
            return
        volume_size = int(volume_size)
        img_gigs = functions.bytes_to_gigabytes(image.size)
        smallest_size = max(img_gigs, image.min_disk)
        if volume_size < smallest_size:
            msg = (_("The Volume size is too small for the"
                     " '%(image_name)s' image and has to be"
                     " greater than or equal to "
                     "'%(smallest_size)d' GB.") %
                   {'image_name': image.name,
                    'smallest_size': smallest_size})
            self._errors['volume_size'] = self.error_class([msg])

    def _check_source_image(self, cleaned_data):
        if not cleaned_data.get('image_id'):
            msg = _("You must select an image.")
            self._errors['image_id'] = self.error_class([msg])
        else:
            self._check_flavor_for_image(cleaned_data)

    def _check_source_volume_image(self, cleaned_data):
        volume_size = self.data.get('volume_size', None)
        if not volume_size:
            msg = _("You must set volume size")
            self._errors['volume_size'] = self.error_class([msg])
        if float(volume_size) <= 0:
            msg = _("Volume size must be greater than 0")
            self._errors['volume_size'] = self.error_class([msg])
        if not cleaned_data.get('image_id'):
            msg = _("You must select an image.")
            self._errors['image_id'] = self.error_class([msg])
            return
        else:
            self._check_flavor_for_image(cleaned_data)
            self._check_volume_for_image(cleaned_data)

    def _check_source_instance_snapshot(self, cleaned_data):
        # using the array form of get blows up with KeyError
        # if instance_snapshot_id is nil
        if not cleaned_data.get('instance_snapshot_id'):
            msg = _("You must select a snapshot.")
            self._errors['instance_snapshot_id'] = self.error_class([msg])

    def _check_source_volume(self, cleaned_data):
        if not cleaned_data.get('volume_id'):
            msg = _("You must select a volume.")
            self._errors['volume_id'] = self.error_class([msg])
        # Prevent launching multiple instances with the same volume.
        # TODO(gabriel): is it safe to launch multiple instances with
        # a snapshot since it should be cloned to new volumes?
        count = cleaned_data.get('count', 1)
        if count > 1:
            msg = _('Launching multiple instances is only supported for '
                    'images and instance snapshots.')
            raise forms.ValidationError(msg)

    def _check_source_volume_snapshot(self, cleaned_data):
        if not cleaned_data.get('volume_snapshot_id'):
            msg = _("You must select a snapshot.")
            self._errors['volume_snapshot_id'] = self.error_class([msg])

    def _check_source(self, cleaned_data):
        # Validate our instance source.
        source_type = self.data.get('source_type', None)
        source_check_methods = {
            'image_id': self._check_source_image,
            'volume_image_id': self._check_source_volume_image,
            'instance_snapshot_id': self._check_source_instance_snapshot,
            'volume_id': self._check_source_volume,
            'volume_snapshot_id': self._check_source_volume_snapshot
        }
        check_method = source_check_methods.get(source_type)
        if check_method:
            check_method(cleaned_data)

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

        self._check_quotas(cleaned_data)
        self._check_source(cleaned_data)

        return cleaned_data

    def populate_flavor_choices(self, request, context):
        return instance_utils.flavor_field_data(request, False)

    def populate_availability_zone_choices(self, request, context):
        try:
            zones = api.nova.availability_zone_list(request)
        except Exception:
            zones = []
            exceptions.handle(request,
                              _('Unable to retrieve availability zones.'))

        zone_list = [(zone.zoneName, zone.zoneName)
                     for zone in zones if zone.zoneState['available']]
        zone_list.sort()
        if not zone_list:
            zone_list.insert(0, ("", _("No availability zones found")))
        elif len(zone_list) > 1:
            zone_list.insert(0, ("", _("Any Availability Zone")))
        return zone_list

    def get_help_text(self, extra_context=None):
        extra = {} if extra_context is None else dict(extra_context)
        try:
            extra['usages'] = quotas.tenant_limit_usages(self.request)
            extra['usages_json'] = json.dumps(extra['usages'])
            extra['cinder_enabled'] = \
                base.is_service_enabled(self.request, 'volume')
            flavors = json.dumps([f._info for f in
                                  instance_utils.flavor_list(self.request)])
            extra['flavors'] = flavors
            images = image_utils.get_available_images(
                self.request, self.initial['project_id'], self._images_cache)
            if images is not None:
                attrs = [{'id': i.id,
                          'min_disk': getattr(i, 'min_disk', 0),
                          'min_ram': getattr(i, 'min_ram', 0),
                          'size': functions.bytes_to_gigabytes(i.size)}
                         for i in images]
                extra['images'] = json.dumps(attrs)

        except Exception:
            exceptions.handle(self.request,
                              _("Unable to retrieve quota information."))
        return super(SetInstanceDetailsAction, self).get_help_text(extra)

    def _init_images_cache(self):
        if not hasattr(self, '_images_cache'):
            self._images_cache = {}

    def _get_volume_display_name(self, volume):
        if hasattr(volume, "volume_id"):
            vol_type = "snap"
            visible_label = _("Snapshot")
        else:
            vol_type = "vol"
            visible_label = _("Volume")
        return (("%s:%s" % (volume.id, vol_type)),
                (_("%(name)s - %(size)s GB (%(label)s)") %
                 {'name': volume.name,
                  'size': volume.size,
                  'label': visible_label}))

    def populate_image_id_choices(self, request, context):
        choices = []
        images = image_utils.get_available_images(request,
                                                  context.get('project_id'),
                                                  self._images_cache)
        for image in images:
            if image.properties.get("image_type", '') != "snapshot":
                image.bytes = getattr(
                    image, 'virtual_size', None) or image.size
                image.volume_size = max(
                    image.min_disk, functions.bytes_to_gigabytes(image.bytes))
                choices.append((image.id, image))
                if context.get('image_id') == image.id and \
                        'volume_size' not in context:
                    context['volume_size'] = image.volume_size
        if choices:
            choices.sort(key=lambda c: c[1].name or '')
            choices.insert(0, ("", _("Select Image")))
        else:
            choices.insert(0, ("", _("No images available")))
        return choices

    def populate_instance_snapshot_id_choices(self, request, context):
        images = image_utils.get_available_images(request,
                                                  context.get('project_id'),
                                                  self._images_cache)
        choices = [(image.id, image.name)
                   for image in images
                   if image.properties.get("image_type", '') == "snapshot"]
        if choices:
            choices.sort(key=operator.itemgetter(1))
            choices.insert(0, ("", _("Select Instance Snapshot")))
        else:
            choices.insert(0, ("", _("No snapshots available")))
        return choices

    def populate_volume_id_choices(self, request, context):
        volumes = []
        try:
            if cinder.is_volume_service_enabled(request):
                available = api.cinder.VOLUME_STATE_AVAILABLE
                volumes = [self._get_volume_display_name(v)
                           for v in cinder.volume_list(self.request,
                           search_opts=dict(status=available, bootable=True))]
        except Exception:
            exceptions.handle(self.request,
                              _('Unable to retrieve list of volumes.'))
        if volumes:
            volumes.insert(0, ("", _("Select Volume")))
        else:
            volumes.insert(0, ("", _("No volumes available")))
        return volumes

    def populate_volume_snapshot_id_choices(self, request, context):
        snapshots = []
        try:
            if cinder.is_volume_service_enabled(request):
                available = api.cinder.VOLUME_STATE_AVAILABLE
                snapshots = [self._get_volume_display_name(s)
                             for s in cinder.volume_snapshot_list(
                             self.request, search_opts=dict(status=available))]
        except Exception:
            exceptions.handle(self.request,
                              _('Unable to retrieve list of volume '
                                'snapshots.'))
        if snapshots:
            snapshots.insert(0, ("", _("Select Volume Snapshot")))
        else:
            snapshots.insert(0, ("", _("No volume snapshots available")))
        return snapshots
Example #26
0
class CreateForm(forms.SelfHandlingForm):
    name = forms.CharField(max_length=255, label=_("Volume Name"),
                           required=False)
    description = forms.CharField(max_length=255, widget=forms.Textarea(
        attrs={'rows': 4}),
        label=_("Description"), required=False)
    volume_source_type = forms.ChoiceField(
        label=_("Volume Source"),
        required=False,
        widget=forms.ThemableSelectWidget(attrs={
            'class': 'switchable',
            'data-slug': 'source'}))
    snapshot_source = forms.ChoiceField(
        label=_("Use snapshot as a source"),
        widget=forms.ThemableSelectWidget(
            attrs={'class': 'snapshot-selector'},
            data_attrs=('size', 'name'),
            transform=lambda x: "%s (%s GiB)" % (x.name, x.size)),
        required=False)
    image_source = forms.ChoiceField(
        label=_("Use image as a source"),
        widget=forms.ThemableSelectWidget(
            attrs={'class': 'image-selector'},
            data_attrs=('size', 'name', 'min_disk'),
            transform=lambda x: "%s (%s)" % (x.name, filesizeformat(x.bytes))),
        required=False)
    volume_source = forms.ChoiceField(
        label=_("Use a volume as source"),
        widget=forms.ThemableSelectWidget(
            attrs={'class': 'image-selector'},
            data_attrs=('size', 'name'),
            transform=lambda x: "%s (%s GiB)" % (x.name, x.size)),
        required=False)
    type = forms.ChoiceField(
        label=_("Type"),
        required=False,
        widget=forms.ThemableSelectWidget(
            attrs={'class': 'switched',
                   'data-switch-on': 'source',
                   'data-source-no_source_type': _('Type'),
                   'data-source-image_source': _('Type')}))
    size = forms.IntegerField(min_value=1, initial=1, label=_("Size (GiB)"))
    availability_zone = forms.ChoiceField(
        label=_("Availability Zone"),
        required=False,
        widget=forms.ThemableSelectWidget(
            attrs={'class': 'switched',
                   'data-switch-on': 'source',
                   'data-source-no_source_type': _('Availability Zone'),
                   'data-source-image_source': _('Availability Zone')}))
    group = forms.ThemableChoiceField(
        label=_("Group"), required=False,
        help_text=_("Group which the new volume belongs to. Choose "
                    "'No group' if the new volume belongs to no group."))

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

        except Exception:
            exceptions.handle(request,
                              _('Unable to load the specified snapshot.'))

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

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

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

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

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

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

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

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

    def _populate_group_choices(self, request):
        try:
            groups = cinder.group_list(request)
        except cinder_exc.VersionNotFoundForAPIMethod:
            del self.fields['group']
            return
        except Exception:
            redirect = reverse("horizon:project:volumes:index")
            exceptions.handle(request,
                              _('Unable to retrieve the volume group list.'),
                              redirect=redirect)
        group_choices = [(g.id, g.name or g.id) for g in groups]
        group_choices.insert(0, ("", _("No group")))
        self.fields['group'].choices = group_choices

    def __init__(self, request, *args, **kwargs):
        super(CreateForm, self).__init__(request, *args, **kwargs)
        volume_types = []
        try:
            volume_types = cinder.volume_type_list(request)
        except Exception:
            redirect_url = reverse("horizon:project:volumes:index")
            error_message = _('Unable to retrieve the volume type list.')
            exceptions.handle(request, error_message, redirect=redirect_url)
        self.fields['type'].choices = [("", _("No volume type"))] + \
                                      [(type.name, type.name)
                                       for type in volume_types]
        if 'initial' in kwargs and 'type' in kwargs['initial']:
            # if there is a default volume type to select, then remove
            # the first ""No volume type" entry
            self.fields['type'].choices.pop(0)

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

        self._populate_group_choices(request)

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

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

    def handle(self, request, data):
        try:
            usages = quotas.tenant_quota_usages(
                self.request, targets=('volumes', 'gigabytes'))
            availableGB = usages['gigabytes']['available']
            availableVol = usages['volumes']['available']

            snapshot_id = None
            image_id = None
            volume_id = None
            source_type = data.get('volume_source_type', None)
            az = data.get('availability_zone', None) or None
            volume_type = data.get('type')

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

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

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

            metadata = {}

            volume = cinder.volume_create(request,
                                          data['size'],
                                          data['name'],
                                          data['description'],
                                          volume_type,
                                          snapshot_id=snapshot_id,
                                          image_id=image_id,
                                          metadata=metadata,
                                          availability_zone=az,
                                          source_volid=volume_id,
                                          group_id=data.get('group') or None)
            message = _('Creating volume "%s"') % volume.name
            messages.info(request, message)
            return volume
        except ValidationError as e:
            self.api_error(e.messages[0])
            return False
        except Exception:
            redirect = reverse("horizon:project:volumes:index")
            exceptions.handle(request,
                              _("Unable to create volume."),
                              redirect=redirect)

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

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

    @memoized
    def get_volume(self, request, id):
        return cinder.volume_get(request, id)
Example #27
0
class AttachForm(forms.SelfHandlingForm):
    instance = forms.ThemableChoiceField(label=_("Attach to Instance"),
                                         help_text=_("Select an instance to "
                                                     "attach to."))

    device = forms.CharField(label=_("Device Name"),
                             widget=forms.TextInput(attrs={'placeholder':
                                                           '/dev/vdc'}),
                             required=False,
                             help_text=_("Actual device name may differ due "
                                         "to hypervisor settings. If not "
                                         "specified, then hypervisor will "
                                         "select a device name."))

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

        # Hide the device field if the hypervisor doesn't support it.
        if not nova.can_set_mount_point():
            self.fields['device'].widget = forms.widgets.HiddenInput()

        # populate volume_id
        volume = kwargs.get('initial', {}).get("volume", None)
        if volume:
            volume_id = volume.id
        else:
            volume_id = None
        self.fields['volume_id'] = forms.CharField(widget=forms.HiddenInput(),
                                                   initial=volume_id)

        # Populate instance choices
        instance_list = kwargs.get('initial', {}).get('instances', [])
        instances = []
        for instance in instance_list:
            if instance.status in tables.VOLUME_ATTACH_READY_STATES and \
                    not any(instance.id == att["server_id"]
                            for att in volume.attachments):
                instances.append((instance.id, '%s (%s)' % (instance.name,
                                                            instance.id)))
        if instances:
            instances.insert(0, ("", _("Select an instance")))
        else:
            instances = (("", _("No instances available")),)
        self.fields['instance'].choices = instances

    def handle(self, request, data):
        instance_choices = dict(self.fields['instance'].choices)
        instance_name = instance_choices.get(data['instance'],
                                             _("Unknown instance (None)"))
        # The name of the instance in the choices list has the ID appended to
        # it, so let's slice that off...
        instance_name = instance_name.rsplit(" (")[0]

        # api requires non-empty device name or None
        device = data.get('device') or None

        try:
            attach = api.nova.instance_volume_attach(request,
                                                     data['volume_id'],
                                                     data['instance'],
                                                     device)
            volume = cinder.volume_get(request, data['volume_id'])
            message = _('Attaching volume %(vol)s to instance '
                        '%(inst)s on %(dev)s.') % {"vol": volume.name,
                                                   "inst": instance_name,
                                                   "dev": attach.device}
            messages.info(request, message)
            return True
        except Exception:
            redirect = reverse("horizon:project:volumes:index")
            exceptions.handle(request,
                              _('Unable to attach volume.'),
                              redirect=redirect)
class CreateEnvironmentForm(horizon_forms.SelfHandlingForm):
    name = forms.CharField(label=_("Environment Name"),
                           help_text=ENV_NAME_HELP_TEXT,
                           max_length=255)

    net_config = horizon_forms.ThemableChoiceField(
        label=_("Environment Default Network"))

    def __init__(self, request, *args, **kwargs):
        super(CreateEnvironmentForm, self).__init__(request, *args, **kwargs)
        env_fixed_network = getattr(settings, 'USE_FIXED_NETWORK', False)
        if env_fixed_network:
            net_choices = net.get_project_assigned_network(request)
            help_text = None
            if not net_choices:
                msg = _("Default network is either not specified for "
                        "this project, or specified incorrectly, "
                        "please contact administrator.")
                messages.error(request, msg)
                raise exceptions.ConfigurationError(msg)
            else:
                self.fields['net_config'].required = False
                self.fields['net_config'].widget.attrs['readonly'] = True
        else:
            net_choices = net.get_available_networks(
                request, murano_networks='translate')

            if net_choices is None:  # NovaNetwork case
                net_choices = [((None, None), _('Unavailable'))]
                help_text = net.NN_HELP
            else:
                net_choices.insert(0, ((None, None), _('Create New')))
                help_text = net.NEUTRON_NET_HELP
        self.fields['net_config'].choices = net_choices
        self.fields['net_config'].help_text = help_text

    def clean_name(self):
        cleaned_data = super(CreateEnvironmentForm, self).clean()
        env_name = cleaned_data.get('name')
        if not env_name.strip():
            self._errors['name'] = self.error_class([ENV_NAME_HELP_TEXT])
        return env_name

    def handle(self, request, data):
        try:
            net_config = ast.literal_eval(data.pop('net_config'))
            if net_config[0] is not None:
                data.update(net.generate_join_existing_net(net_config))
            env = api.environment_create(request, data)
            request.session['env_id'] = env.id
            messages.success(request,
                             u'Created environment "{0}"'.format(data['name']))
            return True
        except exc.HTTPConflict:
            msg = _('Environment with specified name already exists')
            LOG.exception(msg)
            exceptions.handle(request, ignore=True)
            messages.error(request, msg)
            return False
        except Exception:
            msg = _('Failed to create environment')
            LOG.exception(msg)
            exceptions.handle(request)
            messages.error(request, msg)
            return False
Example #29
0
class ManageQosSpecAssociation(forms.SelfHandlingForm):
    qos_spec_choice = forms.ThemableChoiceField(
        label=_("QoS Spec to be associated"),
        help_text=_("Choose associated QoS Spec."))

    def __init__(self, request, *args, **kwargs):
        super(ManageQosSpecAssociation, self).__init__(request,
                                                       *args,
                                                       **kwargs)
        qos_spec_field = self.fields['qos_spec_choice']
        qos_spec_field.choices = \
            self.populate_qos_spec_choices()

    def populate_qos_spec_choices(self):
        # populate qos spec list box
        qos_specs = self.initial["qos_specs"]
        current_qos_spec = self.initial["cur_qos_spec_id"]
        qos_spec_list = [(qos_spec.id, qos_spec.name)
                         for qos_spec in qos_specs
                         if qos_spec.id != current_qos_spec]

        if current_qos_spec:
            # used to remove the current spec
            qos_spec_list.insert(0, ("-1", _("None (removes spec)")))
        if qos_spec_list:
            qos_spec_list.insert(0, ("", _("Select a new QoS spec")))
        else:
            qos_spec_list.insert(0, ("", _("No new QoS spec available")))
        return qos_spec_list

    def handle(self, request, data):
        vol_type_id = self.initial['type_id']
        new_qos_spec_id = data['qos_spec_choice']

        # Update QOS Spec association information
        try:
            # NOTE - volume types can only be associated with
            #        ONE QOS Spec at a time

            # first we need to un-associate the current QOS Spec, if it exists
            cur_qos_spec_id = self.initial['cur_qos_spec_id']
            if cur_qos_spec_id:
                qos_spec = cinder.qos_spec_get(request,
                                               cur_qos_spec_id)
                cinder.qos_spec_disassociate(request,
                                             qos_spec,
                                             vol_type_id)

            # now associate with new QOS Spec, if user wants one associated
            if new_qos_spec_id != '-1':
                qos_spec = cinder.qos_spec_get(request,
                                               new_qos_spec_id)

                cinder.qos_spec_associate(request,
                                          qos_spec,
                                          vol_type_id)

            messages.success(request,
                             _('Successfully updated QoS Spec association.'))
            return True
        except Exception:
            redirect = reverse("horizon:admin:volume_types:index")
            exceptions.handle(request,
                              _('Error updating QoS Spec association.'),
                              redirect=redirect)
Example #30
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)

    @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 len(network_type_choices) == 0:
                self._hide_provider_network_type()
            else:
                self.fields['network_type'].choices = network_type_choices

    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'])
            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])