class UpdatePort(project_forms.UpdatePort): # tenant_id = forms.CharField(widget=forms.HiddenInput()) device_id = forms.CharField(max_length=100, label=_("Device ID"), help_text=_("Device ID attached to the port"), required=False) device_owner = forms.CharField(max_length=100, label=_("Device Owner"), help_text=_("Device owner attached to the " "port"), required=False) binding__host_id = forms.CharField( label=_("Binding: Host"), help_text=_("The ID of the host where the port is allocated. In some " "cases, different implementations can run on different " "hosts."), required=False) mac_address = forms.MACAddressField( label=_("MAC Address"), required=False, help_text=_("Specify a new MAC address for the port")) failure_url = 'horizon:admin:networks:detail' def handle(self, request, data): try: LOG.debug('params = %s', data) extension_kwargs = {} data['admin_state'] = (data['admin_state'] == 'True') if 'binding__vnic_type' in data: extension_kwargs['binding__vnic_type'] = \ data['binding__vnic_type'] if 'mac_state' in data: extension_kwargs['mac_learning_enabled'] = data['mac_state'] if 'port_security_enabled' in data: extension_kwargs['port_security_enabled'] = \ data['port_security_enabled'] port = api.neutron.port_update( request, data['port_id'], name=data['name'], admin_state_up=data['admin_state'], device_id=data['device_id'], device_owner=data['device_owner'], binding__host_id=data['binding__host_id'], mac_address=data['mac_address'], **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 UpdatePortInfoAction(project_workflow.UpdatePortInfoAction): device_id = forms.CharField(max_length=100, label=_("Device ID"), required=False) device_owner = forms.CharField(max_length=100, label=_("Device Owner"), required=False) binding__host_id = forms.CharField(label=_("Binding: Host"), required=False) mac_address = forms.MACAddressField(label=_("MAC Address"), required=False) class Meta(object): name = _("Info") help_text_template = 'admin/networks/ports/_edit_port_help.html'
def test_mac_address_validator(self): GOOD_MAC_ADDRESSES = ( "00:11:88:99:Aa:Ff", "00-11-88-99-Aa-Ff", "0011.8899.AaFf", "00118899AaFf", ) BAD_MAC_ADDRESSES = ( "not a mac", "11:22:33:44:55", "zz:11:22:33:44:55", ) field = forms.MACAddressField() for input in GOOD_MAC_ADDRESSES: self.assertIsNone(field.validate(input)) for input in BAD_MAC_ADDRESSES: self.assertRaises(ValidationError, field.validate, input)
class AddAllowedAddressPairForm(forms.SelfHandlingForm): ip = forms.IPField(label=_("IP Address or CIDR"), help_text=_("A single IP Address or CIDR"), version=forms.IPv4 | forms.IPv6, mask=True) mac = forms.MACAddressField(label=_("MAC Address"), help_text=_("A valid MAC Address"), required=False) failure_url = 'horizon:project:networks:ports:detail' def clean(self): cleaned_data = super(AddAllowedAddressPairForm, self).clean() if '/' not in self.data['ip']: cleaned_data['ip'] = self.data['ip'] return cleaned_data def handle(self, request, data): port_id = self.initial['port_id'] try: port = api.neutron.port_get(request, port_id) current = port.get('allowed_address_pairs', []) current = [pair.to_dict() for pair in current] pair = {'ip_address': data['ip']} if data['mac']: pair['mac_address'] = data['mac'] current.append(pair) port = api.neutron.port_update(request, port_id, allowed_address_pairs=current) msg = _('Port %s was successfully updated.') % port_id messages.success(request, msg) return port except Exception as e: LOG.error('Failed to update port %(port_id)s: %(reason)s', { 'port_id': port_id, 'reason': e }) msg = _('Failed to update port "%s".') % port_id args = (self.initial.get('port_id'), ) redirect = reverse(self.failure_url, args=args) exceptions.handle(request, msg, redirect=redirect) return False
class UpdatePortInfoAction(project_workflow.UpdatePortInfoAction): device_id = forms.CharField(max_length=100, label=_("Device ID"), help_text=_("Device ID attached to the port"), required=False) device_owner = forms.CharField( max_length=100, label=_("Device Owner"), help_text=_("Device owner attached to the port"), required=False) binding__host_id = forms.CharField( label=_("Binding: Host"), help_text=_("The ID of the host where the port is allocated. In some " "cases, different implementations can run on different " "hosts."), required=False) mac_address = forms.MACAddressField( label=_("MAC Address"), required=False, help_text=_("MAC address for the port")) class Meta(object): name = _("Info")
class AddHostInfoAction(workflows.Action): FIELD_LABEL_PERSONALITY = _("Personality") FIELD_LABEL_HOSTNAME = _("Host Name") FIELD_LABEL_MGMT_MAC = _("Management MAC Address") FIELD_LABEL_MGMT_IP = _("Management IP Address") personality = forms.ChoiceField( label=FIELD_LABEL_PERSONALITY, help_text=_("Host Personality"), choices=PERSONALITY_CHOICES, widget=forms.Select(attrs={ 'class': 'switchable', 'data-slug': 'personality' })) subfunctions = forms.ChoiceField( label=FIELD_LABEL_PERFORMANCE_PROFILE, choices=PERFORMANCE_CHOICES, widget=forms.Select( attrs={ 'class': 'switched', 'data-switch-on': 'personality', 'data-personality-' + stx_api.sysinv.PERSONALITY_WORKER: _("Personality Sub-Type") })) hostname = forms.RegexField( label=FIELD_LABEL_HOSTNAME, max_length=255, required=False, regex=r'^[\w\.\-]+$', error_messages={ 'invalid': _('Name may only contain letters,' ' numbers, underscores, ' 'periods and hyphens.') }, widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'personality', 'data-personality-' + stx_api.sysinv.PERSONALITY_WORKER: FIELD_LABEL_HOSTNAME, })) mgmt_mac = forms.MACAddressField( label=FIELD_LABEL_MGMT_MAC, widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'personality', 'data-personality-' + stx_api.sysinv.PERSONALITY_WORKER: FIELD_LABEL_MGMT_MAC, 'data-personality-' + stx_api.sysinv.PERSONALITY_CONTROLLER: FIELD_LABEL_MGMT_MAC, 'data-personality-' + stx_api.sysinv.PERSONALITY_STORAGE: FIELD_LABEL_MGMT_MAC, })) class Meta(object): name = _("Host Info") help_text = _( "From here you can add the configuration for a new host.") def __init__(self, request, *arg, **kwargs): super(AddHostInfoAction, self).__init__(request, *arg, **kwargs) # pesonality cannot be storage if ceph is not configured storage_backend = stx_api.sysinv.get_storage_backend(request) if stx_api.sysinv.STORAGE_BACKEND_CEPH not in storage_backend: self.fields['personality'].choices = \ PERSONALITY_CHOICES_WITHOUT_STORAGE # All-in-one system, personality can be controller or worker. systems = stx_api.sysinv.system_list(request) system_type = systems[0].to_dict().get('system_type') if system_type == constants.TS_AIO: self.fields['personality'].choices = \ PERSONALITY_CHOICES_WITHOUT_STORAGE # Remove worker personality if in DC mode and region if getattr(self.request.user, 'services_region', None) == 'RegionOne' \ and getattr(settings, 'DC_MODE', False): self.fields['personality'].choices = \ [choice for choice in self.fields['personality'].choices if choice[0] != stx_api.sysinv.PERSONALITY_WORKER] def clean(self): cleaned_data = super(AddHostInfoAction, self).clean() return cleaned_data
class CreatePort(forms.SelfHandlingForm): network_name = forms.CharField( label=_("Network Name"), widget=forms.TextInput(attrs={'readonly': 'readonly'}), required=False) network_id = forms.CharField( label=_("Network 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"), initial=True, required=False) device_id = forms.CharField(max_length=100, label=_("Device ID"), help_text=_("Device ID attached to the port"), required=False) device_owner = forms.CharField( max_length=100, label=_("Device Owner"), help_text=_("Owner of the device attached to the port"), required=False) specify_ip = forms.ThemableChoiceField( label=_("Specify IP address or subnet"), help_text=_("To specify a subnet or a fixed IP, select any options."), initial=False, required=False, choices=[('', _("Unspecified")), ('subnet_id', _("Subnet")), ('fixed_ip', _("Fixed IP Address"))], widget=forms.ThemableSelectWidget(attrs={ 'class': 'switchable', 'data-slug': 'specify_ip', })) subnet_id = forms.ThemableChoiceField( label=_("Subnet"), required=False, widget=forms.ThemableSelectWidget( attrs={ 'class': 'switched', 'data-switch-on': 'specify_ip', 'data-specify_ip-subnet_id': _('Subnet'), })) fixed_ip = forms.IPField( label=_("Fixed IP Address"), required=False, help_text=_("Specify the subnet IP address for the new port"), version=forms.IPv4 | forms.IPv6, widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'specify_ip', 'data-specify_ip-fixed_ip': _('Fixed IP Address'), })) mac_address = forms.MACAddressField( label=_("MAC Address"), required=False, help_text=_("Specify the MAC address for the new port")) failure_url = 'horizon:project:networks:detail' def __init__(self, request, *args, **kwargs): super(CreatePort, self).__init__(request, *args, **kwargs) # prepare subnet choices and input area for each subnet subnet_choices = self._get_subnet_choices(kwargs['initial']) if subnet_choices: subnet_choices.insert(0, ('', _("Select a subnet"))) self.fields['subnet_id'].choices = subnet_choices else: self.fields['specify_ip'].widget = forms.HiddenInput() self.fields['subnet_id'].widget = forms.HiddenInput() self.fields['fixed_ip'].widget = forms.HiddenInput() if api.neutron.is_extension_supported(request, 'mac-learning'): self.fields['mac_state'] = forms.BooleanField( label=_("MAC Learning State"), initial=False, required=False) try: if api.neutron.is_extension_supported(request, 'port-security'): self.fields['port_security_enabled'] = forms.BooleanField( label=_("Port Security"), help_text=_("Enable anti-spoofing rules for the port"), initial=True, required=False) except Exception: msg = _("Unable to retrieve port security state") exceptions.handle(self.request, msg) def _get_subnet_choices(self, kwargs): try: network_id = kwargs['network_id'] network = api.neutron.network_get(self.request, network_id) except Exception: return [] return [(subnet.id, '%s %s' % (subnet.name_or_id, subnet.cidr)) for subnet in network.subnets] def handle(self, request, data): try: params = { 'network_id': data['network_id'], 'admin_state_up': data['admin_state'], 'name': data['name'], 'device_id': data['device_id'], 'device_owner': data['device_owner'] } if data.get('specify_ip') == 'subnet_id': if data.get('subnet_id'): params['fixed_ips'] = [{"subnet_id": data['subnet_id']}] elif data.get('specify_ip') == 'fixed_ip': if data.get('fixed_ip'): params['fixed_ips'] = [{"ip_address": data['fixed_ip']}] if data.get('mac_state'): params['mac_learning_enabled'] = data['mac_state'] if 'port_security_enabled' in data: params['port_security_enabled'] = data['port_security_enabled'] # Send mac_address only when it is specified. if data['mac_address']: params['mac_address'] = data['mac_address'] port = api.neutron.port_create(request, **params) if port['name']: msg = _('Port %s was successfully created.') % port['name'] else: msg = _('Port %s was successfully created.') % port['id'] LOG.debug(msg) messages.success(request, msg) return port except Exception: msg = _('Failed to create a port for network %s') \ % data['network_id'] LOG.info(msg) redirect = reverse(self.failure_url, args=(data['network_id'], )) exceptions.handle(request, msg, redirect=redirect)
def test_mac_address_normal_form(self): field = forms.MACAddressField() field.validate("00-11-88-99-Aa-Ff") self.assertEqual(field.mac_address, "00:11:88:99:aa:ff")
class CreatePortInfoAction(workflows.Action): name = forms.CharField(max_length=255, label=_("Name"), required=False) admin_state = forms.BooleanField(label=_("Enable Admin State"), initial=True, required=False) device_id = forms.CharField(max_length=100, label=_("Device ID"), help_text=_("Device ID attached to the port"), required=False) device_owner = forms.CharField( max_length=100, label=_("Device Owner"), help_text=_("Owner of the device attached to the port"), required=False) specify_ip = forms.ThemableChoiceField( label=_("Specify IP address or subnet"), help_text=_("To specify a subnet or a fixed IP, select any options."), required=False, choices=[('', _("Unspecified")), ('subnet_id', _("Subnet")), ('fixed_ip', _("Fixed IP Address"))], widget=forms.ThemableSelectWidget(attrs={ 'class': 'switchable', 'data-slug': 'specify_ip', })) subnet_id = forms.ThemableChoiceField( label=_("Subnet"), required=False, widget=forms.ThemableSelectWidget( attrs={ 'class': 'switched', 'data-switch-on': 'specify_ip', 'data-specify_ip-subnet_id': _('Subnet'), })) fixed_ip = forms.IPField( label=_("Fixed IP Address"), required=False, help_text=_("Specify the subnet IP address for the new port"), version=forms.IPv4 | forms.IPv6, widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'specify_ip', 'data-specify_ip-fixed_ip': _('Fixed IP Address'), })) mac_address = forms.MACAddressField( label=_("MAC Address"), required=False, help_text=_("Specify the MAC address for the new port")) mac_state = forms.BooleanField(label=_("MAC Learning State"), initial=False, required=False) port_security_enabled = forms.BooleanField( label=_("Port Security"), help_text=_("Enable anti-spoofing rules for the port"), initial=True, required=False, widget=forms.CheckboxInput( attrs={ 'class': 'switchable', 'data-slug': 'port_security_enabled', 'data-hide-tab': 'create_port__create_security_groups', 'data-hide-on-checked': 'false' })) binding__vnic_type = forms.ThemableChoiceField( label=_("VNIC Type"), help_text=_("The VNIC type that is bound to the network port"), required=False) def __init__(self, request, context, *args, **kwargs): super(CreatePortInfoAction, self).__init__(request, context, *args, **kwargs) # prepare subnet choices and input area for each subnet subnet_choices = self._get_subnet_choices(context) if subnet_choices: subnet_choices.insert(0, ('', _("Select a subnet"))) self.fields['subnet_id'].choices = subnet_choices else: self.fields['specify_ip'].widget = forms.HiddenInput() self.fields['subnet_id'].widget = forms.HiddenInput() self.fields['fixed_ip'].widget = forms.HiddenInput() self._hide_field_if_not_supported( request, 'mac_state', 'mac-learning', _("Unable to retrieve MAC learning state")) self._hide_field_if_not_supported( request, 'port_security_enabled', 'port-security', _("Unable to retrieve port security state")) self._populate_vnic_type_choices(request) def _hide_field_if_not_supported(self, request, field, extension_alias, failure_message): is_supproted = False try: is_supproted = api.neutron.is_extension_supported( request, extension_alias) except Exception: exceptions.handle(self.request, failure_message) if not is_supproted: del self.fields[field] return is_supproted def _populate_vnic_type_choices(self, request): neutron_settings = getattr(settings, 'OPENSTACK_NEUTRON_NETWORK', {}) supported_vnic_types = neutron_settings.get('supported_vnic_types', ['*']) # When a list of VNIC types is empty, hide the corresponding field. if not supported_vnic_types: del self.fields['binding__vnic_type'] return binding_supported = self._hide_field_if_not_supported( request, 'binding__vnic_type', 'binding', _("Unable to verify the VNIC types extension in Neutron")) if not binding_supported: # binding__vnic_type field is already deleted, so return here return if supported_vnic_types == ['*']: vnic_type_choices = api.neutron.VNIC_TYPES else: vnic_type_choices = [ vnic_type for vnic_type in api.neutron.VNIC_TYPES if vnic_type[0] in supported_vnic_types ] self.fields['binding__vnic_type'].choices = vnic_type_choices def _get_subnet_choices(self, context): try: network_id = context['network_id'] network = api.neutron.network_get(self.request, network_id) except Exception: return [] # NOTE(amotoki): When a user cannot retrieve a subnet info, # subnet ID is stored in network.subnets field. # If so, we skip such subnet as subnet choices. # This happens usually for external networks. # TODO(amotoki): Ideally it is better to disable/hide # Create Port button in the port table, but as of Pike # the default neutron policy.json for "create_port" is empty # and there seems no appropriate policy. This is a dirty hack. return [(subnet.id, '%s %s' % (subnet.name_or_id, subnet.cidr)) for subnet in network.subnets if isinstance(subnet, api.neutron.Subnet)] class Meta(object): name = _("Info") slug = 'create_info' help_text_template = 'project/networks/ports/_create_port_help.html'
class CreatePort(forms.SelfHandlingForm): network_name = forms.CharField( label=_("Network Name"), widget=forms.TextInput(attrs={'readonly': 'readonly'}), required=False) network_id = forms.CharField( label=_("Network ID"), widget=forms.TextInput(attrs={'readonly': 'readonly'})) name = forms.CharField(max_length=255, label=_("Name"), required=False) admin_state = forms.ChoiceField(choices=[(True, _('UP')), (False, _('DOWN'))], label=_("Admin State")) device_id = forms.ChoiceField( label=_("Device ID"), help_text=_("Device ID attached to the port"), required=False) device_owner = forms.CharField(max_length=100, label=_("Device Owner"), help_text=_("Device owner attached to the " "port"), required=False) tenant_id = forms.ChoiceField( label=_("Tenant ID"), required=True, help_text=_("Tenant ID"), ) """add by hades 2018-8-21""" """Aim t attach QoS policy ID or name to the port""" qos_policy_id = forms.ChoiceField( label=_("Qos Policy"), required=False, help_text=_("Qos Policy"), ) mac_address = forms.MACAddressField( label=_("MAC Address"), required=False, help_text=_("Specify the MAC address for the new port")) fixed_ip = forms.IPField( label=_("Fixed IP Address"), required=False, help_text=_("Specify the subnet IP address for the new port"), version=forms.IPv4 | forms.IPv6, ) binding__host_id = forms.CharField( label=_("Binding: Host"), help_text=_("The ID of the host where the port is allocated. In some " "cases, different implementations can run on different " "hosts."), required=False) failure_url = 'horizon:admin:networks:detail' def __init__(self, request, *args, **kwargs): super(CreatePort, self).__init__(request, *args, **kwargs) 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) if api.neutron.is_extension_supported(request, 'mac-learning'): self.fields['mac_state'] = forms.BooleanField( label=_("MAC Learning State"), initial=False, required=False) tenants = instance_utils.tenant_field_data(request) self.fields['tenant_id'].choices = tenants qos_choices = [('', _("Select a project"))] qos = api.neutron.policy_list(request) for q in qos: qos_choices.append((q.id, q.name)) self.fields['qos_policy_id'].choices = qos_choices device_choices = [('', _("Select a project"))] devices = api.nova.server_list(request, all_tenants=True)[0] for dev in devices: device_choices.append((dev.id, dev.name)) self.fields['device_id'].choices = device_choices def handle(self, request, data): try: # We must specify tenant_id of the network which a subnet is # created for if admin user does not belong to the tenant. network = api.neutron.network_get(request, data['network_id']) # data['tenant_id'] = network.tenant_id if data['tenant_id'] == 'null': data['tenant_id'] = network.tenant_id data['admin_state_up'] = (data['admin_state'] == 'True') del data['network_name'] del data['admin_state'] if data['qos_policy_id'] == '': del data['qos_policy_id'] if data['fixed_ip']: data['fixed_ips'] = [{'ip_address': data['fixed_ip']}] del data['fixed_ip'] else: del data['fixed_ip'] if data['mac_address']: pass else: del data['mac_address'] if 'mac_state' in data: data['mac_learning_enabled'] = data['mac_state'] del data['mac_state'] port = api.neutron.port_create(request, **data) msg = _('Port %s was successfully created.') % port['id'] LOG.debug(msg) messages.success(request, msg) return port except Exception: msg = _('Failed to create a port for network %s') \ % data['network_id'] LOG.info(msg) redirect = reverse(self.failure_url, args=(data['network_id'], )) exceptions.handle(request, msg, redirect=redirect)
class CreatePort(forms.SelfHandlingForm): name = forms.CharField(max_length=255, label=_("Name"), required=False) admin_state = forms.BooleanField(label=_("Enable Admin State"), initial=True, required=False) device_id = forms.CharField(max_length=100, label=_("Device ID"), help_text=_("Device ID attached to the port"), required=False) device_owner = forms.CharField( max_length=100, label=_("Device Owner"), help_text=_("Owner of the device attached to the port"), required=False) specify_ip = forms.ThemableChoiceField( label=_("Specify IP address or subnet"), help_text=_("To specify a subnet or a fixed IP, select any options."), required=False, choices=[('', _("Unspecified")), ('subnet_id', _("Subnet")), ('fixed_ip', _("Fixed IP Address"))], widget=forms.ThemableSelectWidget(attrs={ 'class': 'switchable', 'data-slug': 'specify_ip', })) subnet_id = forms.ThemableChoiceField( label=_("Subnet"), required=False, widget=forms.ThemableSelectWidget( attrs={ 'class': 'switched', 'data-switch-on': 'specify_ip', 'data-specify_ip-subnet_id': _('Subnet'), })) fixed_ip = forms.IPField( label=_("Fixed IP Address"), required=False, help_text=_("Specify the subnet IP address for the new port"), version=forms.IPv4 | forms.IPv6, widget=forms.TextInput( attrs={ 'class': 'switched', 'data-switch-on': 'specify_ip', 'data-specify_ip-fixed_ip': _('Fixed IP Address'), })) mac_address = forms.MACAddressField( label=_("MAC Address"), required=False, help_text=_("Specify the MAC address for the new port")) failure_url = 'horizon:project:networks:detail' def __init__(self, request, *args, **kwargs): super(CreatePort, self).__init__(request, *args, **kwargs) # prepare subnet choices and input area for each subnet subnet_choices = self._get_subnet_choices(kwargs['initial']) if subnet_choices: subnet_choices.insert(0, ('', _("Select a subnet"))) self.fields['subnet_id'].choices = subnet_choices else: self.fields['specify_ip'].widget = forms.HiddenInput() self.fields['subnet_id'].widget = forms.HiddenInput() self.fields['fixed_ip'].widget = forms.HiddenInput() if api.neutron.is_extension_supported(request, 'mac-learning'): self.fields['mac_state'] = forms.BooleanField( label=_("MAC Learning State"), initial=False, required=False) try: if api.neutron.is_extension_supported(request, 'port-security'): self.fields['port_security_enabled'] = forms.BooleanField( label=_("Port Security"), help_text=_("Enable anti-spoofing rules for the port"), initial=True, required=False) except Exception: msg = _("Unable to retrieve port security state") exceptions.handle(self.request, msg) def _get_subnet_choices(self, kwargs): try: network_id = kwargs['network_id'] network = api.neutron.network_get(self.request, network_id) except Exception: return [] # NOTE(amotoki): When a user cannot retrieve a subnet info, # subnet ID is stored in network.subnets field. # If so, we skip such subnet as subnet choices. # This happens usually for external networks. # TODO(amotoki): Ideally it is better to disable/hide # Create Port button in the port table, but as of Pike # the default neutron policy.json for "create_port" is empty # and there seems no appropriate policy. This is a dirty hack. return [(subnet.id, '%s %s' % (subnet.name_or_id, subnet.cidr)) for subnet in network.subnets if isinstance(subnet, api.neutron.Subnet)] def handle(self, request, data): try: params = { 'network_id': self.initial['network_id'], 'admin_state_up': data['admin_state'], 'name': data['name'], 'device_id': data['device_id'], 'device_owner': data['device_owner'] } if data.get('specify_ip') == 'subnet_id': if data.get('subnet_id'): params['fixed_ips'] = [{"subnet_id": data['subnet_id']}] elif data.get('specify_ip') == 'fixed_ip': if data.get('fixed_ip'): params['fixed_ips'] = [{"ip_address": data['fixed_ip']}] if data.get('mac_state'): params['mac_learning_enabled'] = data['mac_state'] if 'port_security_enabled' in data: params['port_security_enabled'] = data['port_security_enabled'] # Send mac_address only when it is specified. if data['mac_address']: params['mac_address'] = data['mac_address'] port = api.neutron.port_create(request, **params) if port['name']: msg = _('Port %s was successfully created.') % port['name'] else: msg = _('Port %s was successfully created.') % port['id'] messages.success(request, msg) return port except Exception as e: LOG.info('Failed to create a port for network %(id)s: %(exc)s', { 'id': self.initial['network_id'], 'exc': e }) if isinstance(e, neutron_exc.Forbidden): msg = (_('You are not allowed to create a port ' 'for network %s.') % self.initial['network_id']) else: msg = (_('Failed to create a port for network %s') % self.initial['network_id']) redirect = reverse(self.failure_url, args=(self.initial['network_id'], )) exceptions.handle(request, msg, redirect=redirect)