示例#1
0
class IPMIForm(Form):
    # Max password length via IPMI v2.0 is 20 chars. We only support IPMI
    # v2.0+ compliant boards thus far.
    ipmi_password1 = forms.CharField(label=_("Password"),
                                     max_length=20,
                                     widget=forms.PasswordInput,
                                     required=False)
    ipmi_password2 = forms.CharField(
        label=_("Password confirmation"),
        max_length=20,
        widget=forms.PasswordInput,
        help_text=_("Enter the same password as above, for verification."),
        required=False)
    dhcp = forms.BooleanField(
        label=_("DHCP"),
        required=False,
    )
    ipv4address = IP4AddressFormField(
        initial='',
        required=False,
        label=_("IPv4 Address"),
    )
    ipv4netmaskbit = forms.ChoiceField(
        choices=choices.v4NetmaskBitList,
        required=False,
        label=_("IPv4 Netmask"),
    )
    ipv4gw = IP4AddressFormField(
        initial='',
        required=False,
        label=_("IPv4 Default Gateway"),
    )
    vlanid = forms.IntegerField(
        label=_("VLAN ID"),
        required=False,
        widget=forms.widgets.TextInput(),
    )

    def __init__(self, *args, **kwargs):
        super(IPMIForm, self).__init__(*args, **kwargs)
        self.fields['dhcp'].widget.attrs['onChange'] = (
            'javascript:toggleGeneric('
            '"id_dhcp", ["id_ipv4address", "id_ipv4netmaskbit"]);')

        channels = []
        _n = notifier()
        for i in range(1, 17):
            try:
                data = _n.ipmi_get_lan(channel=i)
            except:
                continue

            if not data:
                continue

            channels.append((i, i))

        self.fields['channel'] = forms.ChoiceField(
            choices=channels,
            label=_('Channel'),
        )
        self.fields.keyOrder.remove('channel')
        self.fields.keyOrder.insert(0, 'channel')

    def clean_ipmi_password2(self):
        ipmi_password1 = self.cleaned_data.get("ipmi_password1", "")
        ipmi_password2 = self.cleaned_data["ipmi_password2"]
        if ipmi_password1 != ipmi_password2:
            raise forms.ValidationError(
                _("The two password fields didn't match."))
        return ipmi_password2

    def clean_ipv4netmaskbit(self):
        try:
            cidr = int(self.cleaned_data.get("ipv4netmaskbit"))
        except ValueError:
            return None
        bits = 0xffffffff ^ (1 << 32 - cidr) - 1
        return socket.inet_ntoa(pack('>I', bits))

    def clean_ipv4address(self):
        ipv4 = self.cleaned_data.get('ipv4address')
        if ipv4:
            ipv4 = str(ipv4)
        return ipv4

    def clean_ipv4gw(self):
        ipv4 = self.cleaned_data.get('ipv4gw')
        if ipv4:
            ipv4 = str(ipv4)
        return ipv4
示例#2
0
class DeviceForm(ModelForm):

    CDROM_path = PathField(
        label=_('CD-ROM (ISO)'),
        required=False,
        dirsonly=False,
    )
    DISK_zvol = forms.ChoiceField(
        label=_('ZVol'),
        required=False,
    )
    DISK_mode = forms.ChoiceField(
        label=_('Mode'),
        choices=choices.VM_DISKMODETYPES,
        required=False,
        initial='AHCI',
    )
    DISK_raw = PathField(
        label=_('Raw File'),
        required=False,
        dirsonly=False,
    )
    DISK_sectorsize = forms.IntegerField(
        label=_('Disk sectorsize'),
        required=False,
        initial=0,
        help_text=_("Logical and physical sector size in bytes of the emulated disk."
                    "If 0, a sector size is not set."),
    )
    NIC_type = forms.ChoiceField(
        label=_('Adapter Type'),
        choices=choices.VM_NICTYPES,
        required=False,
        initial='E1000',
    )
    NIC_attach = forms.ChoiceField(
        label=_('Nic to attach'),
        choices=choices.NICChoices(exclude_configured=False),
        required=False,
    )
    NIC_mac = forms.CharField(
        label=_('Mac Address'),
        required=False,
        help_text=_("You can specify the adapter MAC Address or let it be auto generated."),
        validators=[RegexValidator("^([0-9a-fA-F]{2}([::]?|$)){6}$", "Invalid MAC format.")],
        initial='00:a0:98:FF:FF:FF',
    )
    VNC_resolution = forms.ChoiceField(
        label=_('Resolution'),
        choices=choices.VNC_RESOLUTION,
        required=False,
        initial='1024x768',
    )
    VNC_port = forms.CharField(
        label=_('VNC port'),
        required=False,
        help_text=_("You can specify the VNC port or 0 for auto."),
        validators=[RegexValidator("^[0-9]*$", "Only integer is accepted")],
        initial=0,
    )
    VNC_bind = forms.ChoiceField(
        label=_('Bind to'),
        choices=(),
        required=False,
        initial='0.0.0.0'
    )
    VNC_wait = forms.BooleanField(
        label=_('Wait to boot'),
        required=False,
    )

    class Meta:
        fields = '__all__'
        model = models.Device

    def __init__(self, *args, **kwargs):
        super(DeviceForm, self).__init__(*args, **kwargs)
        self.fields['dtype'].widget.attrs['onChange'] = (
            "deviceTypeToggle();"
        )
        self.fields['VNC_bind'].choices = self.ipv4_list()

        diskchoices = {}
        _n = notifier()
        used_zvol = []
        for volume in Volume.objects.filter():
            zvols = _n.list_zfs_vols(volume.vol_name, sort='name')
            for zvol, attrs in zvols.items():
                if "zvol/" + zvol not in used_zvol:
                    diskchoices["zvol/" + zvol] = "%s (%s)" % (
                        zvol,
                        humanize_size(attrs['volsize']))
        self.fields['DISK_zvol'].choices = diskchoices.items()

        if self.instance.id:
            if self.instance.dtype == 'CDROM':
                self.fields['CDROM_path'].initial = self.instance.attributes.get('path', '')
            elif self.instance.dtype == 'DISK':
                self.fields['DISK_zvol'].initial = self.instance.attributes.get('path', '').replace('/dev/', '')
                self.fields['DISK_mode'].initial = self.instance.attributes.get('type')
                self.fields['DISK_sectorsize'].initial = self.instance.attributes.get('sectorsize', 0)
            elif self.instance.dtype == "RAW":
                self.fields['DISK_raw'].initial = self.instance.attributes.get('path', '')
                self.fields['DISK_mode'].initial = self.instance.attributes.get('type')
                self.fields['DISK_sectorsize'].initial = self.instance.attributes.get('sectorsize', 0)
            elif self.instance.dtype == 'NIC':
                self.fields['NIC_type'].initial = self.instance.attributes.get('type')
                self.fields['NIC_mac'].initial = self.instance.attributes.get('mac')
                self.fields['NIC_attach'].initial = self.instance.attributes.get('nic_attach')
            elif self.instance.dtype == 'VNC':
                vnc_port = self.instance.attributes.get('vnc_port')
                vnc_port = 0 if vnc_port is None else vnc_port

                self.fields['VNC_wait'].initial = self.instance.attributes.get('wait')
                self.fields['VNC_port'].initial = vnc_port
                self.fields['VNC_resolution'].initial = self.instance.attributes.get('vnc_resolution')
                self.fields['VNC_bind'].initial = self.instance.attributes.get('vnc_bind')

    def ipv4_list(self):
        choices = (('0.0.0.0', '0.0.0.0'),)
        with client as c:
            ipv4_addresses = c.call('interfaces.ipv4_in_use')
        for ipv4_addr in ipv4_addresses:
            choices = choices + ((ipv4_addr, ipv4_addr),)
        return choices

    def clean(self):
        vm = self.cleaned_data.get('vm')
        vnc_port = self.cleaned_data.get('VNC_port')
        new_vnc_port = 5900
        if vm and vnc_port == '0':
            new_vnc_port = new_vnc_port + int(vm.id)
            self.cleaned_data['VNC_port'] = str(new_vnc_port)

        return self.cleaned_data

    def save(self, *args, **kwargs):
        vm = self.cleaned_data.get('vm')
        kwargs['commit'] = False
        obj = super(DeviceForm, self).save(*args, **kwargs)
        if self.cleaned_data['dtype'] == 'DISK':
            obj.attributes = {
                'path': '/dev/' + self.cleaned_data['DISK_zvol'],
                'type': self.cleaned_data['DISK_mode'],
                'sectorsize': self.cleaned_data['DISK_sectorsize'],
            }
        elif self.cleaned_data['dtype'] == 'RAW':
            obj.attributes = {
                'path': self.cleaned_data['DISK_raw'],
                'type': self.cleaned_data['DISK_mode'],
                'sectorsize': self.cleaned_data['DISK_sectorsize'],
            }
        elif self.cleaned_data['dtype'] == 'CDROM':
            cdrom_path = self.cleaned_data['CDROM_path']
            if cdrom_path:
                obj.attributes = {
                    'path': cdrom_path,
                }
            else:
                self._errors['CDROM_path'] = self.error_class([_('Please choose an ISO file.')])
        elif self.cleaned_data['dtype'] == 'NIC':
            obj.attributes = {
                'type': self.cleaned_data['NIC_type'],
                'mac': self.cleaned_data['NIC_mac'],
                'nic_attach': self.cleaned_data['NIC_attach'],
            }
        elif self.cleaned_data['dtype'] == 'VNC':
            if vm.bootloader == 'UEFI':
                obj.attributes = {
                    'wait': self.cleaned_data['VNC_wait'],
                    'vnc_port': self.cleaned_data['VNC_port'],
                    'vnc_resolution': self.cleaned_data['VNC_resolution'],
                    'vnc_bind': self.cleaned_data['VNC_bind'],
                }
            else:
                self._errors['dtype'] = self.error_class([_('VNC is only allowed for UEFI')])
                self.cleaned_data.pop('VNC_port', None)
                self.cleaned_data.pop('VNC_wait', None)
                self.cleaned_data.pop('VNC_resolution', None)
                self.cleaned_data.pop('VNC_bind', None)
                return obj

        obj.save()
        return obj
示例#3
0
class IPMIForm(Form):
    ipmi_password1 = forms.CharField(label=_("Password"),
                                     widget=forms.PasswordInput,
                                     required=False)
    ipmi_password2 = forms.CharField(
        label=_("Password confirmation"),
        widget=forms.PasswordInput,
        help_text=_("Enter the same password as above, for verification."),
        required=False)
    dhcp = forms.BooleanField(
        label=_("DHCP"),
        required=False,
    )
    ipv4address = IP4AddressFormField(
        initial='',
        required=False,
        label=_("IPv4 Address"),
    )
    ipv4netmaskbit = forms.ChoiceField(
        choices=choices.v4NetmaskBitList,
        required=False,
        label=_("IPv4 Netmask"),
    )
    ipv4gw = IP4AddressFormField(
        initial='',
        required=False,
        label=_("IPv4 Default Gateway"),
    )
    vlanid = forms.IntegerField(
        label=_("VLAN ID"),
        required=False,
        widget=forms.widgets.TextInput(),
    )

    def __init__(self, *args, **kwargs):
        self.remote = kwargs.pop('remote', None)
        self.initial_fail = False
        with client as c:
            if self.remote:
                try:
                    data = c.call('failover.call_remote', 'ipmi.query',
                                  [[('channel', '=', 1)]])
                except Exception:
                    self.initial_fail = True
                    data = None
            else:
                data = c.call('ipmi.query', [('channel', '=', 1)])
            if data:
                data = data[0]
                num, cidr = struct.unpack('>I',
                                          socket.inet_aton(
                                              data['netmask']))[0], 0
                while num > 0:
                    num = num << 1 & 0xffffffff
                    cidr += 1
                kwargs['initial'] = {
                    'dhcp': data['dhcp'],
                    'ipv4address': data.get('ipaddress'),
                    'ipv4gw': data.get('gateway'),
                    'ipv4netmaskbit': str(cidr),
                    'vlanid': data.get('vlan'),
                }

        super(IPMIForm, self).__init__(*args, **kwargs)
        self.fields['dhcp'].widget.attrs['onChange'] = (
            'javascript:toggleGeneric('
            '"id_dhcp", ["id_ipv4address", "id_ipv4netmaskbit"]);')

        with client as c:
            channels = list(map(lambda i: (i, i), c.call('ipmi.channels')))

        self.fields['channel'] = forms.ChoiceField(
            choices=channels,
            label=_('Channel'),
        )
        key_order(self, 0, 'channel', instance=True)

    def clean_ipmi_password2(self):
        ipmi_password1 = self.cleaned_data.get("ipmi_password1", "")
        ipmi_password2 = self.cleaned_data["ipmi_password2"]
        if ipmi_password1 != ipmi_password2:
            raise forms.ValidationError(
                _("The two password fields didn't match."))
        return ipmi_password2

    def clean(self):
        # Max password length via IPMI v2.0 is 20 chars. We only support IPMI
        # v2.0+ compliant boards thus far.

        cleaned_data = self.cleaned_data
        if len(cleaned_data.get("ipmi_password1", "")) > 20:
            self._errors["ipmi_password1"] = self.error_class(
                [_("A maximum of 20 characters are allowed")])
        return cleaned_data

    def clean_ipv4netmaskbit(self):
        try:
            cidr = int(self.cleaned_data.get("ipv4netmaskbit"))
        except ValueError:
            return None
        bits = 0xffffffff ^ (1 << 32 - cidr) - 1
        return socket.inet_ntoa(pack('>I', bits))

    def clean_ipv4address(self):
        ipv4 = self.cleaned_data.get('ipv4address')
        if ipv4:
            ipv4 = str(ipv4)
        return ipv4

    def clean_ipv4gw(self):
        ipv4 = self.cleaned_data.get('ipv4gw')
        if ipv4:
            ipv4 = str(ipv4)
        return ipv4

    def save(self):
        data = {
            'dhcp': self.cleaned_data.get('dhcp'),
            'ipaddress': self.cleaned_data.get('ipv4address'),
            'netmask': self.cleaned_data.get('ipv4netmaskbit'),
            'gateway': self.cleaned_data.get('ipv4gw'),
            'password': self.cleaned_data.get('ipmi_password2'),
        }
        vlan = self.cleaned_data.get('vlanid')
        if vlan:
            data['vlan'] = vlan
        channel = self.cleaned_data.get('channel')
        with client as c:
            if self.remote:
                return c.call('failover.call_remote', 'ipmi.update',
                              [channel, data])
            else:
                return c.call('ipmi.update', channel, data)
示例#4
0
文件: forms.py 项目: jiangge/freenas
class VMForm(ModelForm):

    root_password = forms.CharField(
        label=_("Root Password"),
        widget=forms.PasswordInput(render_value=True),
        required=False,
    )
    path = PathField(
        label=_("Docker Disk File"),
        dirsonly=False,
        filesonly=False,
    )
    size = forms.IntegerField(
        label=_("Size of Docker Disk File (GiB)"),
        initial=20,
        required=False,
    )

    class Meta:
        fields = '__all__'
        model = models.VM

    def __init__(self, *args, **kwargs):
        super(VMForm, self).__init__(*args, **kwargs)
        if self.instance.id:
            for i in ('vm_type', 'root_password', 'path', 'size'):
                del self.fields[i]
            if self.instance.vm_type != 'Bhyve':
                del self.fields['bootloader']
        else:
            self.fields['vm_type'].widget.attrs['onChange'] = (
                "vmTypeToggle();")
            key_order(self, 0, 'vm_type', instance=True)

    def clean_name(self):
        name = self.cleaned_data.get('name')
        if name:
            name = name.replace(' ', '')
        return name

    def clean_root_password(self):
        vm_type = self.cleaned_data.get('vm_type')
        root_password = self.cleaned_data.get('root_password')
        if vm_type != 'Bhyve' and not root_password:
            raise forms.ValidationError(_('This field is required.'))
        return root_password

    def clean_path(self):
        vm_type = self.cleaned_data.get('vm_type')
        path = self.cleaned_data.get('path')
        if vm_type != 'Bhyve':
            if path and os.path.exists(path):
                raise forms.ValidationError(_('File must not exist.'))
            elif not path:
                raise forms.ValidationError(_('File path is required.'))
        return path

    def clean_size(self):
        vm_type = self.cleaned_data.get('vm_type')
        size = self.cleaned_data.get('size')
        if vm_type != 'Bhyve' and not size:
            raise forms.ValidationError(_('This field is required.'))
        return size

    def save(self, **kwargs):
        with client as c:
            cdata = self.cleaned_data

            # Container boot load is GRUB
            if self.instance.vm_type == 'Container Provider':
                cdata['bootloader'] = 'GRUB'

            if self.instance.id:
                c.call('vm.update', self.instance.id, cdata)
            else:
                if cdata['vm_type'] == 'Container Provider':
                    cdata['devices'] = [
                        {
                            'dtype': 'NIC',
                            'attributes': {
                                'type': 'E1000'
                            }
                        },
                        {
                            'dtype': 'RAW',
                            'attributes': {
                                'path': cdata.pop('path'),
                                'type': 'AHCI',
                                'sectorsize': 0,
                                'size': cdata.pop('size'),
                                'exists': False,
                            }
                        },
                    ]
                    cdata.pop('vm_type')
                    cdata.pop('bootloader')
                    cdata['type'] = 'RancherOS'
                    return c.call('vm.create_container', cdata)

                cdata.pop('root_password')
                cdata.pop('path')
                cdata.pop('size')

                if cdata['bootloader'] == 'UEFI' and cdata[
                        'vm_type'] == 'Bhyve':
                    cdata['devices'] = [
                        {
                            'dtype': 'NIC',
                            'attributes': {
                                'type': 'E1000'
                            }
                        },
                        {
                            'dtype': 'VNC',
                            'attributes': {
                                'wait': False,
                                'vnc_web': False
                            }
                        },
                    ]
                else:
                    cdata['devices'] = [
                        {
                            'dtype': 'NIC',
                            'attributes': {
                                'type': 'E1000'
                            }
                        },
                    ]
                self.instance = models.VM.objects.get(
                    pk=c.call('vm.create', cdata))
        return self.instance

    def delete(self, **kwargs):
        with client as c:
            c.call('vm.delete', self.instance.id)
示例#5
0
文件: forms.py 项目: jiangge/freenas
class DeviceForm(ModelForm):

    CDROM_path = PathField(
        label=_('CD-ROM (ISO)'),
        required=False,
        dirsonly=False,
    )
    DISK_zvol = forms.ChoiceField(
        label=_('ZVol'),
        required=False,
    )
    DISK_mode = forms.ChoiceField(
        label=_('Mode'),
        choices=choices.VM_DISKMODETYPES,
        required=False,
        initial='AHCI',
    )
    DISK_raw = PathField(
        label=_('Raw File'),
        required=False,
        dirsonly=False,
    )
    DISK_raw_boot = forms.BooleanField(
        label=_('Disk boot'),
        widget=forms.widgets.HiddenInput(),
        required=False,
        initial=False,
    )
    ROOT_password = forms.CharField(
        label=_('Password'),
        max_length=50,
        widget=forms.widgets.HiddenInput(),
        required=False,
        help_text=_("Set the password for the rancher user."),
    )
    DISK_sectorsize = forms.IntegerField(
        label=_('Disk sectorsize'),
        required=False,
        initial=0,
        help_text=_(
            "Sector size of the emulated disk in bytes. Both logical and physical sector size are set to this value."
            "If 0, a sector size is not set."),
    )
    DISK_raw_size = forms.CharField(
        label=_('Disk size'),
        widget=forms.widgets.HiddenInput(),
        required=False,
        initial=0,
        validators=[
            RegexValidator(
                "^(\d*)\s?([M|G|T]?)$",
                "Enter M, G, or T after the value to use megabytes, gigabytes or terabytes."
                " When no suffix letter is entered, the units default to gigabytes."
            )
        ],
        help_text=
        _("Resize the existing raw disk. Enter 0 to use the disk with the current size."
          ),
    )
    NIC_type = forms.ChoiceField(
        label=_('Adapter Type'),
        choices=choices.VM_NICTYPES,
        required=False,
        initial='E1000',
    )
    NIC_attach = forms.ChoiceField(
        label=_('NIC to attach'),
        choices=(),
        required=False,
    )
    NIC_mac = forms.CharField(
        label=_('MAC Address'),
        required=False,
        help_text=
        _("Specify the adapter MAC Address or leave empty to be auto generated."
          ),
        validators=[
            RegexValidator("^([0-9a-fA-F]{2}([::]?|$)){6}$",
                           "Invalid MAC format.")
        ],
        initial='00:a0:98:FF:FF:FF',
    )
    VNC_resolution = forms.ChoiceField(
        label=_('Resolution'),
        choices=choices.VNC_RESOLUTION,
        required=False,
        initial='1024x768',
    )
    VNC_port = forms.CharField(
        label=_('VNC port'),
        required=False,
        help_text=_("Specify the VNC port or set to 0 for auto."),
        validators=[RegexValidator("^[0-9]*$", "Only integers are accepted")],
        initial=0,
    )
    VNC_bind = forms.ChoiceField(
        label=_('Bind to'),
        choices=(),
        required=False,
    )
    VNC_wait = forms.BooleanField(
        label=_('Wait to boot'),
        required=False,
    )
    VNC_password = forms.CharField(
        label=_('Password'),
        max_length=8,
        widget=forms.PasswordInput(render_value=True, ),
        required=False,
        help_text=_("The VNC password authentication."
                    "Maximum password length is 8 characters."))
    VNC_web = forms.BooleanField(
        label=_('VNC Web'),
        required=False,
    )

    class Meta:
        fields = '__all__'
        model = models.Device

    def __init__(self, *args, **kwargs):
        super(DeviceForm, self).__init__(*args, **kwargs)
        self.fields['dtype'].widget.attrs['onChange'] = ("deviceTypeToggle();")

        self.fields['VNC_bind'].choices = self.ipv4_list()
        self.fields['NIC_attach'].choices = choices.NICChoices(
            exclude_configured=False,
            include_vlan_parent=True,
            include_lagg_parent=False,
        )

        diskchoices = {}
        with client as c:
            for zvol in c.call('pool.dataset.query',
                               [('type', '=', 'VOLUME')]):
                diskchoices[f'zvol/{zvol["name"]}'] = "%s (%s)" % (
                    zvol['name'], humanize_size(zvol['volsize']['parsed']))
        self.fields['DISK_zvol'].choices = diskchoices.items()

        if self.instance.id:
            if self.instance.dtype == 'CDROM':
                self.fields[
                    'CDROM_path'].initial = self.instance.attributes.get(
                        'path', '')
            elif self.instance.dtype == 'DISK':
                self.fields[
                    'DISK_zvol'].initial = self.instance.attributes.get(
                        'path', '').replace('/dev/', '')
                self.fields[
                    'DISK_mode'].initial = self.instance.attributes.get('type')
                self.fields[
                    'DISK_sectorsize'].initial = self.instance.attributes.get(
                        'sectorsize', 0)
            elif self.instance.dtype == 'RAW':
                self.fields['DISK_raw'].initial = self.instance.attributes.get(
                    'path', '')
                self.fields[
                    'DISK_mode'].initial = self.instance.attributes.get('type')
                self.fields[
                    'DISK_sectorsize'].initial = self.instance.attributes.get(
                        'sectorsize', 0)

                if self.instance.vm.vm_type == 'Container Provider':
                    self.fields['DISK_raw_boot'].widget = forms.CheckboxInput()
                    self.fields['DISK_raw_size'].widget = forms.TextInput()
                    self.fields['ROOT_password'].widget = forms.PasswordInput(
                        render_value=True, )

                self.fields[
                    'DISK_raw_boot'].initial = self.instance.attributes.get(
                        'boot', False)
                self.fields[
                    'DISK_raw_size'].initial = self.instance.attributes.get(
                        'size', '')
                self.fields[
                    'ROOT_password'].initial = self.instance.attributes.get(
                        'rootpwd', '')
            elif self.instance.dtype == 'NIC':
                self.fields['NIC_type'].initial = self.instance.attributes.get(
                    'type')
                self.fields['NIC_mac'].initial = self.instance.attributes.get(
                    'mac')
                self.fields[
                    'NIC_attach'].initial = self.instance.attributes.get(
                        'nic_attach')
            elif self.instance.dtype == 'VNC':
                vnc_port = self.instance.attributes.get('vnc_port')
                vnc_port = 0 if vnc_port is None else vnc_port

                self.fields['VNC_wait'].initial = self.instance.attributes.get(
                    'wait')
                self.fields['VNC_port'].initial = vnc_port
                self.fields[
                    'VNC_resolution'].initial = self.instance.attributes.get(
                        'vnc_resolution')
                self.fields['VNC_bind'].initial = self.instance.attributes.get(
                    'vnc_bind')
                self.fields[
                    'VNC_password'].initial = self.instance.attributes.get(
                        'vnc_password')
                self.fields['VNC_web'].initial = self.instance.attributes.get(
                    'vnc_web')

    def ipv4_list(self):
        choices = ()
        with client as c:
            ipv4_addresses = c.call('vm.get_vnc_ipv4')
        for ipv4_addr in ipv4_addresses:
            choices = choices + ((ipv4_addr, ipv4_addr), )
        return choices

    def clean(self):
        vm = self.cleaned_data.get('vm')
        vnc_port = self.cleaned_data.get('VNC_port')
        new_vnc_port = 5900
        if vm and vnc_port == '0':
            new_vnc_port = new_vnc_port + int(vm.id)
            self.cleaned_data['VNC_port'] = str(new_vnc_port)

        return self.cleaned_data

    def is_container(self, vm_type):
        if vm_type == 'Container Provider':
            return True
        else:
            return False

    def save(self, *args, **kwargs):
        vm = self.cleaned_data.get('vm')
        kwargs['commit'] = False
        obj = super(DeviceForm, self).save(*args, **kwargs)

        if self.cleaned_data['dtype'] == 'DISK':
            obj.attributes = {
                'path': '/dev/' + self.cleaned_data['DISK_zvol'],
                'type': self.cleaned_data['DISK_mode'],
                'sectorsize': self.cleaned_data['DISK_sectorsize'],
            }
        elif self.cleaned_data['dtype'] == 'RAW':
            obj.attributes = {
                'path': self.cleaned_data['DISK_raw'],
                'type': self.cleaned_data['DISK_mode'],
                'sectorsize': self.cleaned_data['DISK_sectorsize'],
                'boot': self.cleaned_data['DISK_raw_boot'],
                'size': self.cleaned_data['DISK_raw_size'],
                'rootpwd': self.cleaned_data['ROOT_password'],
            }
        elif self.cleaned_data['dtype'] == 'CDROM':
            cdrom_path = self.cleaned_data['CDROM_path']
            if cdrom_path:
                obj.attributes = {
                    'path': cdrom_path,
                }
            else:
                self._errors['CDROM_path'] = self.error_class(
                    [_('Please choose an ISO file.')])
        elif self.cleaned_data['dtype'] == 'NIC':
            obj.attributes = {
                'type': self.cleaned_data['NIC_type'],
                'mac': self.cleaned_data['NIC_mac'],
                'nic_attach': self.cleaned_data['NIC_attach'],
            }
        elif self.cleaned_data['dtype'] == 'VNC':
            if vm.bootloader == 'UEFI' and self.is_container(
                    vm.vm_type) is False:
                obj.attributes = {
                    'wait': self.cleaned_data['VNC_wait'],
                    'vnc_port': self.cleaned_data['VNC_port'],
                    'vnc_resolution': self.cleaned_data['VNC_resolution'],
                    'vnc_bind': self.cleaned_data['VNC_bind'],
                    'vnc_password': self.cleaned_data['VNC_password'],
                    'vnc_web': self.cleaned_data['VNC_web'],
                }
            else:
                self._errors['dtype'] = self.error_class(
                    [_('VNC only works with UEFI VMs')])
                self.cleaned_data.pop('VNC_port', None)
                self.cleaned_data.pop('VNC_wait', None)
                self.cleaned_data.pop('VNC_resolution', None)
                self.cleaned_data.pop('VNC_bind', None)
                self.cleaned_data.pop('VNC_password', None)
                self.cleaned_data.pop('VNC_web', None)
                return obj

        obj.save()
        return obj
示例#6
0
class CloudSyncForm(ModelForm):

    attributes = forms.CharField(
        widget=CloudSyncWidget(),
        label=_('Provider'),
    )
    transfers = forms.IntegerField(
        required=False,
        label=_('Transfers'),
        help_text=
        _('The number of file transfers to run in parallel. It can sometimes be useful to set this to a '
          'smaller number if the remote is giving a lot of timeouts or bigger if you have lots of bandwidth '
          'and a fast remote.'),
        widget=forms.widgets.TextInput(),
    )
    bwlimit = forms.CharField(
        required=False,
        label=_('Bandwidth limit'),
        help_text=
        _('Either single bandwidth limit or bandwidth limit schedule in rclone format.<br />'
          'Example: "08:00,512 12:00,10M 13:00,512 18:00,30M 23:00,off".<br />'
          'Default unit is kilobytes.'))
    exclude = forms.CharField(
        required=False,
        label=_('Exclude'),
        help_text=
        _('Newline-separated list of files and directories to exclude from sync.<br />'
          'See https://rclone.org/filtering/ for more details on --exclude option.'
          ),
        widget=forms.Textarea(),
    )

    class Meta:
        exclude = ('credential', 'args')
        fields = '__all__'
        model = models.CloudSync
        widgets = {
            'minute':
            CronMultiple(attrs={
                'numChoices': 60,
                'label': _("minute")
            }),
            'hour':
            CronMultiple(attrs={
                'numChoices': 24,
                'label': _("hour")
            }),
            'daymonth':
            CronMultiple(attrs={
                'numChoices': 31,
                'start': 1,
                'label': _("day of month"),
            }),
            'dayweek':
            forms.CheckboxSelectMultiple(choices=choices.WEEKDAYS_CHOICES),
            'month':
            forms.CheckboxSelectMultiple(choices=choices.MONTHS_CHOICES),
        }

    def __init__(self, *args, **kwargs):
        if "instance" in kwargs and kwargs["instance"].id:
            kwargs.setdefault("initial", {})
            try:
                kwargs["initial"]["encryption_password"] = notifier(
                ).pwenc_decrypt(kwargs["instance"].encryption_password)
            except Exception:
                pass
            try:
                kwargs["initial"]["encryption_salt"] = notifier(
                ).pwenc_decrypt(kwargs["instance"].encryption_salt)
            except Exception:
                pass

            if len(kwargs["instance"].bwlimit
                   ) == 1 and kwargs["instance"].bwlimit[0]["time"] == "00:00":
                if kwargs["instance"].bwlimit[0]['bandwidth'] is not None:
                    kwargs["initial"]["bwlimit"] = humanize_size_rclone(
                        kwargs["instance"].bwlimit[0]['bandwidth'])
                else:
                    kwargs["initial"]["bwlimit"] = ""
            else:
                kwargs["initial"]["bwlimit"] = " ".join([
                    f"{limit['time']},{humanize_size_rclone(limit['bandwidth']) if limit['bandwidth'] else 'off'}"
                    for limit in kwargs["instance"].bwlimit
                ])

            kwargs["initial"]["exclude"] = "\n".join(
                kwargs["instance"].exclude)

        super(CloudSyncForm, self).__init__(*args, **kwargs)
        key_order(self, 2, 'attributes', instance=True)
        mchoicefield(self, 'month', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
        mchoicefield(self, 'dayweek', [1, 2, 3, 4, 5, 6, 7])
        if self.instance.id:
            self.fields['attributes'].initial = {
                'credential': self.instance.credential.id,
            }
            self.fields['attributes'].initial.update(self.instance.attributes)

        self.fields['direction'].widget.attrs['onChange'] = (
            "cloudSyncDirectionToggle();")

    def clean_attributes(self):
        attributes = self.cleaned_data.get('attributes')
        try:
            attributes = json.loads(attributes)
        except ValueError:
            raise forms.ValidationError(_('Invalid provider details.'))

        credential = attributes.get('credential')
        if not credential:
            raise forms.ValidationError(_('This field is required.'))
        qs = CloudCredentials.objects.filter(id=credential)
        if not qs.exists():
            raise forms.ValidationError(_('Invalid credential.'))

        return attributes

    def clean_month(self):
        m = self.data.getlist('month')
        if len(m) == 12:
            return '*'
        m = ','.join(m)
        return m

    def clean_dayweek(self):
        w = self.data.getlist('dayweek')
        if w == '*':
            return w
        if len(w) == 7:
            return '*'
        w = ','.join(w)
        return w

    def clean_bwlimit(self):
        v = self.cleaned_data.get('bwlimit').strip()

        if v and "," not in v:
            v = f"00:00,{v}"

        bwlimit = []
        for t in v.split():
            try:
                time_, bandwidth = t.split(",", 1)
            except ValueError:
                raise forms.ValidationError(_('Invalid value: %r') % t)

            try:
                h, m = time_.split(":", 1)
            except ValueError:
                raise forms.ValidationError(_('Invalid time: %r') % time_)

            try:
                time(int(h), int(m))
            except ValueError:
                raise forms.ValidationError(_('Invalid time: %r') % time_)

            if bandwidth == "off":
                bandwidth = None
            else:
                try:
                    bandwidth = int(bandwidth) * 1024
                except ValueError:
                    try:
                        bandwidth = int(bandwidth[:-1]) * {
                            "b": 1,
                            "k": 1024,
                            "M": 1024 * 1024,
                            "G": 1024 * 1024 * 1024
                        }[bandwidth[-1]]
                    except (KeyError, ValueError):
                        raise forms.ValidationError(
                            _('Invalid bandwidth: %r') % bandwidth)

            bwlimit.append({
                "time": time_,
                "bandwidth": bandwidth,
            })

        for a, b in zip(bwlimit, bwlimit[1:]):
            if a["time"] >= b["time"]:
                raise forms.ValidationError(
                    _('Invalid time order: %s, %s') % (a["time"], b["time"]))

        return bwlimit

    def clean_exclude(self):
        return list(
            filter(
                None,
                map(lambda s: s.strip(),
                    self.cleaned_data.get('exclude').split('\n'))))

    def save(self, **kwargs):
        with client as c:
            cdata = self.cleaned_data
            cdata['credentials'] = cdata['attributes'].pop('credential')
            cdata['schedule'] = {
                'minute': cdata.pop('minute'),
                'hour': cdata.pop('hour'),
                'dom': cdata.pop('daymonth'),
                'month': cdata.pop('month'),
                'dow': cdata.pop('dayweek')
            }
            if self.instance.id:
                c.call('cloudsync.update', self.instance.id, cdata)
            else:
                self.instance = models.CloudSync.objects.get(
                    pk=c.call('cloudsync.create', cdata)['id'])
        return self.instance

    def delete(self, **kwargs):
        with client as c:
            c.call('cloudsync.delete', self.instance.id)