diff --git a/opennebula/install.sh b/opennebula/install.sh index bc85e4c0..c9bdb29b 100755 --- a/opennebula/install.sh +++ b/opennebula/install.sh @@ -3,7 +3,9 @@ set -e reapply_patch() { - if ! patch -f --dry-run -F 0 -R $1 < $2 >/dev/null; then + if ! [[ -e $1 ]]; then + echo "$1 does not exist, OpenNebula is not installed" + elif ! patch -f --dry-run -F 0 -R $1 < $2 >/dev/null; then already_applied=0 if ! patch --no-backup-if-mismatch -r - -F 0 -f $1 < $2; then applied_ok=0 @@ -15,8 +17,13 @@ echo "Reapplying Vitastor patches to OpenNebula's oned.conf, vmm_execrc and down already_applied=1 applied_ok=1 reapply_patch /var/lib/one/remotes/datastore/downloader.sh /var/lib/one/remotes/datastore/vitastor/downloader-vitastor.sh.diff -reapply_patch /etc/one/oned.conf /var/lib/one/remotes/datastore/vitastor/oned.conf.diff reapply_patch /etc/one/vmm_exec/vmm_execrc /var/lib/one/remotes/datastore/vitastor/vmm_execrc.diff +if [[ -e /etc/one/oned.conf ]]; then + if ! /var/lib/one/remotes/datastore/vitastor/patch-oned-conf.py /etc/one/oned.conf; then + applied_ok=0 + already_applied=0 + fi +fi if [[ "$already_applied" = 1 ]]; then echo "OK: Vitastor OpenNebula patches are already applied" elif [[ "$applied_ok" = 1 ]]; then diff --git a/opennebula/remotes/datastore/vitastor/patch-oned-conf.py b/opennebula/remotes/datastore/vitastor/patch-oned-conf.py new file mode 100755 index 00000000..b1326d49 --- /dev/null +++ b/opennebula/remotes/datastore/vitastor/patch-oned-conf.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 +# Patch /etc/one/oned.conf for Vitastor support +# -s = also enable save.vitastor/restore.vitastor overrides + +import re +import os +import sys + +class Fixer: + save_restore = 0 + + def require_sub_cb(self, m, cb): + self.found = 1 + return cb(m) + + def require_sub(self, regexp, cb, text, error): + self.found = 0 + new_text = re.sub(regexp, lambda m: self.require_sub_cb(m, cb), text) + if not self.found and error: + self.errors.append(error) + return new_text + + def fix(self, oned_conf): + self.errors = [] + self.kvm_found = 0 + oned_conf = self.require_sub(r'((?:^|\n)[ \t]*VM_MAD\s*=\s*\[)([^\]]+)\]', lambda m: m.group(1)+self.fix_vm_mad(m.group(2))+']', oned_conf, 'VM_MAD not found') + if not self.kvm_found: + self.errors.append("VM_MAD[NAME=kvm].ARGUMENTS not found") + oned_conf = self.require_sub(r'((?:^|\n)[ \t]*TM_MAD\s*=\s*\[)([^\]]+)\]', lambda m: m.group(1)+self.fix_tm_mad(m.group(2))+']', oned_conf, 'TM_MAD not found') + oned_conf = self.require_sub(r'((?:^|\n)[ \t]*DATASTORE_MAD\s*=\s*\[)([^\]]+)\]', lambda m: m.group(1)+self.fix_datastore_mad(m.group(2))+']', oned_conf, 'DATASTORE_MAD not found') + if oned_conf[-1:] != '\n': + oned_conf += '\n' + if not re.compile(r'(^|\n)[ \t]*INHERIT_DATASTORE_ATTR\s*=\s*"VITASTOR_CONF"').search(oned_conf): + oned_conf += '\nINHERIT_DATASTORE_ATTR="VITASTOR_CONF"\n' + if not re.compile(r'(^|\n)[ \t]*INHERIT_DATASTORE_ATTR\s*=\s*"IMAGE_PREFIX"').search(oned_conf): + oned_conf += '\nINHERIT_DATASTORE_ATTR="IMAGE_PREFIX"\n' + if not re.compile(r'(^|\n)[ \t]*TM_MAD_CONF\s*=\s*\[[^\]]*NAME\s*=\s*"vitastor"').search(oned_conf): + oned_conf += ('\nTM_MAD_CONF = [\n'+ + ' NAME = "vitastor", LN_TARGET = "NONE", CLONE_TARGET = "SELF", SHARED = "YES",\n'+ + ' DS_MIGRATE = "NO", DRIVER = "raw", ALLOW_ORPHANS="format",\n'+ + ' TM_MAD_SYSTEM = "ssh,shared", LN_TARGET_SSH = "SYSTEM", CLONE_TARGET_SSH = "SYSTEM",\n'+ + ' DISK_TYPE_SSH = "FILE", LN_TARGET_SHARED = "NONE",\n'+ + ' CLONE_TARGET_SHARED = "SELF", DISK_TYPE_SHARED = "FILE"\n'+ + ']\n') + if not re.compile(r'(^|\n)[ \t]*DS_MAD_CONF\s*=\s*\[[^\]]*NAME\s*=\s*"vitastor"').search(oned_conf): + oned_conf += ('\nDS_MAD_CONF = [\n'+ + ' NAME = "vitastor",\n'+ + ' REQUIRED_ATTRS = "DISK_TYPE,BRIDGE_LIST",\n'+ + ' PERSISTENT_ONLY = "NO",\n'+ + ' MARKETPLACE_ACTIONS = "export"\n'+ + ']\n') + return oned_conf + + def fix_vm_mad(self, vm_mad_params): + if re.compile(r'\bNAME\s*=\s*"kvm"').search(vm_mad_params): + vm_mad_params = re.sub(r'\b(ARGUMENTS\s*=\s*")([^"]+)"', lambda m: m.group(1)+self.fix_vm_mad_args(m.group(2))+'"', vm_mad_params) + self.kvm_found = 1 + return vm_mad_params + + def fix_vm_mad_args(self, args): + args = self.fix_vm_mad_override(args, 'deploy') + if self.save_restore: + args = self.fix_vm_mad_override(args, 'save') + args = self.fix_vm_mad_override(args, 'restore') + return args + + def fix_vm_mad_override(self, args, override): + m = re.compile(r'-l (\S+)').search(args) + if m and re.compile(override+'='+override+'.vitastor').search(m.group(1)): + return args + elif m and re.compile(override+'=').search(m.group(1)): + self.errors.append(override+"= is already overridden in -l option in VM_MAD[NAME=kvm].ARGUMENTS") + return args + elif m: + return self.require_sub(r'-l (\S+)', lambda m: '-l '+m.group(1)+','+override+'='+override+'.vitastor', args, '-l option not found in VM_MAD[NAME=kvm].ARGUMENTS') + else: + return args+' -l '+override+'='+override+'.vitastor' + + def fix_tm_mad(self, params): + return self.require_sub(r'\b(ARGUMENTS\s*=\s*")([^"]+)"', lambda m: m.group(1)+self.fix_tm_mad_args('d', m.group(2), "TM_MAD")+'"', params, "TM_MAD.ARGUMENTS not found") + + def fix_tm_mad_args(self, opt, args, v): + return self.require_sub('(-'+opt+r') (\S+)', lambda m: self.fix_tm_mad_arg(m), args, "-"+opt+" option not found in "+v+".ARGUMENTS") + + def fix_tm_mad_arg(self, m): + a = m.group(2).split(',') + if 'vitastor' not in a: + a += [ 'vitastor' ] + return m.group(1)+' '+(','.join(a)) + + def fix_datastore_mad(self, params): + params = self.require_sub(r'\b(ARGUMENTS\s*=\s*")([^"]+)"', lambda m: m.group(1)+self.fix_tm_mad_args('d', m.group(2), "DATASTORE_MAD")+'"', params, "DATASTORE_MAD.ARGUMENTS not found") + return self.require_sub(r'\b(ARGUMENTS\s*=\s*")([^"]+)"', lambda m: m.group(1)+self.fix_tm_mad_args('s', m.group(2), "DATASTORE_MAD")+'"', params, "") + +fixer = Fixer() +oned_conf_file = '' +for arg in sys.argv[1:]: + if arg == '-s': + fixer.save_restore = 1 + else: + oned_conf_file = arg + break +if not oned_conf_file: + sys.stderr.write("USAGE: ./patch-oned-conf.py [-s] /etc/one/oned.conf\n-s means also enable save.vitastor/restore.vitastor overrides\n") + sys.exit(1) +with open(oned_conf_file, 'r') as fd: + oned_conf = fd.read() +new_conf = fixer.fix(oned_conf) +if new_conf != oned_conf: + os.rename(oned_conf_file, oned_conf_file+'.bak') + with open(oned_conf_file, 'w') as fd: + fd.write(new_conf) +if len(fixer.errors) > 0: + sys.stderr.write("ERROR: Failed to patch "+oned_conf_file+", patch it manually. Errors:\n- "+('\n- '.join(fixer.errors))+'\n') + sys.exit(1)