Esempio n. 1
0
class OrganizationForm(forms.ModelForm):
    """Form for editing an organization"""
    parent = forms.ChoiceField(required=False)
    data = HStoreField(label='Attributes', required=False)

    class Meta(object):
        model = Organization
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        super(OrganizationForm, self).__init__(*args, **kwargs)
        field = self.fields['parent']
        field.choices = create_hierarchy(Organization)

        if self.instance.id:
            # disallow editing the primary key of existing record
            del self.fields['id']
            # remove self and all descendants from list of selectable parents
            field.choices = cut_branch(field, Organization, self.instance.id)

    def clean_parent(self):
        """Provide a model as the parent.

        This is needed because we use a normal ChoiceField (because of the tree
        structure) that does not provide a model instance when selected.
        """
        parent = self.cleaned_data.get('parent')
        if parent:
            return Organization.objects.get(pk=parent)
        else:
            # Explicitly return None because no parent is an empty string and
            # thus we need to return None, not the empty string
            return None
Esempio n. 2
0
class RoomForm(forms.ModelForm):
    """Form for editing/adding rooms"""
    location = forms.ChoiceField(choices=())
    data = HStoreField(label='Attributes', required=False)

    def __init__(self, *args, **kwargs):
        super(RoomForm, self).__init__(*args, **kwargs)
        self.fields['location'].choices = create_hierarchy(Location)
        if self.instance and self.instance.pk:
            self.fields['id'].widget.attrs['readonly'] = True

    class Meta(object):
        model = Room
        fields = '__all__'

    def clean_location(self):
        data = self.cleaned_data.get('location')
        return Location.objects.get(pk=data)
Esempio n. 3
0
class NetboxModelForm(forms.ModelForm):
    """Modelform for netbox for use in SeedDB"""
    ip = forms.CharField()
    function = forms.CharField(required=False)
    data = HStoreField(label='Attributes', required=False)
    sysname = forms.CharField(required=False)
    virtual_instance = MyModelMultipleChoiceField(
        queryset=Netbox.objects.none(), required=False,
        label='Virtual instances',
        help_text='The list of virtual instances inside this master device')

    class Meta(object):
        model = Netbox
        fields = ['ip', 'room', 'category', 'organization',
                  'groups', 'sysname', 'type', 'data', 'master',
                  'virtual_instance', 'profiles']
        help_texts = {
            'master': 'Select a master device when this IP Device is a virtual'
                      ' instance'
        }

    def __init__(self, *args, **kwargs):
        super(NetboxModelForm, self).__init__(*args, **kwargs)
        self.fields['organization'].choices = create_hierarchy(Organization)

        # Master and instance related queries
        masters = [n.master.pk for n in
                   Netbox.objects.filter(master__isnull=False)]
        self.fields['master'].queryset = self.create_master_query(masters)
        self.fields['virtual_instance'].queryset = self.create_instance_query(masters)

        if self.instance.pk:
            # Set instances that we are master to as initial values
            self.initial['virtual_instance'] = Netbox.objects.filter(
                master=self.instance)

            # Disable fields based on current state
            if self.instance.master:
                self.fields['virtual_instance'].widget.attrs['disabled'] = True
            if self.instance.pk in masters:
                self.fields['master'].widget.attrs['disabled'] = True

            # Set the inital value of the function field
            try:
                netboxinfo = self.instance.info_set.get(variable='function')
            except NetboxInfo.DoesNotExist:
                pass
            else:
                self.fields['function'].initial = netboxinfo.value

        css_class = 'large-4'
        self.helper = FormHelper()
        self.helper.form_action = ''
        self.helper.form_method = 'POST'
        self.helper.form_id = 'seeddb-netbox-form'
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Row(
                Column(
                    Fieldset('Inventory',
                             'ip',
                             Div(id='verify-address-feedback'),
                             'room', 'category', 'organization'),
                    css_class=css_class),
                Column(
                    Fieldset('Management profiles',
                             Field('profiles', css_class='select2'),
                             NavButton('check_connectivity',
                                       'Check connectivity',
                                       css_class='check_connectivity')),
                    Fieldset('Collected info',
                             Div('sysname', 'type',
                                 css_class='hide',
                                 css_id='real_collected_fields')),
                    css_class=css_class),
                Column(
                    Fieldset(
                        'Meta information',
                        'function',
                        Field('groups', css_class='select2'),
                        'data',
                        HTML("<a class='advanced-toggle'><i class='fa fa-caret-square-o-right'>&nbsp;</i>Advanced options</a>"),
                        Div(
                            HTML('<small class="alert-box">NB: An IP Device cannot both have a master and have virtual instances</small>'),
                            'master', 'virtual_instance',
                            css_class='advanced'
                        )
                    ),
                    css_class=css_class),
            ),
        )

    def create_instance_query(self, masters):
        """Creates query for virtual instance multiselect"""
        # - Should not see other masters
        # - Should see those we are master for
        # - Should see those who have no master
        queryset = Netbox.objects.exclude(pk__in=masters).filter(
            Q(master=self.instance.pk) | Q(master__isnull=True))

        if self.instance.pk:
            queryset = queryset.exclude(pk=self.instance.pk)

        return queryset

    def create_master_query(self, masters):
        """Creates query for master dropdown list"""
        # - Should not set those who have master as master
        queryset = Netbox.objects.filter(master__isnull=True)
        if self.instance.pk:
            queryset = queryset.exclude(pk=self.instance.pk)

        return queryset

    def clean_ip(self):
        """Make sure IP-address is valid"""
        name = self.cleaned_data['ip'].strip()
        try:
            ip, _ = resolve_ip_and_sysname(name)
        except SocketError:
            raise forms.ValidationError("Could not resolve name %s" % name)
        return six.text_type(ip)

    def clean_sysname(self):
        """Resolve sysname if not set"""
        sysname = self.cleaned_data.get('sysname')
        ip = self.cleaned_data.get('ip')
        if ip and not sysname:
            _, sysname = resolve_ip_and_sysname(ip)
        return sysname

    def clean(self):
        """Make sure that categories that require communities has that"""
        cleaned_data = self.cleaned_data
        ip = cleaned_data.get('ip')
        cat = cleaned_data.get('category')
        profiles = cleaned_data.get('profiles')
        _logger.warning("cleaning profiles: %r", profiles)

        if ip:
            try:
                self._check_existing_ip(ip)
            except IPExistsException as error:
                self._errors['ip'] = self.error_class(error.message_list)
                del cleaned_data['ip']

        if cat and cat.req_mgmt and not profiles:
            self._errors['profiles'] = self.error_class(
                ["Category %s requires a management profile." % cat.id])
            del cleaned_data['profiles']

        return cleaned_data

    def _check_existing_ip(self, ip):
        msg = []
        _, sysname = resolve_ip_and_sysname(ip)
        if does_ip_exist(ip, self.instance.pk):
            msg.append("IP (%s) is already in database" % ip)
        if does_sysname_exist(sysname, self.instance.pk):
            msg.append("Sysname (%s) is already in database" % sysname)
        if msg:
            raise IPExistsException(msg)

    def save(self, commit=True):
        netbox = super(NetboxModelForm, self).save(commit)
        instances = self.cleaned_data.get('virtual_instance')

        # Clean up instances
        Netbox.objects.filter(
            master=netbox).exclude(pk__in=instances).update(master=None)

        # Add new instances
        for instance in instances:
            instance.master = netbox
            instance.save()

        return netbox