Skip to content

Commit

Permalink
Adding VM Interfaces and ignoring duplicate Virtual Machines and VM I…
Browse files Browse the repository at this point in the history
…nterfaces.
  • Loading branch information
emersonfelipesp committed Oct 11, 2024
1 parent cf2d999 commit 6f74df6
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 18 deletions.
Empty file modified Pipfile.lock
100644 → 100755
Empty file.
149 changes: 142 additions & 7 deletions netbox_proxbox/backend/routes/netbox/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,27 @@ async def _get_by_kwargs(self, **kwargs):

logger.info(f"[GET] Searching '{self.object_name}' by kwargs {kwargs}.")
try:
response = await asyncio.to_thread(self.pynetbox_path.get, **kwargs)
return response
try:
response = await asyncio.to_thread(self.pynetbox_path.get, **kwargs)
return response
except Exception as error:
if "get() returned more than one result." in f"{error}":
logger.info(f"[CHECK DUPLICATE] Object '{self.object_name}' with the same name already found. Checking with '.filter' method")

if self.endpoint == "interfaces" and self.primary_field == "device":

logger.info("[CHECK DUPLICATE] Checking duplicate device using as PRIMARY FIELD the DEVICE.")
result_by_primary = await asyncio.to_thread(self.pynetbox_path.get, virtual_machine=self.primary_field_value)

if result_by_primary:
if result_by_primary.virtual_machine == self.primary_field_value:
logger.info("[CHECK DUPLICATE] Interface with the same Device found. Duplicated object, returning it.")
return result_by_primary

else:
logger.info("[CHECK DUPLICATE] If interface equal, but different devices, return as NOT duplicated.")
return None


except ProxboxException as error: raise error

Expand Down Expand Up @@ -337,8 +356,28 @@ async def post(
data["tags"] = [self.nb.tag.id]
else:
data["tags"].append(self.nb.tag.id)

try:
logger.info(f"[POST] Trying to create {self.object_name} object on Netbox.")

response = await asyncio.to_thread(self.pynetbox_path.create, data)


response = await asyncio.to_thread(self.pynetbox_path.create, data)
except Exception as error:

if "['The fields virtual_machine, name must make a unique set.']}" in f"{error}":
logger.error(f"Error trying to create 'Virtual Machine Interface' because the same 'virtual_machine' name already exists.\nPayload: {data}")
return None

if "['Virtual machine name must be unique per cluster.']" in f"{error}":
logger.error(f"Error trying to create 'Virtual Machine' because Virtual Machine Name must be unique.\nPayload: {data}")
return None

else:
raise ProxboxException(
message=f"[POST] Error trying to create '{self.object_name}' object on Netbox.",
python_exception=error
)

if response:
logger.info(f"[POST] '{self.object_name}' object created successfully. {self.object_name} ID: {response.id}")
Expand All @@ -350,7 +389,7 @@ async def post(
logger.info(f"[POST] '{self.object_name}' object already exists on Netbox. Returning it.")
return check_duplicate_result

except ProxboxException as error: raise error
#except ProxboxException as error: raise error

except Exception as error:
raise ProxboxException(
Expand Down Expand Up @@ -419,11 +458,99 @@ async def _check_duplicate(self, search_params: dict = None, object: dict = None
logger.info("[CHECK DUPLICATE] (0.5) Checking object using only custom PRIMARY FIELD and Proxbox TAG provided by the class attribute.")
print(f"primary field: {self.primary_field} - primary_field_value: {self.primary_field_value}")


print(f'self.primary_field = {self.primary_field} / {self.endpoint}')

if self.primary_field == "address":
logger.info("[CHECK DUPLICATE] Checking duplicate device using as PRIMARY FIELD the ADDRESS.")

result_by_primary = await asyncio.to_thread(self.pynetbox_path.get, address=self.primary_field_value)
try:
result_by_primary = await asyncio.to_thread(self.pynetbox_path.get, address=self.primary_field_value)

except Exception as error:
if "get() returned more than one result" in f"{error}":
try:
result_by_primary = await asyncio.to_thread(self.pynetbox_path.filter, address=self.primary_field_value)

if result_by_primary:
for address in result_by_primary:
print(f"ADDRESS OBJECT: {address}")

except Exception as error:
raise ProxboxException(
message="Error trying to filter IP ADDRESS objects.",
python_exception=error,
)

print(f"self.primary_field_value = {self.primary_field_value}")

if result_by_primary:
logger.info("[CHECK DUPLICATE] IP Address with the same network found. Returning it.")
return result_by_primary

if self.primary_field == "virtual_machine" and self.endpoint == "interfaces":
logger.info("[CHECK DUPLICATE] Checking duplicate device using as PRIMARY FIELD the DEVICE.")

result_by_primary = None

try:
#
# THE ERROR IS HERE.
#
# GET
logger.error("THE ERROR IS HERE.")
result_by_primary = await asyncio.to_thread(
self.pynetbox_path.get,
virtual_machine=self.primary_field_value,
name=object.get("name")
)
logger.error(f"result_by_primary: {result_by_primary}")

if result_by_primary:
for interface in result_by_primary:
print(f"INTERFACE OBJECT: {interface} | {interface.virtual_machine}")

print(f"interface.virtual_machine: {interface.virtual_mchine} | primary_field_value: {self.primary_field_value}")
if interface.virtual_machine == self.primary_field_value:
return interface
else:
return None

except Exception as error:
logger.info(f"[CHECK DUPLICATE] Error trying to get interface using only 'virtual_machine' field as parameter.\n >{error}")
if "get() returned more than one result" in f"{error}":
# FILTER
logger.info("[CHECK DUPLICATE] Found more than one VM INTERFACE object with the same 'virtual_machine' field. Trying to use '.filter' pynetbox method now.")


try:
result_by_primary = await asyncio.to_thread(
self.pynetbox_path.filter,
virtual_machine=self.primary_field_value,
name=object.get("name")
)

if result_by_primary:
for interface in result_by_primary:
print(f"INTERFACE OBJECT: {interface} | {interface.virtual_machine}")

print(f"interface.virtual_machine: {interface.virtual_mchine} | primary_field_value: {self.primary_field_value}")
if interface.virtual_machine == self.primary_field_value:
return interface
else:
return None

except Exception as error:
raise ProxboxException(
message="Error trying to get 'VM Interface' object using 'virtual_machine' and 'name' fields.",
python_exception=f"{error}"
)






else:
result_by_primary = await asyncio.to_thread(self.pynetbox_path.get,
{
Expand All @@ -433,6 +560,16 @@ async def _check_duplicate(self, search_params: dict = None, object: dict = None

print(f"result_by_primary: {result_by_primary}")
if result_by_primary:

if self.endpoint == "interfaces":
logger.info("[CHECK DUPLICATE] If duplicate interface found, check if the devices are the same.")
if result_by_primary.device == self.primary_field_value:
logger.info("[CHECK DUPLICATE] Interface with the same Device found. Duplicated object, returning it.")
return result_by_primary
else:
logger.info("[CHECK DUPLICATE] If interface equal, but different devices, return as NOT duplicated.")
return None

logger.info(f"[CHECK_DUPLICATE] Object found on Netbox. Returning it.")
print(f'result_by_primary: {result_by_primary}')
return result_by_primary
Expand Down Expand Up @@ -469,8 +606,6 @@ async def _check_duplicate(self, search_params: dict = None, object: dict = None

result_by_device = await asyncio.to_thread(self.pynetbox_path.get,
name=object.get("name"),
device__id=device_obj.id,
#device=device_obj,
tag=[self.nb.tag.slug]
)

Expand Down
1 change: 1 addition & 0 deletions netbox_proxbox/backend/routes/netbox/ipam/ip_addresses.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class IPAddress(NetboxBase):
app: str = "ipam"
endpoint: str = "ip_addresses"
object_name: str = "IP Address"

primary_field: str = "address"

async def get_base_dict(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ class VMInterface(NetboxBase):
endpoint = "interfaces"
object_name = "Virtual Machine Interface"

primary_field: str = "virtual_machine"

async def get_base_dict(self):

virtual_machine = await VirtualMachine(nb = self.nb).get()
Expand Down
23 changes: 12 additions & 11 deletions netbox_proxbox/backend/routes/proxbox/clusters/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,9 @@ async def get_nodes(
):

"""Get Proxmox Nodes from a Cluster"""


result = []


await websocket.send_text(data = "Test message")

for px in pxs:

# Get Cluster from Netbox based on Proxmox Cluster Name
Expand Down Expand Up @@ -201,7 +197,7 @@ async def get_nodes(

try:
await log(websocket, f"Creating Netbox '{interface_name}' Interface on '{current_node.name}' Device...")
create_interface = await Interface(nb=nb).post(data={
create_interface = await Interface(nb=nb, primary_field_value=current_node.id).post(data={
"device": current_node.id,
"name": interface_name,
"enabled": enabled,
Expand All @@ -222,7 +218,7 @@ async def get_nodes(
cidr = interface.get("cidr")
print(f"cidr: {cidr}")

if cidr:
if create_interface and cidr:
try:
await log(websocket, "Interface with CIDR/Network. Creating the IP Address object on Netbox...")
# If interface with network configured, create IP Address and attach interface to it.
Expand All @@ -237,7 +233,7 @@ async def get_nodes(
message="Error trying to create IP Address of Interface on Netbox.",
python_exception=error
)



if interface_type == "bridge":
Expand All @@ -253,11 +249,16 @@ async def get_nodes(

try:
await log(websocket, "Searching children interface of a bridge.")
netbox_port = await Interface(nb=nb).get(
device=current_node.name,
print(f"current_node.id: {current_node.id} / current_node: {current_node} / current_node.name: {current_node.name}")
netbox_port = await Interface(nb=nb, primary_field_value=current_node.id).get(
name=port
)
except Exception as error: raise ProxboxException(message="Error trying to search bridge child interface.", python_exception=error)
except Exception as error:
raise ProxboxException(
message="Error trying to search bridge child interface.",
python_exception=f"{error}"
)


print(f"port: {port}")
print(f"netbox_port: {netbox_port}")
Expand All @@ -280,7 +281,7 @@ async def get_nodes(
await log(websocket, f"Creating interface '{port}'...")

try:
new_netbox_port = await Interface(nb=nb).post(data={
new_netbox_port = await Interface(nb=nb, primary_field_value=current_node.id).post(data={
"device": current_node.id,
"name": port,
"enabled": enabled,
Expand Down
Empty file modified poetry.lock
100644 → 100755
Empty file.
Empty file modified pyproject.toml
100644 → 100755
Empty file.
Empty file modified standalone/package-lock.json
100644 → 100755
Empty file.

1 comment on commit 6f74df6

@Uzoma8Chi
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It still does not work for me.
'''
/opt/netbox/venv/lib/python3.12/site-packages/netbox_proxbox/proxbox_api/create/virtualization.py:134: RuntimeWarning: coroutine 'tag' was never awaited
return f"Error creating the '{proxmox_cluster_name}' cluster. Possible errors: the name '{proxmox_cluster_name}' is already used."
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
[OK] Cluster created. -> Error creating the 'testcluster' cluster. Possible errors: the name 'testcluster' is already used.
'''

Please sign in to comment.