Implement LED status indicators for v4, store generated firmware images for faster retrieval
This commit is contained in:
parent
267b613893
commit
6e6c63bed8
9 changed files with 335 additions and 140 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -3,3 +3,4 @@ __pycache__
|
|||
*.pyc
|
||||
static/static_root
|
||||
imagebuilder
|
||||
images/
|
||||
|
|
|
@ -1,59 +1,119 @@
|
|||
# Get IP address on VPN bridge interface through some arcane magic
|
||||
ipaddr(){
|
||||
if="${1:-br-VPN360}"
|
||||
result=$(/sbin/ip -o -4 addr show dev "${if}" 2&>/dev/null | /bin/sed 's/^.*inet // ; s/\/...*$//')
|
||||
/usr/bin/printf %s "${result}"
|
||||
}
|
||||
|
||||
# Disable (broadcast) WiFi device
|
||||
stopwifi(){
|
||||
/sbin/uci set wireless.radio0.disabled=1
|
||||
/sbin/uci commit
|
||||
/sbin/uci commit
|
||||
}
|
||||
|
||||
# Enable (broadcast) WiFi device
|
||||
startwifi(){
|
||||
/sbin/uci set wireless.radio0.disabled=0
|
||||
/sbin/uci commit
|
||||
/sbin/wifi
|
||||
/sbin/wifi
|
||||
}
|
||||
|
||||
# Disable and re-enable (broadcast) WiFi device
|
||||
restartwifi(){
|
||||
stopwifi
|
||||
startwifi
|
||||
}
|
||||
|
||||
. /etc/vpnsecret
|
||||
# Set power LED brightness
|
||||
powerled(){
|
||||
echo $1 > /sys/devices/platform/leds-gpio/leds/gl-ar750:white:power/brightness
|
||||
}
|
||||
|
||||
# Set second LED brightness
|
||||
led2g(){
|
||||
echo $1 > /sys/devices/platform/leds-gpio/leds/gl-ar750:white:wlan2g/brightness
|
||||
}
|
||||
|
||||
# Set third LED brightness
|
||||
led5g(){
|
||||
echo $1 > /sys/devices/platform/leds-gpio/leds/gl-ar750:white:wlan5g/brightness
|
||||
}
|
||||
|
||||
. /etc/vpnsecret # Source the server authentication secret
|
||||
|
||||
# Retrieve hosts file from server
|
||||
/usr/bin/wget -O/etc/hosts https://admin360.kumi.host/hosts --post-data "secret=$SECRET" --no-check-certificate >/var/log/wget 2>&1
|
||||
|
||||
# Prepare for default VPN-WiFi bridge
|
||||
/sbin/uci set wireless.@wifi-iface[0].network="VPN360"
|
||||
/sbin/uci commit
|
||||
|
||||
# Disable WiFi for as long as there is no bridge providing IP addresses
|
||||
stopwifi
|
||||
|
||||
# Turn off all LEDs
|
||||
powerled 0
|
||||
led2g 0
|
||||
led5g 0
|
||||
|
||||
# Launch VPN client
|
||||
/usr/sbin/openvpn /etc/openvpn/client.conf >/var/log/openvpn &
|
||||
|
||||
/bin/sleep 60
|
||||
# Try for approx. 1 minute to get an IP from the VPN before falling back to DHCP
|
||||
counter=0
|
||||
|
||||
if [ $(ipaddr) ]
|
||||
then
|
||||
startwifi
|
||||
while [ True ]
|
||||
do
|
||||
sleep 10
|
||||
if [ $(ipaddr) ]
|
||||
then
|
||||
/usr/bin/wget -O- https://admin360.kumi.host/heartbeat --post-data "secret=$SECRET&ip=$(ipaddr)" --no-check-certificate 2>/var/log/wget | /bin/ash
|
||||
fi
|
||||
done
|
||||
else
|
||||
/sbin/uci set wireless.@wifi-iface[0].network="DHCP"
|
||||
/sbin/uci commit
|
||||
startwifi
|
||||
/sbin/ip a add 192.168.36.1/24 dev br-DHCP
|
||||
/sbin/ifconfig br-DHCP down
|
||||
/sbin/ifconfig br-DHCP up
|
||||
while [ True ]
|
||||
do
|
||||
sleep 10
|
||||
/usr/bin/wget -O- https://admin360.kumi.host/heartbeat --post-data "secret=$SECRET" --no-check-certificate 2>/var/log/wget | /bin/ash
|
||||
done
|
||||
fi
|
||||
while [ $counter -lt 60 ]
|
||||
do
|
||||
powerled $(( counter % 2 )) # Make power LED flash
|
||||
if [ $(ipaddr) ] # = If connection to the server is working
|
||||
then
|
||||
# Turn on LEDs indicating boot completion and connection success
|
||||
powerled 1
|
||||
led5g 1
|
||||
|
||||
# Enable WiFi as the VPN bridge is now functional
|
||||
startwifi
|
||||
|
||||
# Send a heartbeat to the server every 10 seconds
|
||||
# This is also used to transfer commands from the server to the device
|
||||
while [ True ]
|
||||
do
|
||||
/bin/sleep 10
|
||||
|
||||
# Let's hope there is an IP address on the VPN interface
|
||||
# If not, this might be a temporary issue (lost network connection or lease expiration)
|
||||
# We assume that users will reboot the device if it doesn't work for extended periods of time
|
||||
if [ $(ipaddr) ]
|
||||
then
|
||||
/usr/bin/wget -O- https://admin360.kumi.host/heartbeat --post-data "secret=$SECRET&ip=$(ipaddr)" --no-check-certificate 2>/var/log/wget | /bin/ash
|
||||
fi
|
||||
done
|
||||
fi
|
||||
counter=$(( counter + 1 ))
|
||||
/bin/sleep 1 # Wait for a second before re-trying
|
||||
done
|
||||
|
||||
# We should only ever get to this point if no VPN connection was established within a minute
|
||||
|
||||
# Switch WiFi device to the DHCP bridge
|
||||
/sbin/uci set wireless.@wifi-iface[0].network="DHCP"
|
||||
/sbin/uci commit
|
||||
|
||||
# Turn on LEDs indicating connection failure and DHCP fallback
|
||||
powerled 1
|
||||
led2g 1
|
||||
|
||||
# Start WiFi device now bridged to the DHCP and assign server IP
|
||||
startwifi
|
||||
/sbin/ip a add 192.168.36.1/24 dev br-DHCP
|
||||
/sbin/ifconfig br-DHCP down
|
||||
/sbin/ifconfig br-DHCP up
|
||||
|
||||
# Send a heartbeat to the server every 10 seconds
|
||||
# This is also used to transfer commands from the server to the device
|
||||
while [ True ]
|
||||
do
|
||||
sleep 10
|
||||
/usr/bin/wget -O- https://admin360.kumi.host/heartbeat --post-data "secret=$SECRET" --no-check-certificate 2>/var/log/wget | /bin/ash
|
||||
done
|
||||
|
||||
|
|
|
@ -17,19 +17,3 @@ config timeserver 'ntp'
|
|||
list server '2.openwrt.pool.ntp.org'
|
||||
list server '3.openwrt.pool.ntp.org'
|
||||
|
||||
config led
|
||||
option trigger 'netdev'
|
||||
option dev 'br-lan'
|
||||
option mode 'link'
|
||||
option name 'WAN'
|
||||
option sysfs 'gl-ar300m:green:lan'
|
||||
option default '0'
|
||||
|
||||
config led
|
||||
option name 'VPN'
|
||||
option trigger 'netdev'
|
||||
option dev 'br-VPN360'
|
||||
option mode 'link'
|
||||
option sysfs 'gl-ar300m:green:wlan'
|
||||
option default '0'
|
||||
|
||||
|
|
29
manager/migrations/0018_auto_20181225_2225.py
Normal file
29
manager/migrations/0018_auto_20181225_2225.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
# Generated by Django 2.1.3 on 2018-12-25 22:25
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manager', '0017_auto_20181223_0936'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='device',
|
||||
name='firmware',
|
||||
field=models.DateTimeField(blank=True, editable=False, null=True, verbose_name='Firmware Creation Time'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='model',
|
||||
name='firmware',
|
||||
field=models.DateTimeField(auto_now=True, verbose_name='Firmware Modification Date'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='device',
|
||||
name='wifi',
|
||||
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='manager.Wifi'),
|
||||
),
|
||||
]
|
29
manager/migrations/0019_auto_20181225_2228.py
Normal file
29
manager/migrations/0019_auto_20181225_2228.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
# Generated by Django 2.1.3 on 2018-12-25 22:28
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manager', '0018_auto_20181225_2225'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='device',
|
||||
name='lastbeat',
|
||||
field=models.DateTimeField(blank=True, editable=False, null=True, verbose_name='Last Received Timestamp'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='device',
|
||||
name='lasttime',
|
||||
field=models.DateTimeField(blank=True, editable=False, null=True, verbose_name='Last Received IP'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='device',
|
||||
name='wifi',
|
||||
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='manager.Wifi'),
|
||||
),
|
||||
]
|
19
manager/migrations/0020_auto_20181225_2228.py
Normal file
19
manager/migrations/0020_auto_20181225_2228.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 2.1.3 on 2018-12-25 22:28
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manager', '0019_auto_20181225_2228'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='device',
|
||||
name='wifi',
|
||||
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='manager.Wifi'),
|
||||
),
|
||||
]
|
24
manager/migrations/0021_auto_20181225_2230.py
Normal file
24
manager/migrations/0021_auto_20181225_2230.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
# Generated by Django 2.1.3 on 2018-12-25 22:30
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manager', '0020_auto_20181225_2228'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='device',
|
||||
name='update',
|
||||
field=models.BooleanField(default=False, verbose_name='Trigger Firmware Update'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='device',
|
||||
name='wifi',
|
||||
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='manager.Wifi'),
|
||||
),
|
||||
]
|
|
@ -24,6 +24,7 @@ class Model(models.Model):
|
|||
name = models.CharField("Model Name", max_length=100, unique=True)
|
||||
extname = models.CharField("Manufacturer Model Name", max_length=100)
|
||||
config = models.TextField("OpenWRT Compile Config", blank=True, null=True)
|
||||
firmware = models.DateTimeField("Firmware Modification Date", auto_now=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
@ -48,11 +49,13 @@ class Device(models.Model):
|
|||
network = models.ForeignKey(Network, on_delete=models.SET_NULL, blank=True, null=True)
|
||||
wifi = models.OneToOneField(Wifi, on_delete=models.SET_NULL, blank=True, null=True)
|
||||
curip = models.CharField("Current IP Address", max_length=15, blank=True, null=True)
|
||||
lasttime = models.DateTimeField("Last Received IP", blank=True, null=True)
|
||||
lastbeat = models.DateTimeField("Last Received Timestamp", blank=True, null=True)
|
||||
lasttime = models.DateTimeField("Last Received IP", blank=True, null=True, editable=False)
|
||||
lastbeat = models.DateTimeField("Last Received Timestamp", blank=True, null=True, editable=False)
|
||||
secret = models.CharField("Secret", default=getRandom, max_length=128)
|
||||
password = models.CharField("Device Password", default=getRandom, max_length=128)
|
||||
vpnconfig = models.TextField("VPN Configuration", blank=True, null=True, editable=False)
|
||||
firmware = models.DateTimeField("Firmware Creation Time", blank=True, null=True, editable=False)
|
||||
update = models.BooleanField("Trigger Firmware Update", default=False)
|
||||
reboot = models.BooleanField("Trigger Reboot", default=False)
|
||||
|
||||
def __str__(self):
|
||||
|
|
234
manager/views.py
234
manager/views.py
|
@ -6,6 +6,7 @@ from django.views.decorators.csrf import csrf_exempt
|
|||
from django.utils import timezone
|
||||
from django.core.files import File
|
||||
from django.db.models.fields.files import FieldFile
|
||||
|
||||
from .models import Device, Organization, Network, Model
|
||||
|
||||
from distutils.dir_util import copy_tree
|
||||
|
@ -18,6 +19,7 @@ import socket
|
|||
import tempfile
|
||||
import crypt
|
||||
import tarfile
|
||||
import datetime
|
||||
|
||||
def index(request):
|
||||
if request.user.is_authenticated:
|
||||
|
@ -47,6 +49,121 @@ def hosts(request):
|
|||
device.save()
|
||||
return render(request, "manager/hosts", {"device": device})
|
||||
|
||||
def mkfirmware(device, path):
|
||||
if device.firmware and device.firmware > device.model.firmware and glob.glob("%s/%s.bin" % (path, device.id)):
|
||||
return True
|
||||
|
||||
BEFORE = os.getcwd()
|
||||
DEVICEDIR = "/opt/vpnmanager/device-config/%i/" % device.model.id
|
||||
SRCDIR = "/opt/vpnmanager/imagebuilder/%i/" % device.model.id
|
||||
|
||||
if glob.glob(SRCDIR + "/.kumilock"):
|
||||
return False
|
||||
|
||||
with open(SRCDIR + "/.kumilock", "w") as lock:
|
||||
lock.write("")
|
||||
|
||||
tempdir = tempfile.TemporaryDirectory()
|
||||
|
||||
copy_tree(DEVICEDIR, tempdir.name)
|
||||
|
||||
# Write OpenVPN config
|
||||
|
||||
with open(tempdir.name + "/etc/openvpn/client.conf", "w") as vpnconf:
|
||||
vpnconf.write(device.vpnconfig)
|
||||
|
||||
# Write secret
|
||||
|
||||
with open(tempdir.name + "/etc/vpnsecret", "w") as secret:
|
||||
secret.write('SECRET="%s"' % device.secret)
|
||||
|
||||
# Write password
|
||||
|
||||
with open(tempdir.name + "/etc/shadow", "r") as shadow:
|
||||
password = crypt.crypt(device.password, crypt.mksalt(crypt.METHOD_MD5))
|
||||
shadowin = shadow.read()
|
||||
|
||||
with open(tempdir.name + "/etc/shadow", "w") as shadowout:
|
||||
shadowout.write(shadowin.replace("$PASSWORD", password))
|
||||
|
||||
# Write SSID
|
||||
|
||||
with open(tempdir.name + "/etc/config/wireless", "r") as wireless:
|
||||
wirein = wireless.read()
|
||||
|
||||
with open(tempdir.name + "/etc/config/wireless", "w") as wireout:
|
||||
wire = wirein.replace("$SSID", device.serial)
|
||||
|
||||
try:
|
||||
wire2 = wire.replace("$WIFISSID", device.wifi.ssid)
|
||||
wire2 = wire2.replace("$WIFIKEY", device.wifi.key)
|
||||
except:
|
||||
wire2 = wire.replace("$WIFISSID", "NoSuchWiFi")
|
||||
wire2 = wire2.replace("$WIFIKEY", "NoSuchKey")
|
||||
|
||||
wireout.write(wire2)
|
||||
|
||||
|
||||
'''
|
||||
# Generate .tar.gz file
|
||||
|
||||
with tarfile.open(tempdir.name + ".tar.gz", "w:gz") as tar:
|
||||
tar.add(tempdir.name, arcname=os.path.sep)
|
||||
|
||||
with open(tempdir.name + ".tar.gz", "rb") as download:
|
||||
response = HttpResponse(download.read(), content_type="application/tar+gzip")
|
||||
response['Content-Disposition'] = 'inline; filename=' + os.path.basename(device.serial + ".tar.gz")
|
||||
return response
|
||||
'''
|
||||
|
||||
# Create compilation environment
|
||||
|
||||
os.system("rm -rf " + SRCDIR + "/files/")
|
||||
os.mkdir(SRCDIR + "/files/")
|
||||
os.system("cp -r " + tempdir.name + "/* " + SRCDIR + "/files/")
|
||||
|
||||
tempdir.cleanup()
|
||||
|
||||
os.system("rm " + SRCDIR + "/bin/targets/ar71xx/generic/*")
|
||||
|
||||
# Build image
|
||||
|
||||
os.chdir(SRCDIR)
|
||||
|
||||
try:
|
||||
subprocess.call(["/usr/bin/make"])
|
||||
except:
|
||||
os.remove(SRCDIR + "/.kumilock")
|
||||
os.chdir(BEFORE)
|
||||
return False
|
||||
|
||||
os.chdir(BEFORE)
|
||||
|
||||
os.rename(glob.glob(SRCDIR + "/bin/targets/ar71xx/generic/*squashfs-sysupgrade.bin")[0], "%s/%s.bin" % (path, device.id))
|
||||
os.remove(SRCDIR + "/.kumilock")
|
||||
os.system("rm -rf " + SRCDIR + "/files/")
|
||||
os.system("rm " + SRCDIR + "/bin/targets/ar71xx/generic/*")
|
||||
device.firmware = datetime.datetime.now()
|
||||
device.save()
|
||||
return True
|
||||
|
||||
@csrf_exempt
|
||||
def update(request):
|
||||
FWDIR = "/opt/vpnmanager/images/"
|
||||
|
||||
device = get_object_or_404(Device, secret=request.POST.get("secret", ""))
|
||||
|
||||
if not mkfirmware(device, FWDIR):
|
||||
return HttpResponse(status=503)
|
||||
|
||||
device.update = False
|
||||
device.save()
|
||||
|
||||
with open("%s/%s.bin" % (FWDIR, device.id), "rb") as download:
|
||||
response = HttpResponse(download.read(), content_type="application/octet-stream")
|
||||
response['Content-Disposition'] = 'inline; filename=%s.bin' % device.serial
|
||||
return response
|
||||
|
||||
def ping(request, device_id):
|
||||
if request.user.is_authenticated:
|
||||
device = None
|
||||
|
@ -141,103 +258,22 @@ def editdevice(request, device_id):
|
|||
return redirect("/")
|
||||
|
||||
def getconfig(request, device_id):
|
||||
FWDIR = "/opt/vpnmanager/images/"
|
||||
|
||||
if not request.user.is_superuser:
|
||||
return redirect("/")
|
||||
|
||||
device = get_object_or_404(Device, id=device_id)
|
||||
|
||||
BEFORE = os.getcwd()
|
||||
DEVICEDIR = "/opt/vpnmanager/device-config/%i/" % device.model.id
|
||||
SRCDIR = "/opt/vpnmanager/imagebuilder/%i/" % device.model.id
|
||||
|
||||
if glob.glob(SRCDIR + "/.kumilock"):
|
||||
return HttpResponse("Another download is being prepared right now. Please wait for it to finish and try again later.")
|
||||
|
||||
with open(SRCDIR + "/.kumilock", "w") as lock:
|
||||
lock.write("")
|
||||
|
||||
tempdir = tempfile.TemporaryDirectory()
|
||||
|
||||
copy_tree(DEVICEDIR, tempdir.name)
|
||||
|
||||
# Write OpenVPN config
|
||||
|
||||
with open(tempdir.name + "/etc/openvpn/client.conf", "w") as vpnconf:
|
||||
vpnconf.write(device.vpnconfig)
|
||||
|
||||
# Write secret
|
||||
|
||||
with open(tempdir.name + "/etc/vpnsecret", "w") as secret:
|
||||
secret.write('SECRET="%s"' % device.secret)
|
||||
|
||||
# Write password
|
||||
|
||||
with open(tempdir.name + "/etc/shadow", "r") as shadow:
|
||||
password = crypt.crypt(device.password, crypt.mksalt(crypt.METHOD_MD5))
|
||||
shadowin = shadow.read()
|
||||
|
||||
with open(tempdir.name + "/etc/shadow", "w") as shadowout:
|
||||
shadowout.write(shadowin.replace("$PASSWORD", password))
|
||||
|
||||
# Write SSID
|
||||
|
||||
with open(tempdir.name + "/etc/config/wireless", "r") as wireless:
|
||||
wirein = wireless.read()
|
||||
|
||||
with open(tempdir.name + "/etc/config/wireless", "w") as wireout:
|
||||
wire = wirein.replace("$SSID", device.serial)
|
||||
|
||||
try:
|
||||
wire2 = wire.replace("$WIFISSID", device.wifi.ssid)
|
||||
wire2 = wire2.replace("$WIFIKEY", device.wifi.key)
|
||||
except:
|
||||
wire2 = wire.replace("$WIFISSID", "NoSuchWiFi")
|
||||
wire2 = wire2.replace("$WIFIKEY", "NoSuchKey")
|
||||
|
||||
wireout.write(wire2)
|
||||
if not mkfirmware(device, FWDIR):
|
||||
return HttpResponse("Something went wrong generating the firmware image. The server may be busy, please try again later.")
|
||||
|
||||
device.update = False
|
||||
device.save()
|
||||
|
||||
'''
|
||||
# Generate .tar.gz file
|
||||
|
||||
with tarfile.open(tempdir.name + ".tar.gz", "w:gz") as tar:
|
||||
tar.add(tempdir.name, arcname=os.path.sep)
|
||||
|
||||
with open(tempdir.name + ".tar.gz", "rb") as download:
|
||||
response = HttpResponse(download.read(), content_type="application/tar+gzip")
|
||||
response['Content-Disposition'] = 'inline; filename=' + os.path.basename(device.serial + ".tar.gz")
|
||||
return response
|
||||
'''
|
||||
|
||||
# Create compilation environment
|
||||
|
||||
os.system("rm -rf " + SRCDIR + "/files/")
|
||||
os.mkdir(SRCDIR + "/files/")
|
||||
os.system("cp -r " + tempdir.name + "/* " + SRCDIR + "/files/")
|
||||
|
||||
tempdir.cleanup()
|
||||
|
||||
os.system("rm " + SRCDIR + "/bin/targets/ar71xx/generic/*")
|
||||
|
||||
# Build image
|
||||
|
||||
os.chdir(SRCDIR)
|
||||
|
||||
try:
|
||||
subprocess.call(["/usr/bin/make"])
|
||||
except:
|
||||
os.remove(SRCDIR + "/.kumilock")
|
||||
os.chdir(BEFORE)
|
||||
return HttpResponse("Something went wrong building the image file.")
|
||||
|
||||
os.chdir(BEFORE)
|
||||
|
||||
with open(glob.glob(SRCDIR + "/bin/targets/ar71xx/generic/*squashfs-sysupgrade.bin")[0], "rb") as download:
|
||||
with open("%s/%s.bin" % (FWDIR, device.id), "rb") as download:
|
||||
response = HttpResponse(download.read(), content_type="application/octet-stream")
|
||||
response['Content-Disposition'] = 'inline; filename=' + os.path.basename(device.serial + ".bin")
|
||||
os.remove(SRCDIR + "/.kumilock")
|
||||
os.system("rm -rf " + SRCDIR + "/files/")
|
||||
os.system("rm " + SRCDIR + "/bin/targets/ar71xx/generic/*")
|
||||
response['Content-Disposition'] = 'inline; filename=%s.bin' % device.serial
|
||||
return response
|
||||
|
||||
def rebootdevice(request, device_id):
|
||||
|
@ -246,13 +282,23 @@ def rebootdevice(request, device_id):
|
|||
for organization in Organization.objects.filter(users=request.user):
|
||||
device = device or Device.objects.filter(id=device_id, organization=organization)
|
||||
|
||||
if not device:
|
||||
return redirect("/")
|
||||
if device:
|
||||
device[0].reboot = True
|
||||
device[0].save()
|
||||
|
||||
device[0].reboot = True
|
||||
device[0].save()
|
||||
return redirect("/")
|
||||
|
||||
return redirect("/")
|
||||
def updatedevice(request, device_id):
|
||||
if request.user.is_staff:
|
||||
device = None
|
||||
for organization in Organization.objects.filter(users=request.user):
|
||||
device = device or Device.objects.filter(id=device_id, organization=organization)
|
||||
|
||||
if device:
|
||||
device[0].update = True
|
||||
device[0].save()
|
||||
|
||||
return redirect("/")
|
||||
|
||||
def deletedevice(request, device_id):
|
||||
if request.user.is_superuser:
|
||||
|
|
Loading…
Reference in a new issue