| #!/usr/bin/env python2.6 |
| ''' |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| ''' |
| |
| __all__ = ["Environment"] |
| |
| import logging |
| import os |
| import shutil |
| import time |
| from datetime import datetime |
| |
| from resource_management.core import shell |
| from resource_management.core.exceptions import Fail |
| from resource_management.core.providers import find_provider |
| from resource_management.core.utils import AttributeDictionary |
| from resource_management.core.system import System |
| |
| |
| class Environment(object): |
| _instances = [] |
| |
| def __init__(self, basedir=None): |
| """ |
| @param basedir: basedir/files, basedir/templates are the places where templates / static files |
| are looked up |
| @param params: configurations dictionary (this will be accessible in the templates) |
| """ |
| self.log = logging.getLogger("resource_management") |
| self.reset(basedir) |
| |
| def reset(self, basedir): |
| self.system = System.get_instance() |
| self.config = AttributeDictionary() |
| self.resources = {} |
| self.resource_list = [] |
| self.delayed_actions = set() |
| self.update_config({ |
| # current time |
| 'date': datetime.now(), |
| # backups here files which were rewritten while executing File resource |
| 'backup.path': '/tmp/resource_management/backup', |
| # prefix for this files |
| 'backup.prefix': datetime.now().strftime("%Y%m%d%H%M%S"), |
| # dir where templates,failes dirs are |
| 'basedir': basedir, |
| # variables, which can be used in templates |
| 'params': {}, |
| }) |
| |
| def backup_file(self, path): |
| if self.config.backup: |
| if not os.path.exists(self.config.backup.path): |
| os.makedirs(self.config.backup.path, 0700) |
| new_name = self.config.backup.prefix + path.replace('/', '-') |
| backup_path = os.path.join(self.config.backup.path, new_name) |
| self.log.info("backing up %s to %s" % (path, backup_path)) |
| shutil.copy(path, backup_path) |
| |
| def update_config(self, attributes, overwrite=True): |
| for key, value in attributes.items(): |
| attr = self.config |
| path = key.split('.') |
| for pth in path[:-1]: |
| if pth not in attr: |
| attr[pth] = AttributeDictionary() |
| attr = attr[pth] |
| if overwrite or path[-1] not in attr: |
| attr[path[-1]] = value |
| |
| def set_params(self, arg): |
| """ |
| @param arg: is a dictionary of configurations, or a module with the configurations |
| """ |
| if isinstance(arg, dict): |
| variables = arg |
| else: |
| variables = dict((var, getattr(arg, var)) for var in dir(arg)) |
| |
| for variable, value in variables.iteritems(): |
| # don't include system variables, methods, classes, modules |
| if not variable.startswith("__") and \ |
| not hasattr(value, '__call__')and \ |
| not hasattr(value, '__module__') and \ |
| not hasattr(value, '__file__'): |
| self.config.params[variable] = value |
| |
| def run_action(self, resource, action): |
| self.log.debug("Performing action %s on %s" % (action, resource)) |
| |
| provider_class = find_provider(self, resource.__class__.__name__, |
| resource.provider) |
| provider = provider_class(resource) |
| try: |
| provider_action = getattr(provider, 'action_%s' % action) |
| except AttributeError: |
| raise Fail("%r does not implement action %s" % (provider, action)) |
| provider_action() |
| |
| if resource.is_updated: |
| for action, res in resource.subscriptions['immediate']: |
| self.log.info( |
| "%s sending %s action to %s (immediate)" % (resource, action, res)) |
| self.run_action(res, action) |
| for action, res in resource.subscriptions['delayed']: |
| self.log.info( |
| "%s sending %s action to %s (delayed)" % (resource, action, res)) |
| self.delayed_actions |= resource.subscriptions['delayed'] |
| |
| def _check_condition(self, cond): |
| if hasattr(cond, '__call__'): |
| return cond() |
| |
| if isinstance(cond, basestring): |
| ret, out = shell.call(cond) |
| return ret == 0 |
| |
| raise Exception("Unknown condition type %r" % cond) |
| |
| def run(self): |
| with self: |
| # Run resource actions |
| for resource in self.resource_list: |
| self.log.debug("Running resource %r" % resource) |
| |
| if resource.initial_wait: |
| time.sleep(resource.initial_wait) |
| |
| if resource.not_if is not None and self._check_condition( |
| resource.not_if): |
| self.log.debug("Skipping %s due to not_if" % resource) |
| continue |
| |
| if resource.only_if is not None and not self._check_condition( |
| resource.only_if): |
| self.log.debug("Skipping %s due to only_if" % resource) |
| continue |
| |
| for action in resource.action: |
| if not resource.ignore_failures: |
| self.run_action(resource, action) |
| else: |
| try: |
| self.run_action(resource, action) |
| except Exception: |
| pass |
| |
| # Run delayed actions |
| while self.delayed_actions: |
| action, resource = self.delayed_actions.pop() |
| self.run_action(resource, action) |
| |
| @classmethod |
| def get_instance(cls): |
| return cls._instances[-1] |
| |
| @classmethod |
| def get_instance_copy(cls): |
| """ |
| Copy only configurations, but not resources execution state |
| """ |
| old_instance = cls.get_instance() |
| new_instance = Environment() |
| new_instance.config = old_instance.config.copy() |
| |
| return new_instance |
| |
| def __enter__(self): |
| self.__class__._instances.append(self) |
| return self |
| |
| def __exit__(self, exc_type, exc_val, exc_tb): |
| self.__class__._instances.pop() |
| return False |
| |
| def __getstate__(self): |
| return dict( |
| config=self.config, |
| resources=self.resources, |
| resource_list=self.resource_list, |
| delayed_actions=self.delayed_actions, |
| ) |
| |
| def __setstate__(self, state): |
| self.__init__() |
| self.config = state['config'] |
| self.resources = state['resources'] |
| self.resource_list = state['resource_list'] |
| self.delayed_actions = state['delayed_actions'] |