Djagno запускает сервер, сканирует сеть и записывает данные в БД
Моя идея
Хранить данные о сетевых устройствах бросил Django Model (Device Model) в мою базу данных.
- Host configuration needs to be setup by User inside a View (Host Model)
- When the Host configuration is finished the Network should be scanned for devices (Device Model)
- The Data should be stored inside the DB
Фукция create_devices()
вызывается до установки хоста, с migrate
и makemigrations
.
Как я могу это исправить? Правильно ли вообще хранить эти данные через представление в моей базе данных?
В лучшем случае данные в БД будут храниться асинхронно с моим приложением, есть ли способ?
Большое спасибо за помощь!!!
Модель хоста:
class Host(models.Model):
hostname = models.CharField(default="noads", max_length=6)
ipv4_address = models.GenericIPAddressField('IPv4')
ipv4_subnet = models.GenericIPAddressField('IPv4')
gateway = models.GenericIPAddressField('IPv4')
Модель устройства:
class Device(models.Model):
hostname = models.CharField(max_length=64)
mac_address = models.CharField(max_length=64)
ipv4_address = models.GenericIPAddressField('IPv4')
Мое мнение:
def get_arp_table_linux():
"""
Parse the host ARP table on a Linux machine
:return: Machine readable ARP table
:rtype: dict {'ip_address': 'mac_address'}
"""
with open('/proc/net/arp') as proc_net_arp:
arp_data_raw = proc_net_arp.read(-1).split("\n")[1:-1]
parsed_arp_table = (dict(zip(('ip_address', 'type', 'flags', 'hw_address', 'mask', 'device'), v))
for v in (re.split('\s+', i) for i in arp_data_raw))
return {d['ip_address']: d['hw_address'] for d in parsed_arp_table}
def get_devices_in_list():
"""
Gets every device inside the subnet
:return: List of devices
:rtype: list ["ipv4", "ipv4", ...]
"""
device_list = []
device_list_str = []
host = Host.objects.latest('pk')
device_list = ipaddress.ip_network(host.ipv4_address + "/" + host.ipv4_subnet, strict=False).hosts()
for dev in device_list:
device_list_str.append(str(dev))
return device_list_str
def get_available_devices_in_list():
"""
Checks if hosts of get_hosts_in_list are available and removes localhost
:return: List of available hosts
:rtype: list ["ipv4", "ipv4", ...]
"""
host = Host.objects.latest('pk')
available_devices = []
all_devices = get_devices_in_list()
num_threads = 255 #One "big"subnet thread pool
p = multiprocessing.dummy.Pool(num_threads)
def ping(ip):
success = os.system("ping -c 1 " + ip)
if success == 0:
available_devices.append(ip)
p.map(ping, all_devices)
#Deletes localhost from available list
if host.ipv4_address in available_devices: available_devices.remove(host.ipv4_address)
return available_devices
def create_devices():
"""
Creates DB entry of devices if they dont already exist
:return: List of mulitple devices stored in objects
:rtype: list ["Device", "Device", ...]
"""
available_devices = get_available_devices_in_list()
arp_table_of_all_hosts = get_arp_table_linux()
dev_list = []
for deviceip in available_devices:
#If device already exists in DB continue
if arp_table_of_all_hosts.get(deviceip):
if arp_table_of_all_hosts[deviceip] in Device.objects.filter(mac_address = arp_table_of_all_hosts[deviceip]):
continue
else:
devmac = arp_table_of_all_hosts[deviceip]
devname = "unknown" #socket.gethostbyaddr(deviceip)
dev = Device(hostname=devname, mac_address=devmac, ipv4_address=deviceip)
dev.save()
dev_list.append(dev)
return dev_list
class DeviceGetAll(DetailView):
if Host.objects.values():
create_devices()
model = Device
pass
Ваше представление DeviceGetAll
написано неправильно. Условие if
должно быть помещено в некоторые методы представления, а не в определение класса.
Я не понимаю, что именно вы пытаетесь сделать, поэтому не могу знать, в какой метод вам нужно добавить код, но вы можете посмотреть на базовый код DetailView
и посмотреть, может быть, некоторые из этих методов вам пригодятся.
Я даже не знаю, является ли детальное представление лучшим местом для размещения кода, который создает экземпляры одной и той же модели; возможно, он также может идти после создания хоста.
Но если вы хотите использовать DetailView
, то вы можете, например, переопределить метод get_object()
из SingleObjectMixin
(который является одним из родителей DetailView
), ваш код может выглядеть так:
class DeviceGetAll(DetailView):
model = Device
def get_object(self, *args, **kwargs):
if Host.objects.exists():
create_devices()
obj = super().get_object(*args, **kwargs)
return obj
Также, вероятно, вы хотели использовать метод .exists()
в условии if вместо .values()
.
К сожалению, все та же проблема. Я хочу проверить, есть ли данные в базе данных с моделью Host if Host.objects.exists():
Но данных нет, а с функцией exists()
выкидывает ошибку. Может у @Ralf есть другая идея :).
Спасибо за помощь
(В этом представлении он должен создавать устройства, только если существует Host)
class DeviceGetAll(DetailView):
if Host.objects.exists():
create_devices()
model = Device
Ошибка
File "/home/X/NoAds/DjangoWebApp/webapp/urls.py", line 2, in <module>
from . import views
File "/home/X/NoAds/DjangoWebApp/webapp/views.py", line 37, in <module>
class DeviceGetAll(DetailView):
File "/home/X/NoAds/DjangoWebApp/webapp/views.py", line 38, in DeviceGetAll
if Host.objects.exists():
File "/home/X/noads/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/X/noads/lib/python3.8/site-packages/django/db/models/query.py", line 808, in exists
return self.query.has_results(using=self.db)
File "/home/X/noads/lib/python3.8/site-packages/django/db/models/sql/query.py", line 552, in has_results
return compiler.has_results()
File "/home/X/noads/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1145, in has_results
return bool(self.execute_sql(SINGLE))
File "/home/X/noads/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1175, in execute_sql
cursor.execute(sql, params)
File "/home/X/noads/lib/python3.8/site-packages/django/db/backends/utils.py", line 98, in execute
return super().execute(sql, params)
File "/home/X/noads/lib/python3.8/site-packages/django/db/backends/utils.py", line 66, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/home/X/noads/lib/python3.8/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/home/X/noads/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/home/X/noads/lib/python3.8/site-packages/django/db/utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/home/X/noads/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/home/X/noads/lib/python3.8/site-packages/django/db/backends/sqlite3/base.py", line 423, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.OperationalError: no such table: webapp_host