package reservation import ( "context" "errors" "log/slog" "git.staur.ca/stobbsm/kea-manage/lib/types" "github.com/jackc/pgx/v5" ) const insertHostReservation = `INSERT INTO hosts (dhcp_identifier, dhcp_identifier_type, dhcp4_subnet_id, ipv4_address, hostname) VALUES (DECODE(REPLACE($1, ':', ''), 'hex'), $2, $3, (SELECT ($4::inet - '0.0.0.0'::inet)), $5);` const getHostIDWithMacAddr = `SELECT host_id FROM hosts WHERE dhcp4_subnet_id = $1 AND dhcp_identifier_type = $2 AND dhcp_identifier = (DECODE(REPLACE($3, ':', ''), 'hex'));` const insertIfNotExists = `INSERT INTO hosts (dhcp_identifier, dhcp_identifier_type, dhcp4_subnet_id, ipv4_address, hostname) SELECT DECODE(REPLACE($1, ':', ''), 'hex'), $2, $3, (SELECT ($4::inet - '0.0.0.0'::inet)), $5 WHERE NOT EXISTS ( SELECT host_id FROM hosts WHERE dhcp4_subnet_id = $3 AND dhcp_identifier_type = $2 AND dhcp_identifier = DECODE(REPLACE($1, ':', ''), 'hex'));` type ReservationV4 struct { Type int SubnetID int MacAddr string Ipv4 string Hostname string } func ReserveV4MacAddr(mac string, addr string, hostname string, subnet int) *ReservationV4 { r := &ReservationV4{ MacAddr: mac, Type: int(types.MacAddress), SubnetID: subnet, Ipv4: addr, Hostname: hostname, } return r } func (r *ReservationV4) check(conn *pgx.Conn) error { rows, err := conn.Query(context.Background(), getHostIDWithMacAddr, r.SubnetID, r.Type, r.MacAddr) if err != nil { slog.Error("error during check query") return err } slog.Info("check result size") if rv, _ := rows.Values(); len(rv) > 0 { return errors.New("existing record found") } return nil } func (r *ReservationV4) Insert(conn *pgx.Conn) error { tx, err := conn.Begin(context.Background()) if err != nil { return err } defer tx.Rollback(context.Background()) if _, err = tx.Exec(context.Background(), insertIfNotExists, r.MacAddr, r.Type, r.SubnetID, r.Ipv4, r.Hostname); err != nil { return err } if err = tx.Commit(context.Background()); err != nil { return err } return nil }