diff options
-rw-r--r-- | DOCUMENTATION.md | 2 | ||||
-rw-r--r-- | environments/immae-eu.nix | 2 | ||||
-rw-r--r-- | modules/private/buildbot/common/libvirt.py | 306 | ||||
-rw-r--r-- | modules/private/buildbot/default.nix | 18 | ||||
-rw-r--r-- | modules/private/buildbot/projects/test/__init__.py | 19 | ||||
-rw-r--r-- | modules/private/environment.nix | 3 | ||||
-rw-r--r-- | modules/private/gitolite/default.nix | 2 | ||||
-rw-r--r-- | modules/private/system/dilion.nix | 18 | ||||
-rw-r--r-- | modules/private/system/dilion/vms.nix | 146 | ||||
-rw-r--r-- | modules/private/system/dilion/vms/base_configuration.nix | 21 | ||||
-rw-r--r-- | modules/private/system/dilion/vms/base_image.nix | 94 | ||||
-rw-r--r-- | modules/private/system/dilion/vms/buildbot_configuration.nix | 67 | ||||
m--------- | nixops/secrets | 0 |
13 files changed, 686 insertions, 12 deletions
diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index 1697299..50eeca4 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md | |||
@@ -180,7 +180,7 @@ Things to look at during upgrades: | |||
180 | Upgrade to latest unstable | 180 | Upgrade to latest unstable |
181 | ------------------- | 181 | ------------------- |
182 | 182 | ||
183 | - Nothing in particular yet | 183 | - Weechat: https://specs.weechat.org/specs/001285-follow-xdg-base-dir-spec.html |
184 | 184 | ||
185 | Etherpad-lite | 185 | Etherpad-lite |
186 | ------------- | 186 | ------------- |
diff --git a/environments/immae-eu.nix b/environments/immae-eu.nix index ca9e5b5..df57e55 100644 --- a/environments/immae-eu.nix +++ b/environments/immae-eu.nix | |||
@@ -123,7 +123,7 @@ let | |||
123 | sshfs ncdu procps-ng | 123 | sshfs ncdu procps-ng |
124 | 124 | ||
125 | # other tools | 125 | # other tools |
126 | pgloader s3cmd lftp jq cpulimit libxslt gandi-cli | 126 | pgloader s3cmd lftp jq cpulimit libxslt gandi-cli bubblewrap |
127 | 127 | ||
128 | # Terraform + AWS | 128 | # Terraform + AWS |
129 | terraform_0_12 awscli | 129 | terraform_0_12 awscli |
diff --git a/modules/private/buildbot/common/libvirt.py b/modules/private/buildbot/common/libvirt.py new file mode 100644 index 0000000..85fd908 --- /dev/null +++ b/modules/private/buildbot/common/libvirt.py | |||
@@ -0,0 +1,306 @@ | |||
1 | # This file was part of Buildbot. Buildbot is free software: you can | ||
2 | # redistribute it and/or modify it under the terms of the GNU General Public | ||
3 | # License as published by the Free Software Foundation, version 2. | ||
4 | # | ||
5 | # This program is distributed in the hope that it will be useful, but WITHOUT | ||
6 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
7 | # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | ||
8 | # details. | ||
9 | # | ||
10 | # You should have received a copy of the GNU General Public License along with | ||
11 | # this program; if not, write to the Free Software Foundation, Inc., 51 | ||
12 | # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
13 | # | ||
14 | # Portions Copyright Buildbot Team Members | ||
15 | # Portions Copyright 2010 Isotoma Limited | ||
16 | |||
17 | |||
18 | import os | ||
19 | |||
20 | from twisted.internet import defer | ||
21 | from twisted.internet import threads | ||
22 | from twisted.internet import utils | ||
23 | from twisted.python import failure | ||
24 | from twisted.python import log | ||
25 | |||
26 | from buildbot import config | ||
27 | from buildbot.util.eventual import eventually | ||
28 | from buildbot.worker import AbstractLatentWorker | ||
29 | |||
30 | try: | ||
31 | import libvirt | ||
32 | except ImportError: | ||
33 | libvirt = None | ||
34 | |||
35 | import random | ||
36 | import string | ||
37 | |||
38 | def random_string_generator(): | ||
39 | chars = string.ascii_letters | ||
40 | return ''.join(random.choice(chars) for x in range(6)) | ||
41 | |||
42 | class WorkQueue: | ||
43 | |||
44 | """ | ||
45 | I am a class that turns parallel access into serial access. | ||
46 | |||
47 | I exist because we want to run libvirt access in threads as we don't | ||
48 | trust calls not to block, but under load libvirt doesn't seem to like | ||
49 | this kind of threaded use. | ||
50 | """ | ||
51 | |||
52 | def __init__(self): | ||
53 | self.queue = [] | ||
54 | |||
55 | def _process(self): | ||
56 | log.msg("Looking to start a piece of work now...") | ||
57 | |||
58 | # Is there anything to do? | ||
59 | if not self.queue: | ||
60 | log.msg("_process called when there is no work") | ||
61 | return | ||
62 | |||
63 | # Peek at the top of the stack - get a function to call and | ||
64 | # a deferred to fire when its all over | ||
65 | d, next_operation, args, kwargs = self.queue[0] | ||
66 | |||
67 | # Start doing some work - expects a deferred | ||
68 | try: | ||
69 | d2 = next_operation(*args, **kwargs) | ||
70 | except Exception: | ||
71 | d2 = defer.fail() | ||
72 | |||
73 | # Whenever a piece of work is done, whether it worked or not | ||
74 | # call this to schedule the next piece of work | ||
75 | @d2.addBoth | ||
76 | def _work_done(res): | ||
77 | log.msg("Completed a piece of work") | ||
78 | self.queue.pop(0) | ||
79 | if self.queue: | ||
80 | log.msg("Preparing next piece of work") | ||
81 | eventually(self._process) | ||
82 | return res | ||
83 | |||
84 | # When the work is done, trigger d | ||
85 | d2.chainDeferred(d) | ||
86 | |||
87 | def execute(self, cb, *args, **kwargs): | ||
88 | kickstart_processing = not self.queue | ||
89 | d = defer.Deferred() | ||
90 | self.queue.append((d, cb, args, kwargs)) | ||
91 | if kickstart_processing: | ||
92 | self._process() | ||
93 | return d | ||
94 | |||
95 | def executeInThread(self, cb, *args, **kwargs): | ||
96 | return self.execute(threads.deferToThread, cb, *args, **kwargs) | ||
97 | |||
98 | |||
99 | # A module is effectively a singleton class, so this is OK | ||
100 | queue = WorkQueue() | ||
101 | |||
102 | |||
103 | class Domain: | ||
104 | |||
105 | """ | ||
106 | I am a wrapper around a libvirt Domain object | ||
107 | """ | ||
108 | |||
109 | def __init__(self, connection, domain): | ||
110 | self.connection = connection | ||
111 | self.domain = domain | ||
112 | |||
113 | def name(self): | ||
114 | return queue.executeInThread(self.domain.name) | ||
115 | |||
116 | def create(self): | ||
117 | return queue.executeInThread(self.domain.create) | ||
118 | |||
119 | def shutdown(self): | ||
120 | return queue.executeInThread(self.domain.shutdown) | ||
121 | |||
122 | def destroy(self): | ||
123 | return queue.executeInThread(self.domain.destroy) | ||
124 | |||
125 | class Volume: | ||
126 | def __init__(self, connection, volume): | ||
127 | self.connection = connection | ||
128 | self.volume = volume | ||
129 | |||
130 | @defer.inlineCallbacks | ||
131 | def destroy(self): | ||
132 | yield queue.executeInThread(self.volume.wipe) | ||
133 | yield queue.executeInThread(self.volume.delete) | ||
134 | |||
135 | class Pool: | ||
136 | VolumeClass = Volume | ||
137 | def __init__(self, connection, pool): | ||
138 | self.connection = connection | ||
139 | self.pool = pool | ||
140 | |||
141 | @defer.inlineCallbacks | ||
142 | def create_volume(self, xml): | ||
143 | res = yield queue.executeInThread(self.pool.createXML, xml) | ||
144 | return self.VolumeClass(self.connection, res) | ||
145 | |||
146 | class Connection: | ||
147 | |||
148 | """ | ||
149 | I am a wrapper around a libvirt Connection object. | ||
150 | """ | ||
151 | |||
152 | DomainClass = Domain | ||
153 | PoolClass = Pool | ||
154 | |||
155 | def __init__(self, uri): | ||
156 | self.uri = uri | ||
157 | self.connection = libvirt.open(uri) | ||
158 | |||
159 | @defer.inlineCallbacks | ||
160 | def create(self, xml): | ||
161 | """ I take libvirt XML and start a new VM """ | ||
162 | res = yield queue.executeInThread(self.connection.createXML, xml, 0) | ||
163 | return self.DomainClass(self, res) | ||
164 | |||
165 | @defer.inlineCallbacks | ||
166 | def lookup_pool(self, name): | ||
167 | res = yield queue.executeInThread(self.connection.storagePoolLookupByName, name) | ||
168 | return self.PoolClass(self, res) | ||
169 | |||
170 | class LibVirtWorker(AbstractLatentWorker): | ||
171 | |||
172 | def __init__(self, name, password, connection, master_url, base_image=None, **kwargs): | ||
173 | super().__init__(name, password, **kwargs) | ||
174 | if not libvirt: | ||
175 | config.error( | ||
176 | "The python module 'libvirt' is needed to use a LibVirtWorker") | ||
177 | |||
178 | self.master_url = master_url | ||
179 | self.random_name = random_string_generator() | ||
180 | self.connection = connection | ||
181 | self.base_image = base_image | ||
182 | |||
183 | self.domain = None | ||
184 | self.domain_name = "buildbot-" + self.workername + "-" + self.random_name | ||
185 | self.volume = None | ||
186 | self.volume_name = "buildbot-" + self.workername + "-" + self.random_name | ||
187 | self.pool_name = "buildbot-disks" | ||
188 | |||
189 | def reconfigService(self, *args, **kwargs): | ||
190 | if 'build_wait_timeout' not in kwargs: | ||
191 | kwargs['build_wait_timeout'] = 0 | ||
192 | return super().reconfigService(*args, **kwargs) | ||
193 | |||
194 | def canStartBuild(self): | ||
195 | if self.domain and not self.isConnected(): | ||
196 | log.msg( | ||
197 | "Not accepting builds as existing domain but worker not connected") | ||
198 | return False | ||
199 | |||
200 | return super().canStartBuild() | ||
201 | |||
202 | @defer.inlineCallbacks | ||
203 | def _prepare_image(self): | ||
204 | log.msg("Creating temporary image {}".format(self.volume_name)) | ||
205 | pool = yield self.connection.lookup_pool(self.pool_name) | ||
206 | vol_xml = """ | ||
207 | <volume type='file'> | ||
208 | <name>{vol_name}</name> | ||
209 | <capacity unit='G'>10</capacity> | ||
210 | <target> | ||
211 | <format type='qcow2'/> | ||
212 | <permissions> | ||
213 | <mode>0600</mode> | ||
214 | <owner>0</owner> | ||
215 | <group>0</group> | ||
216 | </permissions> | ||
217 | </target> | ||
218 | <backingStore> | ||
219 | <path>/etc/libvirtd/base-images/buildbot.qcow2</path> | ||
220 | <format type='qcow2'/> | ||
221 | </backingStore> | ||
222 | </volume> | ||
223 | """.format(vol_name = self.volume_name) | ||
224 | self.volume = yield pool.create_volume(vol_xml) | ||
225 | |||
226 | @defer.inlineCallbacks | ||
227 | def start_instance(self, build): | ||
228 | """ | ||
229 | I start a new instance of a VM. | ||
230 | |||
231 | If a base_image is specified, I will make a clone of that otherwise i will | ||
232 | use image directly. | ||
233 | |||
234 | If i'm not given libvirt domain definition XML, I will look for my name | ||
235 | in the list of defined virtual machines and start that. | ||
236 | """ | ||
237 | domain_xml = """ | ||
238 | <domain type="kvm"> | ||
239 | <name>{domain_name}</name> | ||
240 | <memory unit="GiB">2</memory> | ||
241 | <vcpu>1</vcpu> | ||
242 | <sysinfo type='smbios'> | ||
243 | <oemStrings> | ||
244 | <entry>buildbot_master_url={master_url}</entry> | ||
245 | <entry>buildbot_worker_name={worker_name}</entry> | ||
246 | </oemStrings> | ||
247 | </sysinfo> | ||
248 | <os> | ||
249 | <type arch="x86_64">hvm</type> | ||
250 | <smbios mode='sysinfo'/> | ||
251 | </os> | ||
252 | <devices> | ||
253 | <emulator>/run/current-system/sw/bin/qemu-system-x86_64</emulator> | ||
254 | <disk type="volume" device="disk"> | ||
255 | <driver name='qemu' type='qcow2' /> | ||
256 | <source type="volume" pool="{pool_name}" volume="{volume_name}" /> | ||
257 | <backingStore type='volume'> | ||
258 | <format type='qcow2'/> | ||
259 | <source type="volume" pool="niximages" volume="buildbot.qcow2" /> | ||
260 | </backingStore> | ||
261 | <target dev="vda" bus="virtio"/> | ||
262 | </disk> | ||
263 | <input type="keyboard" bus="usb"/> | ||
264 | <graphics type="vnc" port="-1" autoport="yes"/> | ||
265 | <interface type="network"> | ||
266 | <source network="immae" /> | ||
267 | </interface> | ||
268 | </devices> | ||
269 | </domain> | ||
270 | """.format(volume_name = self.volume_name, master_url = self.master_url, pool_name = | ||
271 | self.pool_name, domain_name = self.domain_name, worker_name = self.workername) | ||
272 | |||
273 | yield self._prepare_image() | ||
274 | |||
275 | try: | ||
276 | self.domain = yield self.connection.create(domain_xml) | ||
277 | except Exception: | ||
278 | log.err(failure.Failure(), | ||
279 | ("Cannot start a VM ({}), failing gracefully and triggering" | ||
280 | "a new build check").format(self.workername)) | ||
281 | self.domain = None | ||
282 | return False | ||
283 | |||
284 | return [self.domain_name] | ||
285 | |||
286 | def stop_instance(self, fast=False): | ||
287 | """ | ||
288 | I attempt to stop a running VM. | ||
289 | I make sure any connection to the worker is removed. | ||
290 | If the VM was using a cloned image, I remove the clone | ||
291 | When everything is tidied up, I ask that bbot looks for work to do | ||
292 | """ | ||
293 | |||
294 | log.msg("Attempting to stop '{}'".format(self.workername)) | ||
295 | if self.domain is None: | ||
296 | log.msg("I don't think that domain is even running, aborting") | ||
297 | return defer.succeed(None) | ||
298 | |||
299 | domain = self.domain | ||
300 | self.domain = None | ||
301 | |||
302 | d = domain.destroy() | ||
303 | if self.volume is not None: | ||
304 | self.volume.destroy() | ||
305 | |||
306 | return d | ||
diff --git a/modules/private/buildbot/default.nix b/modules/private/buildbot/default.nix index d6753e5..ac34845 100644 --- a/modules/private/buildbot/default.nix +++ b/modules/private/buildbot/default.nix | |||
@@ -107,7 +107,12 @@ in | |||
107 | project_env = with lib.attrsets; | 107 | project_env = with lib.attrsets; |
108 | mapAttrs' (k: v: nameValuePair "BUILDBOT_${k}" v) project.environment // | 108 | mapAttrs' (k: v: nameValuePair "BUILDBOT_${k}" v) project.environment // |
109 | mapAttrs' (k: v: nameValuePair "BUILDBOT_PATH_${k}" (v pkgs)) (attrByPath ["builderPaths"] {} project) // | 109 | mapAttrs' (k: v: nameValuePair "BUILDBOT_PATH_${k}" (v pkgs)) (attrByPath ["builderPaths"] {} project) // |
110 | { BUILDBOT_PROJECT_DIR = ./projects + "/${project.name}"; }; | 110 | { |
111 | BUILDBOT_PROJECT_DIR = ./projects + "/${project.name}"; | ||
112 | BUILDBOT_WORKER_PORT = builtins.toString project.workerPort; | ||
113 | BUILDBOT_HOST = config.hostEnv.fqdn; | ||
114 | BUILDBOT_VIRT_URL = "qemu+ssh://libvirt@dilion.immae.eu/system"; | ||
115 | }; | ||
111 | in builtins.concatStringsSep "\n" | 116 | in builtins.concatStringsSep "\n" |
112 | (lib.mapAttrsToList (envK: envV: "${envK}=${envV}") project_env); | 117 | (lib.mapAttrsToList (envK: envV: "${envK}=${envV}") project_env); |
113 | } | 118 | } |
@@ -126,6 +131,13 @@ in | |||
126 | permissions = "0600"; | 131 | permissions = "0600"; |
127 | user = "buildbot"; | 132 | user = "buildbot"; |
128 | group = "buildbot"; | 133 | group = "buildbot"; |
134 | text = config.myEnv.buildbot.workerPassword; | ||
135 | dest = "buildbot/worker_password"; | ||
136 | } | ||
137 | { | ||
138 | permissions = "0600"; | ||
139 | user = "buildbot"; | ||
140 | group = "buildbot"; | ||
129 | text = builtins.readFile "${config.myEnv.privateFiles}/buildbot_ssh_key"; | 141 | text = builtins.readFile "${config.myEnv.privateFiles}/buildbot_ssh_key"; |
130 | dest = "buildbot/ssh_key"; | 142 | dest = "buildbot/ssh_key"; |
131 | } | 143 | } |
@@ -135,6 +147,7 @@ in | |||
135 | restart = true; | 147 | restart = true; |
136 | paths = [ | 148 | paths = [ |
137 | "/var/secrets/buildbot/ldap" | 149 | "/var/secrets/buildbot/ldap" |
150 | "/var/secrets/buildbot/worker_password" | ||
138 | "/var/secrets/buildbot/ssh_key" | 151 | "/var/secrets/buildbot/ssh_key" |
139 | "/var/secrets/buildbot/${project.name}/environment_file" | 152 | "/var/secrets/buildbot/${project.name}/environment_file" |
140 | ] ++ lib.attrsets.mapAttrsToList (k: v: "/var/secrets/buildbot/${project.name}/${k}") project.secrets; | 153 | ] ++ lib.attrsets.mapAttrsToList (k: v: "/var/secrets/buildbot/${project.name}/${k}") project.secrets; |
@@ -144,6 +157,7 @@ in | |||
144 | description = "buildbot slice"; | 157 | description = "buildbot slice"; |
145 | }; | 158 | }; |
146 | 159 | ||
160 | networking.firewall.allowedTCPPorts = lib.attrsets.mapAttrsToList (k: v: v.workerPort) config.myEnv.buildbot.projects; | ||
147 | systemd.services = lib.attrsets.mapAttrs' (k: project: lib.attrsets.nameValuePair "buildbot-${project.name}" { | 161 | systemd.services = lib.attrsets.mapAttrs' (k: project: lib.attrsets.nameValuePair "buildbot-${project.name}" { |
148 | description = "Buildbot Continuous Integration Server ${project.name}."; | 162 | description = "Buildbot Continuous Integration Server ${project.name}."; |
149 | after = [ "network-online.target" ]; | 163 | after = [ "network-online.target" ]; |
@@ -196,6 +210,7 @@ in | |||
196 | buildbot_secrets=${varDir}/${project.name}/secrets | 210 | buildbot_secrets=${varDir}/${project.name}/secrets |
197 | install -m 0700 -o buildbot -g buildbot -d $buildbot_secrets | 211 | install -m 0700 -o buildbot -g buildbot -d $buildbot_secrets |
198 | install -Dm600 -o buildbot -g buildbot -T /var/secrets/buildbot/ldap $buildbot_secrets/ldap | 212 | install -Dm600 -o buildbot -g buildbot -T /var/secrets/buildbot/ldap $buildbot_secrets/ldap |
213 | install -Dm600 -o buildbot -g buildbot -T /var/secrets/buildbot/worker_password $buildbot_secrets/worker_password | ||
199 | ${builtins.concatStringsSep "\n" (lib.attrsets.mapAttrsToList | 214 | ${builtins.concatStringsSep "\n" (lib.attrsets.mapAttrsToList |
200 | (k: v: "install -Dm600 -o buildbot -g buildbot -T /var/secrets/buildbot/${project.name}/${k} $buildbot_secrets/${k}") project.secrets | 215 | (k: v: "install -Dm600 -o buildbot -g buildbot -T /var/secrets/buildbot/${project.name}/${k} $buildbot_secrets/${k}") project.secrets |
201 | )} | 216 | )} |
@@ -213,6 +228,7 @@ in | |||
213 | }); | 228 | }); |
214 | HOME = "${varDir}/${project.name}"; | 229 | HOME = "${varDir}/${project.name}"; |
215 | PYTHONPATH = "${buildbot.pythonModule.withPackages (self: project.pythonPackages self pkgs ++ [ | 230 | PYTHONPATH = "${buildbot.pythonModule.withPackages (self: project.pythonPackages self pkgs ++ [ |
231 | pkgs.python3Packages.libvirt | ||
216 | pkgs.python3Packages.wokkel | 232 | pkgs.python3Packages.wokkel |
217 | pkgs.python3Packages.treq pkgs.python3Packages.ldap3 buildbot | 233 | pkgs.python3Packages.treq pkgs.python3Packages.ldap3 buildbot |
218 | pkgs.python3Packages.buildbot-worker | 234 | pkgs.python3Packages.buildbot-worker |
diff --git a/modules/private/buildbot/projects/test/__init__.py b/modules/private/buildbot/projects/test/__init__.py index e6b8d51..e2f6f82 100644 --- a/modules/private/buildbot/projects/test/__init__.py +++ b/modules/private/buildbot/projects/test/__init__.py | |||
@@ -1,5 +1,6 @@ | |||
1 | from buildbot.plugins import * | 1 | from buildbot.plugins import * |
2 | from buildbot_common.build_helpers import * | 2 | from buildbot_common.build_helpers import * |
3 | import buildbot_common.libvirt as ilibvirt | ||
3 | import os | 4 | import os |
4 | from buildbot.util import bytes2unicode | 5 | from buildbot.util import bytes2unicode |
5 | import json | 6 | import json |
@@ -10,11 +11,13 @@ class E(): | |||
10 | PROJECT = "test" | 11 | PROJECT = "test" |
11 | BUILDBOT_URL = "https://git.immae.eu/buildbot/{}/".format(PROJECT) | 12 | BUILDBOT_URL = "https://git.immae.eu/buildbot/{}/".format(PROJECT) |
12 | SOCKET = "unix:/run/buildbot/{}.sock".format(PROJECT) | 13 | SOCKET = "unix:/run/buildbot/{}.sock".format(PROJECT) |
13 | PB_SOCKET = "unix:address=/run/buildbot/{}_pb.sock".format(PROJECT) | 14 | PB_SOCKET = os.environ["BUILDBOT_WORKER_PORT"] |
15 | WORKER_HOST = "{}:{}".format(os.environ["BUILDBOT_HOST"], PB_SOCKET) | ||
14 | RELEASE_PATH = "/var/lib/ftp/release.immae.eu/{}".format(PROJECT) | 16 | RELEASE_PATH = "/var/lib/ftp/release.immae.eu/{}".format(PROJECT) |
15 | RELEASE_URL = "https://release.immae.eu/{}".format(PROJECT) | 17 | RELEASE_URL = "https://release.immae.eu/{}".format(PROJECT) |
16 | GIT_URL = "https://git.immae.eu/perso/Immae/TestProject.git" | 18 | GIT_URL = "https://git.immae.eu/perso/Immae/TestProject.git" |
17 | SSH_KEY_PATH = "/var/lib/buildbot/buildbot_key" | 19 | SSH_KEY_PATH = "/var/lib/buildbot/buildbot_key" |
20 | LIBVIRT_URL = os.environ["BUILDBOT_VIRT_URL"] + "?keyfile=" + SSH_KEY_PATH | ||
18 | PUPPET_HOST = "root@backup-1.v.immae.eu" | 21 | PUPPET_HOST = "root@backup-1.v.immae.eu" |
19 | LDAP_HOST = "ldap.immae.eu" | 22 | LDAP_HOST = "ldap.immae.eu" |
20 | LDAP_DN = "cn=buildbot,ou=services,dc=immae,dc=eu" | 23 | LDAP_DN = "cn=buildbot,ou=services,dc=immae,dc=eu" |
@@ -70,8 +73,14 @@ def configure(c): | |||
70 | c["www"]["change_hook_dialects"]["base"] = { | 73 | c["www"]["change_hook_dialects"]["base"] = { |
71 | "custom_class": CustomBase | 74 | "custom_class": CustomBase |
72 | } | 75 | } |
73 | c['workers'].append(worker.LocalWorker("generic-worker-test")) | 76 | c['workers'].append(ilibvirt.LibVirtWorker("test-build", |
74 | c['workers'].append(worker.LocalWorker("deploy-worker-test")) | 77 | open(E.SECRETS_FILE + "/worker_password", "r").read().rstrip(), |
78 | ilibvirt.Connection(E.LIBVIRT_URL), | ||
79 | E.WORKER_HOST)) | ||
80 | c['workers'].append(ilibvirt.LibVirtWorker("test-deploy", | ||
81 | open(E.SECRETS_FILE + "/worker_password", "r").read().rstrip(), | ||
82 | ilibvirt.Connection(E.LIBVIRT_URL), | ||
83 | E.WORKER_HOST)) | ||
75 | 84 | ||
76 | c['schedulers'].append(hook_scheduler("TestProject", timer=1)) | 85 | c['schedulers'].append(hook_scheduler("TestProject", timer=1)) |
77 | c['schedulers'].append(force_scheduler("force_test", ["TestProject_build"])) | 86 | c['schedulers'].append(force_scheduler("force_test", ["TestProject_build"])) |
@@ -109,7 +118,7 @@ def factory(): | |||
109 | logEnviron=False, command=["echo", package])) | 118 | logEnviron=False, command=["echo", package])) |
110 | factory.addSteps(package_and_upload(package, package_dest, package_url)) | 119 | factory.addSteps(package_and_upload(package, package_dest, package_url)) |
111 | 120 | ||
112 | return util.BuilderConfig(name="TestProject_build", workernames=["generic-worker-test"], factory=factory) | 121 | return util.BuilderConfig(name="TestProject_build", workernames=["test-build"], factory=factory) |
113 | 122 | ||
114 | 123 | ||
115 | def compute_build_infos(): | 124 | def compute_build_infos(): |
@@ -143,7 +152,7 @@ def deploy_factory(): | |||
143 | ldap_password=util.Secret("ldap"))) | 152 | ldap_password=util.Secret("ldap"))) |
144 | factory.addStep(steps.MasterShellCommand(command=[ | 153 | factory.addStep(steps.MasterShellCommand(command=[ |
145 | "ssh", "-o", "UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no", "-o", "CheckHostIP=no", "-i", E.SSH_KEY_PATH, puppet_host])) | 154 | "ssh", "-o", "UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no", "-o", "CheckHostIP=no", "-i", E.SSH_KEY_PATH, puppet_host])) |
146 | return util.BuilderConfig(name="TestProject_deploy", workernames=["deploy-worker-test"], factory=factory) | 155 | return util.BuilderConfig(name="TestProject_deploy", workernames=["test-deploy"], factory=factory) |
147 | 156 | ||
148 | from twisted.internet import defer | 157 | from twisted.internet import defer |
149 | from buildbot.process.buildstep import FAILURE | 158 | from buildbot.process.buildstep import FAILURE |
diff --git a/modules/private/environment.nix b/modules/private/environment.nix index 719bf8f..f0af572 100644 --- a/modules/private/environment.nix +++ b/modules/private/environment.nix | |||
@@ -228,6 +228,7 @@ in | |||
228 | ''; | 228 | ''; |
229 | type = submodule { | 229 | type = submodule { |
230 | options = { | 230 | options = { |
231 | rootKeys = mkOption { type = attrsOf str; description = "Keys of root users"; }; | ||
231 | ldap = mkOption { | 232 | ldap = mkOption { |
232 | description = '' | 233 | description = '' |
233 | LDAP credentials for cn=ssh,ou=services,dc=immae,dc=eu dn | 234 | LDAP credentials for cn=ssh,ou=services,dc=immae,dc=eu dn |
@@ -804,6 +805,7 @@ in | |||
804 | description = "Buildbot configuration"; | 805 | description = "Buildbot configuration"; |
805 | type = submodule { | 806 | type = submodule { |
806 | options = { | 807 | options = { |
808 | workerPassword = mkOption { description = "Buildbot worker password"; type = str; }; | ||
807 | user = mkOption { | 809 | user = mkOption { |
808 | description = "Buildbot user"; | 810 | description = "Buildbot user"; |
809 | type = submodule { | 811 | type = submodule { |
@@ -855,6 +857,7 @@ in | |||
855 | ''; | 857 | ''; |
856 | }; | 858 | }; |
857 | pythonPathHome = mkOption { type = bool; description = "Whether to add project’s python home to python path"; }; | 859 | pythonPathHome = mkOption { type = bool; description = "Whether to add project’s python home to python path"; }; |
860 | workerPort = mkOption { type = port; description = "Port for the worker"; }; | ||
858 | secrets = mkOption { | 861 | secrets = mkOption { |
859 | type = attrsOf str; | 862 | type = attrsOf str; |
860 | description = "Secrets for the project to dump as files"; | 863 | description = "Secrets for the project to dump as files"; |
diff --git a/modules/private/gitolite/default.nix b/modules/private/gitolite/default.nix index 6b573e3..e54ee8a 100644 --- a/modules/private/gitolite/default.nix +++ b/modules/private/gitolite/default.nix | |||
@@ -74,7 +74,7 @@ in { | |||
74 | # Installation: https://git.immae.eu/mantisbt/view.php?id=93 | 74 | # Installation: https://git.immae.eu/mantisbt/view.php?id=93 |
75 | services.gitolite = { | 75 | services.gitolite = { |
76 | enable = true; | 76 | enable = true; |
77 | adminPubkey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDXqRbiHw7QoHADNIEuo4nUT9fSOIEBMdJZH0bkQAxXyJFyCM1IMz0pxsHV0wu9tdkkr36bPEUj2aV5bkYLBN6nxcV2Y49X8bjOSCPfx3n6Own1h+NeZVBj4ZByrFmqCbTxUJIZ2bZKcWOFncML39VmWdsVhNjg0X4NBBehqXRIKr2gt3E/ESAxTYJFm0BnU0baciw9cN0bsRGqvFgf5h2P48CIAfwhVcGmPQnnAwabnosYQzRWxR0OygH5Kd8mePh6FheIRIigfXsDO8f/jdxwut8buvNIf3m5EBr3tUbTsvM+eV3M5vKGt7sk8T64DVtepTSdOOWtp+47ktsnHOMh immae@immae.eu"; | 77 | adminPubkey = config.myEnv.sshd.rootKeys.immae_dilion; |
78 | }; | 78 | }; |
79 | }; | 79 | }; |
80 | } | 80 | } |
diff --git a/modules/private/system/dilion.nix b/modules/private/system/dilion.nix index be8269e..a59d607 100644 --- a/modules/private/system/dilion.nix +++ b/modules/private/system/dilion.nix | |||
@@ -76,12 +76,24 @@ | |||
76 | }; | 76 | }; |
77 | 77 | ||
78 | myServices.ssh.modules = [ config.myServices.ssh.predefinedModules.regular ]; | 78 | myServices.ssh.modules = [ config.myServices.ssh.predefinedModules.regular ]; |
79 | imports = builtins.attrValues (import ../..); | 79 | imports = builtins.attrValues (import ../..) ++ [ ./dilion/vms.nix ]; |
80 | 80 | ||
81 | system.nssModules = [ pkgs.libvirt ]; | 81 | system.nssModules = [ pkgs.libvirt ]; |
82 | system.nssDatabases.hosts = lib.mkForce [ "files" "libvirt_guest" "mymachines" "dns" "myhostname" ]; | 82 | system.nssDatabases.hosts = lib.mkForce [ "files" "libvirt_guest" "mymachines" "dns" "myhostname" ]; |
83 | programs.zsh.enable = true; | 83 | programs.zsh.enable = true; |
84 | 84 | ||
85 | users.users.libvirt = { | ||
86 | hashedPassword = "!"; | ||
87 | shell = pkgs.bashInteractive; | ||
88 | isSystemUser = true; | ||
89 | group = "libvirtd"; | ||
90 | packages = [ pkgs.netcat-openbsd ]; | ||
91 | openssh.authorizedKeys.keyFiles = [ | ||
92 | "${privateFiles}/buildbot_ssh_key.pub" | ||
93 | ]; | ||
94 | openssh.authorizedKeys.keys = [ config.myEnv.sshd.rootKeys.ismael_flony ]; | ||
95 | }; | ||
96 | |||
85 | users.users.backup = { | 97 | users.users.backup = { |
86 | hashedPassword = "!"; | 98 | hashedPassword = "!"; |
87 | isSystemUser = true; | 99 | isSystemUser = true; |
@@ -118,7 +130,7 @@ | |||
118 | after = [ "network.target" ]; | 130 | after = [ "network.target" ]; |
119 | 131 | ||
120 | serviceConfig = { | 132 | serviceConfig = { |
121 | ExecStart = "${pkgs.socat}/bin/socat TCP-LISTEN:8022,fork TCP:nixops-99a7e1ba-54dc-11ea-a965-10bf487fe63b-caldance:22"; | 133 | ExecStart = "${pkgs.socat}/bin/socat TCP-LISTEN:8022,fork TCP:caldance:22"; |
122 | }; | 134 | }; |
123 | }; | 135 | }; |
124 | 136 | ||
@@ -170,7 +182,7 @@ | |||
170 | recommendedGzipSettings = true; | 182 | recommendedGzipSettings = true; |
171 | recommendedProxySettings = true; | 183 | recommendedProxySettings = true; |
172 | upstreams = { | 184 | upstreams = { |
173 | caldance.servers."nixops-99a7e1ba-54dc-11ea-a965-10bf487fe63b-caldance:3031" = {}; | 185 | caldance.servers."caldance:3031" = {}; |
174 | }; | 186 | }; |
175 | virtualHosts = { | 187 | virtualHosts = { |
176 | "dev.immae.eu" = { | 188 | "dev.immae.eu" = { |
diff --git a/modules/private/system/dilion/vms.nix b/modules/private/system/dilion/vms.nix new file mode 100644 index 0000000..8d5a57b --- /dev/null +++ b/modules/private/system/dilion/vms.nix | |||
@@ -0,0 +1,146 @@ | |||
1 | # inspired from https://nixos.wiki/wiki/Virtualization_in_NixOS | ||
2 | { config, pkgs, lib, ... }@args: | ||
3 | let | ||
4 | networks = { | ||
5 | immae = { | ||
6 | bridgeNumber = "1"; | ||
7 | ipRange = "192.168.100"; | ||
8 | }; | ||
9 | }; | ||
10 | guests = { | ||
11 | caldance = { | ||
12 | pool = "zfspool"; | ||
13 | cpus = "1"; | ||
14 | memory = "2"; | ||
15 | network = "immae"; | ||
16 | diskSize = "10GiB"; | ||
17 | extraDevicesXML = '' | ||
18 | <filesystem type="mount"> | ||
19 | <source dir="/var/lib/caldance"/> | ||
20 | <target dir="home"/> | ||
21 | </filesystem> | ||
22 | ''; | ||
23 | }; | ||
24 | buildbot = { | ||
25 | pool = "zfspool"; | ||
26 | cpus = "1"; | ||
27 | memory = "3"; | ||
28 | network = "immae"; | ||
29 | diskSize = "10GiB"; | ||
30 | destroyVolumeOnExit = true; | ||
31 | preStart = '' | ||
32 | if ! ${pkgs.libvirt}/bin/virsh pool-info --pool niximages &> /dev/null; then | ||
33 | pool-create-as --name niximages --type dir --target /etc/libvirtd/base-images/ | ||
34 | fi | ||
35 | if ! ${pkgs.libvirt}/bin/virsh pool-info --pool buildbot-disks &> /dev/null; then | ||
36 | mkdir -p /var/lib/libvirt/images/buildbot-disks | ||
37 | pool-create-as --name buildbot-disks --type dir --target /var/lib/libvirt/images/buildbot-disks | ||
38 | fi | ||
39 | ''; | ||
40 | }; | ||
41 | }; | ||
42 | toImage = f: "${import ./vms/base_image.nix f (args // { myEnv = config.myEnv; })}/nixos.qcow2"; | ||
43 | in | ||
44 | { | ||
45 | environment.etc."libvirtd/base-images/nixos.qcow2".source = toImage ./vms/base_configuration.nix; | ||
46 | environment.etc."libvirtd/base-images/buildbot.qcow2".source = toImage ./vms/buildbot_configuration.nix; | ||
47 | systemd.services = lib.mapAttrs' (name: guest: lib.nameValuePair "libvirtd-guest-${name}" { | ||
48 | after = [ "libvirtd.service" "libvirtd-network-${guest.network}.service" ]; | ||
49 | requires = [ "libvirtd.service" "libvirtd-network-${guest.network}.service" ]; | ||
50 | wantedBy = [ "multi-user.target" ]; | ||
51 | serviceConfig = { | ||
52 | Type = "oneshot"; | ||
53 | RemainAfterExit = "yes"; | ||
54 | }; | ||
55 | script = | ||
56 | let | ||
57 | xml = pkgs.writeText "libvirt-guest-${name}.xml" | ||
58 | '' | ||
59 | <domain type="kvm"> | ||
60 | <name>${name}</name> | ||
61 | <uuid>UUID</uuid> | ||
62 | <memory unit="GiB">${guest.memory}</memory> | ||
63 | <vcpu>${guest.cpus}</vcpu> | ||
64 | <os> | ||
65 | <type arch="x86_64">hvm</type> | ||
66 | </os> | ||
67 | <devices> | ||
68 | <emulator>/run/current-system/sw/bin/qemu-system-x86_64</emulator> | ||
69 | <disk type="volume"> | ||
70 | <source pool="${guest.pool}" volume="guest-${name}" /> | ||
71 | <target dev="vda" bus="virtio"/> | ||
72 | </disk> | ||
73 | ${guest.extraDevicesXML or ""} | ||
74 | <input type="keyboard" bus="usb"/> | ||
75 | <graphics type="vnc" port="-1" autoport="yes"/> | ||
76 | <interface type="network"> | ||
77 | <source network="${guest.network}" /> | ||
78 | </interface> | ||
79 | </devices> | ||
80 | <features> | ||
81 | <acpi/> | ||
82 | </features> | ||
83 | </domain> | ||
84 | ''; | ||
85 | in | ||
86 | guest.preStart or "" + '' | ||
87 | if ! ${pkgs.libvirt}/bin/virsh vol-key 'guest-${name}' --pool ${guest.pool} &> /dev/null; then | ||
88 | ${pkgs.libvirt}/bin/virsh vol-create-as --pool ${guest.pool} --name 'guest-${name}' --capacity '${guest.diskSize}' | ||
89 | volume_path=$(${pkgs.libvirt}/bin/virsh vol-path --pool ${guest.pool} --vol 'guest-${name}') | ||
90 | ${pkgs.qemu}/bin/qemu-img convert /etc/libvirtd/base-images/nixos.qcow2 $volume_path | ||
91 | fi | ||
92 | uuid="$(${pkgs.libvirt}/bin/virsh domuuid '${name}' || true)" | ||
93 | ${pkgs.libvirt}/bin/virsh define <(sed "s/UUID/$uuid/" '${xml}') | ||
94 | ${pkgs.libvirt}/bin/virsh start '${name}' | ||
95 | ''; | ||
96 | preStop = '' | ||
97 | ${pkgs.libvirt}/bin/virsh shutdown '${name}' | ||
98 | let "timeout = $(date +%s) + 10" | ||
99 | while [ "$(${pkgs.libvirt}/bin/virsh list --name | grep --count '^${name}$')" -gt 0 ]; do | ||
100 | if [ "$(date +%s)" -ge "$timeout" ]; then | ||
101 | # Meh, we warned it... | ||
102 | ${pkgs.libvirt}/bin/virsh destroy '${name}' | ||
103 | else | ||
104 | # The machine is still running, let's give it some time to shut down | ||
105 | sleep 0.5 | ||
106 | fi | ||
107 | done | ||
108 | '' + lib.optionalString (guest.destroyVolumeOnExit or false) '' | ||
109 | if ${pkgs.libvirt}/bin/virsh vol-key 'guest-${name}' --pool ${guest.pool} &> /dev/null; then | ||
110 | ${pkgs.libvirt}/bin/virsh vol-wipe --pool ${guest.pool} --vol 'guest-${name}' || true | ||
111 | ${pkgs.libvirt}/bin/virsh vol-delete --pool ${guest.pool} --vol 'guest-${name}' | ||
112 | fi | ||
113 | ''; | ||
114 | }) guests // (lib.mapAttrs' (name: network: lib.nameValuePair "libvirtd-network-${name}" { | ||
115 | after = [ "libvirtd.service" ]; | ||
116 | requires = [ "libvirtd.service" ]; | ||
117 | wantedBy = [ "multi-user.target" ]; | ||
118 | serviceConfig = { | ||
119 | Type = "oneshot"; | ||
120 | RemainAfterExit = "yes"; | ||
121 | }; | ||
122 | script = let | ||
123 | xml = pkgs.writeText "libvirt-network-${name}.xml" '' | ||
124 | <network> | ||
125 | <name>${name}</name> | ||
126 | <uuid>UUID</uuid> | ||
127 | <forward mode='nat' /> | ||
128 | <bridge name='virbr${network.bridgeNumber}' /> | ||
129 | <domain name='${name}' localOnly='yes'/> | ||
130 | <ip address='${network.ipRange}.1' netmask='255.255.255.0'> | ||
131 | <dhcp> | ||
132 | <range start='${network.ipRange}.2' end='${network.ipRange}.254'/> | ||
133 | </dhcp> | ||
134 | </ip> | ||
135 | </network> | ||
136 | ''; | ||
137 | in '' | ||
138 | uuid="$(${pkgs.libvirt}/bin/virsh net-uuid '${name}' || true)" | ||
139 | ${pkgs.libvirt}/bin/virsh net-define <(sed "s/UUID/$uuid/" '${xml}') | ||
140 | ${pkgs.libvirt}/bin/virsh net-start '${name}' | ||
141 | ''; | ||
142 | preStop = '' | ||
143 | ${pkgs.libvirt}/bin/virsh net-destroy '${name}' | ||
144 | ''; | ||
145 | }) networks); | ||
146 | } | ||
diff --git a/modules/private/system/dilion/vms/base_configuration.nix b/modules/private/system/dilion/vms/base_configuration.nix new file mode 100644 index 0000000..e2caba2 --- /dev/null +++ b/modules/private/system/dilion/vms/base_configuration.nix | |||
@@ -0,0 +1,21 @@ | |||
1 | { lib, config, ... }@args: | ||
2 | { | ||
3 | options.myEnv = (import ../../../environment.nix (args // { name = "dummy"; })).options.myEnv; | ||
4 | config = { | ||
5 | fileSystems."/".device = "/dev/disk/by-label/nixos"; | ||
6 | boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" "virtio_balloon" "virtio_blk" "virtio_pci" "virtio_ring" ]; | ||
7 | boot.loader = { | ||
8 | grub = { | ||
9 | version = 2; | ||
10 | device = "/dev/vda"; | ||
11 | }; | ||
12 | timeout = 0; | ||
13 | }; | ||
14 | services.openssh.enable = true; | ||
15 | networking.firewall.allowedTCPPorts = [ 22 ]; | ||
16 | users = { | ||
17 | mutableUsers = false; | ||
18 | users.root.openssh.authorizedKeys.keys = [ config.myEnv.sshd.rootKeys.immae_dilion ]; | ||
19 | }; | ||
20 | }; | ||
21 | } | ||
diff --git a/modules/private/system/dilion/vms/base_image.nix b/modules/private/system/dilion/vms/base_image.nix new file mode 100644 index 0000000..8de8560 --- /dev/null +++ b/modules/private/system/dilion/vms/base_image.nix | |||
@@ -0,0 +1,94 @@ | |||
1 | configuration_file: { pkgs ? import <nixpkgs> {}, system ? builtins.currentSystem, myEnv, ... }: | ||
2 | let | ||
3 | config = (import <nixpkgs/nixos/lib/eval-config.nix> { | ||
4 | inherit system; | ||
5 | modules = [ { | ||
6 | myEnv = myEnv; | ||
7 | imports = [ configuration_file ]; | ||
8 | |||
9 | # We want our template image to be as small as possible, but the deployed image should be able to be | ||
10 | # of any size. Hence we resize on the first boot. | ||
11 | systemd.services.resize-main-fs = { | ||
12 | wantedBy = [ "multi-user.target" ]; | ||
13 | serviceConfig.Type = "oneshot"; | ||
14 | script = | ||
15 | '' | ||
16 | # Resize main partition to fill whole disk | ||
17 | echo ", +" | ${pkgs.utillinux}/bin/sfdisk /dev/vda --no-reread -N 1 | ||
18 | ${pkgs.parted}/bin/partprobe | ||
19 | # Resize filesystem | ||
20 | ${pkgs.e2fsprogs}/bin/resize2fs /dev/vda1 | ||
21 | ''; | ||
22 | }; | ||
23 | } ]; | ||
24 | }).config; | ||
25 | in pkgs.vmTools.runInLinuxVM ( | ||
26 | pkgs.runCommand "nixos-base-image" | ||
27 | { | ||
28 | memSize = 768; | ||
29 | preVM = | ||
30 | '' | ||
31 | mkdir $out | ||
32 | diskImage=image.qcow2 | ||
33 | ${pkgs.vmTools.qemu}/bin/qemu-img create -f qcow2 $diskImage 2G | ||
34 | mv closure xchg/ | ||
35 | ''; | ||
36 | postVM = | ||
37 | '' | ||
38 | echo compressing VM image... | ||
39 | ${pkgs.vmTools.qemu}/bin/qemu-img convert -c $diskImage -O qcow2 $out/nixos.qcow2 | ||
40 | ''; | ||
41 | buildInputs = [ pkgs.utillinux pkgs.perl pkgs.parted pkgs.e2fsprogs ]; | ||
42 | exportReferencesGraph = | ||
43 | [ "closure" config.system.build.toplevel ]; | ||
44 | } | ||
45 | '' | ||
46 | # Create the partition | ||
47 | parted /dev/vda mklabel msdos | ||
48 | parted /dev/vda -- mkpart primary ext4 1M -1s | ||
49 | |||
50 | # Format the partition | ||
51 | mkfs.ext4 -L nixos /dev/vda1 | ||
52 | mkdir /mnt | ||
53 | mount /dev/vda1 /mnt | ||
54 | |||
55 | for dir in dev proc sys; do | ||
56 | mkdir /mnt/$dir | ||
57 | mount --bind /$dir /mnt/$dir | ||
58 | done | ||
59 | |||
60 | storePaths=$(perl ${pkgs.pathsFromGraph} /tmp/xchg/closure) | ||
61 | echo filling Nix store... | ||
62 | mkdir -p /mnt/nix/store | ||
63 | set -f | ||
64 | cp -prd $storePaths /mnt/nix/store | ||
65 | # The permissions will be set up incorrectly if the host machine is not running NixOS | ||
66 | chown -R 0:30000 /mnt/nix/store | ||
67 | |||
68 | mkdir -p /mnt/etc/nix | ||
69 | echo 'build-users-group = ' > /mnt/etc/nix/nix.conf | ||
70 | |||
71 | # Register the paths in the Nix database. | ||
72 | export USER=root | ||
73 | printRegistration=1 perl ${pkgs.pathsFromGraph} /tmp/xchg/closure | \ | ||
74 | chroot /mnt ${config.nix.package.out}/bin/nix-store --load-db | ||
75 | |||
76 | # Create the system profile to allow nixos-rebuild to work. | ||
77 | chroot /mnt ${config.nix.package.out}/bin/nix-env \ | ||
78 | -p /nix/var/nix/profiles/system --set ${config.system.build.toplevel} | ||
79 | |||
80 | # `nixos-rebuild' requires an /etc/NIXOS. | ||
81 | mkdir -p /mnt/etc/nixos | ||
82 | touch /mnt/etc/NIXOS | ||
83 | |||
84 | # `switch-to-configuration' requires a /bin/sh | ||
85 | mkdir -p /mnt/bin | ||
86 | ln -s ${config.system.build.binsh}/bin/sh /mnt/bin/sh | ||
87 | |||
88 | # Generate the GRUB menu. | ||
89 | chroot /mnt ${config.system.build.toplevel}/bin/switch-to-configuration boot | ||
90 | |||
91 | umount /mnt/{proc,dev,sys} | ||
92 | umount /mnt | ||
93 | '' | ||
94 | ) | ||
diff --git a/modules/private/system/dilion/vms/buildbot_configuration.nix b/modules/private/system/dilion/vms/buildbot_configuration.nix new file mode 100644 index 0000000..05b02d4 --- /dev/null +++ b/modules/private/system/dilion/vms/buildbot_configuration.nix | |||
@@ -0,0 +1,67 @@ | |||
1 | { pkgs, config, lib, ... }: | ||
2 | { | ||
3 | imports = [ | ||
4 | <nixpkgs/nixos/modules/profiles/qemu-guest.nix> | ||
5 | ./base_configuration.nix | ||
6 | ]; | ||
7 | systemd.services.buildbot-worker.serviceConfig.ExecStartPre = let | ||
8 | cfg = config.services.buildbot-worker; | ||
9 | script = pkgs.writeScript "decode-dmi" '' | ||
10 | #!${pkgs.stdenv.shell} | ||
11 | |||
12 | mkdir -vp "${cfg.buildbotDir}" | ||
13 | varfile=${cfg.buildbotDir}/variables | ||
14 | rm $varfile || true | ||
15 | echo "[DEFAULT]" > $varfile | ||
16 | strings=$(${pkgs.dmidecode}/bin/dmidecode --oem-string count) | ||
17 | for i in $(seq 1 $strings); do | ||
18 | ${pkgs.dmidecode}/bin/dmidecode --oem-string $i >> $varfile | ||
19 | done | ||
20 | chown -R ${cfg.user}:${cfg.group} ${cfg.buildbotDir} | ||
21 | ''; | ||
22 | in | ||
23 | lib.mkForce ["+${script}"]; | ||
24 | systemd.services.buildbot-worker.serviceConfig.ExecStart = let | ||
25 | cfg = config.services.buildbot-worker; | ||
26 | tacFile = pkgs.writeText "buildbot-worker.tac" '' | ||
27 | import os | ||
28 | from io import open | ||
29 | |||
30 | from buildbot_worker.bot import Worker | ||
31 | from twisted.application import service | ||
32 | |||
33 | basedir = '${cfg.buildbotDir}' | ||
34 | |||
35 | # note: this line is matched against to check that this is a worker | ||
36 | # directory; do not edit it. | ||
37 | application = service.Application('buildbot-worker') | ||
38 | |||
39 | import configparser | ||
40 | config = config = configparser.ConfigParser() | ||
41 | config.read("${cfg.buildbotDir}/variables") | ||
42 | master_url_split = config["DEFAULT"]["buildbot_master_url"].split(':') | ||
43 | buildmaster_host = master_url_split[0] | ||
44 | port = int(master_url_split[1]) | ||
45 | workername = config["DEFAULT"]["buildbot_worker_name"] | ||
46 | |||
47 | with open('${cfg.workerPassFile}', 'r', encoding='utf-8') as passwd_file: | ||
48 | passwd = passwd_file.read().strip('\r\n') | ||
49 | keepalive = ${toString cfg.keepalive} | ||
50 | umask = None | ||
51 | maxdelay = 300 | ||
52 | numcpus = None | ||
53 | allow_shutdown = None | ||
54 | |||
55 | s = Worker(buildmaster_host, port, workername, passwd, basedir, | ||
56 | keepalive, umask=umask, maxdelay=maxdelay, | ||
57 | numcpus=numcpus, allow_shutdown=allow_shutdown) | ||
58 | s.setServiceParent(application) | ||
59 | ''; | ||
60 | in | ||
61 | lib.mkForce "${cfg.package.pythonModule.pkgs.twisted}/bin/twistd --nodaemon --pidfile= --logfile - --python ${tacFile}"; | ||
62 | services.buildbot-worker = { | ||
63 | enable = true; | ||
64 | workerPass = config.myEnv.buildbot.workerPassword; | ||
65 | packages = [ pkgs.git pkgs.gzip pkgs.openssh ]; | ||
66 | }; | ||
67 | } | ||
diff --git a/nixops/secrets b/nixops/secrets | |||
Subproject 9ac6c1459d2eeb24be0a991f745b567f0fcb0cc | Subproject 932623303fd674faf8106e03ea0b89195edfdc0 | ||