Skip to content

VM Tracker Client - Reference Documentation

Table of Contents

  1. Overview
  2. Data Structures
  3. Interfaces
  4. Functions
  5. Command Line Parameters
  6. Usage Examples
  7. Error Handling
  8. Integration

Overview

The VM Tracker Client is a service written in Go that automatically sends information about virtual machines (VMs) to a central API server. The client continuously monitors hostname and IP address of a VM and registers this information at regular intervals.

Main Features

  • ✅ Automatic hostname detection
  • ✅ Detection of IPv4 addresses on specific network interfaces
  • ✅ Periodic registration with an API server
  • ✅ Automatic retry on errors
  • ✅ Graceful shutdown on SIGTERM/SIGINT
  • ✅ Configurable update interval

Architecture

┌─────────────────────┐
│   VM Tracker Client │
│                     │
│  ┌───────────────┐  │
│  │ Hostname      │  │
│  │ Detection     │  │
│  └───────────────┘  │
│                     │
│  ┌───────────────┐  │
│  │ IP Address    │  │
│  │ Detection     │  │
│  └───────────────┘  │
│                     │
│  ┌───────────────┐  │
│  │ HTTP Client   │  │
│  │ Registration  │  │
│  └───────────────┘  │
└─────────────────────┘
         │ HTTP POST
         │ /api/register
┌─────────────────────┐
│   API Server        │
└─────────────────────┘

Data Structures

VMInfo

The central data structure containing information about a VM.

Definition

type VMInfo struct {
    Hostname  string `json:"hostname"`
    IPAddress string `json:"ip_address"`
    Interface string `json:"interface"`
}

Fields

Field Type JSON Tag Description
Hostname string hostname The hostname of the VM (e.g., "web-server-01")
IPAddress string ip_address The IPv4 address of the VM (e.g., "192.168.1.100")
Interface string interface The name of the network interface (e.g., "eth0", "enp0s1")

JSON Representation

{
  "hostname": "web-server-01",
  "ip_address": "192.168.1.100",
  "interface": "eth0"
}

Usage

info := VMInfo{
    Hostname:  "my-vm",
    IPAddress: "10.0.0.5",
    Interface: "enp0s1",
}

// JSON marshaling
jsonData, err := json.Marshal(info)
if err != nil {
    log.Fatal(err)
}

// JSON unmarshaling
var vmInfo VMInfo
err = json.Unmarshal(jsonData, &vmInfo)
if err != nil {
    log.Fatal(err)
}

Validation

  • Hostname: Can contain any characters but should conform to a valid hostname format
  • IPAddress: Must be a valid IPv4 address (validated by net.ParseIP())
  • Interface: Must be an existing network interface on the system

Interfaces

HTTPClient

Interface for HTTP operations, enables mocking and testing.

Definition

type HTTPClient interface {
    Post(url, contentType string, body *bytes.Buffer) (*http.Response, error)
}

Methods

Post
Post(url, contentType string, body *bytes.Buffer) (*http.Response, error)

Parameters: - url (string): The complete URL for the POST request - contentType (string): MIME type of the request body (e.g., "application/json") - body (*bytes.Buffer): The request body as a buffer

Return Values: - *http.Response: The HTTP response or nil on error - error: Error information or nil on success

Example:

client := &DefaultHTTPClient{}
body := bytes.NewBufferString(`{"key":"value"}`)
resp, err := client.Post("http://api.example.com/data", "application/json", body)
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

DefaultHTTPClient

Production implementation of the HTTPClient interface.

Definition

type DefaultHTTPClient struct{}

Methods

func (c *DefaultHTTPClient) Post(url, contentType string, body *bytes.Buffer) (*http.Response, error)

Wrapper around the standard http.Post() function.

Usage:

client := &DefaultHTTPClient{}
// Use as HTTPClient interface

Functions

getHostname

Determines the hostname of the system.

Signature

func getHostname() string

Return Values

  • string: The hostname of the system or "unknown" on error

Description

This function uses os.Hostname() to determine the hostname. On error, "unknown" is returned and the error is logged.

Example

hostname := getHostname()
fmt.Printf("Hostname: %s\n", hostname)
// Output: Hostname: web-server-01

Error Handling

  • On errors, a warning is logged: "Error getting hostname: <error>"
  • Return value is always a valid string (never empty)

See Also

  • Reference: main.go:24

getIPAddress

Determines the IPv4 address of a specific network interface.

Signature

func getIPAddress(interfaceName string) (string, error)

Parameters

  • interfaceName (string): Name of the network interface (e.g., "eth0", "enp0s1", "en0")

Return Values

  • string: The IPv4 address of the interface or empty string on error
  • error: Error information or nil on success

Description

This function searches for the specified network interface and returns the first non-loopback IPv4 address found.

Example

ip, err := getIPAddress("eth0")
if err != nil {
    log.Fatal(err)
}
fmt.Printf("IP Address: %s\n", ip)
// Output: IP Address: 192.168.1.100

Errors

Error Type Description
"interface %s not found: %v" The specified interface doesn't exist
"error getting addresses for %s: %v" Error retrieving addresses
"no IPv4 address found on interface %s" No IPv4 address found on the interface

Implementation Details

  1. Searches for the interface with net.InterfaceByName()
  2. Retrieves all addresses with iface.Addrs()
  3. Filters for non-loopback IPv4 addresses
  4. Returns the first address found

See Also

  • Reference: main.go:33

sendRegistration

Sends a VM registration to the API server (production wrapper).

Signature

func sendRegistration(apiURL string, info VMInfo) error

Parameters

  • apiURL (string): Base URL of the API server (e.g., "http://api.example.com:8080")
  • info (VMInfo): VM information to send

Return Values

  • error: Error information or nil on success

Description

This function is a wrapper around sendRegistrationWithClient() and uses the DefaultHTTPClient for production environments.

Example

apiURL := "http://api.example.com:8080"
info := VMInfo{
    Hostname:  "web-01",
    IPAddress: "192.168.1.100",
    Interface: "eth0",
}

err := sendRegistration(apiURL, info)
if err != nil {
    log.Printf("Registration failed: %v", err)
}

See Also

  • sendRegistrationWithClient() for detailed implementation
  • Reference: main.go:70

sendRegistrationWithClient

Sends a VM registration with a custom HTTP client.

Signature

func sendRegistrationWithClient(apiURL string, info VMInfo, client HTTPClient) error

Parameters

  • apiURL (string): Base URL of the API server
  • info (VMInfo): VM information to send
  • client (HTTPClient): HTTP client for the request

Return Values

  • error: Error information or nil on success

Description

Sends an HTTP POST request to <apiURL>/api/register with the VM information as JSON body.

HTTP Request

Endpoint: POST /api/register

Headers:

Content-Type: application/json

Body:

{
  "hostname": "web-server-01",
  "ip_address": "192.168.1.100",
  "interface": "eth0"
}

HTTP Response

Success: - Status Code: 200 OK

Error: - Status Code: != 200 (any error code)

Errors

Error Type Description
"error marshaling JSON: %v" JSON serialization failed
"error sending request: %v" Network error when sending
"server returned status %d" Server returned a non-200 status code

Example with Mock Client

// Mock for testing
mockClient := &MockHTTPClient{
    PostFunc: func(url, contentType string, body *bytes.Buffer) (*http.Response, error) {
        return &http.Response{
            StatusCode: 200,
            Body:       io.NopCloser(bytes.NewBufferString("OK")),
        }, nil
    },
}

info := VMInfo{
    Hostname:  "test-vm",
    IPAddress: "192.168.1.100",
    Interface: "eth0",
}

err := sendRegistrationWithClient("http://api.example.com", info, mockClient)
if err != nil {
    log.Fatal(err)
}

Implementation Details

  1. Marshals VMInfo to JSON
  2. Sends POST request to <apiURL>/api/register
  3. Checks HTTP status code
  4. Properly closes response body

See Also

  • Reference: main.go:74

Command Line Parameters

The VM Tracker Client supports the following command line flags:

-api

Type: string Default: "http://10.0.2.196:8080" Description: URL of the API server

Usage:

./vm-tracker-client -api "http://api.example.com:8080"
./vm-tracker-client -api "https://secure-api.example.com"

Notes: - Trailing slashes are automatically removed - Supports HTTP and HTTPS - Port can be optionally specified


-interface

Type: string Default: "enp0s1" Description: Name of the network interface to monitor

Usage:

./vm-tracker-client -interface "eth0"
./vm-tracker-client -interface "en0"
./vm-tracker-client -interface "wlan0"

Common Interface Names:

Operating System Typical Names
Linux eth0, eth1, enp0s1, enp0s3
macOS en0, en1
Windows Ethernet, Wi-Fi

-interval

Type: int Default: 30 Unit: Seconds Description: Interval between updates

Usage:

./vm-tracker-client -interval 60   # Every 60 seconds
./vm-tracker-client -interval 10   # Every 10 seconds
./vm-tracker-client -interval 300  # Every 5 minutes

Recommended Values: - Development: 10-30 seconds - Production: 60-300 seconds - Low load: 300+ seconds


-retry

Type: int Default: 5 Unit: Seconds Description: Wait time between retry attempts on errors

Usage:

./vm-tracker-client -retry 10  # Wait 10 seconds
./vm-tracker-client -retry 1   # Fast retry


-verbose

Type: bool Default: false Description: Enables verbose logging

Usage:

./vm-tracker-client -verbose
./vm-tracker-client -verbose=true

Output with -verbose:

2025/11/04 12:00:00 Sending registration: {Hostname:web-01 IPAddress:192.168.1.100 Interface:eth0}
2025/11/04 12:00:00 Update sent successfully
2025/11/04 12:00:30 Sending update: {Hostname:web-01 IPAddress:192.168.1.100 Interface:eth0}
2025/11/04 12:00:30 Update sent successfully


Usage Examples

Basic Usage

# Simplest start with default values
./vm-tracker-client

# With custom parameters
./vm-tracker-client \
  -api "http://api.example.com:8080" \
  -interface "eth0" \
  -interval 60 \
  -verbose

Docker Container

docker run -d \
  --name vm-tracker-client \
  --network host \
  vm-tracker-client:latest \
  -api "http://api-server:8080" \
  -interface "eth0" \
  -interval 30

Systemd Service

[Unit]
Description=VM Tracker Client
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/vm-tracker-client \
  -api "http://api.example.com:8080" \
  -interface "eth0" \
  -interval 60 \
  -retry 5
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Kubernetes Deployment

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: vm-tracker-client
spec:
  selector:
    matchLabels:
      app: vm-tracker-client
  template:
    metadata:
      labels:
        app: vm-tracker-client
    spec:
      hostNetwork: true
      containers:
      - name: client
        image: vm-tracker-client:latest
        args:
        - "-api"
        - "http://vm-tracker-api:8080"
        - "-interface"
        - "eth0"
        - "-interval"
        - "60"
        - "-verbose"

Programmatic Usage

package main

import (
    "log"
    "time"
)

func main() {
    apiURL := "http://api.example.com:8080"
    interfaceName := "eth0"

    // Initial registration
    hostname := getHostname()
    ipAddress, err := getIPAddress(interfaceName)
    if err != nil {
        log.Fatalf("Failed to get IP: %v", err)
    }

    info := VMInfo{
        Hostname:  hostname,
        IPAddress: ipAddress,
        Interface: interfaceName,
    }

    err = sendRegistration(apiURL, info)
    if err != nil {
        log.Fatalf("Failed to register: %v", err)
    }

    log.Printf("Successfully registered: %s @ %s", hostname, ipAddress)

    // Periodic updates
    ticker := time.NewTicker(30 * time.Second)
    defer ticker.Stop()

    for range ticker.C {
        // Update and send
        ipAddress, err := getIPAddress(interfaceName)
        if err != nil {
            log.Printf("Error getting IP: %v", err)
            continue
        }

        info.IPAddress = ipAddress
        err = sendRegistration(apiURL, info)
        if err != nil {
            log.Printf("Failed to send update: %v", err)
        }
    }
}

Error Handling

Retry Mechanism

The client implements automatic retry on errors:

Initial Registration

maxRetries := 3
retryCount := 0

for retryCount < maxRetries {
    err := sendRegistration(apiURL, info)
    if err == nil {
        break // Success
    }

    log.Printf("Failed to register: %v, retrying in %d seconds...", err, retryDelay)
    time.Sleep(time.Duration(retryDelay) * time.Second)
    retryCount++
}

if retryCount >= maxRetries {
    log.Fatalf("Failed to register after %d attempts, exiting", maxRetries)
}

Periodic Updates

For periodic updates, errors do not abort, only log:

for {
    select {
    case <-ticker.C:
        err := sendRegistration(apiURL, info)
        if err != nil {
            log.Printf("Failed to send update: %v", err)
            // Wait for next tick
        }
    }
}

Error Types

Error Type Description Handling
Network Error Connection to server failed Retry with exponential backoff
HTTP 4xx Client error (e.g., invalid data) Log, possibly abort
HTTP 5xx Server error Retry with wait time
Interface Error Network interface not found Log, keep trying
JSON Error Serialization error Log, critical error

Signal Handling

Graceful shutdown on SIGTERM/SIGINT:

sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT)

for {
    select {
    case sig := <-sigChan:
        log.Printf("Received signal %v, shutting down...", sig)
        return
    case <-ticker.C:
        // Normal operation
    }
}

Supported Signals: - SIGTERM - Graceful shutdown - SIGINT - Ctrl+C interrupt


Integration

API Server Requirements

The client expects a compatible API server with the following endpoint:

POST /api/register

Request:

POST /api/register HTTP/1.1
Host: api.example.com:8080
Content-Type: application/json

{
  "hostname": "web-server-01",
  "ip_address": "192.168.1.100",
  "interface": "eth0"
}

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "status": "registered",
  "timestamp": "2025-11-04T12:00:00Z"
}

Error Response:

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
  "error": "Invalid request data"
}

Monitoring & Logging

The client writes logs to stdout/stderr:

Log Levels:

Level Example Description
INFO VM Tracker Client starting... Normal operations
INFO Successfully registered with API server Successful actions
WARNING Warning: interface not found, retrying... Non-critical errors
ERROR Failed to register: connection refused Errors with retry
FATAL Failed to register after 3 attempts, exiting Critical errors, program abort

Log Format:

2025/11/04 12:00:00 <Message>

Metrics

For monitoring, the following metrics can be captured:

  • Registration Success Rate: Successful vs. failed registrations
  • API Response Time: Time for /api/register calls
  • Update Interval: Actual vs. configured interval
  • Retry Count: Number of retry attempts
  • Uptime: Runtime of the client

Health Checks

For container orchestration:

# Check if process is running
pgrep -f vm-tracker-client

# Check if updates are being sent (log-based)
timeout 65 tail -f /var/log/vm-tracker.log | grep -q "Update sent"

Appendix

Build Instructions

# Standard build
go build -o vm-tracker-client main.go

# With optimization
go build -ldflags="-s -w" -o vm-tracker-client main.go

# Cross-compilation for Linux
GOOS=linux GOARCH=amd64 go build -o vm-tracker-client-linux main.go

# With version info
go build -ldflags="-X main.Version=1.0.0" -o vm-tracker-client main.go

Testing

# Unit tests
go test -v

# With coverage
go test -v -cover -coverprofile=coverage.out

# Benchmarks
go test -bench=. -benchmem

Dependencies

The client uses only Go Standard Library:

import (
    "bytes"
    "encoding/json"
    "flag"
    "fmt"
    "log"
    "net"
    "net/http"
    "os"
    "os/signal"
    "strings"
    "syscall"
    "time"
)

No external dependencies required!

Performance

Resource Usage: - CPU: < 1% idle, < 5% during updates - Memory: ~5-10 MB RAM - Network: Minimal (~1-2 KB per update)

Scaling: - Can run thousands of instances in parallel - Network load: ~2 KB × (Number of VMs) / Interval - Example: 1000 VMs @ 60s interval = ~33 KB/s

Security

Recommendations:

  1. Use HTTPS: -api "https://api.example.com"
  2. Authentication: Extend with API keys/tokens if needed
  3. Firewall: Only allow outbound connections to API server
  4. Least Privilege: Run client with minimal permissions
  5. Log Rotation: Regularly rotate and archive logs

License

Please refer to the project's license terms.

Support

For questions or problems: - See unittests for test documentation - Create an issue in the repository - Check logs with -verbose flag


Version: 1.0 Last Updated: 2025-11-04 Author: VM Tracker Team