Skip to content

Commit

Permalink
22 contact assignment (#24)
Browse files Browse the repository at this point in the history
- Add checkbox for linking Services to Devices and Virtual Machine
- Changes default behavior for linked objects services to NOT link, **this breaks existing installations that use linked services** and requires the new option to be checked in import sources to maintain existing functionality.
- Adds contact assignment as an import option
- Links the contact assignments to devices and virtual machines.
  • Loading branch information
sol1-matt authored Apr 21, 2023
1 parent 46e2d4e commit 07c9a90
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 20 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ rm -r /usr/share/icingaweb2/modules/netbox

Download and extract the new release, then
move the module into the icingaweb2 modules path.
For example for version 3.1.16.8:
For example for version 3.1.16.9:

```
curl -L https://github.com/sol1/icingaweb2-module-netbox/archive/v3.1.16.8.tar.gz | tar xz
mv icingaweb2-module-netbox-3.1.16.8 /usr/share/icingaweb2/modules/netbox
curl -L https://github.com/sol1/icingaweb2-module-netbox/archive/v3.1.16.9.tar.gz | tar xz
mv icingaweb2-module-netbox-3.1.16.9 /usr/share/icingaweb2/modules/netbox
icingacli module enable netbox
```

Expand Down
37 changes: 33 additions & 4 deletions library/Netbox/Netbox.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,22 @@

namespace Icinga\Module\Netbox;

// use Icinga\Module\Director\Daemon\Logger;

class Netbox
{
public $object_type;
public $type_map = array();
public $prefix = 'nb';

// Netbox now stores some linked object in a generic 'object' which then has a type to say
// what kind of object it is, this maps those values to the $object types used in this module
public $netbox_object_map = array(
"virtualization.virtualmachine" => "vm",
"dcim.device" => "device",
"dcim.site" => "site"
);

function __construct($baseurl, $token, $proxy, $flattenseparator, $flattenkeys, $munge)
{
$this->baseurl = $baseurl;
Expand All @@ -18,8 +28,6 @@ function __construct($baseurl, $token, $proxy, $flattenseparator, $flattenkeys,
$this->munge = $munge;
}



private function httpget(string $url)
{
$ch = curl_init($url);
Expand Down Expand Up @@ -130,6 +138,15 @@ private function makeHelperKeys(array $in) {
$row->keyid = $this->keymaker($row->name);
}

// Contact assignment uses linked object, build a key id from the contact and object names
if ($this->object_type == 'contact_assignment') {
if (property_exists($row, 'object') and property_exists($row, 'contact')) {
if (property_exists($row->contact, 'name') and property_exists($row->object, 'name')) {
$row->keyid = $this->keymaker($row->contact->name . ' ' . $row->object->name);
}
}
}

// Extract the address for the primary ip
// TODO: ipv6 ??
$row->primary_ip_address = NULL; // Make empty field for column headings if no values exist
Expand Down Expand Up @@ -192,6 +209,13 @@ private function makeHelperKeys(array $in) {
}
}

// This turns a linked object into it's proper key id if we know how to match that.
if (property_exists($row, 'object') and property_exists($row, 'content_type') and array_key_exists($row->content_type, $this->netbox_object_map)) {
if (property_exists($row->object, 'name')) {
$row->object_keyid = $this->keymaker($row->object->name, $this->netbox_object_map[$row->content_type]);
}
}

// Custom fields for Netbox
// Icinga satellite
/*
Expand Down Expand Up @@ -598,13 +622,18 @@ public function contactGroups($filter, int $limit = 0)
return $this->get_netbox("/tenancy/contact-groups/?" . $this->default_filter($filter, ""), $limit);
}

public function contactModes($filter, int $limit = 0)
public function contactRoles($filter, int $limit = 0)
{
$this->object_type = 'contact_role';
return $this->get_netbox("/tenancy/contact-roles/?" . $this->default_filter($filter, ""), $limit);
}

// TODO: contactAssignement
public function contactAssignments($filter, int $limit = 0)
{
$this->object_type = 'contact_assignment';
return $this->get_netbox("/tenancy/contact-assignments/?" . $this->default_filter($filter, ""), $limit);
}


// Other
public function platforms($filter, int $limit = 0)
Expand Down
70 changes: 58 additions & 12 deletions library/Netbox/ProvidedHook/Director/ImportSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class ImportSource extends ImportSourceHook
const ContactMode = 54;
const ContactGroupMode = 56;
const ContactRoleMode = 58;
const ContactAssignmentMode = 59;

// Other
const PlatformMode = 60;
Expand All @@ -70,6 +71,26 @@ class ImportSource extends ImportSourceHook
// const FHRPAssociation = 30;



// Assume the list of contacts assignments passed in are all the same type
// as the things passed in.
private function get_contact_assignments($contact_assignments, $things) {
$output = array();
foreach ($things as $thing) {
// make an array here for a list of contacts
$thing->contacts = array();
$thing->contact_keyids = array();
foreach ($contact_assignments as $contact_assignment) {
if ($contact_assignment->object->id == $thing->id) {
array_push($thing->contacts, $contact_assignment->contact->name);
array_push($thing->contact_keyids, strtolower("nbcontact " . preg_replace('/__+/i', '_', preg_replace('/[^0-9a-zA-Z_\-. ]+/i', '_', $contact_assignment->contact->name))));
}
}
$output = array_merge($output, [(object)$thing]);
}
return $output;
}

// TODO: VRF is linked to devices/vm's through ip's. If we need VRF's then we should
// create an array in the import of all the linked ip's and vrf inside the importer
// rather than leaving it to the user to create host templates to link it all together.
Expand Down Expand Up @@ -238,6 +259,7 @@ public static function addSettingsFormFields(QuickForm $form)
self::ContactMode => $form->translate('Contacts'),
self::ContactGroupMode => $form->translate('Contact Groups'),
self::ContactRoleMode => $form->translate('Contact Roles'),
self::ContactAssignmentMode => $form->translate('Contact Assignments'),

// Other
self::PlatformMode => $form->translate('Platforms'),
Expand Down Expand Up @@ -283,6 +305,18 @@ public static function addSettingsFormFields(QuickForm $form)
'description' => $form->translate('Optional search filter to the url to limit netbox data returned (Default: status=active is added without a filter selected)')
));

$form->addElement('checkbox', 'linked_services', array(
'label' => $form->translate('Link Services'),
'required' => false,
'description' => $form->translate('Checking this box will link Service objects for devices and virtual machines during their import. WARNING: This could increase API load to Netbox if you have a lot of services.')
));

$form->addElement('checkbox', 'linked_contacts', array(
'label' => $form->translate('Link Contacts'),
'required' => false,
'description' => $form->translate('Checking this box will link Contact objects for devices and virtual machines during their import. WARNING: This could increase API load to Netbox if you have a lot of contact assignements.')
));

// $form->addElement('multiCheckbox', 'associations', array(
// 'label' => $form->translate("Associate additional data"),
// 'required' => false,
Expand All @@ -296,6 +330,22 @@ public static function addSettingsFormFields(QuickForm $form)

}

private function getLinkedObjects($baseurl, $apitoken, $proxy, $linkservices, $linkcontacts, $content_type, $things)
{
$netboxLinked = new Netbox($baseurl, $apitoken, $proxy, "", "", "");
$services = array();
if ($linkservices) {
$services = $netboxLinked->allservices("", 0);
}
$contact_assignments = array();
if ($linkcontacts) {
$contact_assignments = $netboxLinked->contactAssignments("content_type=" . $content_type, 0);
}
$ranges = $netboxLinked->ipRanges("", 0);
return $this->devices_with_services($services, $this->get_contact_assignments($contact_assignments, $this->get_ip_range($ranges, $things)));

}

public function fetchData(int $limit = 0)
{
$baseurl = $this->getSetting('baseurl');
Expand All @@ -306,15 +356,13 @@ public function fetchData(int $limit = 0)
$flatten = (string)$this->getSetting('flatten');
$flattenkeys = ((string)$this->getSetting('flattenkeys') == '') ? array() : explode(",", (string)$this->getSetting('flattenkeys'));
$munge = ((string)$this->getSetting('munge') == '') ? array() : explode(",", (string)$this->getSetting('munge'));
$linkcontacts = $this->getSetting('linked_contacts');
$linkservices = $this->getSetting('linked_services');
$netbox = new Netbox($baseurl, $apitoken, $proxy, $flatten, $flattenkeys, $munge);
switch ($mode) {
// VM's
case self::VMMode:
$netboxLinked = new Netbox($baseurl, $apitoken, $proxy, "", "", "");
$services = $netboxLinked->allservices("", 0);
$ranges = $netboxLinked->ipRanges("", 0);
$vms = $this->get_ip_range($ranges, $netbox->virtualMachines($filter, $limit));
return $this->devices_with_services($services, $vms);
return $this->getLinkedObjects($baseurl, $apitoken, $proxy, $linkservices, $linkcontacts, "virtualization.virtualmachine", $netbox->virtualMachines($filter, $limit));
case self::ClusterMode:
return $netbox->clusters($filter, $limit);
case self::ClusterGroupMode:
Expand All @@ -326,11 +374,7 @@ public function fetchData(int $limit = 0)

// Device
case self::DeviceMode:
$netboxLinked = new Netbox($baseurl, $apitoken, $proxy, "", "", "");
$services = $netboxLinked->allservices("", 0);
$ranges = $netboxLinked->ipRanges("", 0);
$devices = $this->get_ip_range($ranges, $netbox->devices($filter, $limit));
return $this->devices_with_services($services, $devices, $filter);
return $this->getLinkedObjects($baseurl, $apitoken, $proxy, $linkservices, $linkcontacts, "dcim.device", $netbox->devices($filter, $limit));
case self::DeviceRoleMode:
return $netbox->deviceRoles($filter, $limit);
case self::DeviceTypeMode:
Expand Down Expand Up @@ -371,8 +415,10 @@ public function fetchData(int $limit = 0)
case self::ContactGroupMode:
return $netbox->contactGroups($filter, $limit);
case self::ContactRoleMode:
return $netbox->contactModes($filter, $limit);

return $netbox->contactRoles($filter, $limit);
case self::ContactAssignmentMode:
return $netbox->contactAssignments($filter, $limit);

// Other
case self::PlatformMode:
return $netbox->platforms($filter, $limit);
Expand Down
2 changes: 1 addition & 1 deletion module.info
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Name: Netbox
Version: 3.1.16.8
Version: 3.1.16.9
Depends: director
Description: Import devices, sites and other objects from Netbox

0 comments on commit 07c9a90

Please sign in to comment.