-
Notifications
You must be signed in to change notification settings - Fork 12
/
Makefile
254 lines (206 loc) · 8.83 KB
/
Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
.DEFAULT_GOAL := up
.EXPORT_ALL_VARIABLES:
# Commands
YQ=docker run --rm -i -v $(shell pwd):/workdir mikefarah/yq:4
KINDCONFIG := $(or $(KINDCONFIG),control-plane/kind.yaml)
KUBECONFIG := $(shell pwd)/.kubeconfig
MKE2FS_CONFIG := $(shell pwd)/mke2fs.conf
# Default values
CONTAINERLAB=$(shell which containerlab)
# extra vars can be used by projects that built on the mini-lab, which want to override default configuration
ANSIBLE_EXTRA_VARS_FILE := $(or $(ANSIBLE_EXTRA_VARS_FILE),)
MINI_LAB_FLAVOR := $(or $(MINI_LAB_FLAVOR),sonic)
MINI_LAB_VM_IMAGE := $(or $(MINI_LAB_VM_IMAGE),ghcr.io/metal-stack/mini-lab-vms:latest)
MINI_LAB_SONIC_IMAGE := $(or $(MINI_LAB_SONIC_IMAGE),ghcr.io/metal-stack/mini-lab-sonic:latest)
MACHINE_OS=ubuntu-24.04
MAX_RETRIES := 30
# Machine flavors
ifeq ($(MINI_LAB_FLAVOR),cumulus)
LAB_MACHINES=machine01,machine02
LAB_TOPOLOGY=mini-lab.cumulus.yaml
VRF=vrf20
else ifeq ($(MINI_LAB_FLAVOR),sonic)
LAB_MACHINES=machine01,machine02
LAB_TOPOLOGY=mini-lab.sonic.yaml
VRF=Vrf20
else
$(error Unknown flavor $(MINI_LAB_FLAVOR))
endif
KIND_ARGS=
ifneq ($(K8S_VERSION),)
KIND_ARGS=--image kindest/node:v$(K8S_VERSION)
endif
ifeq ($(CI),true)
DOCKER_COMPOSE_RUN_ARG=--no-TTY --rm
else
DOCKER_COMPOSE_RUN_ARG=--rm
endif
.PHONY: up
up: env control-plane-bake partition-bake
@chmod 600 files/ssh/id_rsa
docker compose up --remove-orphans --force-recreate control-plane partition
@$(MAKE) --no-print-directory start-machines
# for some reason an allocated machine will not be able to phone home
# without restarting the metal-core
# TODO: should be investigated and fixed if possible
sleep 10
ssh -F files/ssh/config leaf01 'systemctl restart metal-core'
ssh -F files/ssh/config leaf02 'systemctl restart metal-core'
.PHONY: restart
restart: down up
.PHONY: down
down: cleanup
.PHONY: control-plane
control-plane: control-plane-bake env
docker compose up --remove-orphans --force-recreate control-plane
.PHONY: control-plane-bake
control-plane-bake:
@if ! which kind > /dev/null; then echo "kind needs to be installed"; exit 1; fi
@if ! kind get clusters | grep metal-control-plane > /dev/null; then \
kind create cluster $(KIND_ARGS) \
--name metal-control-plane \
--config $(KINDCONFIG) \
--kubeconfig $(KUBECONFIG); fi
.PHONY: partition
partition: partition-bake
docker compose up --remove-orphans --force-recreate partition
.PHONY: partition-bake
partition-bake: external_network
docker pull $(MINI_LAB_VM_IMAGE)
ifeq ($(MINI_LAB_FLAVOR),sonic)
docker pull $(MINI_LAB_SONIC_IMAGE)
endif
@if ! sudo $(CONTAINERLAB) --topo $(LAB_TOPOLOGY) inspect | grep -i leaf01 > /dev/null; then \
sudo --preserve-env $(CONTAINERLAB) deploy --topo $(LAB_TOPOLOGY) --reconfigure && \
./scripts/deactivate_offloading.sh; fi
.PHONY: external_network
external_network:
@if ! docker network ls | grep -q mini_lab_ext; then \
docker network create mini_lab_ext \
--driver=bridge \
--gateway=203.0.113.1 \
--subnet=203.0.113.0/24 \
--opt "com.docker.network.driver.mtu=9000" \
--opt "com.docker.network.bridge.name=mini_lab_ext" \
--opt "com.docker.network.bridge.enable_ip_masquerade=true" && \
sudo ip route add 203.0.113.128/25 via 203.0.113.2 dev mini_lab_ext; fi
.PHONY: env
env:
@./env.sh
.PHONY: cleanup
cleanup: cleanup-control-plane cleanup-partition
.PHONY: cleanup-control-plane
cleanup-control-plane:
kind delete cluster --name metal-control-plane
docker compose down
rm -f $(KUBECONFIG)
.PHONY: cleanup-partition
cleanup-partition:
mkdir -p clab-mini-lab
sudo --preserve-env $(CONTAINERLAB) destroy --topo mini-lab.cumulus.yaml
sudo --preserve-env $(CONTAINERLAB) destroy --topo mini-lab.sonic.yaml
docker network rm --force mini_lab_ext
.PHONY: _privatenet
_privatenet: env
docker compose run $(DOCKER_COMPOSE_RUN_ARG) metalctl network list --name user-private-network | grep user-private-network || docker compose run $(DOCKER_COMPOSE_RUN_ARG) metalctl network allocate --partition mini-lab --project 00000000-0000-0000-0000-000000000001 --name user-private-network
.PHONY: machine
machine: _privatenet
docker compose run $(DOCKER_COMPOSE_RUN_ARG) metalctl machine create --description test --name test --hostname test --project 00000000-0000-0000-0000-000000000001 --partition mini-lab --image $(MACHINE_OS) --size v1-small-x86 --userdata "@/tmp/ignition.json" --networks internet-mini-lab,$(shell docker compose run $(DOCKER_COMPOSE_RUN_ARG) metalctl network list --name user-private-network -o template --template '{{ .id }}')
.PHONY: firewall
firewall: _privatenet
docker compose run $(DOCKER_COMPOSE_RUN_ARG) metalctl firewall create --description fw --name fw --hostname fw --project 00000000-0000-0000-0000-000000000001 --partition mini-lab --image firewall-ubuntu-3.0 --size v1-small-x86 --userdata "@/tmp/ignition.json" --firewall-rules-file=/tmp/rules.yaml --networks internet-mini-lab,$(shell docker compose run $(DOCKER_COMPOSE_RUN_ARG) metalctl network list --name user-private-network -o template --template '{{ .id }}')
.PHONY: public-ip
public-ip:
@docker compose run $(DOCKER_COMPOSE_RUN_ARG) metalctl network ip list --name test --network internet-mini-lab -o template --template "{{ .ipaddress }}"
.PHONY: ls
ls: env
docker compose run $(DOCKER_COMPOSE_RUN_ARG) metalctl machine ls
## SWITCH MANAGEMENT ##
.PHONY: ssh-leafconfig
ssh-leafconfig:
@grep "Host leaf01" ~/.ssh/config || echo -e "Host leaf01\n StrictHostKeyChecking no\n IdentityFile $(shell pwd)/files/ssh/id_rsa\n" >>~/.ssh/config
@grep "Host leaf02" ~/.ssh/config || echo -e "Host leaf02\n StrictHostKeyChecking no\n IdentityFile $(shell pwd)/files/ssh/id_rsa\n" >>~/.ssh/config
.PHONY: docker-leaf01
docker-leaf01:
@echo "export DOCKER_HOST=ssh://root@leaf01/var/run/docker.sock"
.PHONY: docker-leaf02
docker-leaf02:
@echo "export DOCKER_HOST=ssh://root@leaf02/var/run/docker.sock"
.PHONY: ssh-leaf01
ssh-leaf01:
ssh -F files/ssh/config leaf01
.PHONY: ssh-leaf02
ssh-leaf02:
ssh -F files/ssh/config leaf02
## MACHINE MANAGEMENT ##
.PHONY: start-machines
start-machines:
docker exec vms /mini-lab/manage_vms.py --names $(LAB_MACHINES) create
.PHONY: _password
_password: env
docker compose run $(DOCKER_COMPOSE_RUN_ARG) metalctl machine consolepassword $(MACHINE_UUID)
.PHONY: password-machine01
password-machine01:
@$(MAKE) --no-print-directory _password MACHINE_UUID=e0ab02d2-27cd-5a5e-8efc-080ba80cf258
.PHONY: password-machine02
password-machine02:
@$(MAKE) --no-print-directory _password MACHINE_UUID=2294c949-88f6-5390-8154-fa53d93a3313
.PHONY: _free-machine
_free-machine: env
docker compose run $(DOCKER_COMPOSE_RUN_ARG) metalctl machine rm $(MACHINE_UUID)
docker exec vms /mini-lab/manage_vms.py --names $(MACHINE_NAME) kill --with-disks
docker exec vms /mini-lab/manage_vms.py --names $(MACHINE_NAME) create
.PHONY: free-machine01
free-machine01:
@$(MAKE) --no-print-directory _free-machine MACHINE_NAME=machine01 MACHINE_UUID=e0ab02d2-27cd-5a5e-8efc-080ba80cf258
.PHONY: free-machine02
free-machine02:
@$(MAKE) --no-print-directory _free-machine MACHINE_NAME=machine02 MACHINE_UUID=2294c949-88f6-5390-8154-fa53d93a3313
.PHONY: _console-machine
_console-machine:
@echo "exit console with CTRL+5 and then quit telnet through q + ENTER"
@docker exec -it vms telnet 127.0.0.1 $(CONSOLE_PORT)
.PHONY: console-machine01
console-machine01:
@$(MAKE) --no-print-directory _console-machine CONSOLE_PORT=4000
.PHONY: console-machine02
console-machine02:
@$(MAKE) --no-print-directory _console-machine CONSOLE_PORT=4001
## SSH TARGETS FOR MACHINES ##
# Python code could be replaced by jq, but it is not preinstalled on Cumulus
.PHONY: ssh-firewall
ssh-firewall:
$(eval fw = $(shell ssh -F files/ssh/config leaf01 "vtysh -c 'show bgp neighbors fw json' | \
python3 -c 'import sys, json; data = json.load(sys.stdin); key = next(iter(data)); print(data[key][\"bgpNeighborAddr\"] + \"%\" + key)'" \
))
ssh -F files/ssh/config $(fw) $(COMMAND)
.PHONY: ssh-machine
ssh-machine:
$(eval machine = $(shell ssh -F files/ssh/config leaf01 "vtysh -c 'show bgp vrf $(VRF) neighbors test json' | \
python3 -c 'import sys, json; data = json.load(sys.stdin); key = next(iter(data)); print(data[key][\"bgpNeighborAddr\"] + \"%\" + key)'" \
))
ssh -F files/ssh/config $(machine) $(COMMAND)
.PHONY: connect-to-www
connect-to-www:
@echo "Attempting to connect to container www..."
@for i in $$(seq 1 $(MAX_RETRIES)); do \
if $(MAKE) ssh-machine COMMAND="sudo curl --connect-timeout 1 --fail --silent http://203.0.113.3" > /dev/null 2>&1; then \
echo "Connected successfully"; \
exit 0; \
else \
echo "Connection failed"; \
if [ $$i -lt $(MAX_RETRIES) ]; then \
echo "Retrying in 2 seconds..."; \
sleep 2; \
else \
echo "Max retries reached"; \
exit 1; \
fi; \
fi; \
done
## DEV TARGETS ##
.PHONY: dev-env
dev-env:
@echo "export METALCTL_API_URL=http://api.172.17.0.1.nip.io:8080/metal"
@echo "export METALCTL_HMAC=metal-admin"
@echo "export KUBECONFIG=$(KUBECONFIG)"