Skip to content

Commit f384413

Browse files
feat: switch_version live progress terminal via SSE job system for all apps; fix MariaDB optimization missing fields
1 parent 260ca43 commit f384413

2 files changed

Lines changed: 116 additions & 67 deletions

File tree

panel/routes/modules.py

Lines changed: 87 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1722,103 +1722,103 @@ def sh(cmd, t=30):
17221722

17231723
elif action == 'switch_version':
17241724
ver = d.get('version', '')
1725-
if mod_id == 'redis' and ver:
1726-
# Stop redis, install specific version from redis.io, restart
1725+
if not ver:
1726+
return jsonify({'ok': False, 'error': 'No version specified'}), 400
1727+
1728+
# Build the switch script per module
1729+
script = None
1730+
ver_check_cmd = None # command to get new version string after switch
1731+
1732+
if mod_id == 'redis':
17271733
script = (
1728-
'systemctl stop redis-server 2>/dev/null || systemctl stop redis 2>/dev/null; '
1734+
'systemctl stop redis-server 2>/dev/null || systemctl stop redis 2>/dev/null && '
17291735
'curl -fsSL https://packages.redis.io/gpg | gpg --batch --yes --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg && '
17301736
'echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/redis.list && '
17311737
'apt-get update -o APT::Update::Error-Mode=any 2>/dev/null && '
1732-
'apt-get install -y --allow-downgrades redis-server=' + ver + '.* 2>/dev/null || '
1733-
'apt-get install -y redis-server && '
1738+
f'apt-get install -y --allow-downgrades redis-server={ver}.* 2>/dev/null || apt-get install -y redis-server && '
17341739
'systemctl start redis-server 2>/dev/null || systemctl start redis'
17351740
)
1736-
out = sh(script, t=120)
1737-
new_ver = sh("redis-server --version 2>/dev/null | grep -oP '[0-9]+[.][0-9]+[.][0-9]+'") or ''
1738-
return jsonify({'ok': True, 'output': out, 'version': new_ver})
1739-
elif mod_id in ('pure-ftpd', 'pure_ftpd') and ver:
1740-
out = sh('apt-get install -y pure-ftpd=' + ver + ' 2>/dev/null || apt-get install -y pure-ftpd 2>&1', t=60)
1741-
return jsonify({'ok': True, 'output': out})
1742-
elif mod_id == 'mariadb' and ver:
1741+
ver_check_cmd = "redis-server --version 2>/dev/null | grep -oP '[0-9]+[.][0-9]+[.][0-9]+'"
1742+
1743+
elif mod_id in ('pure-ftpd', 'pure_ftpd'):
1744+
script = f'apt-get install -y pure-ftpd={ver} 2>/dev/null || apt-get install -y pure-ftpd'
1745+
ver_check_cmd = "pure-ftpd --version 2>/dev/null | grep -oP '[0-9]+[.][0-9]+[.][0-9]+' | head -1"
1746+
1747+
elif mod_id == 'mariadb':
17431748
script = (
17441749
'export DEBIAN_FRONTEND=noninteractive && '
1745-
'systemctl stop mariadb 2>/dev/null; '
1746-
'curl -fsSL https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | bash -s -- --mariadb-server-version=' + ver + ' && '
1750+
'systemctl stop mariadb 2>/dev/null && '
1751+
f'curl -fsSL https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | bash -s -- --mariadb-server-version={ver} && '
17471752
'apt-get update -qq && '
17481753
'apt-get install -y mariadb-server && '
17491754
'systemctl start mariadb'
17501755
)
1751-
out = sh(script, t=300)
1752-
new_ver = sh("mariadb --version 2>/dev/null | grep -oP '[0-9]+[.][0-9]+[.][0-9]+' | head -1") or ''
1753-
return jsonify({'ok': True, 'output': out, 'version': new_ver})
1756+
ver_check_cmd = "mariadb --version 2>/dev/null | grep -oP '[0-9]+[.][0-9]+[.][0-9]+' | head -1"
17541757

1755-
elif mod_id == 'postgresql' and ver:
1758+
elif mod_id == 'mysql':
1759+
script = (
1760+
'export DEBIAN_FRONTEND=noninteractive && '
1761+
f'apt-get install -y --allow-downgrades mysql-server={ver}* 2>/dev/null || '
1762+
'apt-get install -y mysql-server && '
1763+
'systemctl restart mysql'
1764+
)
1765+
ver_check_cmd = "mysql --version 2>/dev/null | grep -oP '[0-9]+[.][0-9]+[.][0-9]+' | head -1"
1766+
1767+
elif mod_id == 'postgresql':
17561768
script = (
17571769
'export DEBIAN_FRONTEND=noninteractive && '
17581770
'rm -f /usr/share/keyrings/postgresql.gpg /etc/apt/sources.list.d/pgdg.list && '
17591771
'curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc -o /tmp/pg.asc && '
17601772
'gpg --batch --no-tty --dearmor -o /usr/share/keyrings/postgresql.gpg /tmp/pg.asc && '
1761-
'echo "deb [signed-by=/usr/share/keyrings/postgresql.gpg] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list && '
1773+
f'echo "deb [signed-by=/usr/share/keyrings/postgresql.gpg] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list && '
17621774
'apt-get update -qq && '
1763-
'apt-get install -y postgresql-' + ver + ' && '
1775+
f'apt-get install -y postgresql-{ver} && '
17641776
'systemctl restart postgresql'
17651777
)
1766-
out = sh(script, t=300)
1767-
new_ver = sh("psql --version 2>/dev/null | grep -oP '[0-9]+[.][0-9]+' | head -1") or ''
1768-
return jsonify({'ok': True, 'output': out, 'version': new_ver})
1778+
ver_check_cmd = "psql --version 2>/dev/null | grep -oP '[0-9]+[.][0-9]+' | head -1"
17691779

1770-
elif mod_id == 'mongodb' and ver:
1780+
elif mod_id == 'mongodb':
17711781
script = (
17721782
'export DEBIAN_FRONTEND=noninteractive && '
1773-
'systemctl stop mongod 2>/dev/null; '
1774-
'rm -f /usr/share/keyrings/mongodb-server-*.gpg /etc/apt/sources.list.d/mongodb*.list && '
1775-
'curl -fsSL https://www.mongodb.org/static/pgp/server-' + ver + '.asc -o /tmp/mongo.asc && '
1776-
'gpg --batch --no-tty --dearmor -o /usr/share/keyrings/mongodb-server-' + ver + '.gpg /tmp/mongo.asc && '
1777-
'echo "deb [signed-by=/usr/share/keyrings/mongodb-server-' + ver + '.gpg] https://repo.mongodb.org/apt/ubuntu $(lsb_release -cs)/mongodb-org/' + ver + ' multiverse" > /etc/apt/sources.list.d/mongodb-org-' + ver + '.list && '
1783+
'systemctl stop mongod 2>/dev/null && '
1784+
f'rm -f /usr/share/keyrings/mongodb-server-*.gpg /etc/apt/sources.list.d/mongodb*.list && '
1785+
f'curl -fsSL https://www.mongodb.org/static/pgp/server-{ver}.asc -o /tmp/mongo.asc && '
1786+
f'gpg --batch --no-tty --dearmor -o /usr/share/keyrings/mongodb-server-{ver}.gpg /tmp/mongo.asc && '
1787+
f'echo "deb [signed-by=/usr/share/keyrings/mongodb-server-{ver}.gpg] https://repo.mongodb.org/apt/ubuntu $(lsb_release -cs)/mongodb-org/{ver} multiverse" > /etc/apt/sources.list.d/mongodb-org-{ver}.list && '
17781788
'apt-get update -qq && '
17791789
'apt-get install -y mongodb-org && '
17801790
'systemctl start mongod'
17811791
)
1782-
out = sh(script, t=300)
1783-
new_ver = sh("mongod --version 2>/dev/null | grep -oP '[0-9]+[.][0-9]+[.][0-9]+' | head -1") or ''
1784-
return jsonify({'ok': True, 'output': out, 'version': new_ver})
1792+
ver_check_cmd = "mongod --version 2>/dev/null | grep -oP '[0-9]+[.][0-9]+[.][0-9]+' | head -1"
17851793

1786-
elif mod_id == 'apache2' and ver:
1794+
elif mod_id == 'apache2':
17871795
script = (
17881796
'export DEBIAN_FRONTEND=noninteractive && '
1789-
'add-apt-repository -y ppa:ondrej/apache2 2>/dev/null; '
1797+
'add-apt-repository -y ppa:ondrej/apache2 2>/dev/null && '
17901798
'apt-get update -qq && '
1791-
'apt-get install -y --allow-downgrades apache2=' + ver + '-* 2>/dev/null || '
1792-
'apt-get install -y apache2 && '
1799+
f'apt-get install -y --allow-downgrades apache2={ver}-* 2>/dev/null || apt-get install -y apache2 && '
17931800
'systemctl restart apache2'
17941801
)
1795-
out = sh(script, t=180)
1796-
new_ver = sh("apache2 -v 2>/dev/null | grep -oP '[0-9]+[.][0-9]+[.][0-9]+' | head -1") or ''
1797-
return jsonify({'ok': True, 'output': out, 'version': new_ver})
1802+
ver_check_cmd = "apache2 -v 2>/dev/null | grep -oP '[0-9]+[.][0-9]+[.][0-9]+' | head -1"
17981803

1799-
elif mod_id == 'nodejs' and ver:
1804+
elif mod_id == 'nodejs':
18001805
script = (
18011806
'export DEBIAN_FRONTEND=noninteractive && '
1802-
'curl -fsSL https://deb.nodesource.com/setup_' + ver + '.x | bash - && '
1807+
f'curl -fsSL https://deb.nodesource.com/setup_{ver}.x | bash - && '
18031808
'apt-get install -y nodejs'
18041809
)
1805-
out = sh(script, t=180)
1806-
new_ver = sh("node --version 2>/dev/null") or ''
1807-
return jsonify({'ok': True, 'output': out, 'version': new_ver})
1810+
ver_check_cmd = "node --version 2>/dev/null"
18081811

1809-
elif mod_id == 'bind9' and ver:
1812+
elif mod_id == 'bind9':
18101813
script = (
18111814
'export DEBIAN_FRONTEND=noninteractive && '
18121815
+ ('add-apt-repository -y ppa:isc/bind && apt-get update -qq && ' if ver == '9.20' else 'apt-get update -qq && ') +
18131816
'apt-get install -y bind9 bind9utils && '
18141817
'(systemctl restart named 2>/dev/null || systemctl restart bind9 2>/dev/null)'
18151818
)
1816-
out = sh(script, t=180)
1817-
new_ver = sh("named -v 2>/dev/null | grep -oP '[0-9]+[.][0-9]+[.][0-9]+' | head -1") or ''
1818-
return jsonify({'ok': True, 'output': out, 'version': new_ver})
1819+
ver_check_cmd = "named -v 2>/dev/null | grep -oP '[0-9]+[.][0-9]+[.][0-9]+' | head -1"
18191820

1820-
elif mod_id == 'nginx' and ver:
1821-
# Switch nginx repo based on channel (stable/mainline)
1821+
elif mod_id == 'nginx':
18221822
repo = 'http://nginx.org/packages/ubuntu' if ver == 'stable' else 'http://nginx.org/packages/mainline/ubuntu'
18231823
script = (
18241824
f'echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] {repo} $(lsb_release -cs) nginx" '
@@ -1827,22 +1827,48 @@ def sh(cmd, t=30):
18271827
'apt-get install -y nginx && '
18281828
'systemctl reload nginx 2>/dev/null || systemctl restart nginx 2>/dev/null'
18291829
)
1830-
out = sh(script, t=120)
1831-
new_ver = sh("nginx -v 2>&1 | grep -oP '[0-9]+[.][0-9]+[.][0-9]+'") or ''
1832-
return jsonify({'ok': True, 'output': out, 'version': new_ver})
1833-
elif mod_id == 'openlitespeed' and ver:
1830+
ver_check_cmd = "nginx -v 2>&1 | grep -oP '[0-9]+[.][0-9]+[.][0-9]+'"
1831+
1832+
elif mod_id == 'openlitespeed':
18341833
script = (
1835-
'systemctl stop lsws 2>/dev/null; '
1834+
'systemctl stop lsws 2>/dev/null && '
18361835
'wget -q https://repo.litespeed.sh -O ls_repo.sh && bash ls_repo.sh && '
18371836
'(apt-get update -o APT::Update::Error-Mode=any 2>/dev/null; true) && '
1838-
f'apt-get install -y --allow-downgrades openlitespeed={ver} 2>/dev/null || '
1839-
'apt-get install -y openlitespeed && '
1837+
f'apt-get install -y --allow-downgrades openlitespeed={ver} 2>/dev/null || apt-get install -y openlitespeed && '
18401838
'systemctl start lsws'
18411839
)
1842-
out = sh(script, t=120)
1843-
new_ver = sh("cat /usr/local/lsws/VERSION 2>/dev/null | grep -oP '[0-9]+[.][0-9]+[.][0-9]+'") or ''
1844-
return jsonify({'ok': True, 'output': out, 'version': new_ver})
1845-
return jsonify({'ok': False, 'error': 'Version switch not supported for ' + mod_id})
1840+
ver_check_cmd = "cat /usr/local/lsws/VERSION 2>/dev/null | grep -oP '[0-9]+[.][0-9]+[.][0-9]+'"
1841+
1842+
if not script:
1843+
return jsonify({'ok': False, 'error': f'Version switch not supported for {mod_id}'}), 400
1844+
1845+
# Run as a streaming job — same system as install/uninstall
1846+
job_id = str(uuid.uuid4())[:8]
1847+
_jobs[job_id] = {'status':'running','lines':[],'done':False,'success':False,'installed':True}
1848+
1849+
def run_switch():
1850+
mod_name = mod['name'] if mod else mod_id
1851+
_jobs[job_id]['lines'].append(f'[VortexPanel] Switching {mod_name} to version {ver}...')
1852+
proc = subprocess.Popen(
1853+
f'DEBIAN_FRONTEND=noninteractive {script} 2>&1',
1854+
shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1
1855+
)
1856+
for line in proc.stdout:
1857+
_jobs[job_id]['lines'].append(line.rstrip())
1858+
proc.wait()
1859+
success = proc.returncode == 0
1860+
new_ver = sh(ver_check_cmd) if ver_check_cmd else ver
1861+
_jobs[job_id]['lines'].append(
1862+
f'[VortexPanel] {"✓ Switched to " + new_ver + " successfully!" if success else "⚠ Switch may have failed — check output above."}'
1863+
)
1864+
_jobs[job_id].update({
1865+
'done': True, 'success': success, 'status': 'done',
1866+
'installed': True, 'installedVer': new_ver,
1867+
})
1868+
panel_cache.invalidate('modules_list')
1869+
1870+
threading.Thread(target=run_switch, daemon=True).start()
1871+
return jsonify({'ok': True, 'job_id': job_id, 'action': 'switch_version'})
18461872

18471873
elif action == 'setup_private_dns':
18481874
networks = d.get('networks', '127.0.0.1;')

web/templates/index.html

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2679,14 +2679,37 @@
26792679
</template>
26802680
</select>
26812681
<button class="btn btn-primary btn-sm"
2682-
@click="post('/api/modules/'+settingsModal.mod.id+'/settings',{action:'switch_version',version:settingsModal.switchVer}).then(r=>{
2683-
if(r.ok){toast('Version switch complete! New version: '+(r.version||settingsModal.switchVer),'success');settingsModal.version=r.version||settingsModal.version;}
2684-
else toast(r.error||'Failed','error');
2685-
})">Switch</button>
2682+
@click="async () => {
2683+
if (!settingsModal.switchVer) { toast('Select a version first', 'error'); return; }
2684+
const modName = settingsModal.mod?.name || settingsModal.mod?.id;
2685+
const label = 'Switching ' + modName + ' to v' + settingsModal.switchVer;
2686+
const r = await post('/api/modules/'+settingsModal.mod.id+'/settings', {action:'switch_version', version:settingsModal.switchVer});
2687+
if (r.ok && r.job_id) {
2688+
settingsModal.show = false;
2689+
jobModal = {show:true, title:label, lines:[], done:false, success:false, action:'switch_version', installedVer:''};
2690+
const es = new EventSource('/api/modules/job/'+r.job_id);
2691+
es.onmessage = (e) => {
2692+
const d = JSON.parse(e.data);
2693+
if (d.line) jobModal.lines.push(d.line);
2694+
if (d.done) {
2695+
es.close();
2696+
jobModal.done = true;
2697+
jobModal.success = d.success;
2698+
jobModal.installedVer = d.installedVer || settingsModal.switchVer;
2699+
if (d.success) {
2700+
settingsModal.version = d.installedVer || settingsModal.switchVer;
2701+
}
2702+
}
2703+
$nextTick(() => { const t = document.querySelector('.job-terminal'); if (t) t.scrollTop = t.scrollHeight; });
2704+
};
2705+
} else {
2706+
toast(r.error || 'Failed to start switch', 'error');
2707+
}
2708+
}">Switch</button>
26862709
</div>
26872710
<div style="font-size:11px;color:var(--text-muted);line-height:1.7">
2688-
⚠ Switching version will restart the service.<br>
2689-
⚠ Ensure your applications are compatible with the new version.
2711+
⚠ Switching version will stop and restart the service. A live progress terminal will show the output.<br>
2712+
⚠ Ensure your applications are compatible with the new version before switching.
26902713
</div>
26912714
</div>
26922715

0 commit comments

Comments
 (0)