blob: 79dc8741c0efd4650012808ab566694b28d333ca [file] [log] [blame]
#!/usr/bin/env python
"""
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.
Ambari Agent
"""
import os
import re
import tempfile
from resource_management.core.logger import Logger
from resource_management.core import shell
from resource_management.libraries.functions import stack_tools
import ambari_simplejson as json # simplejson is much faster comparing to Python 2.6 json module and has the same functions set.
def get_component_version(stack_name, component_name):
"""
For any stack name, returns the version currently installed for a given component.
Because each stack name may have different logic, the input is a generic dictionary.
:param stack_name: one of HDP, HDPWIN, BIGTOP, PHD, etc. usually retrieved from
the command-#.json file's ["hostLevelParams"]["stack_name"]
:param component_name: Component name as a string necessary to get the version
:return: Returns a string if found, e.g., 2.2.1.0-2175, otherwise, returns None
"""
version = None
if stack_name is None or component_name is None:
Logger.error("Could not determine component version because of the parameters is empty. " \
"stack_name: %s, component_name: %s" % (str(stack_name), str(component_name)))
return version
out = None
code = -1
if not stack_name:
Logger.error("Stack name not provided")
elif not component_name:
Logger.error("Component name not provided")
else:
(stack_selector_name, stack_selector_path, stack_selector_package) = stack_tools.get_stack_tool(stack_tools.STACK_SELECTOR_NAME)
if stack_selector_name and stack_selector_path and os.path.exists(stack_selector_path):
tmpfile = tempfile.NamedTemporaryFile()
get_stack_comp_version_cmd = ""
try:
# This is necessary because Ubuntu returns "stdin: is not a tty", see AMBARI-8088
with open(tmpfile.name, 'r') as file:
get_stack_comp_version_cmd = '%s status %s > %s' % (stack_selector_path, component_name, tmpfile.name)
code, stdoutdata = shell.call(get_stack_comp_version_cmd, quiet=True)
out = file.read()
if code != 0 or out is None:
raise Exception("Code is nonzero or output is empty")
Logger.debug("Command: %s\nOutput: %s" % (get_stack_comp_version_cmd, str(out)))
matches = re.findall(r"( [\d\.]+(\-\d+)?)", out)
version = matches[0][0].strip() if matches and len(matches) > 0 and len(matches[0]) > 0 else None
Logger.debug("Version for component %s: %s" % (component_name, str(version)))
except Exception, e:
Logger.error("Could not determine stack version for component %s by calling '%s'. Return Code: %s, Output: %s." %
(component_name, get_stack_comp_version_cmd, str(code), str(out)))
else:
Logger.error("Could not find stack selector for stack: %s" % str(stack_name))
return version
def get_component_version_with_stack_selector(stack_selector_path, component_name):
"""
For specific cases where we deal with HDP add on services from a management pack, the version
needs to be determined by using the specific stack selector itself.
:param stack_selector_path: /usr/bin/hdf-select
Comes from the service which calls for this function.
:param component_name: Component name as a string necessary to get the version
:return: Returns a string if found, e.g., 2.2.1.0-2175, otherwise, returns None
This function can be called by custom services, hence should not be removed
"""
version = None
out = None
code = -1
if not stack_selector_path:
Logger.error("Stack selector path not provided")
elif not os.path.exists(stack_selector_path):
Logger.error("Stack selector path does not exist")
elif not component_name:
Logger.error("Component name not provided")
else:
tmpfile = tempfile.NamedTemporaryFile()
get_stack_comp_version_cmd = ""
try:
# This is necessary because Ubuntu returns "stdin: is not a tty", see AMBARI-8088
with open(tmpfile.name, 'r') as file:
get_stack_comp_version_cmd = '{0} status {1} > {2}' .format(stack_selector_path, component_name, tmpfile.name)
code, stdoutdata = shell.call(get_stack_comp_version_cmd, quiet=True)
out = file.read()
if code != 0 or out is None:
raise Exception("Code is nonzero or output is empty")
Logger.debug("Command: %s\nOutput: %s" % (get_stack_comp_version_cmd, str(out)))
matches = re.findall(r"([\d\.]+\-\d+)", out)
version = matches[0] if matches and len(matches) > 0 else None
except Exception, e:
Logger.error("Could not determine stack version for component %s by calling '%s'. Return Code: %s, Output: %s." %
(component_name, get_stack_comp_version_cmd, str(code), str(out)))
return version
def get_versions_from_stack_root(stack_root):
"""
Given a stack install root, returns a list of stack versions currently installed.
The list of installed stack versions is determined purely based on the stack version directories
found in the stack install root.
Because each stack name may have different logic, the input is a generic dictionary.
:param stack_root: Stack install root directory
:return: Returns list of installed stack versions
"""
if stack_root is None or not os.path.exists(stack_root):
return []
installed_stack_versions = [f for f in os.listdir(stack_root) if os.path.isdir(os.path.join(stack_root, f))
and re.match("([\d\.]+(-\d+)?)", f)]
return installed_stack_versions