From b75f99b2ca8cc3801dd3af13e482b3c7a7454910 Mon Sep 17 00:00:00 2001 From: Fabian Herbert <Fabian.herbert@stud.h-da.de> Date: Mon, 19 May 2025 06:56:28 +0000 Subject: [PATCH] not perfect, but on a good way. The Local Netbox api is missing --- applications/inventory-manager-netbox/Main.go | 65 +- .../config/configNetbox.yaml | 2 +- .../netboxManager/netboxManager.go | 592 ++++++++++-------- .../netboxManager/netboxUtility.go | 369 ++++++++--- 4 files changed, 677 insertions(+), 351 deletions(-) diff --git a/applications/inventory-manager-netbox/Main.go b/applications/inventory-manager-netbox/Main.go index d5742ef9a..2e1179678 100644 --- a/applications/inventory-manager-netbox/Main.go +++ b/applications/inventory-manager-netbox/Main.go @@ -17,6 +17,9 @@ const ( Reset = "\033[0m" ) +// Ich habe einen go.mod eintrage gemacht: +// replace code.fbi.h-da.de/danet/gosdn/internal/netboxapi => ./internal/netboxapi + func main() { var configPathGosdn = flag.String("configGosdn", "config/config.yaml", "Path to the Gosdn configuration file") var configPathNetbox = flag.String("configNetbox", "config/configNetbox.yaml", "Path to the NetBox configuration file") @@ -44,7 +47,66 @@ func main() { if len(elements.Mne) != elementeFigure { //log.Printf("Es wurden %d Elemente gefunden", len(elementss.Mne)) //take the date into Netbox + + + err = netboxManager.FeedNetbox(elements, configPathNetbox) + + + if err != nil { + log.Fatalf("Error creating device: %v", err) + } else { + log.Println("everything is great!") + elementeFigure = len(elements.Mne) + log.Printf("there are %d elementeFigur", elementeFigure) + } + + } else { + log.Printf("The controller has no new data for me. Continuing is pointless^^ elements is empty") + time.Sleep(1 * time.Second) + } + duration = time.Since(start) // Dauer berechnen + //log.Printf("Netbox Dauer: %s\n", duration) + log.Println(string(Yellow), duration, Reset) + + } + + +} + + +/* +func main2() { + var configPathGosdn = flag.String("configGosdn", "config/config.yaml", "Path to the Gosdn configuration file") + var configPathNetbox = flag.String("configNetbox", "config/configNetbox.yaml", "Path to the NetBox configuration file") + var elementeFigure int + flag.Parse() + + for { + start := time.Now() // Startzeit merken + + //getting date from the controller. + elements, err := inventoryManager.CreateGosdnConnectionwitNetzworkElementslist(configPathGosdn) + if err != nil { + log.Fatalf("Error creating the controller connection: %v", err) + } else { + //log.Println("everything is great!") + } + + duration := time.Since(start) // Dauer berechnen + //log.Printf("Gosdn Dauer: %s\n", duration) + log.Println(string(Yellow), duration, Reset) + start = time.Now() // Startzeit merken + + log.Println("length of element.men: ", len(elements.Mne)) + //if elements != nil { + if len(elements.Mne) != elementeFigure { + //log.Printf("Es wurden %d Elemente gefunden", len(elementss.Mne)) + //take the date into Netbox + + err = netboxManager.FeedNetbox(elements, configPathNetbox) + + if err != nil { log.Fatalf("Error creating device: %v", err) } else { @@ -84,5 +146,6 @@ func main() { } else { log.Println("Es ist alles cool!") } - */ + } +*/ \ No newline at end of file diff --git a/applications/inventory-manager-netbox/config/configNetbox.yaml b/applications/inventory-manager-netbox/config/configNetbox.yaml index a378003bc..cf06d93e4 100644 --- a/applications/inventory-manager-netbox/config/configNetbox.yaml +++ b/applications/inventory-manager-netbox/config/configNetbox.yaml @@ -1,5 +1,5 @@ NetboxAddress: "127.0.0.1:8000" -ApiToken: "863b22883c73de7ffc7dbb3c442b26d66b101c8e" +ApiToken: "4c7a48c2bbcc7661255b21fecf29b09d68507b3e" diff --git a/applications/inventory-manager-netbox/netboxManager/netboxManager.go b/applications/inventory-manager-netbox/netboxManager/netboxManager.go index 67d22bcd8..a41ccebca 100644 --- a/applications/inventory-manager-netbox/netboxManager/netboxManager.go +++ b/applications/inventory-manager-netbox/netboxManager/netboxManager.go @@ -1,352 +1,398 @@ package netboxManager import ( - "bytes" - "encoding/json" - "flag" - "io" + "context" "log" - "net/http" "os" - "strconv" "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/networkelement" "code.fbi.h-da.de/danet/gosdn/applications/inventory-manager-netbox/config" + netboxapi "code.fbi.h-da.de/danet/gosdn/internal/netboxapi" "gopkg.in/yaml.v3" ) -func Netzworhandling(netboxURL, apiToken, api string, device map[string]interface{}) (int64, error) { - // Ziel-URL vorbereiten - url := "http://" + netboxURL + "/api" + api - //log.Printf("The URL is: %s", url) +func FeedNetbox(elements *networkelement.GetAllResponse, configPathNetbox *string) error { + var manufacturerID int32 + var deviceTypeID int32 + var deviceRoleID int32 + var siteID int32 + var deviceID int32 + var ifaceID int32 + var ipID int32 + //ctx := context.Background() - // JSON kodieren - body, err := json.Marshal(device) + data, err := os.ReadFile(*configPathNetbox) if err != nil { - log.Fatalf("JSON error: %v", err) - return 0, err + log.Printf("Error reading configuration file: %v", err) + return err } - // HTTP-Request vorbereiten - req, err := http.NewRequest("POST", url, bytes.NewReader(body)) - if err != nil { - log.Fatalf("Request error: %v", err) - return 0, err + // YAML in Config-Struct einlesen + netboxconfig := &config.NetboxConfig{} + if err := yaml.Unmarshal(data, netboxconfig); err != nil { + log.Printf("Error parsing Netbox Config / YAML file: %v", err) + return err } + log.Printf("Netbox Config Adresse: %v", netboxconfig.NetboxAddress) + log.Printf("Netbox Config Token: %v", netboxconfig.ApiToken) - req.Header.Set("Content-Type", "application/json") - req.Header.Set("Authorization", "Token "+apiToken) + client := netboxapi.NewAPIClientFor("http://"+netboxconfig.NetboxAddress, netboxconfig.ApiToken) - // Request senden - resp, err := http.DefaultClient.Do(req) - if err != nil { - log.Fatalf("Sending error: %v", err) - return 0, err - } - defer resp.Body.Close() + manufacturerID = makeManufacturer(client) - // Überprüfe den Statuscode - if resp.StatusCode < 200 || resp.StatusCode >= 300 { - bodyBytes, _ := io.ReadAll(resp.Body) - log.Printf("HTTP error: %d - %s", resp.StatusCode, string(bodyBytes)) - //return 0, err - } + deviceTypeID = makeDeviceType(client, manufacturerID) - // Antwort dekodieren - var result map[string]interface{} - if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { - log.Printf("Response parsing: %v", err) - //return 0, err - } + deviceRoleID = makeDeviceRole(client) - // ID extrahieren - if id, ok := result["id"].(float64); ok { - return int64(id), nil - } + siteID = makeSite(client) - // Wenn ID fehlt: Fallback → über Gerätename suchen - if name, ok := device["name"].(string); ok { + if (manufacturerID == 0) || (deviceTypeID == 0) || (deviceRoleID == 0) || (siteID == 0) { + log.Printf("ich kann kein Gerät hinzufügen, weil ich nicht alle ID habe") + return err + } else { + if elements != nil { + for _, element := range elements.Mne { + deviceID = makeDevice(client, element.Name, deviceTypeID, deviceRoleID, siteID, element.Id, element.Plugin.String(), "active") - //log.Println("Kein Gerät mit dem Namen gefunden:", name) - //log.Println("Keine ID erhalten – versuche bestehendes Gerät mit Namen zu finden:", name) + interfaceType := netboxapi.InterfaceTypeValue("1000base-t") + ifaceID = makeInterface(client, "eth0", deviceID, interfaceType, "Uplink-Port", true) + ipID = int32(makeIPAddress(client, "192.168.1.10/24", int64(ifaceID))) - queryURL := "http://" + netboxURL + "/api" + api + "?name=" + name - log.Println("URL to search for name is: ", queryURL) - reqGet, err := http.NewRequest("GET", queryURL, nil) - if err != nil { - log.Printf("GET-Request-Fehler: %v", err) - return 0, err - } - reqGet.Header.Set("Authorization", "Token "+apiToken) + log.Printf("Gerät erstellt createdDevice: %v ", deviceID) + log.Printf("Interface erstellt mit der ID: %v ", ifaceID) + log.Printf("IP Adresse erstellt mit der ID: %v ", ipID) - respGet, err := http.DefaultClient.Do(reqGet) - if err != nil { - log.Printf("GET error: %v", err) - return 0, err - } - defer respGet.Body.Close() + } - var getResult map[string]interface{} - if err := json.NewDecoder(respGet.Body).Decode(&getResult); err != nil { - log.Printf("GET response parsing: %v", err) - return 0, err } + } + log.Printf("Gerät erstellt createdDevice: %v ", deviceID) + return nil +} - if results, ok := getResult["results"].([]interface{}); ok && len(results) > 0 { - if first, ok := results[0].(map[string]interface{}); ok { - if id, ok := first["id"].(float64); ok { - log.Printf("Bestehendes Gerät gefunden mit ID: %d", int64(id)) - return int64(id), nil - } - } - } +/* if elements != nil { + for _, element := range elements.Mne { - log.Printf("No device found with the name") - } else { + //log.Printf("Test Zeugs, ich will die IP: %v", element.GetMneNotification()) - if model, ok := device["model"].(string); ok { - //log.Println("Keine ID erhalten – versuche bestehendes Gerät mit Model zu finden:", model) + log.Printf("IP Adresse, check: %v", element.TransportAddress) - queryURL := "http://" + netboxURL + "/api" + api + "?model=" + model - log.Println("URL to search for model is: ", queryURL) + //log.Printf("Testen String bekommen: %v", element.String()) - reqGet, err := http.NewRequest("GET", queryURL, nil) - if err != nil { - log.Printf("GET request error: %v", err) - return 0, err - } - reqGet.Header.Set("Authorization", "Token "+apiToken) + device = createDeviceWithParameter(element.Name, strconv.FormatInt(deviceTypeID, 10), strconv.FormatInt(deviceRoleID, 10), strconv.FormatInt(siteID, 10), element.Id, element.Plugin.String(), "active") + id, err = Netzworhandling(netboxconfig.NetboxAddress, netboxconfig.ApiToken, "/dcim/devices/", device) + deviceID := id + if err != nil { + log.Printf("Error creating a Device: %v", err) + return err + } else { + log.Printf("Device successfully created or found with the deviceID: %d\n", deviceID) + } - respGet, err := http.DefaultClient.Do(reqGet) + Newinterface := createInterfaceWithParameter("Name-eth0", strconv.FormatInt(deviceID, 10), "1000base-t", "Main uplink", true) + id, err = Netzworhandling(netboxconfig.NetboxAddress, netboxconfig.ApiToken, "/ipam/ip-addresses/", Newinterface) + NewinterfaceID := id + if err != nil { + log.Printf("Error creating a Interface: %v", err) + return err + } else { + log.Printf("Interface successfully created or found with the interfaceID: %d\n", NewinterfaceID) + //IP hinzufügen + //NewIpAddress := createIPAddressWithParameter("192.168.1.10/24", strconv.FormatInt(NewinterfaceID, 10)) + NewIpAddress := createIPAddressWithParameter(element.TransportAddress+"/32", strconv.FormatInt(NewinterfaceID, 10)) + + id, err = Netzworhandling(netboxconfig.NetboxAddress, netboxconfig.ApiToken, "/dcim/devices/", NewIpAddress) + ipAddressID := id if err != nil { - log.Printf("GET error: %v", err) - return 0, err - } - defer respGet.Body.Close() - - var getResult map[string]interface{} - if err := json.NewDecoder(respGet.Body).Decode(&getResult); err != nil { - log.Printf("GET response parsing: %v", err) - return 0, err - } - - if results, ok := getResult["results"].([]interface{}); ok && len(results) > 0 { - if first, ok := results[0].(map[string]interface{}); ok { - if id, ok := first["id"].(float64); ok { - log.Printf("Existing device found with ID: %d", int64(id)) - return int64(id), nil - } + log.Printf("Error creating a IP Address: %v", err) + return err + } else { + if ipAddressID == 0 { + log.Printf("No IP Address created in Netbox. IP adress: %s\n", element.TransportAddress) + } else { + log.Printf("IP Address successfully created or found with the ipAddressID: %d\n", ipAddressID) } } - log.Printf("No device found with this model") } } - - log.Printf("No ID found in response and no device can be found by name or model") - return 0, nil +} else { + //log.Fatalf("The controller has no data for me. Continuing is pointless. ^^ elementss is empty.") } +return nil -func FeedNetbox(elements *networkelement.GetAllResponse, configPathNetbox *string) error { - var device map[string]interface{} - - flag.Parse() +*/ - //log.Printf("Config path: %s", *configPathNetbox) +func makeManufacturer(client *netboxapi.APIClient) int32 { + var ManufacturerID int32 + ManufacturerID = 0 + slug := "EindeutigerName4" + manufacturer := CreateManufacturer("Grosse Box hersteller4", slug, "Wichtig gros und ganz alleine da oben") - // Read config file - data, err := os.ReadFile(*configPathNetbox) + //createdManufacturer, reqManufacturer, err := client.DcimAPI.DcimManufacturersCreate(context.Background()).ManufacturerRequest(*manufacturer).Execute() + created, resp, err := client.DcimAPI.DcimManufacturersCreate(context.Background()).ManufacturerRequest(*manufacturer).Execute() if err != nil { - log.Printf("Error reading configuration file: %v", err) - return err + log.Printf("Fehler beim Erstellen des Herstellers: %v", err) + log.Printf("Fehler beim Erstellen des Herstellers, reqManufacturer: %v", resp.Status) + //suche nach slug + manufacturerList, resp, err := client.DcimAPI.DcimManufacturersList(context.Background()).Slug([]string{slug}).Execute() + if err != nil { + log.Printf("Fehler beim Abfragen des Herstellers: %v", err) + //return err + } + if len(manufacturerList.Results) > 0 { + existingManufacturer := manufacturerList.Results[0] + ManufacturerID = existingManufacturer.Id + log.Printf("Hersteller existiert bereits mit ID: %d", ManufacturerID) + log.Printf("Hersteller existiert bereits mit der URL: %v", existingManufacturer.Url) + } else { + log.Printf("Hersteller mit Slug '%s' nicht gefunden.", slug) + log.Printf("Fehler: %v", resp.Status) + } + } else { + ManufacturerID = created.Id + log.Printf("Jippi, Herstller angelegt: %v", ManufacturerID) + log.Printf("Jippi, Die Link zu dem Gerät lautet: %v", created.Url) } + return ManufacturerID +} - // YAML in Config-Struct einlesen - netboxconfig := &config.NetboxConfig{} - if err := yaml.Unmarshal(data, netboxconfig); err != nil { - log.Printf("Error parsing Netbox Config / YAML file: %v", err) - return err - } - //log.Printf("Netbox Config Adresse: %v", netboxconfig.NetboxAddress) - //log.Printf("Netbox Config Token: %v", netboxconfig.ApiToken) +func makeDeviceType(client *netboxapi.APIClient, manufacturerID int32) int32 { + var deviceTypeID int32 = 0 + slug := "eindeutige-id-slug" // genau so wie du ihn in CreateDeviceType übergibst + model := "model" + uHeight := float64(5) - //Manufacturers Hersteller - device = createManufacturerWithParameter("Uni Controller", "Uni-Controller", "Die Wichtige große Box. nicht ausschalten") - id, err := Netzworhandling(netboxconfig.NetboxAddress, netboxconfig.ApiToken, "/dcim/manufacturers/", device) - if err != nil { - log.Printf("Error creating a manufacturer: %v", err) - return err - } - manufacturerID := id - log.Printf("Manufacturer successfully created or found with the manufacturerID: %d\n", manufacturerID) + manufacturerRef := netboxapi.Int32AsBriefDeviceTypeRequestManufacturer(&manufacturerID) + deviceType := CreateDeviceType(manufacturerRef, model, slug, uHeight) - //Device Types Gerätetyp device_type - device = createdeviceTypeWithParameter(strconv.FormatInt(manufacturerID, 10), "Main Controller", "Main-Controller", "1") - id, err = Netzworhandling(netboxconfig.NetboxAddress, netboxconfig.ApiToken, "/dcim/device-types/", device) - if err != nil { - log.Printf("Error creating a Device Type: %v", err) - return err - } - deviceTypeID := id - log.Printf("Device Types successfully created or found with the deviceTypeID: %d\n", deviceTypeID) + created, resp, err := client.DcimAPI.DcimDeviceTypesCreate(context.Background()). + WritableDeviceTypeRequest(*deviceType). + Execute() - //device-roles Geräterolle - device = createDeviceRoleWithParameter("Haupt Controller", "Haupt-Controller", "Ganz wichtig Kiste", "ff0000", "offline") - id, err = Netzworhandling(netboxconfig.NetboxAddress, netboxconfig.ApiToken, "/dcim/device-roles/", device) if err != nil { - log.Printf("Error creating a Device Role: %v", err) - return err - } - deviceRoleID := id - log.Printf("Device Role successfully created or found with the deviceRoleID: %d\n", deviceRoleID) + log.Printf("Fehler beim Erstellen des Gerätetyps: %v", err) + log.Printf("Fehler beim Erstellen des Gerätetyps, reqDeviceType: %v", resp.Status) - //Sites Standort List - device = createSiteWithParameter("Darmstadt V1", "darmstadt-v1", "description", "physicalAddress", "shippingAddress", "comments", "active") - id, err = Netzworhandling(netboxconfig.NetboxAddress, netboxconfig.ApiToken, "/dcim/sites/", device) - if err != nil { - log.Printf("Error creating a Site: %v", err) - return err - } - siteID := id - log.Printf("Site successfully created or found with the siteID: %d\n", siteID) - - /* - for _, element := range elements.Mne { - log.Printf("element.Name: %v", element.Name) - log.Printf("element.Id: %v", element.Id) - log.Printf("element.Plugin: %v", element.Plugin) + // versuche über Slug zu finden + list, resp, err := client.DcimAPI.DcimDeviceTypesList(context.Background()).Slug([]string{slug}).Execute() + if err != nil { + log.Printf("Fehler beim Abfragen des Device Types: %v", err) + } else if len(list.Results) > 0 { + existing := list.Results[0] + deviceTypeID = existing.Id + log.Printf("Device Type existiert bereits mit ID: %d", deviceTypeID) + log.Printf("Device Type existiert bereits unter: %v", existing.Url) + } else { + log.Printf("Kein Device Type mit Slug '%s' gefunden.", slug) + log.Printf("Fehler: %v", resp.Status) } - */ - log.Printf(" ") - log.Printf(" ") - if elements != nil { - for _, element := range elements.Mne { + } else { + deviceTypeID = created.Id + log.Printf("Gerätetyp erfolgreich angelegt: ID %d", deviceTypeID) + log.Printf("URL zum Gerätetyp: %s", created.Url) + } + return deviceTypeID +} - //log.Printf("Test Zeugs, ich will die IP: %v", element.GetMneNotification()) +func makeDeviceRole(client *netboxapi.APIClient) int32 { + var deviceRoleID int32 = 0 + slug := "grossUndWichtig" // muss slug-konform sein (keine Leerzeichen, Kleinbuchstaben) - log.Printf("IP Adresse, check: %v", element.TransportAddress) + role := CreateDeviceRole("Wichtige Box", slug, "Ist WohlWichtigGenug, damit es hier ist", "ff0000") - //log.Printf("Testen String bekommen: %v", element.String()) + created, resp, err := client.DcimAPI.DcimDeviceRolesCreate(context.Background()). + DeviceRoleRequest(*role). + Execute() - device = createDeviceWithParameter(element.Name, strconv.FormatInt(deviceTypeID, 10), strconv.FormatInt(deviceRoleID, 10), strconv.FormatInt(siteID, 10), element.Id, element.Plugin.String(), "active") - id, err = Netzworhandling(netboxconfig.NetboxAddress, netboxconfig.ApiToken, "/dcim/devices/", device) - deviceID := id - if err != nil { - log.Printf("Error creating a Device: %v", err) - return err - } else { - log.Printf("Device successfully created or found with the deviceID: %d\n", deviceID) - } + if err != nil { + log.Printf("Fehler beim Erstellen der Device Role: %v", err) + log.Printf("Fehlerhafte Antwort: %v", resp.Status) - Newinterface := createInterfaceWithParameter("Name-eth0", strconv.FormatInt(deviceID, 10), "1000base-t", "Main uplink", true) - id, err = Netzworhandling(netboxconfig.NetboxAddress, netboxconfig.ApiToken, "/ipam/ip-addresses/", Newinterface) - NewinterfaceID := id - if err != nil { - log.Printf("Error creating a Interface: %v", err) - return err - } else { - log.Printf("Interface successfully created or found with the interfaceID: %d\n", NewinterfaceID) - //IP hinzufügen - //NewIpAddress := createIPAddressWithParameter("192.168.1.10/24", strconv.FormatInt(NewinterfaceID, 10)) - NewIpAddress := createIPAddressWithParameter(element.TransportAddress+"/32", strconv.FormatInt(NewinterfaceID, 10)) - - id, err = Netzworhandling(netboxconfig.NetboxAddress, netboxconfig.ApiToken, "/dcim/devices/", NewIpAddress) - ipAddressID := id - if err != nil { - log.Printf("Error creating a IP Address: %v", err) - return err - } else { - if ipAddressID == 0 { - log.Printf("No IP Address created in Netbox. IP Address: %s\n", element.TransportAddress) - } else { - log.Printf("IP Address successfully created or found with the ipAddressID: %d\n", ipAddressID) - } - } - } + // versuche, die Rolle über den Slug zu finden + list, resp, err := client.DcimAPI.DcimDeviceRolesList(context.Background()).Slug([]string{slug}).Execute() + if err != nil { + log.Printf("Fehler beim Abfragen der Device Role: %v", err) + } else if len(list.Results) > 0 { + existing := list.Results[0] + deviceRoleID = existing.Id + log.Printf("Device Role existiert bereits mit ID: %d", deviceRoleID) + log.Printf("Device Role URL: %s", existing.Url) + } else { + log.Printf("Keine Device Role mit Slug '%s' gefunden.", slug) + log.Printf("Fehler: %v", resp.Status) } } else { - //log.Fatalf("The controller has no data for me. Continuing is pointless. ^^ elementss is empty.") + deviceRoleID = created.Id + log.Printf("Device Role erfolgreich erstellt: ID %d", deviceRoleID) + log.Printf("Device Role URL: %s", created.Url) } - return nil + + return deviceRoleID } -/* -// create one Device in Netbox with JSON and HTTP -func Netboxmanager() error { - var device map[string]interface{} - //gehMirNichtAufdenSack() - // Configpfad aus CLI-Flag holen - configFileNetbox := flag.String("configNetbox", "config/configNetbox.yaml", "Pfad zur NetBox-Konfigurationsdatei") - flag.Parse() - log.Printf("Config-Pfad: %s", *configFileNetbox) - - // Datei lesen - data, err := os.ReadFile(*configFileNetbox) - if err != nil { - log.Printf("Fehler beim Lesen der Konfigurationsdatei: %v", err) - return err - } +func makeSite(client *netboxapi.APIClient) int32 { + var siteID int32 = 0 + slug := "darmstadt-der-groe" // slug muss URL-konform sein - // YAML in Config-Struct einlesen - netboxconfig := &config.NetboxConfig{} - if err := yaml.Unmarshal(data, netboxconfig); err != nil { - log.Printf("Fehler beim Parsen der YAML-Datei: %v", err) - return err - } - log.Printf("Netbox Config Adresse: %v", netboxconfig.NetboxAddress) - log.Printf("Netbox Config Token: %v", netboxconfig.ApiToken) + site := CreateSite( + "Darmstadt v2", + slug, + "Ort brauchen eine beschreibung", + "In der Uni und dann in den Keller oder ins Labor", + "Da so und dann Links", + "comments", + ) - //Manufacturers Hersteller - device = createManufacturerWithParameter("HerstellerName2", "slug2", "description") - id, err := Netzworhandling(netboxconfig.NetboxAddress, netboxconfig.ApiToken, "/dcim/manufacturers/", device) - if err != nil { - log.Printf("Fehler beim erstellen eines Herstellers: %v", err) - return err - } - manufacturerID := id - log.Printf("Hersteller erfolgreich erstellt oder gefunden mit der manufacturerID: %d\n", manufacturerID) + created, resp, err := client.DcimAPI.DcimSitesCreate(context.Background()). + WritableSiteRequest(*site). + Execute() - //Device Types Gerätetyp device_type - device = createdeviceTypeWithParameter(strconv.FormatInt(manufacturerID, 10), "model5", "slug5", "1") - id, err = Netzworhandling(netboxconfig.NetboxAddress, netboxconfig.ApiToken, "/dcim/device-types/", device) if err != nil { - log.Printf("Fehler beim erstellen des Gerätetyps: %v", err) - return err + log.Printf("Fehler beim Erstellen der Site: %v", err) + log.Printf("Fehlerhafte Antwort: %v", resp.Status) + + // versuche, die Site über den Slug zu finden + list, resp, err := client.DcimAPI.DcimSitesList(context.Background()).Slug([]string{slug}).Execute() + if err != nil { + log.Printf("Fehler beim Abfragen der Site: %v", err) + } else if len(list.Results) > 0 { + existing := list.Results[0] + siteID = existing.Id + log.Printf("Site existiert bereits mit ID: %d", siteID) + log.Printf("Site URL: %s", existing.Url) + } else { + log.Printf("Keine Site mit Slug '%s' gefunden.", slug) + log.Printf("Fehler: %v", resp.Status) + } + } else { + siteID = created.Id + log.Printf("Site erfolgreich erstellt: ID %d", siteID) + log.Printf("Site URL: %s", created.Url) } - deviceTypeID := id - log.Printf("Gerätetyp erfolgreich erstellt oder gefunden mit der deviceTypeID: %d\n", deviceTypeID) - //deviceTypeID = 16 - //log.Printf("Hacki lösung DeviceRoleID manuell ändern: %d\n", deviceTypeID) //TODO + return siteID +} + +func makeDevice(client *netboxapi.APIClient, name string, deviceTypeID, roleID, siteID int32, serial, description, status string) int32 { + var deviceID int32 = 0 + + // Gerät anlegen + device := CreateDevice(name, deviceTypeID, roleID, siteID, serial, description, status) + + // Versuch, das Gerät zu erstellen + createdDevice, resp, err := client.DcimAPI. + DcimDevicesCreate(context.Background()). + WritableDeviceWithConfigContextRequest(*device). + Execute() - //device-roles Geräterolle - device = createDeviceRoleWithParameter("name2", "slug5", "description", "ff0000", "offline") - id, err = Netzworhandling(netboxconfig.NetboxAddress, netboxconfig.ApiToken, "/dcim/device-roles/", device) if err != nil { - log.Printf("Fehler beim erstellen der Geräterolle: %v", err) - return err + log.Printf("Fehler beim Erstellen des Geräts: %v", err) + if resp != nil { + log.Printf("HTTP-Status: %s", resp.Status) + } + + // Fallback: Suche nach vorhandenem Gerät anhand Name + existing, resp, err := client.DcimAPI. + DcimDevicesList(context.Background()). + Name([]string{name}). + Execute() + + if err != nil { + log.Printf("Fehler bei der Gerätesuche: %v", err) + } else if len(existing.Results) > 0 { + deviceID = existing.Results[0].Id + log.Printf("Gerät existiert bereits: ID %d, URL: %s", deviceID, existing.Results[0].Url) + } else { + log.Printf("Kein bestehendes Gerät mit Name '%s' gefunden.", name) + log.Printf("Status: %d", resp.StatusCode) + } + } else { + deviceID = createdDevice.Id + log.Printf("Gerät erfolgreich erstellt: ID %d, URL: %s", deviceID, createdDevice.Url) } - deviceRoleID := id - log.Printf("Geräterolle erfolgreich erstellt oder gefunden mit der deviceRoleID: %d\n", deviceRoleID) - device = createSiteWithParameter("Darmstadt", "darmstadt", "description", "physicalAddress", "shippingAddress", "comments", "active") - id, err = Netzworhandling(netboxconfig.NetboxAddress, netboxconfig.ApiToken, "/dcim/sites/", device) + return deviceID +} + +func makeInterface(client *netboxapi.APIClient, name string, deviceID int32, interfaceType netboxapi.InterfaceTypeValue, description string, enabled bool) int32 { + var interfaceID int32 = 0 + + // NetBox erwartet ein BriefInterfaceRequestDevice + deviceRef := netboxapi.Int32AsBriefInterfaceRequestDevice(&deviceID) + iface := CreateInterface(name, deviceRef, interfaceType, description, enabled) + + createdIface, resp, err := client.DcimAPI. + DcimInterfacesCreate(context.Background()). + WritableInterfaceRequest(*iface). + Execute() + if err != nil { - log.Printf("Fehler beim erstellen der Geräterolle: %v", err) - return err + log.Printf("Fehler beim Erstellen der Schnittstelle: %v", err) + if resp != nil { + log.Printf("HTTP Status: %s", resp.Status) + } + + // Suche nach bestehender Schnittstelle mit Name + Device + existing, resp, err := client.DcimAPI. + DcimInterfacesList(context.Background()). + Name([]string{name}). + DeviceId([]int32{deviceID}). + Execute() + + if err != nil { + log.Printf("Fehler bei Schnittstellen-Suche: %v", err) + } else if len(existing.Results) > 0 { + interfaceID = existing.Results[0].Id + log.Printf("Schnittstelle existiert bereits: ID %d, URL: %s", interfaceID, existing.Results[0].Url) + } else { + log.Printf("Keine bestehende Schnittstelle '%s' gefunden für Device-ID %d.", name, deviceID) + log.Printf("Status: %d", resp.StatusCode) + } + } else { + interfaceID = createdIface.Id + log.Printf("Schnittstelle erfolgreich erstellt: ID %d, URL: %s", interfaceID, createdIface.Url) } - siteID := id - log.Printf("Geräterolle erfolgreich erstellt oder gefunden mit der siteID: %d\n", siteID) - device = createDeviceWithParameter("name", strconv.FormatInt(deviceTypeID, 10), strconv.FormatInt(deviceRoleID, 10), strconv.FormatInt(siteID, 10), "serial", "description", "active") - id, err = Netzworhandling(netboxconfig.NetboxAddress, netboxconfig.ApiToken, "/dcim/devices/", device) + return interfaceID +} + +func makeIPAddress(client *netboxapi.APIClient, address string, interfaceID int64) int64 { + var ipID int64 = 0 + + ip := CreateIPAddress(address, interfaceID) + + createdIP, resp, err := client.IpamAPI. + IpamIpAddressesCreate(context.Background()). + WritableIPAddressRequest(*ip). + Execute() + if err != nil { - log.Printf("Fehler beim erstellen des Gerätes: %v", err) - return err + log.Printf("Fehler beim Erstellen der IP-Adresse: %v", err) + if resp != nil { + log.Printf("HTTP Status: %s", resp.Status) + } + + // Suche nach bereits existierender IP-Adresse + existing, resp, err := client.IpamAPI. + IpamIpAddressesList(context.Background()). + Address([]string{address}). + Execute() + + if err != nil { + log.Printf("Fehler beim Suchen nach IP-Adresse '%s': %v", address, err) + } else if len(existing.Results) > 0 { + ipID = int64(existing.Results[0].Id) // für Fehler 8 + log.Printf("IP-Adresse existiert bereits: ID %d, URL: %s", ipID, existing.Results[0].Url) + } else { + log.Printf("Keine bestehende IP-Adresse gefunden: %s", address) + log.Printf("Status: %d", resp.StatusCode) + } + } else { + ipID := int64(createdIP.Id) + log.Printf("IP-Adresse erfolgreich erstellt: ID %d, URL: %s", ipID, createdIP.Url) } - deviceID := id - log.Printf("Gerät erfolgreich erstellt oder gefunden mit der deviceID: %d\n", deviceID) - return nil + return ipID } -*/ + diff --git a/applications/inventory-manager-netbox/netboxManager/netboxUtility.go b/applications/inventory-manager-netbox/netboxManager/netboxUtility.go index 013612462..3c4ed8428 100644 --- a/applications/inventory-manager-netbox/netboxManager/netboxUtility.go +++ b/applications/inventory-manager-netbox/netboxManager/netboxUtility.go @@ -1,112 +1,329 @@ package netboxManager -func createDeviceWithParameter(name, deviceTypeID, deviceRoleID, siteID, serial, description, status string) map[string]interface{} { - // /api/dcim/devices/ Gerät - device := map[string]interface{}{ - "name": name, - "device_type": deviceTypeID, - "role": deviceRoleID, - "site": siteID, - "serial": serial, - "description": description, - "status": status, +import ( + netbox "code.fbi.h-da.de/danet/gosdn/internal/netboxapi" +) + +// Hilfsfunktion +func Int32Ptr(i int32) *int32 { + return &i +} +func Int64Ptr(i int64) *int64 { + return &i +} +func StringPtr(s string) *string { + return &s +} + +// createDevice creates a device in NetBox +func CreateDevice(name string, deviceTypeID, roleID, siteID int32, serial, description, status string) *netbox.WritableDeviceWithConfigContextRequest { + // /dcim/device-types/ Gerätetyp + device := &netbox.WritableDeviceWithConfigContextRequest{ + Name: *netbox.NewNullableString(&name), + Role: netbox.DeviceWithConfigContextRequestRole{Int32: Int32Ptr(roleID)}, + Site: netbox.DeviceWithConfigContextRequestSite{Int32: Int32Ptr(siteID)}, + DeviceType: netbox.DeviceBayTemplateRequestDeviceType{Int32: Int32Ptr(deviceTypeID)}, + Serial: &serial, + Description: &description, + Status: (*netbox.DeviceStatusValue)(&status), } return device } -func createdeviceTypeWithParameter(manufacturerID, model, slug, uHeight string) map[string]interface{} { +// CreateDeviceType creates a deicetype in NetBox +func CreateDeviceType(manufacturerID netbox.BriefDeviceTypeRequestManufacturer, model, slug string, uHeight float64) *netbox.WritableDeviceTypeRequest { // /dcim/device-types/ Gerätetyp - device := map[string]interface{}{ - "manufacturer": manufacturerID, - "model": model, - "slug": slug, - "u_height": uHeight, + deviceType := &netbox.WritableDeviceTypeRequest{ + Model: model, + Slug: slug, + UHeight: &uHeight, + Manufacturer: manufacturerID, } - return device + return deviceType } -func createManufacturerWithParameter(name, slug, description string) map[string]interface{} { +// CreateManufacturer creates a manufacturer in NetBox +func CreateManufacturer(name, slug, description string) *netbox.ManufacturerRequest { // /dcim/manufacturers/ Hersteller - device := map[string]interface{}{ - "name": name, - "slug": slug, - "description": description, + manufacturer := &netbox.ManufacturerRequest{ + Name: name, + Slug: slug, + Description: StringPtr(description), } - return device + return manufacturer } -func createDeviceRoleWithParameter(name, slug, description, color, active string) map[string]interface{} { +// CreateDeviceRole creates a device role in NetBox +func CreateDeviceRole(name, slug, description, color string) *netbox.DeviceRoleRequest { // /dcim/device-roles/ Geräterolle - device := map[string]interface{}{ - "name": name, - "slug": slug, - "description": description, - "color": color, - "status": active, + deviceRole := &netbox.DeviceRoleRequest{ + Name: name, + Slug: slug, + Description: StringPtr(description), + Color: &color, } - return device + return deviceRole } -func createSiteWithParameter(name, slug, description, physicalAddress, shippingAddress, comments, status string) map[string]interface{} { +// CreateSite creates a site in NetBox +func CreateSite(name, slug, description, physicalAddress, shippingAddress, comments string) *netbox.WritableSiteRequest { // /dcim/sites/ Standorts - device := map[string]interface{}{ - "name": name, - "slug": slug, - "description": description, - "physicalAddress": physicalAddress, - "shippingAddress": shippingAddress, - "comments": comments, - "status": status, + site := &netbox.WritableSiteRequest{ + Name: name, + Slug: slug, + Description: StringPtr(description), + PhysicalAddress: StringPtr(physicalAddress), + ShippingAddress: StringPtr(shippingAddress), + Comments: StringPtr(comments), + //Status: &status, vielleicht brauche ich es ja doch nicht?!?! + //, status netbox.LocationStatus } - return device + return site } -// createLocationWithParameter creates a Interface -func createInterfaceWithParameter(name, deviceID, interfaceType, - description string, enabled bool) map[string]interface{} { - // /api/dcim/interfaces/ Schnittstelle List - device := map[string]interface{}{ - "device": deviceID, - "name": name, - "type": interfaceType, // z. B. "1000base-t" - "description": description, - "enabled": enabled, +// CreateInterface creates an interface in NetBox +func CreateInterface(name string, deviceID netbox.BriefInterfaceRequestDevice, interfaceType netbox.InterfaceTypeValue, description string, enabled bool) *netbox.WritableInterfaceRequest { + + interrface := &netbox.WritableInterfaceRequest{ + Name: name, + Device: deviceID, + Type: interfaceType, + Description: StringPtr(description), + Enabled: &enabled, } - return device + return interrface } -// createIPAddressWithParameter erstellt eine IP-Adresse und weist sie einem Interface zu -func createIPAddressWithParameter(address, interfaceID string) map[string]interface{} { +// CreateIPAddress creates an IP address in NetBox +func CreateIPAddress(address string, interfaceID int64) *netbox.WritableIPAddressRequest { + assignedType := "ipam.interface" // /api/ipam/ip-addresses/ - device := map[string]interface{}{ - "address": address, // z. B. "192.168.0.1/24" - "assigned_object_type": "dcim.interface", - "assigned_object_id": interfaceID, + + ip := &netbox.WritableIPAddressRequest{ + Address: address, + AssignedObjectType: *netbox.NewNullableString(&assignedType), + AssignedObjectId: *netbox.NewNullableInt64(&interfaceID), } - return device + return ip } /* - func createTagWithParameter(name, slug, description string) map[string]interface{} { - device := map[string]interface{}{ - "name": name, - "slug": slug, - "description": description, - } - return device +// CreateTag creates a tag in NetBox +func CreateTag(client *netbox.Client, name, slug, description string) (*models.Tag, error) { + tag := &models.Tag{ + Name: name, + Slug: slug, + Description: description, + } + + createdTag, err := client.Extras.ExtrasTagsCreate( + extras.NewExtrasTagsCreateParams().WithData(tag).WithContext(context.Background()), + nil, + ) + if err != nil { + return nil, fmt.Errorf("Fehler beim Erstellen des Tags: %w", err) } - func createModultypWithParameter(model, partNumber, description, comments, manufacturerID string) map[string]interface{} { + return createdTag.Payload, nil +} + +//createmodultyp creates a modultyp in NetBox +func CreateModuleType(client *netbox.Client, model, partNumber, description, comments, manufacturerID string) (*models.ModuleType, error) { ///api/dcim/module-types/ Modultypen - device := map[string]interface{}{ - "model": model, - "partNumber": partNumber, - //"weight" : "9", - //"weight_unit": "KiloGramm", - "description": description, - "comments": comments, - "manufacturer": manufacturerID, + moduleType := &models.ModuleType{ + Model: model, + PartNumber: partNumber, + Description: description, + Comments: comments, + Manufacturer: &models.NestedManufacturer{ID: manufacturerID}, } - return device + + createdModuleType, err := client.Dcim.DcimModuleTypesCreate( + dcim.NewDcimModuleTypesCreateParams().WithData(moduleType).WithContext(context.Background()), + nil, + ) + if err != nil { + return nil, fmt.Errorf("Fehler beim Erstellen des Modultyps: %w", err) + } + + return createdModuleType.Payload, nil +} +/* + + +// createDevice creates a deicetype in NetBox +func CreateDeviceType(client *netbox.NetBoxAPI, manufacturerID int64, model, slug string, uHeight float64) (*models.DeviceType, error) { + // /dcim/device-types/ Gerätetyp + deviceType := &models.DeviceType{ + Manufacturer: manufacturerID, + Model: &model, + Slug: &slug, + UHeight: &uHeight, + } + params := &dcim.DcimDeviceTypesCreateParams{ + Data: deviceType, + Context: context.Background(), + } + + created, err := client.Dcim.DcimDeviceTypesCreate(params, nil) + if err != nil { + return nil, err + } + return created.Payload, nil +} + +// createDevice creates a manufacturer in NetBox +func CreateManufacturer(client *netbox.NetBoxAPI, name, slug, description string) (*models.Manufacturer, error) { + // /dcim/manufacturers/ Hersteller + manufacturer := &models.Manufacturer{ + Name: &name, + Slug: &slug, + Description: description, + } + params := &dcim.DcimManufacturersCreateParams{ + Data: manufacturer, + Context: context.Background(), + } + + created, err := client.Dcim.DcimManufacturersCreate(params, nil) + if err != nil { + return nil, err + } + return created.Payload, nil +} + +// createDevice creates a device role in NetBox +func CreateDeviceRole(client *netbox.NetBoxAPI, name, slug, description, color, status string) (*models.DeviceRole, error) { + // /dcim/device-roles/ Geräterolle + deviceRole := &models.DeviceRole{ + Name: &name, + Slug: &slug, + Description: description, + Color: &color, + Status: &status, + } + + params := &dcim.DcimDeviceRolesCreateParams{ + Data: deviceRole, + Context: context.Background(), + } + + created, err := client.Dcim.DcimDeviceRolesCreate(params, nil) + if err != nil { + return nil, err + } + return created.Payload, nil +} + +// createDevice creates a site in NetBox +func CreateSite(client *netbox.NetBoxAPI, name, slug, description, physicalAddress, shippingAddress, comments, status string) (*models.Site, error) { + // /dcim/sites/ Standorts + site := &models.Site{ + Name: &name, + Slug: &slug, + Description: description, + PhysicalAddress: physicalAddress, + ShippingAddress: shippingAddress, + Comments: comments, + Status: &status, + } + + params := &dcim.DcimSitesCreateParams{ + Data: site, + Context: context.Background(), + } + + created, err := client.Dcim.DcimSitesCreate(params, nil) + if err != nil { + return nil, err + } + return created.Payload, nil +} + +// CreateInterface creates an interface in NetBox +func CreateInterface(client *netbox.NetBoxAPI, name string, deviceID int64, interfaceType, description string, enabled bool) (*models.Interface, error) { + // /api/dcim/interfaces/ Schnittstelle Liste + + interrface := &models.Interface{ + Name: &name, + Device: &deviceID, + Type: &interfaceType, // z. B. "1000base-t" + Description: description, + Enabled: &enabled, + } + params := &dcim.DcimInterfacesCreateParams{ + Data: interrface, + Context: context.Background(), + } + + created, err := client.Dcim.DcimInterfacesCreate(params, nil) + if err != nil { + return nil, err + } + return created.Payload, nil +} + +// CreateIPAddress creates an IP address in NetBox +func CreateIPAddress(client *netbox.NetBoxAPI, address string, interfaceID int64) (*models.IPAddress, error) { + assignedType := "dcim.interface" + // /api/ipam/ip-addresses/ + + ip := &models.IPAddress{ + Address: &address, + AssignedObjectType: &assignedType, + AssignedObjectID: &interfaceID, + } + params := &ipam.IpamIPAddressesCreateParams{ + Data: ip, + Context: context.Background(), + } + + created, err := client.Ipam.IpamIPAddressesCreate(params, nil) + if err != nil { + return nil, err + } + return created.Payload, nil +} + +/* +// CreateTag creates a tag in NetBox +func CreateTag(client *netbox.Client, name, slug, description string) (*models.Tag, error) { + tag := &models.Tag{ + Name: name, + Slug: slug, + Description: description, + } + + createdTag, err := client.Extras.ExtrasTagsCreate( + extras.NewExtrasTagsCreateParams().WithData(tag).WithContext(context.Background()), + nil, + ) + if err != nil { + return nil, fmt.Errorf("Fehler beim Erstellen des Tags: %w", err) + } + + return createdTag.Payload, nil +} + +//createmodultyp creates a modultyp in NetBox +func CreateModuleType(client *netbox.Client, model, partNumber, description, comments, manufacturerID string) (*models.ModuleType, error) { + ///api/dcim/module-types/ Modultypen + moduleType := &models.ModuleType{ + Model: model, + PartNumber: partNumber, + Description: description, + Comments: comments, + Manufacturer: &models.NestedManufacturer{ID: manufacturerID}, + } + + createdModuleType, err := client.Dcim.DcimModuleTypesCreate( + dcim.NewDcimModuleTypesCreateParams().WithData(moduleType).WithContext(context.Background()), + nil, + ) + if err != nil { + return nil, fmt.Errorf("Fehler beim Erstellen des Modultyps: %w", err) + } + + return createdModuleType.Payload, nil } */ -- GitLab