Netbox Sync MAC Addresses Task¤
task api name:
sync_mac_addresses
The Netbox Sync MAC Addresses Task synchronizes interface MAC addresses from live network devices into NetBox. The task collects current MAC address state from devices, compares it against existing NetBox MAC address objects, and applies create or update operations to bring NetBox into alignment.
How It Works¤
The task follows a three-step pipeline:
- Collect live state — Run a Nornir
parse_ttpjob against the target devices to collect live MAC addresses per interface. - Fetch NetBox state — Retrieve existing MAC address objects from NetBox for the discovered MACs.
- Reconcile — Compare live versus NetBox state and apply changes:
- Create — MAC not present in NetBox at all: create a new MAC address object assigned to the correct interface.
- Update — MAC exists in NetBox but has no
assigned_object(unassigned): assign it to the correct interface. - In sync — MAC already assigned to the correct interface: no action needed.
- Error — MAC exists in NetBox and is assigned to a different interface: report a conflict error without modifying the record.
Result Structure¤
Both dry-run and live-run return the same structure, keyed by device name:
{
"<device>": {
"created": ["aa:bb:cc:dd:ee:01", "aa:bb:cc:dd:ee:02"],
"updated": ["aa:bb:cc:dd:ee:03"],
"in_sync": ["aa:bb:cc:dd:ee:04"]
}
}
In dry-run mode (dry_run=True) the lists reflect what would happen — no changes are written to NetBox.
In live-run mode (dry_run=False, default) the lists reflect what was actually done.
Conflict errors (MAC assigned to a different interface) are reported in res["errors"] and do not appear in any action list.
Filtering¤
MAC address collection can be scoped using glob patterns so that only a subset of interfaces and MACs is considered:
filter_by_name— match interface names, e.g."Loopback*"or"Ethernet[1-4]"filter_by_description— match interface descriptions, e.g."uplink*"or"p2p*"filter_by_mac— match MAC address strings, e.g."aa:bb:cc:*"
All filters are applied before the reconciliation step. Interfaces or MACs that do not match are completely ignored — they are neither created nor updated.
Branching Support¤
The task is branch-aware and can push changes into a NetBox branch. The Netbox Branching Plugin must be installed. Specify the branch parameter; the branch is created automatically if it does not already exist.
Duplicate MAC Handling¤
NetBox permits multiple MAC address records with the same MAC value. The task handles this safely:
- If a MAC exists in NetBox with an assigned interface that matches the live data — reported as
in_sync. - If a MAC exists in NetBox with an assigned interface that differs from the live data — reported as a conflict error; the record is not modified.
- If a MAC exists in NetBox but is unassigned — the record is updated to point at the correct interface.
- If both an assigned (conflicting) and an unassigned copy of the same MAC exist in NetBox, the assigned (conflicting) entry takes precedence and a conflict error is raised.
Examples¤
Sync MAC addresses for a list of devices:
nf#netbox sync mac-addresses devices ceos-spine-1 ceos-spine-2
Preview changes without writing to NetBox (dry run):
nf#netbox sync mac-addresses devices ceos-spine-1 dry-run
Restrict sync to Ethernet interfaces only:
nf#netbox sync mac-addresses devices ceos-spine-1 filter-by-name "Ethernet*"
Restrict sync to interfaces whose description matches a glob pattern:
nf#netbox sync mac-addresses devices ceos-spine-1 filter-by-description "uplink*"
Restrict sync to a specific MAC prefix:
nf#netbox sync mac-addresses devices ceos-spine-1 filter-by-mac "aa:bb:cc:*"
Sync MAC addresses into a NetBox branch:
nf#netbox sync mac-addresses devices ceos-spine-1 ceos-spine-2 branch sprint-42-macs
Sync using Nornir host filters instead of explicit device names:
nf#netbox sync mac-addresses FC spine
from norfab.core.nfapi import NorFab
nf = NorFab(inventory="./inventory.yaml")
nf.start()
client = nf.make_client()
# sync MAC addresses for specific devices
result = client.run_job(
"netbox",
"sync_mac_addresses",
workers="any",
kwargs={
"devices": ["ceos-spine-1", "ceos-spine-2"],
},
)
# dry run — preview creates/updates without writing
result = client.run_job(
"netbox",
"sync_mac_addresses",
workers="any",
kwargs={
"devices": ["ceos-spine-1", "ceos-spine-2"],
"dry_run": True,
},
)
# restrict sync to Ethernet interfaces only
result = client.run_job(
"netbox",
"sync_mac_addresses",
workers="any",
kwargs={
"devices": ["ceos-spine-1"],
"filter_by_name": "Ethernet*",
},
)
# restrict sync to interfaces with a specific description pattern
result = client.run_job(
"netbox",
"sync_mac_addresses",
workers="any",
kwargs={
"devices": ["ceos-spine-1"],
"filter_by_description": "uplink*",
},
)
# restrict sync to a specific MAC prefix
result = client.run_job(
"netbox",
"sync_mac_addresses",
workers="any",
kwargs={
"devices": ["ceos-spine-1"],
"filter_by_mac": "aa:bb:cc:*",
},
)
# sync into a NetBox branch
result = client.run_job(
"netbox",
"sync_mac_addresses",
workers="any",
kwargs={
"devices": ["ceos-spine-1", "ceos-spine-2"],
"branch": "sprint-42-macs",
},
)
# use Nornir host filters instead of explicit device names
result = client.run_job(
"netbox",
"sync_mac_addresses",
workers="any",
kwargs={
"FC": "spine",
},
)
nf.destroy()
NORFAB Netbox Sync MAC Addresses Command Shell Reference¤
NorFab shell supports these command options for the sync_mac_addresses task:
nf# man tree netbox.sync.mac-addresses
root
└── netbox: Netbox service
└── sync: Sync Netbox data
└── mac-addresses: Sync device MAC addresses with NetBox
├── timeout: Job timeout in seconds
├── workers: Filter worker to target, default 'any'
├── verbose-result: Control output details, default 'False'
├── progress: Display progress events, default 'True'
├── instance: Netbox instance name to target
├── dry-run: Return reconciliation plan without pushing changes to NetBox
├── devices: List of NetBox device names to sync
├── filter-by-name: Glob pattern to restrict sync by interface name, e.g. 'Ethernet*'
├── filter-by-description: Glob pattern to restrict sync by interface description
├── filter-by-mac: Glob pattern to restrict sync by MAC address, e.g. 'aa:bb:*'
├── branch: Branching plugin branch name to push changes into
├── FO: Filter Nornir hosts using Filter Object
├── FB: Filter Nornir hosts by name using Glob Patterns
├── FH: Filter Nornir hosts by hostname
├── FC: Filter Nornir hosts by name containment
├── FR: Filter Nornir hosts by name using Regular Expressions
├── FG: Filter Nornir hosts by group
├── FP: Filter Nornir hosts by hostname using IP Prefix
├── FL: Filter Nornir hosts by names list
├── FM: Filter Nornir hosts by platform
└── FN: Negate the Nornir host filter match
nf#
Python API Reference¤
Synchronize MAC addresses from live devices into NetBox.
The task follows a three-step pipeline:
- Collect live state: Run a Nornir
parse_ttpget interfaces job against devices to collect live MAC addresses per interface. - Fetch NetBox state: Retrieve existing MAC address objects from NetBox.
- Reconcile: Create new MAC address objects or update existing unassigned ones to point at the correct interface.
Dry-run mode (dry_run=True): returns the reconciliation plan without
making any changes. Result is keyed by device name::
{
"<device>": {
"created": ["aa:bb:cc:dd:ee:01", ...],
"updated": ["aa:bb:cc:dd:ee:02", ...],
"in_sync": ["aa:bb:cc:dd:ee:03", ...]
}
}
Live-run mode (dry_run=False, default): applies changes and returns
the same structure showing what was done.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
job
|
Job
|
NorFab Job object containing relevant metadata. |
required |
instance
|
str
|
The NetBox instance name to use. |
None
|
dry_run
|
bool
|
If True, no changes will be made to NetBox. |
False
|
timeout
|
int
|
Timeout in seconds for the Nornir parse_ttp job. |
60
|
devices
|
list
|
List of device names to sync. |
None
|
branch
|
str
|
NetBox branch name to use. |
None
|
filter_by_name
|
str
|
Glob pattern to restrict which interfaces
are included by name, e.g. |
None
|
filter_by_description
|
str
|
Glob pattern to restrict which
interfaces are included by description, e.g. |
None
|
filter_by_mac
|
str
|
Glob pattern to restrict which MAC addresses
are included, e.g. |
None
|
**kwargs
|
Any
|
Additional Nornir host filter keyword arguments passed to
|
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
Result |
Result
|
Per-device action summary with |
Source code in norfab\workers\netbox_worker\interfaces_tasks.py
1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 | |