Skip to content

Commit

Permalink
connectivity flow updates
Browse files Browse the repository at this point in the history
  • Loading branch information
Costya-Y committed Apr 22, 2024
1 parent 4bf7b60 commit 7b76977
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 34 deletions.
17 changes: 9 additions & 8 deletions cloudshell/cp/proxmox/flows/connectivity_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ def get_vnics(self, vm_id: int) -> Collection[VnicInfo]:
def get_vnic_info(vnic: dict) -> VnicInfo:
return VnicInfo(
vnic.get("name"),
int(self.vnic_name_to_index(vnic.name, vm)),
self._network_can_be_replaced(vnic.network),
int(vnic.get("index")),
True,
)

return tuple(map(get_vnic_info, self._api.get_vm_ifaces_info(vm_id)))
Expand All @@ -117,12 +117,13 @@ def set_vlan(
network = self._networks[net_settings.name]

logger.info(f"Connecting {network} to the {target}.{vnic_name} iface")
try:
vnic = target.get_vnic(vnic_name)
except VnicNotFound:
vnic = create_new_vnic(target, network, vnic_name)
else:
vnic.connect(network)
# try:
# vnic = target.get_vnic(vnic_name)
# except VnicNotFound:
# vnic = create_new_vnic(target, network, vnic_name)
# else:
# vnic.connect(network)
mac = ""

return vnic.mac_address

Expand Down
77 changes: 53 additions & 24 deletions cloudshell/cp/proxmox/handlers/proxmox_handler.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import logging
import re
import time
from functools import cached_property, partial
from typing import TYPE_CHECKING, Any
Expand Down Expand Up @@ -140,32 +141,49 @@ def get_vm_info(self, vm_id: int) -> dict:
)
raise e

def get_vm_ifaces_info(self, vm_id: int) -> list[dict]:
"""Get Virtual Machine network interfaces details."""
def get_vm_ifaces_info(self, vm_id):
dataregexp = re.compile(
r"^(?P<type>\w+)=(?P<mac>([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})+),"
r".*bridge=(?P<bridge>\w+),"
r".*tag=(?P<vlan>\d+)(,.*)?$"
)
# net0: virtio=02:00:00:00:00:01,bridge=vmbr0,tag=10
# [model=](e1000 | e1000-82540em | e1000-82544gc | e1000-82545em | e1000e
# | i82551 | i82557b | i82559er | ne2k_isa | ne2k_pci | pcnet | rtl8139
# | virtio | vmxnet3) [,bridge=<bridge>] [,firewall=<boolean>]
# [,link_down=<boolean>] [,macaddr=<XX:XX:XX:XX:XX:XX>] [,mtu=<integer>]
# [,queues=<integer>] [,rate=<number>] [,tag=<integer>]
# [,trunks=<vlanid[;vlanid...]>]
result = {}
try:
node = self.get_node_by_vmid(vm_id)
data = self._obj.get_net_ifaces(node=node, vm_id=vm_id)

ifaces = []
for iface in data.get("result", []):
iface_ipv4 = "Undefined"
iface_ipv6 = "Undefined"
for ip in iface.get(IP_LIST, []):
if ip.get(ADDRESS_TYPE) == "ipv4":
iface_ipv4 = ip.get(IP_ADDRESS)
elif ip.get(ADDRESS_TYPE) == "ipv6":
iface_ipv6 = ip.get(IP_ADDRESS)

ifaces.append(
{
"name": iface.get(IFACE_NAME),
"mac": iface.get(MAC),
"ipv4": iface_ipv4,
"ipv6": iface_ipv6,
}
)

return ifaces
config = self._obj.get_vm_config(node=node, vm_id=vm_id)
guest_data = self._obj.get_net_ifaces(node=node, vm_id=vm_id)
guest_ifaces = {x.get(MAC): x for x in guest_data.get("result", [])}
for k, v in config.items():
if k.startswith("net"):
vnic_data = dataregexp.search(v).groupdict()
mac = vnic_data.pop("mac")
iface = guest_ifaces.get(mac)
iface_ipv4 = "Undefined"
iface_ipv6 = "Undefined"
if vnic_data:
for ip in iface.get(IP_LIST, []):
if ip.get(ADDRESS_TYPE) == "ipv4":
iface_ipv4 = ip.get(IP_ADDRESS)
elif ip.get(ADDRESS_TYPE) == "ipv6":
iface_ipv6 = ip.get(IP_ADDRESS)
result[mac] = vnic_data.update(
{"name": k,
"index": k.replace("net", ""),
"guest_name": iface.get(IFACE_NAME),
"mac": iface.get(MAC),
"ipv4": iface_ipv4,
"ipv6": iface_ipv6,
}
)

return result
except VmDoesNotExistException as e:
logger.error(
f"Virtual machine with vm_id {vm_id} doesn't exist."
Expand Down Expand Up @@ -209,6 +227,17 @@ def _task_waiter(
if status == "running" or exit_status.upper() != "OK":
raise UnsuccessfulOperationException(msg)

def attach_interface(self, vm_id: int, vnic_id: int) -> None:
"""Attach interface to Virtual Machine."""
node = self.get_node_by_vmid(vm_id)
upid = self._obj.attach_interface(node=node, vm_id=vm_id, vnic_id=vnic_id)

self._task_waiter(
node=node,
upid=upid,
msg=f"Failed to attach interface {vnic_id} during {{attempt*timeout}} sec"
)

def get_snapshots_list(self, vm_id: int) -> list[int | bytes]:
"""Get list of existing snapshots."""
node = self.get_node_by_vmid(vm_id)
Expand Down
49 changes: 47 additions & 2 deletions cloudshell/cp/proxmox/handlers/rest_api_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,10 +311,38 @@ def assign_vlan(
data += f",bridge={vlan_tag},tag={vlan_tag},firewall={int(enable_firewall)}"
return self._do_post(
path=f"nodes/{node}/qemu/{vm_id}/config",
json={interface_id: data},
json={f"net{interface_id}": data},
http_error_map=error_map,
cookies={COOKIES: self.ticket}
)

@Decorators.get_data()
def attach_interface(
self,
node: str,
network_bridge: str,
interface_id: str,
vm_id: int,
vlan_tag: str,
interface_type: str = "virtio",
mac_address: str = "",
enable_firewall: bool = True,
) -> requests.Response:
""""""
error_map = {
400: ParamsException,
401: AuthAPIException,
}
data = f"{interface_type}"
if mac_address:
data += f":{mac_address}"
data += f",bridge={network_bridge},tag={vlan_tag},firewall={int(enable_firewall)}"
return self._do_put(
path=f"nodes/{node}/qemu/{vm_id}/config",
http_error_map=error_map,
data=f"net{interface_id}={data}",
cookies={COOKIES: self.ticket}
)
# return self._do_post(
# path=f"nodes/{node}/network",
# json={"type": vlan_type, "iface": vlan_name, "autostart": int(autostart),
Expand Down Expand Up @@ -604,6 +632,21 @@ def get_vm_osinfo(self, node: str, vm_id: int) -> requests.Response:
cookies={COOKIES: self.ticket}
)

@Decorators.get_data()
def get_vm_config(self, node: str, vm_id: int) -> requests.Response:
""""""
error_map = {
400: ParamsException,
401: AuthAPIException,
}
# self.session.headers.update({})

return self._do_get(
path=f"/nodes/{node}/qemu/{vm_id}/config",
http_error_map=error_map,
cookies={COOKIES: self.ticket}
)


if __name__ == "__main__":
# session = requests.Session()
Expand All @@ -624,7 +667,9 @@ def get_vm_osinfo(self, node: str, vm_id: int) -> requests.Response:
password="Password1"
)
api.connect()
res = api.get_vm_ifaces(node="proxmox1", vm_id=101)
res = api.attach_interface(node="proxmox1", vm_id=101, network_bridge="vmbr1",
interface_id="3", vlan_tag="65")
res1 = api.get_vm_ifaces(node="proxmox1", vm_id=101)
res = api.get_task_status(node="proxmox1", upid="UPID:proxmox1:0034308A:11F8AFA1:660C23DC:qmsnapshot:100:root@pam:")

# print(get_node_by_vmid(vm_id=102))
Expand Down

0 comments on commit 7b76977

Please sign in to comment.