330 lines
8.7 KiB
Go
Raw Normal View History

2025-03-11 14:07:01 +03:00
package eth
import (
"encoding/json"
"fmt"
"gopkg.in/yaml.v3"
"io"
"log"
"net"
"net/http"
2025-03-12 22:35:36 +03:00
"network_configurator/models"
2025-03-11 14:07:01 +03:00
"os"
"os/exec"
)
2025-03-12 22:35:36 +03:00
const netplanFilePath = "/etc/netplan/eth.yaml"
2025-03-11 14:07:01 +03:00
func NetplanHandler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
getNetplanConfig(w, r)
case http.MethodPut:
updateNetplanConfig(w, r)
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
}
func getNetplanConfig(w http.ResponseWriter, r *http.Request) {
config, err := readNetplanConfig()
if err != nil {
http.Error(w, fmt.Sprintf("Failed to read config: %v", err), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(config)
}
func updateNetplanConfig(w http.ResponseWriter, r *http.Request) {
2025-03-12 22:35:36 +03:00
var updatedConfig models.NetplanConfig
2025-03-11 14:07:01 +03:00
err := json.NewDecoder(r.Body).Decode(&updatedConfig)
if err != nil {
http.Error(w, fmt.Sprintf("Failed to decode request body: %v", err), http.StatusBadRequest)
return
}
err = writeNetplanConfig(updatedConfig)
if err != nil {
http.Error(w, fmt.Sprintf("Failed to write config: %v", err), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("Netplan configuration updated successfully"))
}
2025-03-12 22:35:36 +03:00
func readNetplanConfig() (*models.NetplanConfig, error) {
2025-03-11 14:07:01 +03:00
yamlFile, err := os.ReadFile(netplanFilePath)
if err != nil {
return nil, fmt.Errorf("failed to read netplan file: %w", err)
}
2025-03-12 22:35:36 +03:00
var config models.NetplanConfig
2025-03-11 14:07:01 +03:00
err = yaml.Unmarshal(yamlFile, &config)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal yaml: %w", err)
}
return &config, nil
}
2025-03-12 22:35:36 +03:00
func writeNetplanConfig(config models.NetplanConfig) error {
2025-03-11 14:07:01 +03:00
savedConfig, err := readNetplanConfig()
if err != nil {
return fmt.Errorf("failed to read eth yaml: %w", err)
}
yamlData, err := yaml.Marshal(config)
if err != nil {
return fmt.Errorf("failed to marshal yaml: %w", err)
}
err = os.WriteFile(netplanFilePath, yamlData, 0644)
if err != nil {
return fmt.Errorf("failed to write netplan file: %w", err)
}
cmd := exec.Command("netplan", "apply")
output, err := cmd.CombinedOutput()
if err != nil {
yamlData, err := yaml.Marshal(*savedConfig)
if err != nil {
return fmt.Errorf("failed to marshal yaml: %w", err)
}
err = os.WriteFile(netplanFilePath, yamlData, 0644)
if err != nil {
return fmt.Errorf("failed to write netplan file: %w", err)
}
return fmt.Errorf("Ошибка при выполнении команды: %s\n Вывод команды: %s\n", err, output)
}
return nil
}
func RawNetplanHandler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
getRawNetplanConfig(w, r)
case http.MethodPut:
updateRawNetplanConfig(w, r)
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
}
func getRawNetplanConfig(w http.ResponseWriter, r *http.Request) {
content, err := readRawNetplanConfig()
if err != nil {
http.Error(w, fmt.Sprintf("Failed to read raw config: %v", err), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "text/plain")
w.Write([]byte(content))
}
func updateRawNetplanConfig(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, fmt.Sprintf("Failed to read request body: %v", err), http.StatusBadRequest)
return
}
rawYamlContent := string(body)
// Валидация YAML перед записью
if !isValidYAML(rawYamlContent) {
http.Error(w, "Invalid YAML content", http.StatusBadRequest)
return
}
err = writeRawNetplanConfig(rawYamlContent)
if err != nil {
http.Error(w, fmt.Sprintf("Failed to write raw config: %v", err), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("Raw Netplan configuration updated successfully"))
}
func readRawNetplanConfig() (string, error) {
2025-03-12 22:35:36 +03:00
2025-03-11 14:07:01 +03:00
yamlFile, err := os.ReadFile(netplanFilePath)
if err != nil {
return "", fmt.Errorf("failed to read netplan file: %w", err)
}
2025-03-12 22:35:36 +03:00
2025-03-11 14:07:01 +03:00
return string(yamlFile), nil
}
func writeRawNetplanConfig(content string) error {
2025-03-12 22:35:36 +03:00
savedConfig, err := readRawNetplanConfig()
if err != nil {
return fmt.Errorf("failed to read eth yaml: %w", err)
}
err = os.WriteFile(netplanFilePath, []byte(content), 0644)
2025-03-11 14:07:01 +03:00
if err != nil {
return fmt.Errorf("failed to write netplan file: %w", err)
}
2025-03-12 22:35:36 +03:00
cmd := exec.Command("netplan", "apply")
output, err := cmd.CombinedOutput()
if err != nil {
err = os.WriteFile(netplanFilePath, []byte(savedConfig), 0644)
if err != nil {
return fmt.Errorf("failed to write netplan file: %w", err)
}
return fmt.Errorf("Ошибка при выполнении команды: %s\n Вывод команды: %s\n", err, output)
}
2025-03-11 14:07:01 +03:00
return nil
}
// isValidYAML проверяет, является ли строка валидным YAML
func isValidYAML(yamlString string) bool {
var temp map[interface{}]interface{}
err := yaml.Unmarshal([]byte(yamlString), &temp)
return err == nil
}
// Функция для создания тестового файла eth.yaml (для демонстрации)
func createTestNetplanFile() {
initialYaml := `
network:
version: 2
renderer: networkd
ethernets:
eth0:
dhcp4: yes
addresses: [192.168.8.111/24]
nameservers:
addresses: [8.8.8.8, 8.8.4.4]
`
err := os.WriteFile(netplanFilePath, []byte(initialYaml), 0644)
if err != nil {
log.Fatalf("Failed to create test netplan file: %v", err)
}
fmt.Println("Test netplan file created at:", netplanFilePath)
}
func init() {
// Создаем тестовый файл при запуске сервера, если его нет (для демонстрации)
if _, err := os.Stat(netplanFilePath); os.IsNotExist(err) {
createTestNetplanFile()
}
}
// MacAdres HTTP handler для получения MAC адреса интерфейса eth0
func MacAdres(w http.ResponseWriter, r *http.Request) {
interfaces, err := net.Interfaces()
if err != nil {
2025-03-12 22:35:36 +03:00
response := models.MacAddressResponse{
2025-03-11 14:07:01 +03:00
Error: fmt.Sprintf("Failed to get network interfaces: %v", err),
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError) // 500 Internal Server Error
json.NewEncoder(w).Encode(response)
return
}
var eth0Interface *net.Interface
for _, iface := range interfaces {
if iface.Name == "eth0" {
eth0Interface = &iface
break
}
}
if eth0Interface == nil {
2025-03-12 22:35:36 +03:00
response := models.MacAddressResponse{
2025-03-11 14:07:01 +03:00
Error: "Interface eth0 not found",
Interface: "eth0",
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusNotFound) // 404 Not Found
json.NewEncoder(w).Encode(response)
return
}
macAddress := eth0Interface.HardwareAddr.String()
2025-03-12 22:35:36 +03:00
response := models.MacAddressResponse{
2025-03-11 14:07:01 +03:00
MacAddress: macAddress,
Interface: "eth0",
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(response)
}
// InterfaceIPs HTTP handler для получения списка IP адресов интерфейса eth0
func InterfaceIPs(w http.ResponseWriter, r *http.Request) {
interfaces, err := net.Interfaces()
if err != nil {
2025-03-12 22:35:36 +03:00
response := models.InterfaceIPsResponse{
2025-03-11 14:07:01 +03:00
Error: fmt.Sprintf("Failed to get network interfaces: %v", err),
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError) // 500 Internal Server Error
json.NewEncoder(w).Encode(response)
return
}
var eth0Interface *net.Interface
for _, iface := range interfaces {
if iface.Name == "eth0" {
eth0Interface = &iface
break
}
}
if eth0Interface == nil {
2025-03-12 22:35:36 +03:00
response := models.InterfaceIPsResponse{
2025-03-11 14:07:01 +03:00
Interface: "eth0",
Error: "Interface eth0 not found",
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusNotFound) // 404 Not Found
json.NewEncoder(w).Encode(response)
return
}
addrs, err := eth0Interface.Addrs()
if err != nil {
2025-03-12 22:35:36 +03:00
response := models.InterfaceIPsResponse{
2025-03-11 14:07:01 +03:00
Interface: "eth0",
Error: fmt.Sprintf("Failed to get addresses for eth0: %v", err),
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError) // 500 Internal Server Error
json.NewEncoder(w).Encode(response)
return
}
ipAddresses := make([]string, 0)
for _, addr := range addrs {
2025-03-12 22:35:36 +03:00
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil || ipnet.IP.To16() != nil {
2025-03-11 14:07:01 +03:00
ipAddresses = append(ipAddresses, ipnet.IP.String())
}
}
}
2025-03-12 22:35:36 +03:00
response := models.InterfaceIPsResponse{
2025-03-11 14:07:01 +03:00
Interface: "eth0",
IPAddresses: ipAddresses,
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK) // 200 OK
json.NewEncoder(w).Encode(response)
}