-
Notifications
You must be signed in to change notification settings - Fork 0
Copilot/sub pr 16 #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| name: CI | ||
|
|
||
| on: | ||
| push: | ||
| paths: | ||
| - "aios-layer/**" | ||
| pull_request: | ||
| paths: | ||
| - "aios-layer/**" | ||
|
|
||
| jobs: | ||
| build-test: | ||
| runs-on: ubuntu-latest | ||
| defaults: | ||
| run: | ||
| working-directory: aios-layer | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-go@v5 | ||
| with: | ||
| go-version: "1.22" | ||
| - run: go mod download | ||
| - run: make build | ||
| - run: ./scripts/run_checks.sh | ||
| - uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: aios-layer-reports | ||
| path: aios-layer/reports | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| /bin | ||
| /reports |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| # Contributing | ||
|
|
||
| Thanks for contributing to AIOS Layer! | ||
|
|
||
| ## Development setup | ||
|
|
||
| ```bash | ||
| make build | ||
| make test | ||
| ``` | ||
|
|
||
| ## Code style | ||
|
|
||
| - Go fmt (`gofmt`) required. | ||
| - Keep security-sensitive changes documented in `SECURITY.md`. | ||
|
|
||
| ## Pull requests | ||
|
|
||
| - Include tests for new behavior. | ||
| - Update docs if user-facing changes are introduced. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| MIT License | ||
|
|
||
| Copyright (c) 2025 | ||
|
|
||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the "Software"), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
|
|
||
| The above copyright notice and this permission notice shall be included in all | ||
| copies or substantial portions of the Software. | ||
|
|
||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| SOFTWARE. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| SHELL := /usr/bin/env bash | ||
|
|
||
| .PHONY: build test bench run | ||
|
|
||
| build: | ||
| go build -o bin/aios-agent ./agent | ||
| go build -o bin/aiosctl ./cli | ||
|
Comment on lines
+5
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| test: | ||
| go test -count=2 ./agent/... ./cli/... | ||
|
|
||
| bench: | ||
| mkdir -p reports | ||
| go test ./agent/... -run ^$ -bench . -benchmem -count=2 | tee reports/bench.log | ||
|
|
||
| run: | ||
| ./bin/aios-agent -config config/aios.yaml | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| # AIOS Layer (MVP) | ||
|
|
||
| AIOS Layer is a reproducible, secure-by-default AI/GPU “OS-style layer” that runs on top of an existing host OS. It provides a minimal host agent, GPU-aware scheduling, runtime launch hooks, and a CLI + optional UI for inference workflows. | ||
|
|
||
| ## 10-minute Quickstart (Ubuntu 24.04 + NVIDIA) | ||
|
|
||
| 1) **Install prerequisites** | ||
|
|
||
| ```bash | ||
| sudo apt-get update | ||
| sudo apt-get install -y docker.io docker-compose-plugin | ||
| # NVIDIA drivers + container toolkit (see docs below) | ||
| ``` | ||
|
|
||
| 2) **Build + run** | ||
|
|
||
| ```bash | ||
| cd aios-layer | ||
| make build | ||
| ./scripts/run_demo.sh | ||
| ``` | ||
|
|
||
| 3) **Request a lease + run inference** | ||
|
|
||
| ```bash | ||
| ./bin/aiosctl lease --agent http://127.0.0.1:8080 --user demo --duration 300 | ||
| ./bin/aiosctl infer --endpoint http://127.0.0.1:8000/v1/chat/completions --prompt "Hello from AIOS" | ||
| ``` | ||
|
|
||
| 4) **Open the UI** | ||
|
|
||
| ```bash | ||
| python3 -m http.server 9000 -d ui | ||
| # visit http://127.0.0.1:9000/index.html | ||
| ``` | ||
|
|
||
| ## Architecture Overview | ||
|
|
||
| - **Control plane**: `aios-agent` manages GPU discovery, scheduling, policy enforcement, and runtime launch. | ||
| - **Data plane**: model servers run in containers (vLLM in the MVP). | ||
| - **Interface**: `aiosctl` CLI and a static UI. | ||
|
|
||
| See `docs/architecture.md` for diagrams and rationale. | ||
|
|
||
| ## NVIDIA GPU Integration (MVP) | ||
|
|
||
| - Driver + `nvidia-container-toolkit` required for GPU containers. | ||
| - GPU discovery via `nvidia-smi` (NVML alternative in v1). | ||
| - Scheduler uses exclusive GPU leases (time-based). | ||
| - CPU-only fallback is enabled when no GPU is detected. | ||
|
|
||
| ## Security | ||
|
|
||
| - Minimal privileges for the agent and containers. | ||
| - Example seccomp + AppArmor profiles in `deploy/security`. | ||
| - No telemetry; metrics are local-only. | ||
|
|
||
| ## Tests | ||
|
|
||
| ```bash | ||
| make test | ||
| ./scripts/run_checks.sh | ||
| ``` | ||
|
|
||
| Test and benchmark logs are written to `reports/` when using `./scripts/run_checks.sh`. | ||
|
|
||
| ## License | ||
|
|
||
| MIT |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| # Security Policy | ||
|
|
||
| ## Reporting | ||
|
|
||
| Please report security issues by opening a private security advisory in the repository. | ||
|
|
||
| ## Supported versions | ||
|
|
||
| Only the latest release is supported. | ||
|
|
||
| ## Hardening | ||
|
|
||
| - Run `aios-agent` as a non-root user. | ||
| - Use AppArmor and seccomp profiles in `deploy/security`. | ||
| - Avoid granting containers additional capabilities. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| package config | ||
|
|
||
| import ( | ||
| "os" | ||
|
|
||
| "gopkg.in/yaml.v3" | ||
| ) | ||
|
|
||
| type Config struct { | ||
| Server ServerConfig `yaml:"server"` | ||
| Policy PolicyConfig `yaml:"policy"` | ||
| Scheduler SchedulerConfig `yaml:"scheduler"` | ||
| Runtime RuntimeConfig `yaml:"runtime"` | ||
| Model ModelConfig `yaml:"model"` | ||
| Metrics MetricsConfig `yaml:"metrics"` | ||
| } | ||
|
|
||
| type ServerConfig struct { | ||
| ListenAddress string `yaml:"listen_address"` | ||
| } | ||
|
|
||
| type PolicyConfig struct { | ||
| MaxGPUsPerUser int `yaml:"max_gpus_per_user"` | ||
| MaxDurationSec int `yaml:"max_duration_sec"` | ||
| } | ||
|
|
||
| type SchedulerConfig struct { | ||
| LeaseTTLSeconds int `yaml:"lease_ttl_seconds"` | ||
| } | ||
|
|
||
| type RuntimeConfig struct { | ||
| DockerSocket string `yaml:"docker_socket"` | ||
| ModelImage string `yaml:"model_image"` | ||
| ModelPort int `yaml:"model_port"` | ||
| EnableLaunch bool `yaml:"enable_launch"` | ||
| } | ||
|
|
||
| type ModelConfig struct { | ||
| Endpoint string `yaml:"endpoint"` | ||
| } | ||
|
|
||
| type MetricsConfig struct { | ||
| Enabled bool `yaml:"enabled"` | ||
| } | ||
|
|
||
| func Load(path string) (Config, error) { | ||
| data, err := os.ReadFile(path) | ||
| if err != nil { | ||
| return Config{}, err | ||
| } | ||
| var cfg Config | ||
| if err := yaml.Unmarshal(data, &cfg); err != nil { | ||
| return Config{}, err | ||
| } | ||
| return cfg, nil | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| package gpu | ||
|
|
||
| import ( | ||
| "bufio" | ||
| "bytes" | ||
| "errors" | ||
| "os/exec" | ||
| "strconv" | ||
| "strings" | ||
| ) | ||
|
|
||
| type GPU struct { | ||
| Index int `json:"index"` | ||
| Name string `json:"name"` | ||
| MemoryTotal int `json:"memory_total_mb"` | ||
| } | ||
|
|
||
| func Discover() ([]GPU, error) { | ||
| cmd := exec.Command("nvidia-smi", "--query-gpu=index,name,memory.total", "--format=csv,noheader,nounits") | ||
| output, err := cmd.Output() | ||
| if err != nil { | ||
| return nil, errors.New("nvidia-smi not available") | ||
| } | ||
|
Comment on lines
+21
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| return parseCSV(output) | ||
| } | ||
|
|
||
| func parseCSV(data []byte) ([]GPU, error) { | ||
| var gpus []GPU | ||
| scanner := bufio.NewScanner(bytes.NewReader(data)) | ||
| for scanner.Scan() { | ||
| line := strings.TrimSpace(scanner.Text()) | ||
| if line == "" { | ||
| continue | ||
| } | ||
| parts := strings.Split(line, ",") | ||
| if len(parts) < 3 { | ||
| continue | ||
| } | ||
| index, err := strconv.Atoi(strings.TrimSpace(parts[0])) | ||
| if err != nil { | ||
| continue | ||
| } | ||
| name := strings.TrimSpace(parts[1]) | ||
| mem, err := strconv.Atoi(strings.TrimSpace(parts[2])) | ||
| if err != nil { | ||
| continue | ||
| } | ||
|
Comment on lines
+39
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The index, err := strconv.Atoi(strings.TrimSpace(parts[0]))
if err != nil {
log.Printf("failed to parse GPU index from line '%s': %v", line, err)
continue
}
name := strings.TrimSpace(parts[1])
mem, err := strconv.Atoi(strings.TrimSpace(parts[2]))
if err != nil {
log.Printf("failed to parse GPU memory from line '%s': %v", line, err)
continue
} |
||
| gpus = append(gpus, GPU{Index: index, Name: name, MemoryTotal: mem}) | ||
| } | ||
| if err := scanner.Err(); err != nil { | ||
| return nil, err | ||
| } | ||
| return gpus, nil | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,21 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package policy | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import "errors" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type Policy struct { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MaxGPUsPerUser int | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MaxDurationSec int | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (p Policy) ValidateRequest(existingLeases int, requestedDuration int) error { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if p.MaxGPUsPerUser > 0 && existingLeases >= p.MaxGPUsPerUser { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return errors.New("gpu quota exceeded") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if p.MaxDurationSec > 0 && requestedDuration > p.MaxDurationSec { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return errors.New("requested duration exceeds policy") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if requestedDuration <= 0 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return errors.New("invalid duration") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+10
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package runtime | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "os/exec" | ||
| ) | ||
|
|
||
| type DockerLauncher struct { | ||
| Socket string | ||
| Image string | ||
| ModelPort int | ||
| } | ||
|
|
||
| func (d DockerLauncher) Launch(gpuIndex int) error { | ||
| args := []string{ | ||
| "-H", d.Socket, | ||
| "run", "--rm", "-d", | ||
| "--gpus", fmt.Sprintf("device=%d", gpuIndex), | ||
| "-p", fmt.Sprintf("%d:%d", d.ModelPort, d.ModelPort), | ||
| d.Image, | ||
| } | ||
| cmd := exec.Command("docker", args...) | ||
| return cmd.Run() | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The CI workflow can be optimized by caching Go modules to speed up subsequent builds. Consider adding a caching step for
~/go/pkg/modand the Go build cache before thego mod downloadstep. You can useactions/cachefor this.