Skip to content
Snippets Groups Projects
Select Git revision
  • v2
  • main default protected
2 results

models.py

Blame
  • models.py 5.46 KiB
    from netbox_proxmox_sync.api.config import (
        NETBOX_DEFAULT_TAG_COLOR,
        NETBOX_VM_ROLE_ID,
    )
    # Classes to ensure NetBox and Proxmox data have the exact same format and fields,
    # which makes updating stuff correctly easier
    
    
    class VirtualMachine:
        def __init__(self, vmid, name, status, node_name, cluster_name, vcpus, maxmem,
                     role_id, tags=[], maxdisk=None, description=None, id=None):
            self.vmid = vmid
            self.name = name
            self.status = status
            self.node_name = node_name
            self.cluster_name = cluster_name
            self.role_id = role_id
            self.vcpus = vcpus
            self.maxmem = maxmem
            self.tags = sorted(tags)
            self.maxdisk = maxdisk
            self.description = description
            self.id = id
    
        def to_dict(self):
            # Trust me, it's important that they're sorted
            vm_data = {
                'name': self.name,
                'status': self.status,
                'device': {'name': self.node_name},
                'cluster': {'name': self.cluster_name},
                'vcpus': self.vcpus,
                'memory': self.maxmem,
                'role': self.role_id,
                'tags': [{'name': tag} for tag in self.tags],
                'custom_fields': {'vmid': self.vmid}
            }
            # Both these fields may be None, so we have to set them separately
            if self.maxdisk is not None and self.maxdisk > 0:
                vm_data['disk'] = int(self.maxdisk)
            if self.description is not None:
                # NetBox only allows 200 char description, but our VMs have more
                # so we store the description in the "comments" instead
                vm_data['comments'] = self.description
            if self.id is not None:
                vm_data['id'] = self.id
            return vm_data
    
    
    class VirtualInterface:
        def __init__(self, name, vm_name, mac_address, vlan_id, id=None):
            self.name = name
            self.vm_name = vm_name
            self.mac_address = mac_address
            self.vlan_id = vlan_id
            self.id = id
    
        def to_dict(self):
            interface = {
                'name': self.name,
                'virtual_machine': {'name': self.vm_name},
                'mac_address': self.mac_address,
                'mode': 'access',
                'untagged_vlan': {'vid': self.vlan_id},
                # 'bridge': bridge
            }
            if self.id is not None:
                interface['id'] = self.id
            return interface
    
    
    class VirtualMachineTag:
        def __init__(self, name, id=None, color=NETBOX_DEFAULT_TAG_COLOR):
            self.name = name
            self.slug = name.lower().replace(' ', '-').replace('.', '_')
            self.color = color
            self.id = id
    
        def to_dict(self):
            vm_tag = {
                'name': self.name,
                'slug': self.slug,
                'color': self.color,
                'object_types': ['virtualization.virtualmachine'],
            }
            if self.id is not None:
                vm_tag['id'] = self.id
            return vm_tag
    
    
    def tag_from_netbox(netbox_tag):
        return VirtualMachineTag(
            id=netbox_tag['id'],
            name=netbox_tag['name'],
            # slug=netbox_tag.slug,
            color=netbox_tag['color'],
        ).to_dict()
    
    
    def vm_from_netbox(netbox_vm):
        return VirtualMachine(
            id=netbox_vm['id'],
            vmid=netbox_vm['custom_fields']['vmid'],
            name=netbox_vm['name'],
            status=netbox_vm['status']['value'],
            # FIXME: some of these are tricky
            node_name=netbox_vm['device']['name'] if netbox_vm['device'] else None,
            cluster_name=netbox_vm['cluster']['name'] if netbox_vm['device'] else None,
            role_id=netbox_vm['role']['id'] if netbox_vm['role'] else None,
            vcpus=netbox_vm['vcpus'],
            maxmem=netbox_vm['memory'],
            tags=[tag['name'] for tag in netbox_vm['tags']],
            maxdisk=netbox_vm.get('disk'),
            description=netbox_vm.get('comments'),
        ).to_dict()
    
    
    def interface_from_netbox(netbox_interface):
        return VirtualInterface(
            id=netbox_interface['id'],
            name=netbox_interface['name'],
            vm_name=netbox_interface['virtual_machine']['name'],
            mac_address=netbox_interface['mac_address'].upper(),
            vlan_id=netbox_interface['untagged_vlan']['vid'] if netbox_interface['untagged_vlan'] else None,
        ).to_dict()
    
    
    def tag_from_proxmox(tag_name, color=NETBOX_DEFAULT_TAG_COLOR):
        return VirtualMachineTag(
            tag_name,
            color,
        ).to_dict()
    
    
    def vm_from_proxmox(cluster_name, proxmox_node_name, proxmox_vm, tags=[]):
        maxdisk = proxmox_vm.get('maxdisk')
        if maxdisk is not None:
            maxdisk = int(maxdisk) / 2 ** 20  # B -> MB
        memory = int(proxmox_vm['maxmem']) / 2**20  # B -> MB
        return VirtualMachine(
            vmid=proxmox_vm['vmid'],
            name=proxmox_vm['name'],
            status='active' if proxmox_vm['status'] == 'running' else 'offline',
            node_name=proxmox_node_name,
            cluster_name=cluster_name,
            vcpus=proxmox_vm['cpus'],
            role_id=NETBOX_VM_ROLE_ID,
            maxmem=memory,
            tags=tags,
            maxdisk=maxdisk,
            description=proxmox_vm.get('description'),
        ).to_dict()
    
    
    def interface_from_proxmox(proxmox_vm_name, interface_name, proxmox_interface):
        # net[0-9]+: 'virtio=00:00:00:00:00:00,bridge=vmbr<VID>'
        mac = proxmox_interface.split('virtio=')[1].split(',')[0]
        vlan_id = int(proxmox_interface.split('bridge=vmbr')[1].split(',firewall')[0])
        return VirtualInterface(
            name=f'{proxmox_vm_name}:{interface_name}',
            vm_name=proxmox_vm_name,
            mac_address=mac.upper(),
            vlan_id=vlan_id,
        ).to_dict()