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'] 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
class GeneralConfigAction(workflows.Action): nodegroup_name = forms.CharField(label=_("Template Name")) description = forms.CharField(label=_("Description"), required=False, widget=forms.Textarea(attrs={'rows': 4})) flavor = forms.ChoiceField(label=_("OpenStack Flavor")) availability_zone = forms.ChoiceField( label=_("Availability Zone"), help_text=_("Launch instances in this availability zone."), required=False, widget=forms.Select(attrs={"class": "availability_zone_field"})) storage = forms.ChoiceField( label=_("Storage location"), help_text=_("Choose a storage location"), choices=[("ephemeral_drive", "Ephemeral Drive"), ("cinder_volume", "Cinder Volume")], widget=forms.Select(attrs={"class": "storage_field"})) volumes_per_node = forms.IntegerField( label=_("Volumes per node"), required=False, initial=1, widget=forms.TextInput(attrs={"class": "volume_per_node_field"})) volumes_size = forms.IntegerField( label=_("Volumes size (GB)"), required=False, initial=10, widget=forms.TextInput(attrs={"class": "volume_size_field"})) hidden_configure_field = forms.CharField( required=False, widget=forms.HiddenInput(attrs={"class": "hidden_configure_field"})) def __init__(self, request, *args, **kwargs): super(GeneralConfigAction, self).__init__(request, *args, **kwargs) hlps = helpers.Helpers(request) plugin, hadoop_version = ( workflow_helpers.get_plugin_and_hadoop_version(request)) process_choices = [] try: version_details = saharaclient.plugin_get_version_details( request, plugin, hadoop_version) for service, processes in version_details.node_processes.items(): for process in processes: process_choices.append( (str(service) + ":" + str(process), process)) except Exception: exceptions.handle(request, _("Unable to generate process choices.")) if not saharaclient.SAHARA_AUTO_IP_ALLOCATION_ENABLED: pools = network.floating_ip_pools_list(request) pool_choices = [(pool.id, pool.name) for pool in pools] pool_choices.insert(0, (None, "Do not assign floating IPs")) self.fields['floating_ip_pool'] = forms.ChoiceField( label=_("Floating IP Pool"), choices=pool_choices, required=False) self.fields["processes"] = forms.MultipleChoiceField( label=_("Processes"), widget=forms.CheckboxSelectMultiple(), help_text=_("Processes to be launched in node group"), choices=process_choices) self.fields["plugin_name"] = forms.CharField( widget=forms.HiddenInput(), initial=plugin) self.fields["hadoop_version"] = forms.CharField( widget=forms.HiddenInput(), initial=hadoop_version) node_parameters = hlps.get_general_node_group_configs( plugin, hadoop_version) for param in node_parameters: self.fields[param.name] = workflow_helpers.build_control(param) def populate_flavor_choices(self, request, context): flavors = nova_utils.flavor_list(request) if flavors: return nova_utils.sort_flavor_list(request, flavors) return [] def populate_availability_zone_choices(self, request, context): # The default is None, i.e. not specifying any availability zone az_list = [(None, _('No availability zone specified'))] az_list.extend([(az.zoneName, az.zoneName) for az in nova_utils.availability_zone_list(request) if az.zoneState['available']]) return az_list def get_help_text(self): extra = dict() plugin, hadoop_version = ( workflow_helpers.get_plugin_and_hadoop_version(self.request)) extra["plugin_name"] = plugin extra["hadoop_version"] = hadoop_version return super(GeneralConfigAction, self).get_help_text(extra) class Meta: name = _("Configure Node Group Template") help_text_template = ("project/data_processing.nodegroup_templates" "/_configure_general_help.html")
class ModifyPlanForm(forms.SelfHandlingForm): id = forms.CharField(label=_("ID"), widget=forms.HiddenInput()) name = forms.CharField(max_length=255, label=_("Name")) code = forms.CharField(max_length=32, label=_("Code")) service_type = forms.ChoiceField(label = _('Service Type'), choices=[]) rate = forms.FloatField(label=_('Rate')) setup_fee = forms.FloatField(label=_('Setup Fee'), required=False) billing_type = forms.ChoiceField( label = _('Billing Type'), choices=[], required=False, widget=forms.Select(attrs={ 'class': 'switchable', 'data-slug': 'billing_type' }) ) ref_id = forms.ChoiceField( label = _('Flavor'), choices=[], required=False, widget=forms.Select(attrs={ 'class': 'switched', 'data-switch-on': 'billing_type', 'data-billing_type-1': _('Flavor') }) ) attr_instances = forms.FloatField( label=_("Instances"), required=False, widget=forms.NumberInput(attrs={ 'step': 1, 'class': 'switched', 'data-switch-on': 'billing_type', 'data-billing_type-2': _('Instances') }) ) attr_cpu = forms.FloatField( label=_("CPU"), required=False, widget=forms.NumberInput(attrs={ 'step': 1, 'class': 'switched', 'data-switch-on': 'billing_type', 'data-billing_type-2': _('CPU') }) ) attr_ram = forms.FloatField( label=_("RAM (MB)"), required=False, widget=forms.NumberInput(attrs={ 'step': 1, 'class': 'switched', 'data-switch-on': 'billing_type', 'data-billing_type-2': _('RAM (GB)') }) ) attr_storage = forms.FloatField( label=_("Storage (GB)"), required=False, widget=forms.NumberInput(attrs={ 'step': 1, 'class': 'switched', 'data-switch-on': 'billing_type', 'data-billing_type-2': _('Storage (GB)') }) ) description = forms.CharField(label = _('Description')) metadata_mark = forms.CharField(max_length=255, label=_("Image Mark"), required=False) def __init__(self, request, *args, **kwargs): super(ModifyPlanForm, self).__init__(request, *args, **kwargs) # set discount types self.fields['service_type'].choices = gen_service_types(request) self.fields['billing_type'].choices = gen_billing_types(request) self.fields['billing_type'].choices.append((None, '-')) self.fields['ref_id'].choices = gen_flavors(request) def handle(self, request, data): type_id = data.pop('id', None) if not type_id: exceptions.handle(request, _('Invalid request.')) return False try: attr_instances = data.pop('attr_instances') attr_cpu = data.pop('attr_cpu') attr_ram = data.pop('attr_ram') attr_storage = data.pop('attr_storage') if int(data['billing_type']) == RAB_BILLING_TYPE_ID: data['attrs'] = {} if attr_instances: data['attrs']['instances'] = attr_instances if attr_cpu: data['attrs']['cpu'] = attr_cpu if attr_ram: data['attrs']['ram'] = attr_ram if attr_storage: data['attrs']['storage'] = attr_storage modify_plan(request, type_id, data) return True except Exception: exceptions.handle(request, _('Unable to modify billing plan.'))
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()
class AttachInterface(forms.SelfHandlingForm): instance_id = forms.CharField(widget=forms.HiddenInput()) specification_method = forms.ThemableChoiceField( label=_("The way to specify an interface"), initial=False, widget=forms.ThemableSelectWidget(attrs={ 'class': 'switchable', 'data-slug': 'specification_method', })) port = forms.ThemableChoiceField( label=_("Port"), required=False, widget=forms.ThemableSelectWidget( attrs={ 'class': 'switched', 'data-switch-on': 'specification_method', 'data-specification_method-port': _('Port'), })) network = forms.ThemableChoiceField( label=_("Network"), required=False, widget=forms.ThemableSelectWidget( attrs={ 'class': 'switched', 'data-switch-on': 'specification_method', 'data-specification_method-network': _('Network'), })) fixed_ip = forms.IPField( label=_("Fixed IP Address"), required=False, help_text=_("IP address for the new port"), version=forms.IPv4 | forms.IPv6, widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'specification_method', 'data-specification_method-network': _('Fixed IP Address'), })) def __init__(self, request, *args, **kwargs): super(AttachInterface, self).__init__(request, *args, **kwargs) networks = instance_utils.network_field_data(request, include_empty_option=True, with_cidr=True) self.fields['network'].choices = networks choices = [('network', _("by Network (and IP address)"))] ports = instance_utils.port_field_data(request, with_network=True) if len(ports) > 0: self.fields['port'].choices = ports choices.append(('port', _("by Port"))) self.fields['specification_method'].choices = choices def clean_network(self): specification_method = self.cleaned_data.get('specification_method') network = self.cleaned_data.get('network') if specification_method == 'network' and not network: msg = _('This field is required.') self._errors['network'] = self.error_class([msg]) return network def handle(self, request, data): instance_id = data['instance_id'] try: net_id = port_id = fixed_ip = None if data['specification_method'] == 'port': port_id = data.get('port') else: net_id = data.get('network') if data.get('fixed_ip'): fixed_ip = data.get('fixed_ip') api.nova.interface_attach(request, instance_id, net_id=net_id, fixed_ip=fixed_ip, port_id=port_id) 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
class AddRule(forms.SelfHandlingForm): id = forms.CharField(widget=forms.HiddenInput()) rule_menu = forms.ChoiceField( label=_('Rule'), widget=forms.ThemableSelectWidget(attrs={ 'class': 'switchable', 'data-slug': 'rule_menu' })) description = forms.CharField( label=_('Description'), required=False, max_length=255, widget=forms.Textarea(attrs={'rows': 2}), help_text=_('A brief description of the security group rule ' 'you are adding')) # "direction" field is enabled only when custom mode. # It is because most common rules in local_settings.py is meaningful # when its direction is 'ingress'. direction = forms.ChoiceField( label=_('Direction'), required=False, widget=forms.ThemableSelectWidget( attrs={ 'class': 'switched', 'data-switch-on': 'rule_menu', 'data-rule_menu-tcp': _('Direction'), 'data-rule_menu-udp': _('Direction'), 'data-rule_menu-icmp': _('Direction'), 'data-rule_menu-custom': _('Direction'), 'data-rule_menu-all_tcp': _('Direction'), 'data-rule_menu-all_udp': _('Direction'), 'data-rule_menu-all_icmp': _('Direction'), })) ip_protocol = forms.IntegerField( label=_('IP Protocol'), required=False, help_text=_("Enter an integer value between 0 and 255."), validators=[utils_validators.validate_ip_protocol], widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'rule_menu', 'data-rule_menu-custom': _('IP Protocol') })) port_or_range = forms.ChoiceField( label=_('Open Port'), choices=[('port', _('Port')), ('range', _('Port Range'))], widget=forms.ThemableSelectWidget( attrs={ 'class': 'switchable switched', 'data-slug': 'range', 'data-switch-on': 'rule_menu', 'data-rule_menu-tcp': _('Open Port'), 'data-rule_menu-udp': _('Open Port') })) port = forms.IntegerField( label=_("Port"), required=False, help_text=_("Enter an integer value " "between 1 and 65535."), widget=forms.TextInput( attrs={ 'class': 'switched', 'data-required-when-shown': 'true', 'data-switch-on': 'range', 'data-range-port': _('Port') }), validators=[utils_validators.validate_port_range]) from_port = forms.IntegerField( label=_("From Port"), required=False, help_text=_("Enter an integer value " "between 1 and 65535."), widget=forms.TextInput( attrs={ 'class': 'switched', 'data-required-when-shown': 'true', 'data-switch-on': 'range', 'data-range-range': _('From Port') }), validators=[utils_validators.validate_port_range]) to_port = forms.IntegerField( label=_("To Port"), required=False, help_text=_("Enter an integer value " "between 1 and 65535."), widget=forms.TextInput( attrs={ 'class': 'switched', 'data-required-when-shown': 'true', 'data-switch-on': 'range', 'data-range-range': _('To Port') }), validators=[utils_validators.validate_port_range]) icmp_type = forms.IntegerField( label=_("Type"), required=False, help_text=_("Enter a value for ICMP type " "in the range (-1: 255)"), widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'rule_menu', 'data-rule_menu-icmp': _('Type') }), validators=[utils_validators.validate_icmp_type_range]) icmp_code = forms.IntegerField( label=_("Code"), required=False, help_text=_("Enter a value for ICMP code " "in the range (-1: 255)"), widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'rule_menu', 'data-rule_menu-icmp': _('Code') }), validators=[utils_validators.validate_icmp_code_range]) remote = forms.ChoiceField( label=_('Remote'), choices=[('cidr', _('CIDR')), ('sg', _('Security Group'))], help_text=_('To specify an allowed IP ' 'range, select "CIDR". ' 'To allow access from all ' 'members of another security ' 'group select "Security ' 'Group".'), widget=forms.ThemableSelectWidget(attrs={ 'class': 'switchable', 'data-slug': 'remote' })) cidr = forms.IPField(label=_("CIDR"), required=False, initial="0.0.0.0/0", help_text=_("Classless Inter-Domain Routing " "(e.g. 192.168.0.0/24, or " "2001:db8::/128)"), version=forms.IPv4 | forms.IPv6, mask=True, widget=forms.TextInput( attrs={ 'class': 'switched', 'data-required-when-shown': 'true', 'data-switch-on': 'remote', 'data-remote-cidr': _('CIDR') })) security_group = forms.ChoiceField( label=_('Security Group'), required=False, widget=forms.ThemableSelectWidget( attrs={ 'class': 'switched', 'data-required-when-shown': 'true', 'data-switch-on': 'remote', 'data-remote-sg': _('Security Group') })) # When cidr is used ethertype is determined from IP version of cidr. # When source group, ethertype needs to be specified explicitly. ethertype = forms.ChoiceField(label=_('Ether Type'), required=False, choices=[('IPv4', _('IPv4')), ('IPv6', _('IPv6'))], widget=forms.ThemableSelectWidget( attrs={ 'class': 'switched', 'data-slug': 'ethertype', 'data-switch-on': 'remote', 'data-remote-sg': _('Ether Type') })) def __init__(self, *args, **kwargs): sg_list = kwargs.pop('sg_list', []) super(AddRule, self).__init__(*args, **kwargs) # Determine if there are security groups available for the # remote group option; add the choices and enable the option if so. if sg_list: security_groups_choices = sg_list else: security_groups_choices = [("", _("No security groups available"))] self.fields['security_group'].choices = security_groups_choices # TODO(amotoki): settings.SECURITY_GROUP_RULES may contains 'backend' # parameter. If 'backend' is used, error message should be emitted. backend = 'neutron' rules_dict = settings.SECURITY_GROUP_RULES common_rules = [(k, rules_dict[k]['name']) for k in rules_dict if rules_dict[k].get('backend', backend) == backend] common_rules.sort() custom_rules = [('tcp', _('Custom TCP Rule')), ('udp', _('Custom UDP Rule')), ('icmp', _('Custom ICMP Rule')), ('custom', _('Other Protocol'))] self.fields['rule_menu'].choices = custom_rules + common_rules self.rules = rules_dict self.fields['direction'].choices = [('ingress', _('Ingress')), ('egress', _('Egress'))] self.fields['ip_protocol'].help_text = _( "Enter an integer value between -1 and 255 " "(-1 means wild card).") self.fields['port_or_range'].choices = [ ('port', _('Port')), ('range', _('Port Range')), ('all', _('All ports')), ] if not settings.OPENSTACK_NEUTRON_NETWORK['enable_ipv6']: self.fields['cidr'].version = forms.IPv4 self.fields['ethertype'].widget = forms.TextInput( attrs={'readonly': 'readonly'}) self.fields['ethertype'].initial = 'IPv4' try: is_desc_supported = api.neutron.is_extension_supported( self.request, 'standard-attr-description') except Exception: exceptions.handle( self.request, _('Failed to check if description field is supported.')) is_desc_supported = False if not is_desc_supported: del self.fields['description'] def _update_and_pop_error(self, cleaned_data, key, value): cleaned_data[key] = value self.errors.pop(key, None) def _clean_rule_icmp(self, cleaned_data, rule_menu): icmp_type = cleaned_data.get("icmp_type", None) icmp_code = cleaned_data.get("icmp_code", None) self._update_and_pop_error(cleaned_data, 'ip_protocol', rule_menu) if icmp_type == -1 and icmp_code != -1: msg = _('ICMP code is provided but ICMP type is missing.') raise ValidationError(msg) if self.errors.get('icmp_type'): msg = _('The ICMP type not in range (-1, 255)') raise ValidationError(msg) if self.errors.get('icmp_code'): msg = _('The ICMP code not in range (-1, 255)') raise ValidationError(msg) self._update_and_pop_error(cleaned_data, 'from_port', icmp_type) self._update_and_pop_error(cleaned_data, 'to_port', icmp_code) self._update_and_pop_error(cleaned_data, 'port', None) def _clean_rule_tcp_udp(self, cleaned_data, rule_menu): port_or_range = cleaned_data.get("port_or_range") from_port = cleaned_data.get("from_port", None) to_port = cleaned_data.get("to_port", None) port = cleaned_data.get("port", None) self._update_and_pop_error(cleaned_data, 'ip_protocol', rule_menu) self._update_and_pop_error(cleaned_data, 'icmp_code', None) self._update_and_pop_error(cleaned_data, 'icmp_type', None) if port_or_range == 'all': self._update_and_pop_error(cleaned_data, 'port', None) self._update_and_pop_error(cleaned_data, 'from_port', None) self._update_and_pop_error(cleaned_data, 'to_port', None) elif port_or_range == "port": self._update_and_pop_error(cleaned_data, 'from_port', port) self._update_and_pop_error(cleaned_data, 'to_port', port) if port is None: msg = _('The specified port is invalid.') raise ValidationError(msg) else: self._update_and_pop_error(cleaned_data, 'port', None) if from_port is None: msg = _('The "from" port number is invalid.') raise ValidationError(msg) if to_port is None: msg = _('The "to" port number is invalid.') raise ValidationError(msg) if to_port < from_port: msg = _('The "to" port number must be greater than ' 'or equal to the "from" port number.') raise ValidationError(msg) def _clean_rule_custom(self, cleaned_data, rule_menu): # custom IP protocol rule so we need to fill unused fields so # the validation works unused_fields = [ 'icmp_code', 'icmp_type', 'from_port', 'to_port', 'port' ] for unused_field in unused_fields: self._update_and_pop_error(cleaned_data, unused_field, None) def _apply_rule_menu(self, cleaned_data, rule_menu): cleaned_data['ip_protocol'] = self.rules[rule_menu]['ip_protocol'] cleaned_data['from_port'] = int(self.rules[rule_menu]['from_port']) cleaned_data['to_port'] = int(self.rules[rule_menu]['to_port']) self._update_and_pop_error(cleaned_data, 'icmp_code', None) self._update_and_pop_error(cleaned_data, 'icmp_type', None) if rule_menu not in ['all_tcp', 'all_udp', 'all_icmp']: direction = self.rules[rule_menu].get('direction') cleaned_data['direction'] = direction def _clean_rule_menu(self, cleaned_data): rule_menu = cleaned_data.get('rule_menu') if rule_menu == 'icmp': self._clean_rule_icmp(cleaned_data, rule_menu) elif rule_menu in ('tcp', 'udp'): self._clean_rule_tcp_udp(cleaned_data, rule_menu) elif rule_menu == 'custom': self._clean_rule_custom(cleaned_data, rule_menu) else: self._apply_rule_menu(cleaned_data, rule_menu) def _adjust_ip_protocol_of_icmp(self, data): # Note that this needs to be called after IPv4/IPv6 is determined. try: ip_protocol = int(data['ip_protocol']) except ValueError: # string representation of IP protocol ip_protocol = data['ip_protocol'] is_ipv6 = data['ethertype'] == 'IPv6' if isinstance(ip_protocol, int): # When IP protocol number is specified, we assume a user # knows more detail on IP protocol number, # so a warning message on a mismatch between IP proto number # and IP version is displayed. if is_ipv6 and ip_protocol == 1: msg = _('58 (ipv6-icmp) should be specified for IPv6 ' 'instead of 1.') self._errors['ip_protocol'] = self.error_class([msg]) elif not is_ipv6 and ip_protocol == 58: msg = _('1 (icmp) should be specified for IPv4 ' 'instead of 58.') self._errors['ip_protocol'] = self.error_class([msg]) else: # ICMPv6 uses different an IP protocol name and number. # To allow 'icmp' for both IPv4 and IPv6 in the form, # we need to replace 'icmp' with 'ipv6-icmp' based on IP version. if is_ipv6 and ip_protocol == 'icmp': data['ip_protocol'] = 'ipv6-icmp' def clean(self): cleaned_data = super(AddRule, self).clean() self._clean_rule_menu(cleaned_data) # NOTE(amotoki): There are two cases where cleaned_data['direction'] # is empty: (1) Nova Security Group is used. Since "direction" is # HiddenInput, direction field exists but its value is ''. # (2) Template except all_* is used. In this case, the default value # is None. To make sure 'direction' field has 'ingress' or 'egress', # fill this field here if it is not specified. if not cleaned_data['direction']: cleaned_data['direction'] = 'ingress' remote = cleaned_data.get("remote") if remote == "cidr": self._update_and_pop_error(cleaned_data, 'security_group', None) else: self._update_and_pop_error(cleaned_data, 'cidr', None) # If cleaned_data does not contain a non-empty value, IPField already # has validated it, so skip the further validation for cidr. # In addition cleaned_data['cidr'] is None means source_group is used. if 'cidr' in cleaned_data and cleaned_data['cidr'] is not None: cidr = cleaned_data['cidr'] if not cidr: msg = _('CIDR must be specified.') self._errors['cidr'] = self.error_class([msg]) else: # If cidr is specified, ethertype is determined from IP address # version. It is used only when Neutron is enabled. ip_ver = netaddr.IPNetwork(cidr).version cleaned_data['ethertype'] = 'IPv6' if ip_ver == 6 else 'IPv4' self._adjust_ip_protocol_of_icmp(cleaned_data) return cleaned_data def handle(self, request, data): redirect = reverse("horizon:project:security_groups:detail", args=[data['id']]) params = {} if 'description' in data: params['description'] = data['description'] try: rule = api.neutron.security_group_rule_create( request, filters.get_int_or_uuid(data['id']), data['direction'], data['ethertype'], data['ip_protocol'], data['from_port'], data['to_port'], data['cidr'], data['security_group'], **params) messages.success( request, _('Successfully added rule: %s') % six.text_type(rule)) return rule except exceptions.Conflict as error: exceptions.handle(request, error, redirect=redirect) except Exception: exceptions.handle(request, _('Unable to add rule to security group.'), redirect=redirect)
def __init__(self, request, context, *args, **kwargs): super().__init__(request, context, *args, **kwargs) if not setting_utils.get_dict_config('OPENSTACK_NEUTRON_NETWORK', 'enable_ipv6'): self.fields['ipv6_modes'].widget = forms.HiddenInput()
class CreateNetwork(forms.SelfHandlingForm): name = forms.CharField(max_length=255, label=_("Name"), required=False) tenant_id = forms.ThemableChoiceField(label=_("Project")) if api.neutron.is_port_profiles_supported(): widget = None else: widget = forms.HiddenInput() net_profile_id = forms.ChoiceField(label=_("Network Profile"), required=False, widget=widget) network_type = forms.ChoiceField( label=_("Provider Network Type"), help_text=_("The physical mechanism by which the virtual " "network is implemented."), widget=forms.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."), initial='default', widget=forms.TextInput(attrs={ 'class': 'switched', 'data-switch-on': 'network_type', })) segmentation_id = forms.IntegerField( label=_("Segmentation ID"), widget=forms.TextInput(attrs={ 'class': 'switched', 'data-switch-on': 'network_type', })) admin_state = forms.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) @classmethod def _instantiate(cls, request, *args, **kwargs): return cls(request, *args, **kwargs) def __init__(self, request, *args, **kwargs): super(CreateNetwork, self).__init__(request, *args, **kwargs) tenant_choices = [('', _("Select a project"))] tenants, has_more = api.keystone.tenant_list(request) for tenant in tenants: if tenant.enabled: tenant_choices.append((tenant.id, tenant.name)) self.fields['tenant_id'].choices = tenant_choices if api.neutron.is_port_profiles_supported(): self.fields['net_profile_id'].choices = ( self.get_network_profile_choices(request)) 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) # 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 get_network_profile_choices(self, request): profile_choices = [('', _("Select a profile"))] for profile in self._get_profiles(request, 'network'): profile_choices.append((profile.id, profile.name)) return profile_choices def _get_profiles(self, request, type_p): profiles = [] try: profiles = api.neutron.profile_list(request, type_p) except Exception: msg = _('Network Profiles could not be retrieved.') exceptions.handle(request, msg) return profiles def _hide_provider_network_type(self): self.fields['network_type'].widget = forms.HiddenInput() self.fields['physical_network'].widget = forms.HiddenInput() self.fields['segmentation_id'].widget = forms.HiddenInput() self.fields['network_type'].required = False self.fields['physical_network'].required = False self.fields['segmentation_id'].required = False def handle(self, request, data): try: params = { 'name': data['name'], 'tenant_id': data['tenant_id'], 'admin_state_up': data['admin_state'], 'shared': data['shared'], 'router:external': data['external'] } if api.neutron.is_port_profiles_supported(): params['net_profile_id'] = data['net_profile_id'] if api.neutron.is_extension_supported(request, 'provider'): network_type = data['network_type'] params['provider:network_type'] = network_type if network_type in self.nettypes_with_physnet: params['provider:physical_network'] = ( data['physical_network']) if network_type in self.nettypes_with_seg_id: params['provider:segmentation_id'] = ( data['segmentation_id']) network = api.neutron.network_create(request, **params) msg = _('Network %s was successfully created.') % data['name'] LOG.debug(msg) messages.success(request, msg) return network except Exception: redirect = reverse('horizon:network: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])
class UpdateSubnet(user_forms.UpdateSubnet): tenant_id = forms.CharField(widget=forms.HiddenInput()) failure_url = 'horizon:admin:networks:detail'
class CreateUserForm(PasswordMixin, BaseUserForm): # 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")) company = forms.CharField( label=_("Company Name"), required=False) contact = forms.CharField( label=_("Contact"), required=False) email = forms.EmailField( label=_("Email"), required=True) telephone = forms.CharField( label=_("Telephone"), required=True) project = forms.DynamicChoiceField(label=_("Primary Project"), required=PROJECT_REQUIRED, add_item_link=ADD_PROJECT_URL, widget=forms.HiddenInput()) role_id = forms.ChoiceField(label=_("Role"), required=PROJECT_REQUIRED, widget=forms.HiddenInput()) region_id = forms.ChoiceField(label=_("Primary Region"), required=True) cdnLimit = forms.BooleanField(label=_("CDN Limit"), required=False, initial=False) safeCard = forms.CharField(widget=forms.HiddenInput(), required=False) def __init__(self, *args, **kwargs): roles = kwargs.pop('roles') regions = kwargs.pop('regions') super(CreateUserForm, self).__init__(*args, **kwargs) # Reorder form fields from multiple inheritance ''' self.fields.keyOrder = ["domain_id", "domain_name", "name", "email", "password", "confirm_password", "project", "role_id", "region_id"] ''' role_choices = [(role.id, role.name) for role in roles] self.fields['role_id'].choices = role_choices region_choices = [] for region in regions: region_choices.append((region.id, region.description)) region_choices.insert(0, ('', _("Select a region"))) self.fields['region_id'].choices = region_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 ''' # 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) try: LOG.info('Creating user with name "%s"' % data['name']) if "email" in data: data['email'] = data['email'] or None if 'cdnLimit' in data and data['cdnLimit']: cdnLimit = 1 else: cdnLimit = 0 new_user = api.keystone.user_create(request, name=data['name'], email=data['email'], password=data['password'], project=data['project'], region_id=data['region_id'], enabled=True, domain=domain.id, parent_id=request.user.id, company=data['company'], contact=data['contact'], telephone=data['telephone'], cdnLimit=cdnLimit) #billing center add by ying.zhou gift_balance = 0 try: gift_balance = getattr(settings,"GIFT_BANLANCE",0) logging.error('settings set is %s',gift_balance) except Exception as e: logging.error('settings not set gift_balance') data_toBilling={"account":{'account_id':'','username':data['name'],'cash_balance':0,'gift_balance':gift_balance,'type':'normal','credit_line':0,'status':'normal','user_id':new_user.id}} try: billingClinect=billing.BillingUser(request) billingUser=billingClinect.create_billingUser(data_toBilling) if not billingUser: userC = UserCenter() userC.deleteUser(new_user) new_user=None except Exception as e: LOG.error(str(e)) LOG.error(traceback.format_exc()) userC = UserCenter() userC.deleteUser(new_user) new_user=None 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.'))
class UpdateUserForm(BaseUserForm): # 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")) company = forms.CharField( label=_("Company Name"), required=False) contact = forms.CharField( label=_("Contact"), required=False) email = forms.EmailField( label=_("Email"), required=True) telephone = forms.CharField( label=_("Telephone"), required=True) project = forms.ChoiceField(label=_("Primary Project"), required=PROJECT_REQUIRED, widget=forms.HiddenInput) regionId = forms.ChoiceField(label=_("Primary Region"), required=PROJECT_REQUIRED) cdnLimit = forms.BooleanField(label=_("CDN Limit"), required=False, initial=False) safeCard = forms.CharField(widget=forms.HiddenInput(), required=False) def __init__(self, request, *args, **kwargs): super(UpdateUserForm, self).__init__(request, *args, **kwargs) 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 region_choices = [] user_id=kwargs['initial'].get('id', None) regions = api.keystone.list_regions_for_user(self.request, user_id) for region in regions: region_choices.append((region['id'], region['description'])) region_choices.insert(0, ('', _("Select a region"))) self.fields['regionId'].choices = region_choices def update_billing_accout(self, request, project_id, data): client = billing.RequestClient(request) account = client.get_account(project_id) params = {} params['account'] = {} params['account']['username'] = data['name'] ret = client.api_request('/account/update/' + account['account_id'], method='PUT', data=json.dumps(params)) user = json.loads(ret.read()) if user['success'] != 'success': raise def handle(self, request, data): user = data.pop('id') data.pop('domain_id') data.pop('domain_name') try: if "email" in data: data['email'] = data['email'] or None if "company" in data: data['company'] = data['company'] or None if "telephone" in data: data['telephone'] = data['telephone'] or None if "contact" in data: data['contact'] = data['contact'] or None if "cdnLimit" in data: if data['cdnLimit']: data['cdnLimit'] = 1 else: data['cdnLimit'] = 0 response = api.keystone.user_update(request, user, **data) self.update_billing_accout(request, data['project'], 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
class SetGroupAction(workflows.Action): # To reuse horizon instance launch code related to Networking, # form filed must be 'network' only network = fields.CustomMultiChoiceField(label=_("Groups"), widget=forms.CheckboxSelectMultiple(), error_messages={ 'required': _( "At least one group must" " be specified.")}, help_text=_("Launch member instance in" " these groups")) widget = forms.HiddenInput() def __init__(self, request, *args, **kwargs): super(SetGroupAction, self).__init__(request, *args, **kwargs) policy_targetid = self.request.path.split("/")[-2] ptg = client.policy_target_get(request, policy_targetid) subnet_dedails = None for subnet_id in ptg.subnets: try: subnet = api.neutron.subnet_get(request, subnet_id) if subnet_dedails is None: subnet_dedails = subnet['cidr'] else: subnet_dedails = subnet_dedails + ";" + subnet['cidr'] allocation_pools = subnet['allocation_pools'] if allocation_pools: start = allocation_pools[0]['start'] end = allocation_pools[0]['end'] subnet_dedails = subnet_dedails + "," + start subnet_dedails = subnet_dedails + "," + end except Exception as e: LOG.error(str(e)) pass initial_value = policy_targetid + ":" + subnet_dedails self.fields['network'].initial = [initial_value] class Meta(object): name = _("Groups") def clean(self): cleaned_data = super(SetGroupAction, self).clean() if not cleaned_data.get("network", None): raise forms.ValidationError(_( 'At least one group must be selected.')) return cleaned_data def populate_network_choices(self, request, context): try: pt_list = [] pts = client.policy_target_list(request, tenant_id=request.user.tenant_id) for pt in pts: pt.set_id_as_name_if_empty() subnet_dedails = None for subnet_id in pt.subnets: try: subnet = api.neutron.subnet_get(request, subnet_id) if subnet_dedails is None: subnet_dedails = subnet['cidr'] else: subnet_dedails += ";" + subnet['cidr'] allocation_pools = subnet['allocation_pools'] if allocation_pools: start = allocation_pools[0]['start'] end = allocation_pools[0]['end'] subnet_dedails = subnet_dedails + "," + start subnet_dedails = subnet_dedails + "," + end except Exception as e: LOG.error(str(e)) pass pt.id = pt.id + ":" + subnet_dedails pt_list.append((pt.id, pt.name)) return sorted(pt_list, key=lambda obj: obj[1]) except Exception: msg = _("Failed to retrieve groups") LOG.error(msg) exceptions.handle(request, msg, redirect=shortcuts.redirect)
class CreateNetwork(forms.SelfHandlingForm): name = forms.CharField(max_length=255, label=_("Name"), required=False) tenant_id = forms.ChoiceField(label=_("Project")) if api.neutron.is_port_profiles_supported(): widget = None else: widget = forms.HiddenInput() net_profile_id = forms.ChoiceField(label=_("Network Profile"), required=False, widget=widget) network_type = forms.ChoiceField( label=_("Provider Network Type"), help_text=_("The physical mechanism by which the virtual " "network is implemented."), widget=forms.Select(attrs={ 'class': 'switchable', 'data-slug': 'network_type' })) physical_network = forms.CharField( max_length=255, label=_("Physical Network"), help_text=_("The name of the physical network over which the " "virtual network is implemented."), initial='default', widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'network_type', 'data-network_type-flat': _('Physical Network'), 'data-network_type-vlan': _('Physical Network') })) segmentation_id = forms.IntegerField( label=_("Segmentation ID"), widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'network_type', 'data-network_type-vlan': _('Segmentation ID'), 'data-network_type-gre': _('Segmentation ID'), 'data-network_type-vxlan': _('Segmentation ID') })) # TODO(amotoki): make UP/DOWN translatable admin_state = forms.ChoiceField(choices=[(True, 'UP'), (False, 'DOWN')], label=_("Admin State")) shared = forms.BooleanField(label=_("Shared"), initial=False, required=False) external = forms.BooleanField(label=_("External Network"), initial=False, required=False) @classmethod def _instantiate(cls, request, *args, **kwargs): return cls(request, *args, **kwargs) def __init__(self, request, *args, **kwargs): super(CreateNetwork, self).__init__(request, *args, **kwargs) tenant_choices = [('', _("Select a project"))] tenants, has_more = api.keystone.tenant_list(request) for tenant in tenants: if tenant.enabled: tenant_choices.append((tenant.id, tenant.name)) self.fields['tenant_id'].choices = tenant_choices if api.neutron.is_port_profiles_supported(): self.fields['net_profile_id'].choices = ( self.get_network_profile_choices(request)) if api.neutron.is_extension_supported(request, 'provider'): neutron_settings = getattr(settings, 'OPENSTACK_NEUTRON_NETWORK', {}) seg_id_range = neutron_settings.get('segmentation_id_range', {}) self.seg_id_range = { 'vlan': seg_id_range.get('vlan', SEGMENTATION_ID_RANGE.get('vlan')), 'gre': seg_id_range.get('gre', SEGMENTATION_ID_RANGE.get('gre')), 'vxlan': seg_id_range.get('vxlan', SEGMENTATION_ID_RANGE.get('vxlan')) } seg_id_help = ( _("For VLAN networks, the VLAN VID on the physical " "network that realizes the virtual network. Valid VLAN VIDs " "are %(vlan_min)s through %(vlan_max)s. For GRE or VXLAN " "networks, the tunnel ID. Valid tunnel IDs for GRE networks " "are %(gre_min)s through %(gre_max)s. For VXLAN networks, " "%(vxlan_min)s through %(vxlan_max)s.") % { 'vlan_min': self.seg_id_range['vlan'][0], 'vlan_max': self.seg_id_range['vlan'][1], 'gre_min': self.seg_id_range['gre'][0], 'gre_max': self.seg_id_range['gre'][1], 'vxlan_min': self.seg_id_range['vxlan'][0], 'vxlan_max': self.seg_id_range['vxlan'][1] }) self.fields['segmentation_id'].help_text = seg_id_help supported_provider_types = neutron_settings.get( 'supported_provider_types', ['*']) if supported_provider_types == ['*']: network_type_choices = PROVIDER_TYPES else: network_type_choices = [ net_type for net_type in PROVIDER_TYPES if net_type[0] in supported_provider_types ] if len(network_type_choices) == 0: self._hide_provider_network_type() else: self.fields['network_type'].choices = network_type_choices else: self._hide_provider_network_type() def get_network_profile_choices(self, request): profile_choices = [('', _("Select a profile"))] for profile in self._get_profiles(request, 'network'): profile_choices.append((profile.id, profile.name)) return profile_choices def _get_profiles(self, request, type_p): profiles = [] try: profiles = api.neutron.profile_list(request, type_p) except Exception: msg = _('Network Profiles could not be retrieved.') exceptions.handle(request, msg) return profiles def _hide_provider_network_type(self): self.fields['network_type'].widget = forms.HiddenInput() self.fields['physical_network'].widget = forms.HiddenInput() self.fields['segmentation_id'].widget = forms.HiddenInput() self.fields['network_type'].required = False self.fields['physical_network'].required = False self.fields['segmentation_id'].required = False def handle(self, request, data): try: params = { 'name': data['name'], 'tenant_id': data['tenant_id'], 'admin_state_up': (data['admin_state'] == 'True'), 'shared': data['shared'], 'router:external': data['external'] } if api.neutron.is_port_profiles_supported(): params['net_profile_id'] = data['net_profile_id'] if api.neutron.is_extension_supported(request, 'provider'): network_type = data['network_type'] params['provider:network_type'] = network_type if network_type in ['flat', 'vlan']: params['provider:physical_network'] = ( data['physical_network']) if network_type in ['vlan', 'gre', 'vxlan']: params['provider:segmentation_id'] = ( data['segmentation_id']) network = api.neutron.network_create(request, **params) msg = _('Network %s was successfully created.') % data['name'] LOG.debug(msg) messages.success(request, msg) return network except Exception: redirect = reverse('horizon:admin:networks:index') msg = _('Failed to create network %s') % data['name'] exceptions.handle(request, msg, redirect=redirect) def clean(self): cleaned_data = super(CreateNetwork, self).clean() 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 in ['local', 'gre']): # 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 in ['local', 'flat']: # In this case the segmentation ID is not required, so we can # ignore any errors. del self._errors['segmentation_id'] elif network_type in ['vlan', 'gre', 'vxlan']: 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']: if network_type == 'vlan': msg = _('For VLAN networks, valid VLAN IDs are %(min)s ' 'through %(max)s.') % seg_id_range elif network_type == 'gre': msg = _('For GRE networks, valid tunnel IDs are %(min)s ' 'through %(max)s.') % seg_id_range elif network_type == 'vxlan': msg = _('For VXLAN networks, valid tunnel IDs are %(min)s ' 'through %(max)s.') % seg_id_range self._errors['segmentation_id'] = self.error_class([msg])
class EditTagsForm(ImageForm): image_id = forms.CharField(widget=forms.HiddenInput())
class UpdatePort(forms.SelfHandlingForm): network_id = forms.CharField(widget=forms.HiddenInput()) port_id = forms.CharField(label=_("ID"), widget=forms.TextInput( attrs={'readonly': 'readonly'})) name = forms.CharField(max_length=255, label=_("Name"), required=False) admin_state = forms.BooleanField(label=_("Enable Admin State"), required=False) failure_url = 'horizon:project:networks:detail' def __init__(self, request, *args, **kwargs): super(UpdatePort, self).__init__(request, *args, **kwargs) try: if api.neutron.is_extension_supported(request, 'binding'): neutron_settings = getattr(settings, 'OPENSTACK_NEUTRON_NETWORK', {}) supported_vnic_types = neutron_settings.get( 'supported_vnic_types', ['*']) if supported_vnic_types: if supported_vnic_types == ['*']: vnic_type_choices = VNIC_TYPES else: vnic_type_choices = [ vnic_type for vnic_type in VNIC_TYPES if vnic_type[0] in supported_vnic_types ] self.fields['binding__vnic_type'] = forms.ChoiceField( choices=vnic_type_choices, label=_("Binding: VNIC Type"), help_text=_( "The VNIC type that is bound to the neutron port"), required=False) except Exception: msg = _("Unable to verify the VNIC types extension in Neutron") exceptions.handle(self.request, msg) try: if api.neutron.is_extension_supported(request, 'mac-learning'): self.fields['mac_state'] = forms.BooleanField( label=_("MAC Learning State"), initial=False, required=False) except Exception: msg = _("Unable to retrieve MAC learning state") exceptions.handle(self.request, msg) def handle(self, request, data): try: LOG.debug('params = %s' % data) extension_kwargs = {} if 'binding__vnic_type' in data: extension_kwargs['binding__vnic_type'] = \ data['binding__vnic_type'] if 'mac_state' in data: extension_kwargs['mac_learning_enabled'] = data['mac_state'] port = api.neutron.port_update(request, data['port_id'], name=data['name'], admin_state_up=data['admin_state'], **extension_kwargs) msg = _('Port %s was successfully updated.') % data['port_id'] LOG.debug(msg) messages.success(request, msg) return port except Exception: msg = _('Failed to update port %s') % data['port_id'] LOG.info(msg) redirect = reverse(self.failure_url, args=[data['network_id']]) exceptions.handle(request, msg, redirect=redirect)
class ConfigureNodegroupsAction(workflows.Action): hidden_nodegroups_field = forms.CharField( required=False, widget=forms.HiddenInput(attrs={"class": "hidden_nodegroups_field"})) forms_ids = forms.CharField( required=False, widget=forms.HiddenInput()) def __init__(self, request, *args, **kwargs): super(ConfigureNodegroupsAction, self). \ __init__(request, *args, **kwargs) plugin = request.REQUEST.get("plugin_name") version = request.REQUEST.get("hadoop_version") if plugin and not version: version_name = plugin + "_version" version = request.REQUEST.get(version_name) if not plugin or not version: self.templates = saharaclient.nodegroup_template_find(request) else: self.templates = saharaclient.nodegroup_template_find( request, plugin_name=plugin, hadoop_version=version) deletable = request.REQUEST.get("deletable", dict()) request_source = None if 'forms_ids' in request.POST: request_source = request.POST elif 'forms_ids' in request.REQUEST: request_source = request.REQUEST if request_source: self.groups = [] for id in json.loads(request_source['forms_ids']): group_name = "group_name_" + str(id) template_id = "template_id_" + str(id) count = "count_" + str(id) serialized = "serialized_" + str(id) self.groups.append({"name": request_source[group_name], "template_id": request_source[template_id], "count": request_source[count], "id": id, "deletable": deletable.get( request_source[group_name], "true"), "serialized": request_source[serialized]}) whelpers.build_node_group_fields(self, group_name, template_id, count, serialized) def clean(self): cleaned_data = super(ConfigureNodegroupsAction, self).clean() if cleaned_data.get("hidden_nodegroups_field", None) \ == "create_nodegroup": self._errors = dict() return cleaned_data class Meta(object): name = _("Node Groups")
class RecordForm(forms.SelfHandlingForm): '''Base class for RecordCreate and RecordUpdate forms. Sets-up all of the form fields and implements the complex validation logic. ''' domain_id = forms.CharField(widget=forms.HiddenInput()) domain_name = forms.CharField(widget=forms.HiddenInput()) type = forms.ChoiceField( label=_("Record Type"), required=False, choices=[ ('a', _('A - Address record')), ('aaaa', _('AAAA - IPv6 address record')), ('cname', _('CNAME - Canonical name record')), ('mx', _('MX - Mail exchange record')), ('ptr', _('PTR - Pointer record')), ('spf', _('SPF - Sender Policy Framework')), ('srv', _('SRV - Service locator')), ('sshfp', _('SSHFP - SSH Public Key Fingerprint')), ('txt', _('TXT - Text record')), ], widget=forms.Select(attrs={ 'class': 'switchable', 'data-slug': 'record_type', }), ) name = forms.CharField( max_length=256, required=False, widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'record_type', 'data-record_type-a': _('Name'), 'data-record_type-aaaa': _('Name'), 'data-record_type-cname': _('Name'), 'data-record_type-mx': _('Name'), 'data-record_type-ns': _('Name'), 'data-record_type-ptr': _('Name'), 'data-record_type-soa': _('Name'), 'data-record_type-spf': _('Name'), 'data-record_type-srv': _('Name'), 'data-record_type-sshfp': _('Name'), 'data-record_type-txt': _('Name'), }), ) data = forms.CharField( required=False, widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'record_type', 'data-record_type-a': _('IP Address'), 'data-record_type-aaaa': _('IP Address'), 'data-record_type-cname': _('Canonical Name'), 'data-record_type-ns': _('Name Server'), 'data-record_type-mx': _('Mail Server'), 'data-record_type-ptr': _('PTR Domain Name'), 'data-record_type-soa': _('Value'), 'data-record_type-srv': _('Value'), }), ) txt = forms.CharField( label=_('TXT'), required=False, widget=forms.Textarea( attrs={ 'class': 'switched', 'data-switch-on': 'record_type', 'data-record_type-txt': _('Text'), 'data-record_type-spf': _('Text'), 'data-record_type-sshfp': _('Text'), }), ) priority = forms.IntegerField( min_value=0, max_value=65535, required=False, widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'record_type', 'data-record_type-mx': _('Priority'), 'data-record_type-srv': _('Priority'), }), ) ttl = forms.IntegerField( label=_('TTL'), min_value=0, max_value=MAX_TTL, required=False, widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'record_type', 'data-record_type-a': _('TTL'), 'data-record_type-aaaa': _('TTL'), 'data-record_type-cname': _('TTL'), 'data-record_type-mx': _('TTL'), 'data-record_type-ptr': _('TTL'), 'data-record_type-soa': _('TTL'), 'data-record_type-spf': _('TTL'), 'data-record_type-srv': _('TTL'), 'data-record_type-sshfp': _('TTL'), 'data-record_type-txt': _('TTL'), }), ) description = forms.CharField( label=_("Description"), required=False, max_length=160, widget=forms.Textarea(), ) def clean_type(self): '''Type value needs to be uppercased before it is sent to the API.''' return self.cleaned_data['type'].upper() def clean(self): '''Handles the validation logic for the domain record form. Validation gets pretty complicated due to the fact that the different record types (A, AAAA, MX, etc) have different requirements for each of the fields. ''' cleaned_data = super(RecordForm, self).clean() record_type = cleaned_data['type'] domain_name = cleaned_data['domain_name'] # Name field if self._is_field_blank(cleaned_data, 'name'): if record_type in ['A', 'AAAA', 'CNAME', 'SRV', 'TXT', 'PTR']: self._add_required_field_error('name') elif record_type == 'MX': cleaned_data['name'] = domain_name else: if record_type == 'SRV': if not re.match(SRV_NAME_REGEX, cleaned_data['name']): self._add_field_error('name', _('Enter a valid SRV name')) else: cleaned_data['name'] += domain_name else: if not re.match(WILDCARD_DOMAIN_NAME_REGEX, cleaned_data['name']): self._add_field_error( 'name', _('Enter a valid hostname.' ' The hostname should end' ' with a period.')) elif not cleaned_data['name'].endswith(domain_name): self._add_field_error( 'name', _('Name must be in the current domain')) # Data field if self._is_field_blank(cleaned_data, 'data'): if record_type in ['A', 'AAAA', 'CNAME', 'MX', 'SRV']: self._add_required_field_error('data') else: if record_type == 'A': try: validators.validate_ipv4_address(cleaned_data['data']) except ValidationError: self._add_field_error('data', _('Enter a valid IPv4 address')) elif record_type == 'AAAA': try: validators.validate_ipv6_address(cleaned_data['data']) except ValidationError: self._add_field_error('data', _('Enter a valid IPv6 address')) elif record_type in ['CNAME', 'MX', 'PTR']: if not re.match(DOMAIN_NAME_REGEX, cleaned_data['data']): self._add_field_error('data', _('Enter a valid hostname')) elif record_type == 'SRV': if not re.match(SRV_DATA_REGEX, cleaned_data['data']): self._add_field_error('data', _('Enter a valid SRV record')) # Txt field if self._is_field_blank(cleaned_data, 'txt'): if record_type == 'TXT': self._add_required_field_error('txt') else: if record_type == 'TXT': cleaned_data['data'] = cleaned_data['txt'] if record_type == 'SSHFP': if not re.match(SSHFP_DATA_REGEX, cleaned_data['txt']): self._add_field_error('txt', _('Enter a valid SSHFP record')) cleaned_data['data'] = cleaned_data['txt'] cleaned_data.pop('txt') # Priority field if self._is_field_blank(cleaned_data, 'priority'): if record_type in ['MX', 'SRV']: self._add_required_field_error('priority') # Rename 'id' to 'record_id' if 'id' in cleaned_data: cleaned_data['record_id'] = cleaned_data.pop('id') # Remove domain_name cleaned_data.pop('domain_name') return cleaned_data def _add_required_field_error(self, field): '''Set a required field error on the specified field.''' self._add_field_error(field, _('This field is required')) def _add_field_error(self, field, msg): '''Set the specified msg as an error on the field.''' self._errors[field] = self.error_class([msg]) def _is_field_blank(self, cleaned_data, field): '''Returns a flag indicating whether the specified field is blank.''' return field in cleaned_data and not cleaned_data[field]
class UpdateImageForm(forms.SelfHandlingForm): image_id = forms.CharField(widget=forms.HiddenInput()) name = forms.CharField(max_length=255, label=_("Name")) description = forms.CharField(max_length=255, widget=forms.Textarea(attrs={'rows': 4}), label=_("Description"), required=False) kernel = forms.CharField( max_length=36, label=_("Kernel ID"), required=False, widget=forms.TextInput(attrs={'readonly': 'readonly'}), ) ramdisk = forms.CharField( max_length=36, label=_("Ramdisk ID"), required=False, widget=forms.TextInput(attrs={'readonly': 'readonly'}), ) architecture = forms.CharField( label=_("Architecture"), required=False, widget=forms.TextInput(attrs={'readonly': 'readonly'}), ) disk_format = forms.ThemableChoiceField(label=_("Format"), ) minimum_disk = forms.IntegerField(label=_("Minimum Disk (GB)"), min_value=0, help_text=_('The minimum disk size' ' required to boot the' ' image. If unspecified,' ' this value defaults to' ' 0 (no minimum).'), required=False) minimum_ram = forms.IntegerField(label=_("Minimum RAM (MB)"), min_value=0, help_text=_('The minimum memory size' ' required to boot the' ' image. If unspecified,' ' this value defaults to' ' 0 (no minimum).'), required=False) public = forms.BooleanField(label=_("Public"), required=False) protected = forms.BooleanField(label=_("Protected"), required=False) def __init__(self, request, *args, **kwargs): super(UpdateImageForm, self).__init__(request, *args, **kwargs) self.fields['disk_format'].choices = [ (value, name) for value, name in IMAGE_FORMAT_CHOICES if value ] if not policy.check((("image", "publicize_image"), ), request): self.fields['public'].widget = forms.CheckboxInput( attrs={ 'readonly': 'readonly', 'disabled': 'disabled' }) self.fields['public'].help_text = _( 'Non admin users are not allowed to make images public.') def handle(self, request, data): image_id = data['image_id'] error_updating = _('Unable to update image "%s".') meta = create_image_metadata(data) try: image = api.glance.image_update(request, image_id, **meta) messages.success(request, _('Image was successfully updated.')) return image except Exception: exceptions.handle(request, error_updating % image_id)
def hide_subnetpool_choices(self): self.fields['address_source'].widget = forms.HiddenInput() self.fields['subnetpool'].choices = [] self.fields['subnetpool'].widget = forms.HiddenInput() self.fields['prefixlen'].widget = forms.HiddenInput()
class GeneralConfigAction(workflows.Action): hidden_configure_field = forms.CharField( required=False, widget=forms.HiddenInput(attrs={"class": "hidden_configure_field"})) hidden_to_delete_field = forms.CharField( required=False, widget=forms.HiddenInput(attrs={"class": "hidden_to_delete_field"})) cluster_template_name = forms.CharField(label=_("Template Name")) description = forms.CharField(label=_("Description"), required=False, widget=forms.Textarea(attrs={'rows': 4})) use_autoconfig = forms.BooleanField( label=_("Auto-configure"), help_text=_("If selected, instances of a cluster will be " "automatically configured during creation. Otherwise you " "should manually specify configuration values"), required=False, widget=forms.CheckboxInput(), initial=True, ) is_public = acl_utils.get_is_public_form(_("cluster template")) is_protected = acl_utils.get_is_protected_form(_("cluster template")) anti_affinity = aa.anti_affinity_field() def __init__(self, request, *args, **kwargs): super(GeneralConfigAction, self).__init__(request, *args, **kwargs) plugin, hadoop_version = whelpers.\ get_plugin_and_hadoop_version(request) self.fields["plugin_name"] = forms.CharField( widget=forms.HiddenInput(), initial=plugin ) self.fields["hadoop_version"] = forms.CharField( widget=forms.HiddenInput(), initial=hadoop_version ) populate_anti_affinity_choices = aa.populate_anti_affinity_choices def get_help_text(self): extra = dict() plugin, hadoop_version = whelpers\ .get_plugin_and_hadoop_version(self.request) extra["plugin_name"] = plugin extra["hadoop_version"] = hadoop_version return super(GeneralConfigAction, self).get_help_text(extra) def clean(self): cleaned_data = super(GeneralConfigAction, self).clean() if cleaned_data.get("hidden_configure_field", None) \ == "create_nodegroup": self._errors = dict() return cleaned_data class Meta(object): name = _("Details") help_text_template = ("cluster_templates/_configure_general_help.html")
def __init__(self, request, context, *args, **kwargs): super(CreateSubnetDetailAction, self).__init__(request, context, *args, **kwargs) if not getattr(settings, 'OPENSTACK_NEUTRON_NETWORK', {}).get( 'enable_ipv6', True): self.fields['ipv6_modes'].widget = forms.HiddenInput()
class GeneralConfigAction(workflows.Action): nodegroup_name = forms.CharField(label=_("Template Name"), required=True) description = forms.CharField(label=_("Description"), required=False, widget=forms.Textarea) flavor = forms.ChoiceField(label=_("OpenStack Flavor"), required=True) storage = forms.ChoiceField( label=_("Storage location"), required=True, help_text=_("Storage"), choices=[("ephemeral_drive", "Ephemeral Drive"), ("cinder_volume", "Cinder Volume")], widget=forms.Select(attrs={"class": "storage_field"})) volumes_per_node = forms.IntegerField( label=_("Volumes per node"), required=False, initial=1, widget=forms.TextInput(attrs={"class": "volume_per_node_field"})) volumes_size = forms.IntegerField( label=_("Volumes size (GB)"), required=False, initial=10, widget=forms.TextInput(attrs={"class": "volume_size_field"})) hidden_configure_field = forms.CharField( required=False, widget=forms.HiddenInput(attrs={"class": "hidden_configure_field"})) def __init__(self, request, *args, **kwargs): super(GeneralConfigAction, self).__init__(request, *args, **kwargs) sahara = saharaclient.client(request) hlps = helpers.Helpers(sahara) plugin, hadoop_version = whelpers.\ get_plugin_and_hadoop_version(request) process_choices = [] version_details = sahara.plugins.get_version_details( plugin, hadoop_version) for service, processes in version_details.node_processes.items(): for process in processes: process_choices.append( (str(service) + ":" + str(process), process)) if not saharaclient.AUTO_ASSIGNMENT_ENABLED: pools = network.floating_ip_pools_list(request) pool_choices = [(pool.id, pool.name) for pool in pools] pool_choices.insert(0, (None, "Do not assign floating IPs")) self.fields['floating_ip_pool'] = forms.ChoiceField( label=_("Floating IP pool"), choices=pool_choices, required=False) self.fields["processes"] = forms.MultipleChoiceField( label=_("Processes"), required=True, widget=forms.CheckboxSelectMultiple(), help_text=_("Processes to be launched in node group"), choices=process_choices) self.fields["plugin_name"] = forms.CharField( widget=forms.HiddenInput(), initial=plugin) self.fields["hadoop_version"] = forms.CharField( widget=forms.HiddenInput(), initial=hadoop_version) node_parameters = hlps.get_general_node_group_configs( plugin, hadoop_version) for param in node_parameters: self.fields[param.name] = whelpers.build_control(param) def populate_flavor_choices(self, request, context): try: flavors = nova.flavor_list(request) flavor_list = [(flavor.id, "%s" % flavor.name) for flavor in flavors] except Exception: flavor_list = [] exceptions.handle(request, _('Unable to retrieve instance flavors.')) return sorted(flavor_list) def get_help_text(self): extra = dict() plugin, hadoop_version = whelpers.\ get_plugin_and_hadoop_version(self.request) extra["plugin_name"] = plugin extra["hadoop_version"] = hadoop_version return super(GeneralConfigAction, self).get_help_text(extra) class Meta: name = _("Configure Node Group Template") help_text_template = \ ("nodegroup_templates/_configure_general_help.html")
class LaunchForm(forms.SelfHandlingForm): name = forms.CharField(max_length=80, label=_("Server Name")) image_id = forms.CharField(widget=forms.HiddenInput()) tenant_id = forms.CharField(widget=forms.HiddenInput()) user_data = forms.CharField(widget=forms.Textarea, label=_("User Data"), required=False) # make the dropdown populate when the form is loaded not when django is # started def __init__(self, *args, **kwargs): super(LaunchForm, self).__init__(*args, **kwargs) flavorlist = kwargs.get('initial', {}).get('flavorlist', []) self.fields['flavor'] = forms.ChoiceField( choices=flavorlist, label=_("Flavor"), help_text="Size of Image to launch") keynamelist = kwargs.get('initial', {}).get('keynamelist', []) self.fields['key_name'] = forms.ChoiceField( choices=keynamelist, label=_("Key Name"), required=False, help_text="Which keypair to use for authentication") securitygrouplist = kwargs.get('initial', {}).get('securitygrouplist', []) self.fields['security_groups'] = forms.MultipleChoiceField( choices=securitygrouplist, label=_("Security Groups"), required=True, initial=['default'], widget=forms.CheckboxSelectMultiple(), help_text="Launch instance in these Security Groups") # setting self.fields.keyOrder seems to break validation, # so ordering fields manually field_list = ('name', 'user_data', 'flavor', 'key_name') for field in field_list[::-1]: self.fields.insert(0, field, self.fields.pop(field)) def handle(self, request, data): image_id = data['image_id'] tenant_id = data['tenant_id'] try: image = api.image_get_meta(request, image_id) flavor = api.flavor_get(request, data['flavor']) api.server_create(request, data['name'], image, flavor, data.get('key_name'), normalize_newlines(data.get('user_data')), data.get('security_groups')) msg = _('Instance was successfully launched') LOG.info(msg) messages.success(request, msg) return redirect( 'horizon:nova:instances_and_volumes:instances:index') except api_exceptions.ApiException, e: LOG.exception( 'ApiException while creating instances of image "%s"' % image_id) messages.error(request, _('Unable to launch instance: %s') % e.message)
class CreateBackupForm(forms.SelfHandlingForm): name = forms.CharField(max_length=255, label=_("Backup Name")) description = forms.CharField(widget=forms.Textarea(attrs={'rows': 4}), label=_("Description"), required=False) container_name = forms.CharField( max_length=255, label=_("Container Name"), validators=[containers_utils.no_slash_validator], required=False) volume_id = forms.CharField(widget=forms.HiddenInput()) snapshot_id = forms.ThemableChoiceField(label=_("Backup Snapshot"), required=False) def __init__(self, request, *args, **kwargs): super().__init__(request, *args, **kwargs) if kwargs['initial'].get('snapshot_id'): snap_id = kwargs['initial']['snapshot_id'] try: snapshot = api.cinder.volume_snapshot_get(request, snap_id) self.fields['snapshot_id'].choices = [(snapshot.id, snapshot.name)] self.fields['snapshot_id'].initial = snap_id except Exception: redirect = reverse('horizon:project:snapshots:index') exceptions.handle(request, _('Unable to fetch snapshot'), redirect=redirect) else: try: sop = {'volume_id': kwargs['initial']['volume_id']} snapshots = api.cinder.volume_snapshot_list(request, search_opts=sop) snapshots.sort(key=operator.attrgetter('id', 'created_at')) snapshotChoices = [[snapshot.id, snapshot.name] for snapshot in snapshots] if not snapshotChoices: snapshotChoices.insert(0, ('', _("No snapshot for this volume"))) else: snapshotChoices.insert( 0, ('', _("Select snapshot to backup (Optional)"))) self.fields['snapshot_id'].choices = snapshotChoices except Exception: redirect = reverse('horizon:project:volumes:index') exceptions.handle(request, _('Unable to fetch snapshots'), redirect=redirect) def handle(self, request, data): try: volume = api.cinder.volume_get(request, data['volume_id']) snapshot_id = data['snapshot_id'] or None force = False if volume.status == 'in-use': force = True backup = api.cinder.volume_backup_create( request, data['volume_id'], data['container_name'], data['name'], data['description'], force=force, snapshot_id=snapshot_id ) message = _('Creating volume backup "%s"') % data['name'] messages.info(request, message) return backup except Exception: redirect = reverse('horizon:project:volumes:index') exceptions.handle(request, _('Unable to create volume backup.'), redirect=redirect)
class RebuildInstanceForm(forms.SelfHandlingForm): instance_id = forms.CharField(widget=forms.HiddenInput()) image = forms.ChoiceField(label=_("Select Image"), widget=forms.ThemableSelectWidget( attrs={'class': 'image-selector'}, data_attrs=('size', 'display-name'), transform=_image_choice_title)) password = forms.RegexField( label=_("Rebuild Password"), required=False, widget=forms.PasswordInput(render_value=False), regex=validators.password_validator(), error_messages={'invalid': validators.password_validator_msg()}) confirm_password = forms.CharField( label=_("Confirm Rebuild Password"), required=False, widget=forms.PasswordInput(render_value=False)) disk_config = forms.ThemableChoiceField(label=_("Disk Partition"), required=False) def __init__(self, request, *args, **kwargs): super(RebuildInstanceForm, self).__init__(request, *args, **kwargs) instance_id = kwargs.get('initial', {}).get('instance_id') self.fields['instance_id'].initial = instance_id images = image_utils.get_available_images(request, request.user.tenant_id) choices = [(image.id, image) for image in images] if choices: choices.insert(0, ("", _("Select Image"))) else: choices.insert(0, ("", _("No images available"))) self.fields['image'].choices = choices if not api.nova.can_set_server_password(): del self.fields['password'] del self.fields['confirm_password'] try: if not api.nova.extension_supported("DiskConfig", request): del self.fields['disk_config'] else: # Set our disk_config choices config_choices = [("AUTO", _("Automatic")), ("MANUAL", _("Manual"))] self.fields['disk_config'].choices = config_choices except Exception: exceptions.handle( request, _('Unable to retrieve extensions ' 'information.')) def clean(self): cleaned_data = super(RebuildInstanceForm, self).clean() if 'password' in cleaned_data: passwd = cleaned_data.get('password') confirm = cleaned_data.get('confirm_password') if passwd is not None and confirm is not None: if passwd != confirm: raise forms.ValidationError(_("Passwords do not match.")) return cleaned_data # We have to protect the entire "data" dict because it contains the # password and confirm_password strings. @sensitive_variables('data', 'password') def handle(self, request, data): instance = data.get('instance_id') image = data.get('image') password = data.get('password') or None disk_config = data.get('disk_config', None) try: api.nova.server_rebuild(request, instance, image, password, disk_config) messages.info(request, _('Rebuilding instance %s.') % instance) except Exception: redirect = reverse('horizon:project:instances:index') exceptions.handle(request, _("Unable to rebuild instance."), redirect=redirect) return True
class CreateUserForm(BaseUserForm): # 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(label=_("User Name")) email = forms.EmailField(label=_("Email"), required=False) password = forms.RegexField( label=_("Password"), widget=forms.PasswordInput(render_value=False), regex=validators.password_validator(), error_messages={'invalid': validators.password_validator_msg()}) confirm_password = forms.CharField( label=_("Confirm Password"), required=False, widget=forms.PasswordInput(render_value=False)) project = forms.DynamicChoiceField(label=_("Primary Project"), add_item_link=ADD_PROJECT_URL) role_id = forms.ChoiceField(label=_("Role")) def __init__(self, *args, **kwargs): roles = kwargs.pop('roles') super(CreateUserForm, self).__init__(*args, **kwargs) 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 # 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) try: LOG.info('Creating user with name "%s"' % data['name']) new_user = api.keystone.user_create(request, name=data['name'], email=data['email'], password=data['password'], project=data['project'], enabled=True, domain=domain.id) messages.success( request, _('User "%s" was successfully created.') % data['name']) if data['role_id']: 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 Exception: exceptions.handle(request, _('Unable to create user.'))
class AddRule(forms.SelfHandlingForm): id = forms.CharField(widget=forms.HiddenInput()) rule_menu = forms.ChoiceField( label=_('Rule'), widget=forms.Select(attrs={ 'class': 'switchable', 'data-slug': 'rule_menu' })) # "direction" field is enabled only when custom mode. # It is because most common rules in local_settings.py is meaningful # when its direction is 'ingress'. direction = forms.ChoiceField( label=_('Direction'), required=False, widget=forms.Select( attrs={ 'class': 'switched', 'data-switch-on': 'rule_menu', 'data-rule_menu-tcp': _('Direction'), 'data-rule_menu-udp': _('Direction'), 'data-rule_menu-icmp': _('Direction'), 'data-rule_menu-custom': _('Direction'), 'data-rule_menu-all_tcp': _('Direction'), 'data-rule_menu-all_udp': _('Direction'), 'data-rule_menu-all_icmp': _('Direction'), })) ip_protocol = forms.IntegerField( label=_('IP Protocol'), required=False, help_text=_("Enter an integer value between 0 and 255 " "(or -1 which means wildcard)."), validators=[utils_validators.validate_ip_protocol], widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'rule_menu', 'data-rule_menu-custom': _('IP Protocol') })) port_or_range = forms.ChoiceField( label=_('Open Port'), choices=[('port', _('Port')), ('range', _('Port Range'))], widget=forms.Select( attrs={ 'class': 'switchable switched', 'data-slug': 'range', 'data-switch-on': 'rule_menu', 'data-rule_menu-tcp': _('Open Port'), 'data-rule_menu-udp': _('Open Port') })) port = forms.IntegerField( label=_("Port"), required=False, help_text=_("Enter an integer value " "between 1 and 65535."), widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'range', 'data-range-port': _('Port') }), validators=[utils_validators.validate_port_range]) from_port = forms.IntegerField( label=_("From Port"), required=False, help_text=_("Enter an integer value " "between 1 and 65535."), widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'range', 'data-range-range': _('From Port') }), validators=[utils_validators.validate_port_range]) to_port = forms.IntegerField( label=_("To Port"), required=False, help_text=_("Enter an integer value " "between 1 and 65535."), widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'range', 'data-range-range': _('To Port') }), validators=[utils_validators.validate_port_range]) icmp_type = forms.IntegerField( label=_("Type"), required=True, help_text=_("Enter a value for ICMP type " "in the range (-1: 255)"), widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'rule_menu', 'data-rule_menu-icmp': _('Type') }), validators=[utils_validators.validate_port_range]) icmp_code = forms.IntegerField( label=_("Code"), required=True, help_text=_("Enter a value for ICMP code " "in the range (-1: 255)"), widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'rule_menu', 'data-rule_menu-icmp': _('Code') }), validators=[utils_validators.validate_port_range]) remote = forms.ChoiceField(label=_('Remote'), choices=[('cidr', _('CIDR')), ('sg', _('Security Group'))], help_text=_('To specify an allowed IP ' 'range, select "CIDR". ' 'To allow access from all ' 'members of another security ' 'group select "Security ' 'Group".'), widget=forms.Select(attrs={ 'class': 'switchable', 'data-slug': 'remote' })) cidr = forms.IPField(label=_("CIDR"), required=False, initial="0.0.0.0/0", help_text=_("Classless Inter-Domain Routing " "(e.g. 192.168.0.0/24, or " "2001:db8::/128)"), version=forms.IPv4 | forms.IPv6, mask=True, widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'remote', 'data-remote-cidr': _('CIDR') })) security_group = forms.ChoiceField( label=_('Security Group'), required=False, widget=forms.Select( attrs={ 'class': 'switched', 'data-switch-on': 'remote', 'data-remote-sg': _('Security ' 'Group') })) # When cidr is used ethertype is determined from IP version of cidr. # When source group, ethertype needs to be specified explicitly. ethertype = forms.ChoiceField(label=_('Ether Type'), required=False, choices=[('IPv4', _('IPv4')), ('IPv6', _('IPv6'))], widget=forms.Select( attrs={ 'class': 'switched', 'data-slug': 'ethertype', 'data-switch-on': 'remote', 'data-remote-sg': _('Ether Type') })) def __init__(self, *args, **kwargs): sg_list = kwargs.pop('sg_list', []) super(AddRule, self).__init__(*args, **kwargs) # Determine if there are security groups available for the # remote group option; add the choices and enable the option if so. if sg_list: security_groups_choices = sg_list else: security_groups_choices = [("", _("No security groups available"))] self.fields['security_group'].choices = security_groups_choices backend = api.network.security_group_backend(self.request) rules_dict = getattr(settings, 'SECURITY_GROUP_RULES', []) common_rules = [(k, rules_dict[k]['name']) for k in rules_dict if rules_dict[k].get('backend', backend) == backend] common_rules.sort() custom_rules = [('tcp', _('Custom TCP Rule')), ('udp', _('Custom UDP Rule')), ('icmp', _('Custom ICMP Rule'))] if backend == 'neutron': custom_rules.append(('custom', _('Other Protocol'))) self.fields['rule_menu'].choices = custom_rules + common_rules self.rules = rules_dict if backend == 'neutron': self.fields['direction'].choices = [('ingress', _('Ingress')), ('egress', _('Egress'))] else: # direction and ethertype are not supported in Nova secgroup. self.fields['direction'].widget = forms.HiddenInput() self.fields['ethertype'].widget = forms.HiddenInput() # ip_protocol field is to specify arbitrary protocol number # and it is available only for neutron security group. self.fields['ip_protocol'].widget = forms.HiddenInput() def _update_and_pop_error(self, cleaned_data, key, value): cleaned_data[key] = value self.errors.pop(key, None) def _clean_rule_icmp(self, cleaned_data, rule_menu): icmp_type = cleaned_data.get("icmp_type", None) icmp_code = cleaned_data.get("icmp_code", None) self._update_and_pop_error(cleaned_data, 'ip_protocol', rule_menu) if icmp_type is None: msg = _('The ICMP type is invalid.') raise ValidationError(msg) if icmp_code is None: msg = _('The ICMP code is invalid.') raise ValidationError(msg) if icmp_type not in range(-1, 256): msg = _('The ICMP type not in range (-1, 255)') raise ValidationError(msg) if icmp_code not in range(-1, 256): msg = _('The ICMP code not in range (-1, 255)') raise ValidationError(msg) self._update_and_pop_error(cleaned_data, 'from_port', icmp_type) self._update_and_pop_error(cleaned_data, 'to_port', icmp_code) self._update_and_pop_error(cleaned_data, 'port', None) def _clean_rule_tcp_udp(self, cleaned_data, rule_menu): port_or_range = cleaned_data.get("port_or_range") from_port = cleaned_data.get("from_port", None) to_port = cleaned_data.get("to_port", None) port = cleaned_data.get("port", None) self._update_and_pop_error(cleaned_data, 'ip_protocol', rule_menu) self._update_and_pop_error(cleaned_data, 'icmp_code', None) self._update_and_pop_error(cleaned_data, 'icmp_type', None) if port_or_range == "port": self._update_and_pop_error(cleaned_data, 'from_port', port) self._update_and_pop_error(cleaned_data, 'to_port', port) if port is None: msg = _('The specified port is invalid.') raise ValidationError(msg) else: self._update_and_pop_error(cleaned_data, 'port', None) if from_port is None: msg = _('The "from" port number is invalid.') raise ValidationError(msg) if to_port is None: msg = _('The "to" port number is invalid.') raise ValidationError(msg) if to_port < from_port: msg = _('The "to" port number must be greater than ' 'or equal to the "from" port number.') raise ValidationError(msg) def _clean_rule_custom(self, cleaned_data, rule_menu): # custom IP protocol rule so we need to fill unused fields so # the validation works self._update_and_pop_error(cleaned_data, 'icmp_code', None) self._update_and_pop_error(cleaned_data, 'icmp_type', None) def _apply_rule_menu(self, cleaned_data, rule_menu): cleaned_data['ip_protocol'] = self.rules[rule_menu]['ip_protocol'] cleaned_data['from_port'] = int(self.rules[rule_menu]['from_port']) cleaned_data['to_port'] = int(self.rules[rule_menu]['to_port']) self._update_and_pop_error(cleaned_data, 'icmp_code', None) self._update_and_pop_error(cleaned_data, 'icmp_type', None) if rule_menu not in ['all_tcp', 'all_udp', 'all_icmp']: direction = self.rules[rule_menu].get('direction') cleaned_data['direction'] = direction def _clean_rule_menu(self, cleaned_data): rule_menu = cleaned_data.get('rule_menu') if rule_menu == 'icmp': self._clean_rule_icmp(cleaned_data, rule_menu) elif rule_menu == 'tcp' or rule_menu == 'udp': self._clean_rule_tcp_udp(cleaned_data, rule_menu) elif rule_menu == 'custom': self._clean_rule_custom(cleaned_data, rule_menu) else: self._apply_rule_menu(cleaned_data, rule_menu) def clean(self): cleaned_data = super(AddRule, self).clean() self._clean_rule_menu(cleaned_data) # NOTE(amotoki): There are two cases where cleaned_data['direction'] # is empty: (1) Nova Security Group is used. Since "direction" is # HiddenInput, direction field exists but its value is ''. # (2) Template except all_* is used. In this case, the default value # is None. To make sure 'direction' field has 'ingress' or 'egress', # fill this field here if it is not specified. if not cleaned_data['direction']: cleaned_data['direction'] = 'ingress' remote = cleaned_data.get("remote") if remote == "cidr": self._update_and_pop_error(cleaned_data, 'security_group', None) else: self._update_and_pop_error(cleaned_data, 'cidr', None) # If cleaned_data does not contain a non-empty value, IPField already # has validated it, so skip the further validation for cidr. # In addition cleaned_data['cidr'] is None means source_group is used. if 'cidr' in cleaned_data and cleaned_data['cidr'] is not None: cidr = cleaned_data['cidr'] if not cidr: msg = _('CIDR must be specified.') self._errors['cidr'] = self.error_class([msg]) else: # If cidr is specified, ethertype is determined from IP address # version. It is used only when Neutron is enabled. ip_ver = netaddr.IPNetwork(cidr).version cleaned_data['ethertype'] = 'IPv6' if ip_ver == 6 else 'IPv4' return cleaned_data def handle(self, request, data): redirect = reverse( "horizon:virtual:access_and_security:" "security_groups:detail", args=[data['id']]) try: rule = api.network.security_group_rule_create( request, filters.get_int_or_uuid(data['id']), data['direction'], data['ethertype'], data['ip_protocol'], data['from_port'], data['to_port'], data['cidr'], data['security_group']) messages.success( request, _('Successfully added rule: %s') % six.text_type(rule)) return rule except exceptions.Conflict as error: exceptions.handle(request, error, redirect=redirect) except Exception: exceptions.handle(request, _('Unable to add rule to security group.'), redirect=redirect)
class AddRule(forms.SelfHandlingForm): id = forms.CharField(widget=forms.HiddenInput()) sequence_id = forms.ChoiceField(label=_('Sequence Id'), help_text=_("Choose the Sequence Id for " " this rule.")) simple_action = forms.ChoiceField(label=_('Action'), choices=[('pass', 'Pass'), ('deny', 'Deny')], help_text=_( "Actions that will be applied " " on the traffic that matches" " the rules")) protocol = forms.ChoiceField( label=_('IP Protocol'), choices=[('any', 'ANY'), ('tcp', 'TCP'), ('udp', 'UDP'), ('icmp', 'ICMP')], help_text=_("TCP, UDP, ICMP or All protocols")) direction = forms.ChoiceField(label=_('Direction'), choices=[('<>', '<> Bidirectional'), ('>', '> Unidirectional')], help_text=_("Direction of traffic on which" " the rule will be applied")) srctype = forms.ChoiceField(label=_('Source Type'), choices=[('srcnets', _('Source Network')), ('srccidr', _('Source CIDR')), ('srcpols', _('Source Network Policy'))], help_text=_('To specify an allowed IP ' 'range, select "CIDR". To ' 'allow access from a network ' 'select "Network". To ' 'allow access from a network ' 'policy select "Network Policy".'), widget=forms.Select(attrs={ 'class': 'switchable', 'data-slug': 'srctype' })) dsttype = forms.ChoiceField(label=_('Destination Type'), choices=[('dstnets', _('Destination Network')), ('dstcidr', _('Destination CIDR')), ('dstpols', _('Destination Network Policy'))], help_text=_('To specify an allowed IP ' 'range, select "CIDR". To ' 'allow access from a network ' 'select "Network". To ' 'allow access from a network ' 'policy select "Network Policy".'), widget=forms.Select(attrs={ 'class': 'switchable', 'data-slug': 'dsttype' })) srccidr = fields.IPField(label=_("Source CIDR"), required=False, initial="0.0.0.0/0", help_text=_("Classless Inter-Domain Routing " "(e.g. 192.168.0.0/24)"), version=fields.IPv4, mask=True, widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'srctype', 'data-srctype-srccidr': _('Source CIDR') })) srcnets = forms.ChoiceField( label=_('Source Network'), required=False, widget=forms.Select( attrs={ 'class': 'switched', 'data-switch-on': 'srctype', 'data-srctype-srcnets': _('Source Network') })) srcpols = forms.ChoiceField( label=_('Source Network Policy'), required=False, widget=forms.Select( attrs={ 'class': 'switched', 'data-switch-on': 'srctype', 'data-srctype-srcpols': _('Source Network Policy') })) dstcidr = fields.IPField( label=_("Destination CIDR"), required=False, initial="0.0.0.0/0", help_text=_("Classless Inter-Domain Routing " "(e.g. 192.168.0.0/24)"), version=fields.IPv4, mask=True, widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'dsttype', 'data-dsttype-dstcidr': _('Destination CIDR') })) dstnets = forms.ChoiceField( label=_('Destination Network'), required=False, widget=forms.Select( attrs={ 'class': 'switched', 'data-switch-on': 'dsttype', 'data-dsttype-dstnets': _('Destination Network') })) dstpols = forms.ChoiceField( label=_('Destination Network Policy'), required=False, widget=forms.Select( attrs={ 'class': 'switched', 'data-switch-on': 'dsttype', 'data-dsttype-dstpols': _('Destination Network Policy') })) src_ports = forms.CharField(label=_("Source Ports"), required=False, help_text=_("Originating Port list i.e. " "80 or 80,443,8080,8443-8446"), initial="any") dst_ports = forms.CharField(label=_("Destination Ports"), required=False, help_text=_("Destination Port list i.e. " "80 or 80,443,8080,8443-8446"), initial="any") def __init__(self, *args, **kwargs): policy_list = kwargs.pop('policy_list', []) network_list = kwargs.pop('network_list', []) services_list = kwargs.pop('services_list', []) super(AddRule, self).__init__(*args, **kwargs) if policy_list: policy_choices = policy_list else: policy_choices = [("", _("No network policies available"))] self.fields['srcpols'].choices = policy_choices self.fields['dstpols'].choices = policy_choices if network_list: network_choices = network_list else: network_choices = [] self.fields['srcnets'].choices = network_choices self.fields['dstnets'].choices = network_choices pol_id = kwargs['initial']['id'] sequence_id_choices = [("last", "Last Rule"), ("first", "First Rule")] try: pol_obj = policy_show(self.request, policy_id=pol_id) seq_list = [] for rule in pol_obj['entries']['policy_rule']: seq_val = "after:{0}".format(rule['rule_sequence']) seq_val_lbl = "{0}".format(rule['rule_sequence']) seq_list.append((seq_val, seq_val_lbl)) sequence_id_choices.append(('After Rule', seq_list)) except: pol_obj = {} self.fields['sequence_id'].choices = sequence_id_choices def clean(self): cleaned_data = super(AddRule, self).clean() simple_action = cleaned_data.get("simple_action", None) direction = cleaned_data.get("direction", None) protocol = cleaned_data.get("protocol", None) src_ports = cleaned_data.get("src_ports", None) dst_ports = cleaned_data.get("dst_ports", None) sequence_id = cleaned_data.get("sequence_id", None) srctype = cleaned_data.get("srctype", None) dsttype = cleaned_data.get("dsttype", None) srccidr = cleaned_data.get("srccidr", None) srcnets = cleaned_data.get("srcnets", None) srcpols = cleaned_data.get("srcpols", None) dstcidr = cleaned_data.get("dstcidr", None) dstnets = cleaned_data.get("dstnets", None) dstpols = cleaned_data.get("dstpols", None) return cleaned_data def handle(self, request, data): policy_id = data['id'] src_port_list = [] if data['src_ports'] == 'any': sport = {'end_port': -1, 'start_port': -1} src_port_list.append(sport) elif len(data['src_ports']): src_port_str = data['src_ports'].split(',') for s in src_port_str: range_str = s.split('-') if len(range_str) == 2: sport = { 'end_port': int(range_str[1]), 'start_port': int(range_str[0]) } elif len(range_str) == 1: sport = { 'end_port': int(range_str[0]), 'start_port': int(range_str[0]) } src_port_list.append(sport) dst_port_list = [] if data['dst_ports'] == 'any': dport = {'end_port': -1, 'start_port': -1} dst_port_list.append(dport) elif len(data['dst_ports']): dst_port_str = data['dst_ports'].split(',') for d in dst_port_str: drange_str = d.split('-') if len(drange_str) == 2: dport = { 'end_port': int(drange_str[1]), 'start_port': int(drange_str[0]) } elif len(drange_str) == 1: dport = { 'end_port': int(drange_str[0]), 'start_port': int(drange_str[0]) } dst_port_list.append(dport) rule = { 'direction': data['direction'], 'protocol': data['protocol'], 'action_list': { 'simple_action': data['simple_action'] }, 'src_ports': src_port_list, 'dst_ports': dst_port_list, 'application': [], 'rule_sequence': { 'major': -1, 'minor': -1 } } if data['srctype'] == 'srcnets': rule['src_addresses'] = [{ 'security_group': None, 'subnet': None, 'virtual_network': data['srcnets'], 'network_policy': None }] elif data['srctype'] == 'srccidr': ip = IPNetwork(data['srccidr']) rule['src_addresses'] = [{ 'security_group': None, 'subnet': { 'ip_prefix': str(ip.ip), 'ip_prefix_len': ip.prefixlen }, 'virtual_network': None, 'network_policy': None }] elif data['srctype'] == 'srcpols': rule['src_addresses'] = [{ 'security_group': None, 'subnet': None, 'virtual_network': None, 'network_policy': data['srcpols'] }] if data['dsttype'] == 'dstnets': rule['dst_addresses'] = [{ 'security_group': None, 'subnet': None, 'virtual_network': data['dstnets'], 'network_policy': None }] elif data['dsttype'] == 'dstcidr': ip = IPNetwork(data['dstcidr']) rule['dst_addresses'] = [{ 'security_group': None, 'subnet': { 'ip_prefix': str(ip.ip), 'ip_prefix_len': ip.prefixlen }, 'virtual_network': None, 'network_policy': None }] elif data['dsttype'] == 'dstpols': rule['dst_addresses'] = [{ 'security_group': None, 'subnet': None, 'virtual_network': None, 'network_policy': data['dstpols'] }] try: policy_obj = policy_show(request, policy_id=policy_id) if not policy_obj['entries']: policy_obj['entries'] = {} policy_obj['entries']['policy_rule'] = [] if data['sequence_id'] == 'last': policy_obj['entries']['policy_rule'].append(rule) elif data['sequence_id'] == 'first': policy_obj['entries']['policy_rule'].insert(0, rule) else: seq = int(data['sequence_id'].split(':')[1]) policy_obj['entries']['policy_rule'].insert(seq, rule) policy_update_dict = policy_obj.__dict__['_apidict']['entries'] for rule in policy_update_dict['policy_rule']: rule['rule_sequence'] = {'major': -1, 'minor': -1} policy = policy_modify(request, policy_id=policy_id, entries=policy_update_dict) messages.success( request, _('Successfully added rule to policy : %s') % policy.name) return policy except: redirect = reverse("horizon:project:networks:" "policy:detail", args=[data['id']]) exceptions.handle(request, _('Unable to add rule to policy.'), redirect=redirect)
class UpdateImageForm(forms.SelfHandlingForm): image_id = forms.CharField(widget=forms.HiddenInput()) name = forms.CharField(max_length=255, label=_("Name")) description = forms.CharField(max_length=255, label=_("Description"), required=False) kernel = forms.CharField( max_length=36, label=_("Kernel ID"), required=False, widget=forms.TextInput(attrs={'readonly': 'readonly'}), ) ramdisk = forms.CharField( max_length=36, label=_("Ramdisk ID"), required=False, widget=forms.TextInput(attrs={'readonly': 'readonly'}), ) architecture = forms.CharField( label=_("Architecture"), required=False, widget=forms.TextInput(attrs={'readonly': 'readonly'}), ) disk_format = forms.ChoiceField(label=_("Format"), ) minimum_disk = forms.IntegerField(label=_("Minimum Disk (GB)"), min_value=0, help_text=_('The minimum disk size' ' required to boot the' ' image. If unspecified,' ' this value defaults to' ' 0 (no minimum).'), required=False) minimum_ram = forms.IntegerField(label=_("Minimum RAM (MB)"), min_value=0, help_text=_('The minimum memory size' ' required to boot the' ' image. If unspecified,' ' this value defaults to' ' 0 (no minimum).'), required=False) public = forms.BooleanField(label=_("Public"), required=False) protected = forms.BooleanField(label=_("Protected"), required=False) def __init__(self, request, *args, **kwargs): super(UpdateImageForm, self).__init__(request, *args, **kwargs) self.fields['disk_format'].choices = [ (value, name) for value, name in IMAGE_FORMAT_CHOICES if value ] if not policy.check((("image", "publicize_image"), ), request): self.fields['public'].widget = forms.CheckboxInput( attrs={'readonly': 'readonly'}) def handle(self, request, data): image_id = data['image_id'] error_updating = _('Unable to update image "%s".') if data['disk_format'] in ['aki', 'ari', 'ami']: container_format = data['disk_format'] else: container_format = 'bare' meta = { 'is_public': data['public'], 'protected': data['protected'], 'disk_format': data['disk_format'], 'container_format': container_format, 'name': data['name'], 'min_ram': (data['minimum_ram'] or 0), 'min_disk': (data['minimum_disk'] or 0), 'properties': { 'description': data['description'] } } if data.get('kernel'): meta['properties']['kernel_id'] = data['kernel'] if data.get('ramdisk'): meta['properties']['ramdisk_id'] = data['ramdisk'] if data.get('architecture'): meta['properties']['architecture'] = data['architecture'] # Ensure we do not delete properties that have already been # set on an image. meta['purge_props'] = False try: image = api.glance.image_update(request, image_id, **meta) messages.success(request, _('Image was successfully updated.')) return image except Exception: exceptions.handle(request, error_updating % image_id)
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.'))