summaryrefslogtreecommitdiff
path: root/contractor
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2020-04-09 15:23:27 +0300
committerLars Wirzenius <liw@liw.fi>2020-04-09 15:23:27 +0300
commit9f3e1dd3dc0ada615789000f385c9e52fe9a9879 (patch)
treec0ae6a82c528fc45f1c9188ded5f01fb3d004dc1 /contractor
parent5fca00b7aadbd5d3f52dca3fdc7f0c084d9e3136 (diff)
downloadick-contractor-9f3e1dd3dc0ada615789000f385c9e52fe9a9879.tar.gz
Change: upload workspace, sources to worker image, not via worker
Diffstat (limited to 'contractor')
-rwxr-xr-xcontractor151
1 files changed, 102 insertions, 49 deletions
diff --git a/contractor b/contractor
index 0615d33..5fd3ab7 100755
--- a/contractor
+++ b/contractor
@@ -14,6 +14,26 @@ import cliapp
import yaml
+# The device in the manager VM for the workspace disk.
+WS_DEV = '/dev/vdb'
+
+
+# The worker VM image file on manager VM.
+WORKER_IMG = 'worker.img'
+
+
+# The temporary worker VM image file, used while worker VM is running.
+TEMP_IMG = 'temp.img'
+
+
+# The UID of the worker account, on the worker VM.
+WORKER_UID = 1000
+
+
+# The GID of the worker account, on the worker VM.
+WORKER_GID = 1000
+
+
class ExecResult:
@@ -87,6 +107,13 @@ class ContractorApplication(cliapp.Application):
self.error('could not upload image to worker')
sys.exit(1)
+ self.verbose('setting up workspace on worker')
+ ws = bs.workspace()
+ source = bs.source()
+ if m.setup_workspace(ws, source).failed():
+ self.error('could not set up workspace')
+ sys.exit(1)
+
self.verbose('starting worker')
w = m.start_worker()
if not w:
@@ -103,19 +130,6 @@ class ContractorApplication(cliapp.Application):
else:
self.verbose('no packages to install')
- ws = bs.workspace()
- if ws and os.path.exists(ws):
- self.verbose('upload saved workspace from {}'.format(ws))
- if w.upload_workspace(ws).failed():
- self.error('failed to upload workspace')
- sys.exit(1)
-
- self.verbose('upload source code from{}'.format(bs.source()))
- if w.upload_source(bs.source()).failed():
- self.error('failed to upload source')
- sys.exit(1)
-
-
# self.verbose('Running build commands')
# o = self.on_worker(
# 'worker', ['sh', '-euxc', build['build']],
@@ -162,19 +176,21 @@ class ContractorApplication(cliapp.Application):
def cmd_worker_image(self, args):
img = args[0]
- self.verbose('Copying VM image {} to manager VM as worker.img'.format(img))
- tgt = '{}:worker.img'.format(self.ssh_target())
+ self.verbose(
+ 'Copying VM image {} to manager VM as {}'.format(
+ img, WORKER_IMG))
+ tgt = '{}:{}'.format(self.ssh_target(), WORKER_IMG)
argv = ['rsync', '-aHSs', '--', img, tgt]
cliapp.runcmd(argv)
def cmd_worker_start(self, args):
self.verbose('mkfs on workspace disk')
- o = self.on_manager(['sudo', 'mkfs', '-t', 'ext4', '/dev/vdb'])
+ o = self.on_manager(['sudo', 'mkfs', '-t', 'ext4', WS_DEV])
if o is None:
self.error('Failed to mkfs workspace')
sys.exit(1)
- img = 'worker.img'
+ img = WORKER_IMG
self.verbose('Creating worker VM using {} on manager VM'.format(img))
o = self.on_manager(['./create-vm', img])
if o is None:
@@ -405,7 +421,7 @@ class Manager:
self.virsh(['undefine', 'worker'])
def upload_worker_image(self, filename):
- return rsync(filename, '{}:worker.img'.format(self._target))
+ return rsync(filename, '{}:{}'.format(self._target, WORKER_IMG))
def start_worker(self):
if self.copy_worker_image().failed():
@@ -431,8 +447,8 @@ class Manager:
'--cpu=host',
'--import',
'--os-variant=debian9',
- '--disk=path=temp.img,cache=none',
- '--disk=path=/dev/vdb,cache=none',
+ '--disk=path={},cache=none'.format(TEMP_IMG),
+ '--disk=path={},cache=none'.format(WS_DEV),
'--network=network=default',
'--graphics=spice',
'--noautoconsole',
@@ -444,8 +460,8 @@ class Manager:
return self.wait_for_worker()
def copy_worker_image(self):
- self.ssh(['rm', '-f', 'temp.img'])
- return self.ssh(['cp', 'worker.img', 'temp.img'])
+ self.ssh(['rm', '-f', TEMP_IMG])
+ return self.ssh(['cp', WORKER_IMG, TEMP_IMG])
def get_cpu_count(self):
er = self.ssh(['lscpu'], quiet=True)
@@ -486,6 +502,70 @@ class Manager:
return w
time.sleep(2)
+ def setup_workspace(self, saved_workspace, source):
+ er = self.setup_helper(saved_workspace, source)
+ if er.failed():
+ logging.error('Could not set up workspace')
+ self.umount(WS_DEV)
+ self.kpartx('-dsv')
+ return er
+
+ def setup_helper(self, saved_workspace, source):
+ er = self.kpartx('-asv')
+ if er.failed():
+ return er
+
+ er = self.mount(WS_DEV)
+ if er.failed():
+ return er
+
+ er = self.ssh(
+ ['sudo', 'chown', '{}:{}'.format(WORKER_UID, WORKER_GID),
+ '/mnt'])
+ if er.failed():
+ return er
+
+ er = self.ssh(
+ ['sudo', 'install', '-d', '--owner={}'.format(WORKER_UID),
+ '--group={}'.format(WORKER_GID), '/mnt/src'])
+ if er.failed():
+ return er
+
+ if os.path.exists(saved_workspace):
+ er = rsync(
+ '{}/.'.format(saved_workspace),
+ '{}:/mnt/.'.format(self._target))
+ if er.failed():
+ return er
+
+ er = rsync(
+ '{}/.'.format(source),
+ '{}:/mnt/src/.'.format(self._target))
+ if er.failed():
+ return er
+
+ return er
+
+ def kpartx(self, options):
+ er = self.ssh(['sudo', 'kpartx', options, TEMP_IMG])
+ if er.failed():
+ logging.error('Could not add partitions for worker image')
+ return er
+
+ def mount(self, device):
+ er = self.ssh(['sudo', 'mount', device, '/mnt'])
+ if er.failed():
+ logging.error('Could not mount device')
+ return er
+
+ def umount(self, device):
+ er = self.ssh(['sudo', 'umount', device])
+ if er.failed():
+ logging.error('Could not mount device')
+ return er
+
+
+
class Worker:
@@ -503,32 +583,5 @@ class Worker:
['sudo', 'DEBIAN_FRONTEND=noninteractive',
'apt-get', '-y', 'install'] + pkgs)
- def upload_workspace(self, dirname):
- return rsync(
- '{}/.'.format(dirname),
- '{}/workspace/.'.format(self._target))
-
- def upload_source(self, dirname):
- er = self.ssh(['sudo', 'chown', 'worker:worker', '/workspace'])
- if er.failed():
- logging.error('Could not set /workspace ownership')
- return er
-
- er = self.ssh(
- ['sudo', 'install', '-d', '--owner=worker', '--group=worker',
- '/workspace/src'])
- if er.failed():
- logging.error('Could not create /workspace/src on worker')
- return er
-
- return rsync(
- '{}/.'.format(dirname),
- '{}:/workspace/src/.'.format(self._target))
-
- def create_dir(self, dirname):
- return self.ssh(
- ['sudo', 'install', '-d', '--owner=worker', '--group=worker',
- dirname])
-
ContractorApplication().run()