@ -3,7 +3,9 @@ from rest_framework.urlpatterns import format_suffix_patterns
|
|||||||
|
|
||||||
from .views import access, index
|
from .views import access, index
|
||||||
|
|
||||||
from .views.itam import device as itam_device, software as itam_software, config as itam_config
|
from .views.itam import software as itam_software, config as itam_config
|
||||||
|
from .views.itam.device import detail as itam_device
|
||||||
|
from .views.itam.device import inventory
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", index.IndexView.as_view(), name='_api_home'),
|
path("", index.IndexView.as_view(), name='_api_home'),
|
||||||
@ -21,6 +23,8 @@ urlpatterns = [
|
|||||||
path("software/", itam_software.List.as_view(), name="_api_softwares"),
|
path("software/", itam_software.List.as_view(), name="_api_softwares"),
|
||||||
path("software/<int:pk>/", itam_software.Detail.as_view(), name="_api_software_view"),
|
path("software/<int:pk>/", itam_software.Detail.as_view(), name="_api_software_view"),
|
||||||
|
|
||||||
|
path("device/inventory/<slug:slug>", inventory.Collect.as_view(), name="_api_device_inventory"),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
urlpatterns = format_suffix_patterns(urlpatterns)
|
urlpatterns = format_suffix_patterns(urlpatterns)
|
||||||
|
|||||||
0
app/api/views/itam/device/__init__.py
Normal file
0
app/api/views/itam/device/__init__.py
Normal file
259
app/api/views/itam/device/inventory.py
Normal file
259
app/api/views/itam/device/inventory.py
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
# from django.contrib.auth.mixins import PermissionRequiredMixin, LoginRequiredMixin
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
|
||||||
|
from django.http import JsonResponse
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
|
from rest_framework import generics, views
|
||||||
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
from access.models import Organization
|
||||||
|
|
||||||
|
from core.http.common import Http
|
||||||
|
|
||||||
|
from itam.models.device import Device, DeviceType, DeviceOperatingSystem, DeviceSoftware
|
||||||
|
from itam.models.operating_system import OperatingSystem, OperatingSystemVersion
|
||||||
|
from itam.models.software import Software, SoftwareCategory, SoftwareVersion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Collect(views.APIView):
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
|
||||||
|
data = json.loads(request.body)
|
||||||
|
|
||||||
|
status = Http.Status.BAD_REQUEST
|
||||||
|
|
||||||
|
device = None
|
||||||
|
device_operating_system = None
|
||||||
|
operating_system = None
|
||||||
|
operating_system_version = None
|
||||||
|
|
||||||
|
organization = Organization.objects.get(pk=1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
if Device.objects.filter(name=data['details']['name']).exists():
|
||||||
|
|
||||||
|
device = Device.objects.get(name=data['details']['name'])
|
||||||
|
|
||||||
|
else: # Create the device
|
||||||
|
|
||||||
|
device = Device.objects.create(
|
||||||
|
name = data['details']['name'],
|
||||||
|
device_type = DeviceType.objects.get(pk=1),
|
||||||
|
serial_number = data['details']['serial_number'],
|
||||||
|
uuid = data['details']['uuid'],
|
||||||
|
organization = organization,
|
||||||
|
)
|
||||||
|
|
||||||
|
status = Http.Status.CREATED
|
||||||
|
|
||||||
|
|
||||||
|
if OperatingSystem.objects.filter( slug=data['os']['name'] ).exists():
|
||||||
|
|
||||||
|
operating_system = OperatingSystem.objects.get( slug=data['os']['name'] )
|
||||||
|
|
||||||
|
else: # Create Operating System
|
||||||
|
|
||||||
|
operating_system = OperatingSystem.objects.create(
|
||||||
|
name = data['os']['name'],
|
||||||
|
organization = device.organization,
|
||||||
|
is_global = True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if OperatingSystemVersion.objects.filter( name=data['os']['version_major'], operating_system=operating_system ).exists():
|
||||||
|
|
||||||
|
operating_system_version = OperatingSystemVersion.objects.get(
|
||||||
|
organization = device.organization,
|
||||||
|
is_global = True,
|
||||||
|
name = data['os']['version_major'],
|
||||||
|
operating_system = operating_system
|
||||||
|
)
|
||||||
|
|
||||||
|
else: # Create Operating System Version
|
||||||
|
|
||||||
|
operating_system_version = OperatingSystemVersion.objects.create(
|
||||||
|
organization = device.organization,
|
||||||
|
is_global = True,
|
||||||
|
name = data['os']['version_major'],
|
||||||
|
operating_system = operating_system,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if DeviceOperatingSystem.objects.filter( version=data['os']['version'], device=device, operating_system_version=operating_system_version ).exists():
|
||||||
|
|
||||||
|
device_operating_system = DeviceOperatingSystem.objects.get(
|
||||||
|
device=device,
|
||||||
|
version = data['os']['version'],
|
||||||
|
operating_system_version = operating_system_version,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not device_operating_system.installdate: # Only update install date if empty
|
||||||
|
|
||||||
|
device_operating_system.installdate = timezone.now()
|
||||||
|
|
||||||
|
device_operating_system.save()
|
||||||
|
|
||||||
|
else: # Create Operating System Version
|
||||||
|
|
||||||
|
device_operating_system = DeviceOperatingSystem.objects.create(
|
||||||
|
organization = device.organization,
|
||||||
|
device=device,
|
||||||
|
version = data['os']['version'],
|
||||||
|
operating_system_version = operating_system_version,
|
||||||
|
installdate = timezone.now()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
for inventory in list(data['software']):
|
||||||
|
|
||||||
|
software = None
|
||||||
|
software_category = None
|
||||||
|
software_version = None
|
||||||
|
|
||||||
|
device_software = None
|
||||||
|
|
||||||
|
|
||||||
|
if SoftwareCategory.objects.filter( name = inventory['category'] ).exists():
|
||||||
|
|
||||||
|
software_category = SoftwareCategory.objects.get(
|
||||||
|
name = inventory['category']
|
||||||
|
)
|
||||||
|
|
||||||
|
else: # Create Software Category
|
||||||
|
|
||||||
|
software_category = SoftwareCategory.objects.create(
|
||||||
|
organization = device.organization,
|
||||||
|
is_global = True,
|
||||||
|
name = inventory['category'],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if Software.objects.filter( name = inventory['name'] ).exists():
|
||||||
|
|
||||||
|
software = Software.objects.get(
|
||||||
|
name = inventory['name']
|
||||||
|
)
|
||||||
|
|
||||||
|
if not software.category:
|
||||||
|
|
||||||
|
software.category = software_category
|
||||||
|
software.save()
|
||||||
|
|
||||||
|
else: # Create Software
|
||||||
|
|
||||||
|
software = Software.objects.create(
|
||||||
|
organization = device.organization,
|
||||||
|
is_global = True,
|
||||||
|
name = inventory['name'],
|
||||||
|
category = software_category,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
pattern = r"^(\d+:)?(?P<semver>\d+\.\d+(\.\d+)?)"
|
||||||
|
|
||||||
|
semver = re.search(pattern, str(inventory['version']), re.DOTALL)
|
||||||
|
|
||||||
|
|
||||||
|
if semver:
|
||||||
|
|
||||||
|
semver = semver['semver']
|
||||||
|
|
||||||
|
else:
|
||||||
|
semver = inventory['version']
|
||||||
|
|
||||||
|
|
||||||
|
if SoftwareVersion.objects.filter( name = semver, software = software ).exists():
|
||||||
|
|
||||||
|
software_version = SoftwareVersion.objects.get(
|
||||||
|
name = semver,
|
||||||
|
software = software,
|
||||||
|
)
|
||||||
|
|
||||||
|
else: # Create Software Category
|
||||||
|
|
||||||
|
software_version = SoftwareVersion.objects.create(
|
||||||
|
organization = device.organization,
|
||||||
|
is_global = True,
|
||||||
|
name = semver,
|
||||||
|
software = software,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if DeviceSoftware.objects.filter( software = software, device=device ).exists():
|
||||||
|
|
||||||
|
device_software = DeviceSoftware.objects.get(
|
||||||
|
device = device,
|
||||||
|
software = software
|
||||||
|
)
|
||||||
|
|
||||||
|
else: # Create Software
|
||||||
|
|
||||||
|
device_software = DeviceSoftware.objects.create(
|
||||||
|
organization = device.organization,
|
||||||
|
is_global = True,
|
||||||
|
installedversion = software_version,
|
||||||
|
software = software,
|
||||||
|
device = device,
|
||||||
|
action=None
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if device_software: # Update the Inventoried software
|
||||||
|
|
||||||
|
clear_installed_software = DeviceSoftware.objects.filter(
|
||||||
|
device = device,
|
||||||
|
software = software
|
||||||
|
)
|
||||||
|
|
||||||
|
# Clear installed version of all installed software
|
||||||
|
# any found later with no version to be removed
|
||||||
|
clear_installed_software.update(installedversion=None)
|
||||||
|
|
||||||
|
|
||||||
|
if not device_software.installed: # Only update install date if blank
|
||||||
|
|
||||||
|
device_software.installed = timezone.now()
|
||||||
|
|
||||||
|
device_software.save()
|
||||||
|
|
||||||
|
device_software.installedversion = software_version
|
||||||
|
|
||||||
|
device_software.save()
|
||||||
|
|
||||||
|
|
||||||
|
if not device_software.installed: # Only update install date if blank
|
||||||
|
|
||||||
|
device_software.installed = timezone.now()
|
||||||
|
|
||||||
|
device_software.save()
|
||||||
|
|
||||||
|
|
||||||
|
if device and operating_system and operating_system_version and device_operating_system:
|
||||||
|
|
||||||
|
# Remove software no longer installed
|
||||||
|
DeviceSoftware.objects.filter(
|
||||||
|
device = device,
|
||||||
|
software = software,
|
||||||
|
).delete()
|
||||||
|
|
||||||
|
status = Http.Status.OK
|
||||||
|
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
|
||||||
|
print(f'An error occured{e}')
|
||||||
|
|
||||||
|
status = Http.Status.SERVER_ERROR
|
||||||
|
|
||||||
|
|
||||||
|
return Response(data='OK',status=status)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_view_name(self):
|
||||||
|
return "Inventory"
|
||||||
17
app/core/http/common.py
Normal file
17
app/core/http/common.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from enum import IntEnum
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Http():
|
||||||
|
"""Common HTTP Related objects"""
|
||||||
|
|
||||||
|
|
||||||
|
class Status(IntEnum):
|
||||||
|
"""HTTP server status codes."""
|
||||||
|
|
||||||
|
OK = 200
|
||||||
|
CREATED = 201
|
||||||
|
|
||||||
|
BAD_REQUEST = 400
|
||||||
|
|
||||||
|
SERVER_ERROR = 500
|
||||||
@ -7,8 +7,6 @@ about: https://gitlab.com/nofusscomputing/infrastructure/configuration-managemen
|
|||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
## Access
|
|
||||||
|
|
||||||
to access the api, it can be done with the following command:
|
to access the api, it can be done with the following command:
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
@ -18,6 +16,48 @@ curl -X GET http://127.0.0.1:8000/api/ -H 'Authorization: Token <token>'
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Inventory Report Collection
|
||||||
|
|
||||||
|
|
||||||
|
## Inventory Reports
|
||||||
|
|
||||||
|
- url `/api/device/inventory/<device slug>`
|
||||||
|
|
||||||
|
- method `POST`
|
||||||
|
|
||||||
|
- content `application/json`
|
||||||
|
|
||||||
|
Passing a valid inventory report to this endpoint will update the device within the app if the device already exists.
|
||||||
|
|
||||||
|
Report Format
|
||||||
|
|
||||||
|
``` json
|
||||||
|
|
||||||
|
{
|
||||||
|
"details": {
|
||||||
|
"name": "string",
|
||||||
|
"serial_number": "string",
|
||||||
|
"uuid": "string"
|
||||||
|
},
|
||||||
|
"os": {
|
||||||
|
"name": "debian|ubuntu",
|
||||||
|
"version_major": "major version number",
|
||||||
|
"version": "as reported"
|
||||||
|
},
|
||||||
|
"software": [
|
||||||
|
{
|
||||||
|
"name": "string",
|
||||||
|
"category": "string",
|
||||||
|
"version": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
## User Token
|
## User Token
|
||||||
|
|
||||||
To generate a user token to access the api, use command `python3 manage.py drf_create_token <username>`
|
To generate a user token to access the api, use command `python3 manage.py drf_create_token <username>`
|
||||||
|
|||||||
Reference in New Issue
Block a user