#!/opt/cloudlinux/venv/bin/python3 -bb
# coding=utf-8
# Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2019 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# http://cloudlinux.com/docs/LICENSE.TXT
import logging
import pwd
import subprocess
from clcommon.public_hooks.lib import ModifyDomainHook, ModifyUserHook
from clcommon.lib.cledition import lve_supported_or_exit
from websiteisolation.id_registry import registry_path_by_username
log = logging.getLogger(__name__)
class DomainLimitsHook(ModifyDomainHook, ModifyUserHook):
"""
Keep the LVD on-disk state (domains.json + binary id-registry)
in sync with control-panel domain and user events so that
per-domain limits keep working.
"""
LVECTL = '/usr/sbin/lvectl'
@lve_supported_or_exit
def post_modify_domain(
self, username, domain,
new_domain=None, include_subdomains=None,
old_docroot=None, new_docroot=None, **kwargs):
if not registry_path_by_username(username):
return
current_domain = new_domain or domain
cmd = [
self.LVECTL, 'regenerate-domains',
'--username', username,
'--domain', current_domain,
]
if new_domain:
cmd += ['--old-domain', domain]
if old_docroot:
cmd += ['--old-docroot', old_docroot]
result = subprocess.run(cmd, capture_output=True, check=False)
if result.returncode != 0:
log.warning(
'regenerate-domains failed (rc=%d): %s',
result.returncode,
result.stderr.decode(errors='replace').strip(),
)
@lve_supported_or_exit
def post_delete_domain(self, username, domain, **kwargs):
"""Drop the registrations the deleted domain leaves behind.
Nothing else does: the registry entry is written by root, the
panel never learns of it, and the single-domain regenerate path
needs a docroot the panel can still resolve. Left alone the
entry, its domains.json record and its kernel LVE outlive the
domain, and every later `lvectl apply` reports the account as
holding a registration the panel no longer lists (CLOS-7467).
"""
if not registry_path_by_username(username):
return
cmd = [
self.LVECTL, 'regenerate-domains',
'--username', username,
'--deleted-domain', domain,
]
result = subprocess.run(cmd, capture_output=True, check=False)
if result.returncode != 0:
log.warning(
'regenerate-domains after domain deletion failed (rc=%d): %s',
result.returncode,
result.stderr.decode(errors='replace').strip(),
)
@lve_supported_or_exit
def pre_delete_user(self, username, **kwargs):
"""Tear down the per-domain state of an account being deleted.
Runs before deletion because the marker is keyed by uid, which no
longer resolves once the account is gone. Left alone, the marker,
lvp