Skip to content
Snippets Groups Projects
netboxManager.go 13.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • package netboxManager
    
    import (
    
    	"log"
    	"os"
    
    	"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"
    
    	temp "code.fbi.h-da.de/danet/gosdn/models/generated/openconfig"
    	"github.com/openconfig/gnmi/proto/gnmi"
    	"github.com/openconfig/ygot/ytypes"
    
    	"gopkg.in/yaml.v3"
    )
    
    
    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()
    
    	data, err := os.ReadFile(*configPathNetbox)
    
    	if err != nil {
    
    		log.Printf("Error reading configuration file: %v", err)
    		return 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)
    
    	client := netboxapi.NewAPIClientFor("http://"+netboxconfig.NetboxAddress, netboxconfig.ApiToken)
    
    	manufacturerID = makeManufacturer(client)
    
    	deviceTypeID = makeDeviceType(client, manufacturerID)
    
    	deviceRoleID = makeDeviceRole(client)
    
    	log.Printf(" ")
    	log.Printf(" ")
    
    
    	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 {
    
    				modelFormGNMI, err := GetModelAsStruct(element.GetMneNotification())
    				if err != nil {
    					log.Printf("Fehler beim Umwandeln des Element: %v", err)
    					log.Printf("ModelAsStruct modelFormGNMI: %v", modelFormGNMI)
    				}
    
    				deviceID = makeDevice(client, element.Name, deviceTypeID, deviceRoleID, siteID, element.Id, element.Plugin.String(), "active")
    				//log.Printf("Gerät erstellt createdDevice: %v ", deviceID)
    
    				for name, iface := range modelFormGNMI.Interfaces.Interface {
    					if iface == nil {
    						continue
    					}
    
    					log.Printf("")
    					log.Printf("")
    					//log.Printf("Interface Name (Key): %s", name)
    					interfaceType := netboxapi.InterfaceTypeValue("1000base-t")
    					ifaceID = makeInterface(client, name, deviceID, interfaceType, "Beschreibungstext, hier kann was sinvolle rein", true)
    					log.Printf("Interface erstellt mit der ID: %v ", ifaceID)
    
    					for idx, subif := range iface.Subinterfaces.Subinterface {
    						log.Printf("Subinterface [%d] index: %v", idx, *subif.Index)
    						if subif.Ipv4 != nil && subif.Ipv4.Addresses != nil {
    							for k := range subif.Ipv4.Addresses.Address {
    								ipID = int32(makeIPAddress(client, k+"/24", element.GetName()+"das ist der Beschreibungtext", "active", "dcim.interface", int64(ifaceID)))
    								log.Printf("IP Adresse erstellt mit der ID: %v ", ipID)
    							}
    						}
    						if subif.Ipv6 != nil && subif.Ipv6.Addresses != nil {
    							for k := range subif.Ipv6.Addresses.Address {
    								ipID = int32(makeIPAddress(client, k+"/64", element.GetName()+"das ist der beschreibungtext", "active", "dcim.interface", int64(ifaceID)))
    								log.Printf("IP Adresse erstellt mit der ID: %v ", ipID)
    							}
    						}
    					}
    
    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")
    
    	//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("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)
    
    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)
    
    	manufacturerRef := netboxapi.Int32AsBriefDeviceTypeRequestManufacturer(&manufacturerID)
    	deviceType := CreateDeviceType(manufacturerRef, model, slug, uHeight)
    
    	created, resp, err := client.DcimAPI.DcimDeviceTypesCreate(context.Background()).
    		WritableDeviceTypeRequest(*deviceType).
    		Execute()
    
    
    	if err != nil {
    
    		log.Printf("Fehler beim Erstellen des Gerätetyps: %v", err)
    		log.Printf("Fehler beim Erstellen des Gerätetyps, reqDeviceType: %v", resp.Status)
    
    		// 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)
    
    	} else {
    		deviceTypeID = created.Id
    		log.Printf("Gerätetyp erfolgreich angelegt: ID %d", deviceTypeID)
    		log.Printf("URL zum Gerätetyp: %s", created.Url)
    	}
    	return deviceTypeID
    }
    
    func makeDeviceRole(client *netboxapi.APIClient) int32 {
    	var deviceRoleID int32 = 0
    	slug := "grossUndWichtig" // muss slug-konform sein (keine Leerzeichen, Kleinbuchstaben)
    
    	role := CreateDeviceRole("Wichtige Box", slug, "Ist WohlWichtigGenug, damit es hier ist", "ff0000")
    
    	created, resp, err := client.DcimAPI.DcimDeviceRolesCreate(context.Background()).
    		DeviceRoleRequest(*role).
    		Execute()
    
    	if err != nil {
    		log.Printf("Fehler beim Erstellen der Device Role: %v", err)
    		log.Printf("Fehlerhafte Antwort: %v", resp.Status)
    
    		// 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)
    
    		deviceRoleID = created.Id
    		log.Printf("Device Role erfolgreich erstellt: ID %d", deviceRoleID)
    		log.Printf("Device Role URL: %s", created.Url)
    
    func makeSite(client *netboxapi.APIClient) int32 {
    	var siteID int32 = 0
    	slug := "darmstadt-der-groe" // slug muss URL-konform sein
    
    	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",
    	)
    
    	created, resp, err := client.DcimAPI.DcimSitesCreate(context.Background()).
    		WritableSiteRequest(*site).
    		Execute()
    
    
    	if err != nil {
    
    		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)
    
    	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()
    
    
    	if err != nil {
    
    		//log.Printf("Fehler beim Erstellen des Geräts: %v", err)
    
    		if resp != nil {
    			log.Printf("HTTP-Status: %s", resp.Status)
    		}
    
    
    		// Fallback: Searching for the Device with the 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)
    
    	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 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)
    
    func makeIPAddress(client *netboxapi.APIClient, address, description, status, assignedType string, interfaceID int64) int64 {
    
    	//addressWithoutPort := extractIP(address)
    	//addressWithoutPort = addressWithoutPort + "/32"
    	//ip := CreateIPAddress(address, description, "active", "dcim.interface", interfaceID)
    	ip := CreateIPAddress(address, description, status, assignedType, interfaceID)
    
    
    	createdIP, resp, err := client.IpamAPI.
    		IpamIpAddressesCreate(context.Background()).
    		WritableIPAddressRequest(*ip).
    		Execute()
    
    
    	if err != nil {
    
    		log.Printf("Fehler beim Erstellen der IP-Adresse: %v", err)
    		if resp != nil {
    
    			log.Printf("Fehlerhafte Antwort: %v", address)
    
    			log.Printf("HTTP Status: %s", resp.Status)
    
    			log.Printf("HTTP Request: %v", resp.Request)
    			log.Printf("HTTP Body: %s", resp.Body)
    			log.Printf("HTTP StatusCode: %d", resp.StatusCode)
    
    		}
    
    		// 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)
    
    func GetModelAsStruct(gnmiNotifications []*gnmi.Notification) (*temp.Device, error) {
    	modelAsSchema := ytypes.Schema{
    		Root:       &temp.Device{},
    		SchemaTree: temp.SchemaTree,
    	}
    
    	err := ytypes.UnmarshalNotifications(&modelAsSchema, gnmiNotifications, &ytypes.IgnoreExtraFields{})
    	if err != nil {
    		return nil, err
    	}
    
    	modelAsStruct, ok := modelAsSchema.Root.(*temp.Device)
    	if !ok {
    		return nil, errors.New("dynamic cast fail")
    	}
    
    	return modelAsStruct, nil
    }
    
    /*
    	func extractPort(address string) string {
    		parts := strings.Split(address, ":")
    		if len(parts) == 2 {
    			return parts[1]
    		}
    		return address // falls kein Doppelpunkt vorhanden ist
    	}
    
    func extractIP(address string) string {
    	parts := strings.Split(address, ":")
    	if len(parts) == 2 {
    		return parts[0]
    	}
    	return address
    }
    */