diff options
Diffstat (limited to 'azurelinuxagent/pa/deprovision/default.py')
-rw-r--r-- | azurelinuxagent/pa/deprovision/default.py | 129 |
1 files changed, 114 insertions, 15 deletions
diff --git a/azurelinuxagent/pa/deprovision/default.py b/azurelinuxagent/pa/deprovision/default.py index ced87ee..90d16c7 100644 --- a/azurelinuxagent/pa/deprovision/default.py +++ b/azurelinuxagent/pa/deprovision/default.py @@ -17,13 +17,17 @@ # Requires Python 2.4+ and Openssl 1.0+ # +import glob +import os.path import signal import sys + import azurelinuxagent.common.conf as conf -from azurelinuxagent.common.exception import ProtocolError -from azurelinuxagent.common.future import read_input import azurelinuxagent.common.utils.fileutil as fileutil import azurelinuxagent.common.utils.shellutil as shellutil + +from azurelinuxagent.common.exception import ProtocolError +from azurelinuxagent.common.future import read_input from azurelinuxagent.common.osutil import get_osutil from azurelinuxagent.common.protocol import get_protocol_util @@ -68,15 +72,19 @@ class DeprovisionHandler(object): def regen_ssh_host_key(self, warnings, actions): warnings.append("WARNING! All SSH host key pairs will be deleted.") actions.append(DeprovisionAction(fileutil.rm_files, - ['/etc/ssh/ssh_host_*key*'])) + [conf.get_ssh_key_glob()])) def stop_agent_service(self, warnings, actions): warnings.append("WARNING! The waagent service will be stopped.") actions.append(DeprovisionAction(self.osutil.stop_agent_service)) + def del_dirs(self, warnings, actions): + dirs = [conf.get_lib_dir(), conf.get_ext_log_dir()] + actions.append(DeprovisionAction(fileutil.rm_dirs, dirs)) + def del_files(self, warnings, actions): - files_to_del = ['/root/.bash_history', '/var/log/waagent.log'] - actions.append(DeprovisionAction(fileutil.rm_files, files_to_del)) + files = ['/root/.bash_history', '/var/log/waagent.log'] + actions.append(DeprovisionAction(fileutil.rm_files, files)) def del_resolv(self, warnings, actions): warnings.append("WARNING! /etc/resolv.conf will be deleted.") @@ -92,9 +100,63 @@ class DeprovisionHandler(object): actions.append(DeprovisionAction(fileutil.rm_files, ["/var/db/dhclient.leases.hn0", "/var/lib/NetworkManager/dhclient-*.lease"])) - def del_lib_dir(self, warnings, actions): - dirs_to_del = [conf.get_lib_dir()] - actions.append(DeprovisionAction(fileutil.rm_dirs, dirs_to_del)) + + def del_lib_dir_files(self, warnings, actions): + known_files = [ + 'HostingEnvironmentConfig.xml', + 'Incarnation', + 'Protocol', + 'SharedConfig.xml', + 'WireServerEndpoint' + ] + known_files_glob = [ + 'Extensions.*.xml', + 'ExtensionsConfig.*.xml', + 'GoalState.*.xml' + ] + + lib_dir = conf.get_lib_dir() + files = [f for f in \ + [os.path.join(lib_dir, kf) for kf in known_files] \ + if os.path.isfile(f)] + for p in known_files_glob: + files += glob.glob(os.path.join(lib_dir, p)) + + if len(files) > 0: + actions.append(DeprovisionAction(fileutil.rm_files, files)) + + def cloud_init_dirs(self, include_once=True): + dirs = [ + "/var/lib/cloud/instance", + "/var/lib/cloud/instances/", + "/var/lib/cloud/data" + ] + if include_once: + dirs += [ + "/var/lib/cloud/scripts/per-once" + ] + return dirs + + def cloud_init_files(self, include_once=True): + files = [ + "/etc/sudoers.d/90-cloud-init-users" + ] + if include_once: + files += [ + "/var/lib/cloud/sem/config_scripts_per_once.once" + ] + return files + + def del_cloud_init(self, warnings, actions, include_once=True): + dirs = [d for d in self.cloud_init_dirs(include_once=include_once) \ + if os.path.isdir(d)] + if len(dirs) > 0: + actions.append(DeprovisionAction(fileutil.rm_dirs, dirs)) + + files = [f for f in self.cloud_init_files(include_once=include_once) \ + if os.path.isfile(f)] + if len(files) > 0: + actions.append(DeprovisionAction(fileutil.rm_files, files)) def reset_hostname(self, warnings, actions): localhost = ["localhost.localdomain"] @@ -117,7 +179,8 @@ class DeprovisionHandler(object): if conf.get_delete_root_password(): self.del_root_password(warnings, actions) - self.del_lib_dir(warnings, actions) + self.del_cloud_init(warnings, actions) + self.del_dirs(warnings, actions) self.del_files(warnings, actions) self.del_resolv(warnings, actions) @@ -126,19 +189,55 @@ class DeprovisionHandler(object): return warnings, actions + def setup_changed_unique_id(self): + warnings = [] + actions = [] + + self.del_cloud_init(warnings, actions, include_once=False) + self.del_dhcp_lease(warnings, actions) + self.del_lib_dir_files(warnings, actions) + self.del_resolv(warnings, actions) + + return warnings, actions + def run(self, force=False, deluser=False): warnings, actions = self.setup(deluser) - for warning in warnings: - print(warning) - if not force: - confirm = read_input("Do you want to proceed (y/n)") - if not confirm.lower().startswith('y'): - return + self.do_warnings(warnings) + self.do_confirmation(force=force) + self.do_actions(actions) + + def run_changed_unique_id(self): + ''' + Clean-up files and directories that may interfere when the VM unique + identifier has changed. + While users *should* manually deprovision a VM, the files removed by + this routine will help keep the agent from getting confused + (since incarnation and extension settings, among other items, will + no longer be monotonically increasing). + ''' + warnings, actions = self.setup_changed_unique_id() + + self.do_warnings(warnings) + self.do_actions(actions) + + def do_actions(self, actions): self.actions_running = True for action in actions: action.invoke() + self.actions_running = False + + def do_confirmation(self, force=False): + if force: + return True + + confirm = read_input("Do you want to proceed (y/n)") + return True if confirm.lower().startswith('y') else False + + def do_warnings(self, warnings): + for warning in warnings: + print(warning) def handle_interrupt_signal(self, signum, frame): if not self.actions_running: |