-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdocker-control.py
119 lines (106 loc) · 4.01 KB
/
docker-control.py
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
import paho.mqtt.client as mqtt
import docker
import time
import json
import traceback
docker_client = docker.from_env()
service_name = "docker"
announce_packet = {
"title": "Docker Control Script",
"description": "Manages Docker containers",
"author": "Randy Herban <[email protected]>",
"url": None,
"source": "github.com/spectrumx/docker/docker-control.py",
"output": {},
"version": "0.1",
"type": "service",
"time_started": time.time(),
}
# Define MQTT callbacks
def on_connect(client, userdata, flags, rc):
global service_name
print(f"{service_name} connected to mqtt: {rc}")
send_status(client)
def on_message(client, userdata, msg):
try:
payload = msg.payload.decode()
print(f"Received message: {payload}")
parts = payload.split()
if parts[0] == "start":
start_container(' '.join(parts[1:]))
elif parts[0] == "stop":
stop_container(' '.join(parts[1:]))
elif parts[0] == "pull":
pull_container(' '.join(parts[1:]))
elif parts[0] == "run":
# Assume rest of input is a dictionary which will get passed directly to containers.run()
json_string = ' '.join(parts[2:]).replace("'", '"')
run_container(parts[1], json.loads(json_string))
elif parts[0] == "status":
# List this as a valid command, but we send status with every command
pass
else:
print(f"Unknown command: {parts[0]}")
send_status(client)
except Exception as err:
print(f"Failed to parse incoming message: {msg.payload.decode()}\n{err}\n{traceback.format_exc()}")
def send_status(client):
global service_name
# Get Docker container status
containers_info = []
for container in docker_client.containers.list():
container_info = {
'id': container.id,
'name': container.name,
'status': container.status,
'image': container.image.tags
}
containers_info.append(container_info)
#payload["docker"] = containers_info
payload = {
"state": "online",
"timestamp": time.time(),
"task_name": "tasks.admin.save_docker",
"arguments": {"containers": containers_info},
}
client.publish(service_name + "/status", json.dumps(payload), retain=True)
def run_container(name, args):
try:
container = docker_client.containers.run(name, **args, detach=True)
print(f"Running container: {container.name} with {args}")
except docker.errors.NotFound:
print(f"Container not found: {args}")
except docker.errors.APIError as e:
print(f"API error: {e}")
def start_container(container_name):
try:
container = docker_client.containers.get(container_name)
container.start()
print(f"Started container: {container_name}")
except docker.errors.NotFound:
print(f"Container not found: {container_name}")
except docker.errors.APIError as e:
print(f"API error: {e}")
def stop_container(container_name):
try:
container = docker_client.containers.get(container_name)
container.stop()
print(f"Stopped container: {container_name}")
except docker.errors.NotFound:
print(f"Container not found: {container_name}")
def pull_container(image_name):
try:
docker_client.images.pull(image_name)
print(f"Pulled image: {image_name}")
except docker.errors.APIError as e:
print(f"Failed to pull image: {image_name}, error: {e}")
# Initialize MQTT client
mqtt_client = mqtt.Client()
mqtt_client.on_message = on_message
mqtt_client.on_connect = on_connect
#Set last will & testament which sends an offline status when this client disconnects. Has to come before the connect() call.
mqtt_client.will_set(service_name + "/status", payload=json.dumps({"state":"offline"}), qos=0, retain=True)
mqtt_client.connect('localhost', 1883, 60)
mqtt_client.subscribe(service_name + "/command")
# Start MQTT loop in background, since there's no active tasks for us to run
mqtt_client.loop_forever()