# Copyright (c) 2015, MapR Technologies # # Licensed 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. import collections from oslo_config import cfg import sahara.exceptions as e from sahara.i18n import _ import sahara.plugins.mapr.abstract.cluster_context as cc import sahara.plugins.mapr.domain.distro as distro import sahara.plugins.mapr.services.management.management as mng import sahara.plugins.mapr.services.maprfs.maprfs as mfs import sahara.plugins.mapr.services.oozie.oozie as oozie from sahara.plugins.mapr.services.swift import swift import sahara.plugins.mapr.services.yarn.yarn as yarn import sahara.plugins.mapr.util.general as g import sahara.plugins.mapr.util.service_utils as su import sahara.plugins.utils as u CONF = cfg.CONF CONF.import_opt("enable_data_locality", "sahara.topology.topology_helper") class BaseClusterContext(cc.AbstractClusterContext): ubuntu_base = 'http://package.mapr.com/releases/v%s/ubuntu/ mapr optional' centos_base = 'http://package.mapr.com/releases/v%s/redhat/' def __init__(self, cluster, version_handler, added=None, removed=None): self._cluster = cluster self._distro = None self._all_services = version_handler.get_services() self._required_services = version_handler.get_required_services() self._cluster_services = None self._mapr_home = '/opt/mapr' self._name_node_uri = 'maprfs:///' self._cluster_mode = None self._node_aware = None self._oozie_server_uri = None self._oozie_server = None self._oozie_http = None self._some_instance = None self._configure_sh_path = None self._configure_sh = None self._mapr_db = None self._hadoop_home = None self._hadoop_version = None self._added_instances = added or [] self._removed_instances = removed or [] self._changed_instances = ( self._added_instances + self._removed_instances) self._existing_instances = [i for i in self.get_instances() if i not in self._changed_instances] self._restart = collections.defaultdict(list) self._ubuntu_base_repo = None self._ubuntu_ecosystem_repo = None self._centos_base_repo = None self._centos_ecosystem_repo = None self._repos = {} self._is_prebuilt = None self._local_repo = '/opt/mapr-repository' self._mapr_version = None @property def cluster(self): return self._cluster @property def cluster_services(self): if not self._cluster_services: self._cluster_services = self.get_cluster_services() return self._cluster_services @property def required_services(self): return self._required_services @property def all_services(self): return self._all_services @property def mapr_home(self): return self._mapr_home @property def hadoop_version(self): return self._hadoop_version @property def hadoop_home(self): if not self._hadoop_home: f = '%(mapr_home)s/hadoop/hadoop-%(hadoop_version)s' args = { 'mapr_home': self.mapr_home, 'hadoop_version': self.hadoop_version, } self._hadoop_home = f % args return self._hadoop_home @property def name_node_uri(self): return self._name_node_uri @property def oozie_server_uri(self): if not self._oozie_server_uri: oozie_http = self.oozie_http url = 'http://%s/oozie' % oozie_http if oozie_http else None self._oozie_server_uri = url return self._oozie_server_uri @property def oozie_server(self): if not self._oozie_server: self._oozie_server = self.get_instance(oozie.OOZIE) return self._oozie_server @property def oozie_http(self): if not self._oozie_http: oozie_server = self.oozie_server ip = oozie_server.management_ip if oozie_server else None self._oozie_http = '%s:11000' % ip if ip else None return self._oozie_http @property def cluster_mode(self): return self._cluster_mode @property def is_node_aware(self): return self._node_aware and CONF.enable_data_locality @property def some_instance(self): if not self._some_instance: self._some_instance = self.cluster.node_groups[0].instances[0] return self._some_instance @property def distro(self): if not self._distro: self._distro = distro.get(self.some_instance) return self._distro @property def mapr_db(self): if self._mapr_db is None: mapr_db = mfs.MapRFS.ENABLE_MAPR_DB_CONFIG mapr_db = self._get_cluster_config_value(mapr_db) self._mapr_db = '-noDB' if not mapr_db else '' return self._mapr_db @property def configure_sh_path(self): if not self._configure_sh_path: self._configure_sh_path = '%s/server/configure.sh' % self.mapr_home return self._configure_sh_path @property def configure_sh(self): if not self._configure_sh: f = ('%(script_path)s' ' -N %(cluster_name)s' ' -C %(cldbs)s' ' -Z %(zookeepers)s' ' -no-autostart -f %(m7)s') args = { 'script_path': self.configure_sh_path, 'cluster_name': self.cluster.name, 'cldbs': self.get_cldb_nodes_ip(), 'zookeepers': self.get_zookeeper_nodes_ip(), 'm7': self.mapr_db } self._configure_sh = f % args return self._configure_sh def _get_cluster_config_value(self, config): cluster_configs = self.cluster.cluster_configs service = config.applicable_target name = config.name if service in cluster_configs and name in cluster_configs[service]: return cluster_configs[service][name] else: return config.default_value def get_instances(self, node_process=None): if node_process is not None: node_process = su.get_node_process_name(node_process) return u.get_instances(self.cluster, node_process) def get_instance(self, node_process): node_process_name = su.get_node_process_name(node_process) instances = u.get_instances(self.cluster, node_process_name) return instances[0] if instances else None def get_instances_ip(self, node_process): return [i.internal_ip for i in self.get_instances(node_process)] def get_instance_ip(self, node_process): i = self.get_instance(node_process) return i.internal_ip if i else None def get_zookeeper_nodes_ip_with_port(self, separator=','): return separator.join(['%s:%s' % (ip, mng.ZK_CLIENT_PORT) for ip in self.get_instances_ip(mng.ZOOKEEPER)]) def check_for_process(self, instance, process): return su.has_node_process(instance, process) def get_services_configs_dict(self, services=None): if not services: services = self.cluster_services result = dict() for service in services: result.update(service.get_configs_dict()) return result def get_chosen_service_version(self, service_name): service_configs = self.cluster.cluster_configs.get(service_name, None) if not service_configs: return None return service_configs.get('%s Version' % service_name, None) def get_cluster_services(self, node_group=None): node_processes = None if node_group: node_processes = node_group.node_processes else: node_processes = [np for ng in self.cluster.node_groups for np in ng.node_processes] node_processes = g.unique_list(node_processes) services = g.unique_list(node_processes, self.get_service) return services + [swift.Swift()] def get_service(self, node_process): ui_name = self.get_service_name_by_node_process(node_process) if ui_name is None: raise e.InvalidDataException( _('Service not found in services list')) version = self.get_chosen_service_version(ui_name) service = self._find_service_instance(ui_name, version) if service is None: raise e.InvalidDataException(_('Can not map service')) return service def _find_service_instance(self, ui_name, version): for service in self.all_services: if service.ui_name == ui_name: if version is not None and service.version != version: continue return service def get_service_name_by_node_process(self, node_process): node_process_name = su.get_node_process_name(node_process) for service in self.all_services: service_node_processes = [np.ui_name for np in service.node_processes] if node_process_name in service_node_processes: return service.ui_name def get_instances_count(self, node_process=None): if node_process is not None: node_process = su.get_node_process_name(node_process) return u.get_instances_count(self.cluster, node_process) def get_node_groups(self, node_process=None): if node_process is not None: node_process = su.get_node_process_name(node_process) return u.get_node_groups(self.cluster, node_process) def get_cldb_nodes_ip(self, separator=','): return separator.join(self.get_instances_ip(mfs.CLDB)) def get_zookeeper_nodes_ip(self, separator=','): return separator.join( self.get_instances_ip(mng.ZOOKEEPER)) def get_resourcemanager_ip(self): return self.get_instance_ip(yarn.RESOURCE_MANAGER) def get_historyserver_ip(self): return self.get_instance_ip(yarn.HISTORY_SERVER) def has_control_nodes(self, instances): for inst in instances: zookeepers = self.check_for_process(inst, mng.ZOOKEEPER) cldbs = self.check_for_process(inst, mfs.CLDB) if zookeepers or cldbs: return True return False def is_present(self, service): is_service_subclass = lambda s: isinstance(s, service.__class__) return any(is_service_subclass(s) for s in self.cluster_services) def filter_instances(self, instances, node_process=None, service=None): if node_process: return su.filter_by_node_process(instances, node_process) if service: return su.filter_by_service(instances, service) return list(instances) def removed_instances(self, node_process=None, service=None): instances = self._removed_instances return self.filter_instances(instances, node_process, service) def added_instances(self, node_process=None, service=None): instances = self._added_instances return self.filter_instances(instances, node_process, service) def changed_instances(self, node_process=None, service=None): instances = self._changed_instances return self.filter_instances(instances, node_process, service) def existing_instances(self, node_process=None, service=None): instances = self._existing_instances return self.filter_instances(instances, node_process, service) @property def should_be_restarted(self): return self._restart @property def mapr_repos(self): if not self._repos: self._repos = { "ubuntu_mapr_base_repo": self.ubuntu_base_repo, "ubuntu_mapr_ecosystem_repo": self.ubuntu_ecosystem_repo, "centos_mapr_base_repo": self.centos_base_repo, "centos_mapr_ecosystem_repo": self.centos_ecosystem_repo, } return self._repos @property def local_repo(self): return self._local_repo @property def is_prebuilt(self): if self._is_prebuilt is None: self._is_prebuilt = g.is_directory( self.some_instance, self.local_repo) return self._is_prebuilt @property def mapr_version(self): return self._mapr_version @property def ubuntu_base_repo(self): if not self._ubuntu_base_repo: self._ubuntu_base_repo = self.ubuntu_base % self.mapr_version return self._ubuntu_base_repo @property def ubuntu_ecosystem_repo(self): return self._ubuntu_ecosystem_repo @property def centos_base_repo(self): if not self._centos_base_repo: self._centos_base_repo = self.centos_base % self.mapr_version return self._centos_base_repo @property def centos_ecosystem_repo(self): return self._centos_ecosystem_repo