123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 |
- #!/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.
- """
- import re
- import time
- import sys
- import urllib2
- import base64
- import httplib
- # simplejson is much faster comparing to Python 2.6 json module and has the same functions set.
- import ambari_simplejson as json
- from StringIO import StringIO as BytesIO
- from resource_management.core.logger import Logger
- from ambari_commons.inet_utils import openurl
- from ambari_commons.exceptions import TimeoutError
- from resource_management.core.exceptions import Fail
- from resource_management.libraries.functions.format import format
- from resource_management.libraries.functions.decorator import safe_retry
- class Rangeradmin:
- sInstance = None
- def __init__(self, url='http://localhost:6080', skip_if_rangeradmin_down = True):
- self.baseUrl = url
- self.urlLogin = self.baseUrl + '/login.jsp'
- self.urlLoginPost = self.baseUrl + '/j_spring_security_check'
- self.urlRepos = self.baseUrl + '/service/assets/assets'
- self.urlReposPub = self.baseUrl + '/service/public/api/repository'
- self.urlPolicies = self.baseUrl + '/service/public/api/policy'
- self.urlGroups = self.baseUrl + '/service/xusers/groups'
- self.urlUsers = self.baseUrl + '/service/xusers/users'
- self.urlSecUsers = self.baseUrl + '/service/xusers/secure/users'
- self.skip_if_rangeradmin_down = skip_if_rangeradmin_down
- if self.skip_if_rangeradmin_down:
- Logger.info("Rangeradmin: Skip ranger admin if it's down !")
- @safe_retry(times=5, sleep_time=8, backoff_factor=1.5, err_class=Fail, return_on_fail=None)
- def get_repository_by_name_urllib2(self, name, component, status, usernamepassword):
- """
- :param name: name of the component, from which, function will search in list of repositories
- :param component: component for which repository has to be checked
- :param status: active or inactive
- :param usernamepassword: user credentials using which repository needs to be searched
- :return Returns Ranger repository dict if found otherwise None
- """
- try:
- searchRepoURL = self.urlReposPub + "?name=" + name + "&type=" + component + "&status=" + status
- request = urllib2.Request(searchRepoURL)
- base64string = base64.encodestring(usernamepassword).replace('\n', '')
- request.add_header("Content-Type", "application/json")
- request.add_header("Accept", "application/json")
- request.add_header("Authorization", "Basic {0}".format(base64string))
- result = openurl(request, timeout=20)
- response_code = result.getcode()
- response = json.loads(result.read())
- if response_code == 200 and len(response['vXRepositories']) > 0:
- for repo in response['vXRepositories']:
- repoDump = json.loads(json.JSONEncoder().encode(repo))
- if repoDump['name'].lower() == name.lower():
- return repoDump
- return None
- else:
- return None
- except urllib2.URLError, e:
- if isinstance(e, urllib2.HTTPError):
- raise Fail("Error getting {0} repository for component {1}. Http status code - {2}. \n {3}".format(name, component, e.code, e.read()))
- else:
- raise Fail("Error getting {0} repository for component {1}. Reason - {2}.".format(name, component, e.reason))
- except httplib.BadStatusLine:
- raise Fail("Ranger Admin service is not reachable, please restart the service and then try again")
- except TimeoutError:
- raise Fail("Connection to Ranger Admin failed. Reason - timeout")
-
-
-
- def create_ranger_repository(self, component, repo_name, repo_properties,
- ambari_ranger_admin, ambari_ranger_password,
- admin_uname, admin_password, policy_user):
- """
- :param component: name of the component, from which it will get or create repository
- :param repo_name: name of the repository to be get or create
- :param repo_properties: dict of repository to be create if not exist
- :param ambari_ranger_admin: ambari admin user creation username
- :param ambari_ranger_password: ambari admin user creation password
- :param admin_uname: ranger admin username
- :param admin_password: ranger admin password
- :param policy_user: use this policy user for policies that will be used during repository creation
- """
- response_code = self.check_ranger_login_urllib2(self.baseUrl)
- repo_data = json.dumps(repo_properties)
- ambari_ranger_password = unicode(ambari_ranger_password)
- admin_password = unicode(admin_password)
- ambari_username_password_for_ranger = format('{ambari_ranger_admin}:{ambari_ranger_password}')
-
- if response_code is not None and response_code == 200:
- user_resp_code = self.create_ambari_admin_user(ambari_ranger_admin, ambari_ranger_password, format("{admin_uname}:{admin_password}"))
- if user_resp_code is not None and user_resp_code == 200:
- retryCount = 0
- while retryCount <= 5:
- repo = self.get_repository_by_name_urllib2(repo_name, component, 'true', ambari_username_password_for_ranger)
- if repo is not None:
- Logger.info('{0} Repository {1} exist'.format(component.title(), repo['name']))
- break
- else:
- response = self.create_repository_urllib2(repo_data, ambari_username_password_for_ranger, policy_user)
- if response is not None:
- Logger.info('{0} Repository created in Ranger admin'.format(component.title()))
- break
- else:
- if retryCount < 5:
- Logger.info("Retry Repository Creation is being called")
- time.sleep(15) # delay for 15 seconds
- retryCount += 1
- else:
- Logger.error('{0} Repository creation failed in Ranger admin'.format(component.title()))
- break
- else:
- Logger.error('Ambari admin user creation failed')
- elif not self.skip_if_rangeradmin_down:
- Logger.error("Connection to Ranger Admin failed !")
- @safe_retry(times=5, sleep_time=8, backoff_factor=1.5, err_class=Fail, return_on_fail=None)
- def create_repository_urllib2(self, data, usernamepassword, policy_user):
- """
- :param data: repository dict
- :param usernamepassword: user credentials using which repository needs to be created
- :param policy_user: use this policy user for policies that will be used during repository creation
- :return Returns created repository response else None
- """
- try:
- searchRepoURL = self.urlReposPub
- base64string = base64.encodestring('{0}'.format(usernamepassword)).replace('\n', '')
- headers = {
- 'Accept': 'application/json',
- "Content-Type": "application/json"
- }
- request = urllib2.Request(searchRepoURL, data, headers)
- request.add_header("Authorization", "Basic {0}".format(base64string))
- result = openurl(request, timeout=20)
- response_code = result.getcode()
- response = json.loads(json.JSONEncoder().encode(result.read()))
- if response_code == 200:
- Logger.info('Repository created Successfully')
- # Get Policies
- repoData = json.loads(data)
- repoName = repoData['name']
- typeOfPolicy = repoData['repositoryType']
- # Get Policies by repo name
- policyList = self.get_policy_by_repo_name(name=repoName, component=typeOfPolicy, status="true",
- usernamepassword=usernamepassword)
- if policyList is not None and (len(policyList)) > 0:
- policiesUpdateCount = 0
- for policy in policyList:
- updatedPolicyObj = self.get_policy_params(typeOfPolicy, policy, policy_user)
- policyResCode, policyResponse = self.update_ranger_policy(updatedPolicyObj['id'],
- json.dumps(updatedPolicyObj), usernamepassword)
- if policyResCode == 200:
- policiesUpdateCount = policiesUpdateCount + 1
- else:
- Logger.info('Policy Update failed')
- # Check for count of updated policies
- if len(policyList) == policiesUpdateCount:
- Logger.info(
- "Ranger Repository created successfully and policies updated successfully providing ambari-qa user all permissions")
- return response
- else:
- return None
- else:
- Logger.info("Policies not found for the newly created Repository")
- return None
- else:
- Logger.info('Repository creation failed')
- return None
- except urllib2.URLError, e:
- if isinstance(e, urllib2.HTTPError):
- raise Fail("Error creating repository. Http status code - {0}. \n {1}".format(e.code, e.read()))
- else:
- raise Fail("Error creating repository. Reason - {0}.".format(e.reason))
- except httplib.BadStatusLine:
- raise Fail("Ranger Admin service is not reachable, please restart the service and then try again")
- except TimeoutError:
- raise Fail("Connection to Ranger Admin failed. Reason - timeout")
- @safe_retry(times=75, sleep_time=8, backoff_factor=1, err_class=Fail, return_on_fail=None)
- def check_ranger_login_urllib2(self, url):
- """
- :param url: ranger admin host url
- :return Returns login check response
- """
- try:
- response = openurl(url, timeout=20)
- response_code = response.getcode()
- return response_code
- except urllib2.URLError, e:
- if isinstance(e, urllib2.HTTPError):
- raise Fail("Connection to Ranger Admin failed. Http status code - {0}. \n {1}".format(e.code, e.read()))
- else:
- raise Fail("Connection to Ranger Admin failed. Reason - {0}.".format(e.reason))
- except httplib.BadStatusLine, e:
- raise Fail("Ranger Admin service is not reachable, please restart the service and then try again")
- except TimeoutError:
- raise Fail("Connection to Ranger Admin failed. Reason - timeout")
- @safe_retry(times=5, sleep_time=8, backoff_factor=1.5, err_class=Fail, return_on_fail=None)
- def get_policy_by_repo_name(self, name, component, status, usernamepassword):
- """
- :param name: repository name
- :param component: component name for which policy needs to be searched
- :param status: true or false
- :param usernamepassword: user credentials using which policy needs to be searched
- :return Returns successful response else None
- """
- try:
- searchPolicyURL = self.urlPolicies + "?repositoryName=" + name + "&repositoryType=" + component + "&isEnabled=" + status
- request = urllib2.Request(searchPolicyURL)
- base64string = base64.encodestring(usernamepassword).replace('\n', '')
- request.add_header("Content-Type", "application/json")
- request.add_header("Accept", "application/json")
- request.add_header("Authorization", "Basic {0}".format(base64string))
- result = openurl(request, timeout=20)
- response_code = result.getcode()
- response = json.loads(result.read())
- if response_code == 200 and len(response['vXPolicies']) > 0:
- return response['vXPolicies']
- else:
- return None
- except urllib2.URLError, e:
- if isinstance(e, urllib2.HTTPError):
- Logger.error("Error getting policy from repository {0} for component {1}. Http status code - {2}. \n {3}".format(name, component, e.code, e.read()))
- else:
- Logger.error("Error getting policy from repository {0} for component {1}. Reason - {2}.".format(name, component, e.reason))
- return None
- except httplib.BadStatusLine:
- Logger.error("Ranger Admin service is not reachable, please restart the service and then try again")
- return None
- except TimeoutError:
- raise Fail("Connection to Ranger Admin failed. Reason - timeout")
- @safe_retry(times=5, sleep_time=8, backoff_factor=1.5, err_class=Fail, return_on_fail=None)
- def update_ranger_policy(self, policyId, data, usernamepassword):
- """
- :param policyId: policy id which needs to be updated
- :param data: policy data that needs to be updated
- :param usernamepassword: user credentials using which policy needs to be updated
- :return Returns successful response and response code else None
- """
- try:
- searchRepoURL = self.urlPolicies + "/" + str(policyId)
- base64string = base64.encodestring('{0}'.format(usernamepassword)).replace('\n', '')
- headers = {
- 'Accept': 'application/json',
- "Content-Type": "application/json"
- }
- request = urllib2.Request(searchRepoURL, data, headers)
- request.add_header("Authorization", "Basic {0}".format(base64string))
- request.get_method = lambda: 'PUT'
- result = openurl(request, timeout=20)
- response_code = result.getcode()
- response = json.loads(json.JSONEncoder().encode(result.read()))
- if response_code == 200:
- Logger.info('Policy updated Successfully')
- return response_code, response
- else:
- Logger.error('Update Policy failed')
- return None, None
- except urllib2.URLError, e:
- if isinstance(e, urllib2.HTTPError):
- Logger.error("Error updating policy. Http status code - {0}. \n {1}".format(e.code, e.read()))
- else:
- Logger.error("Error updating policy. Reason - {0}.".format(e.reason))
- return None, None
- except httplib.BadStatusLine:
- Logger.error("Ranger Admin service is not reachable, please restart the service and then try again")
- return None, None
- except TimeoutError:
- raise Fail("Connection to Ranger Admin failed. Reason - timeout")
- def get_policy_params(self, typeOfPolicy, policyObj, policy_user):
- """
- :param typeOfPolicy: component name for which policy has to be get
- :param policyObj: policy dict
- :param policy_user: policy user that needs to be updated
- :returns Returns updated policy dict
- """
- typeOfPolicy = typeOfPolicy.lower()
- if typeOfPolicy == "hdfs":
- policyObj['permMapList'] = [{'userList': [policy_user], 'permList': ['read', 'write', 'execute', 'admin']}]
- elif typeOfPolicy == "hive":
- policyObj['permMapList'] = [{'userList': [policy_user],
- 'permList': ['select', 'update', 'create', 'drop', 'alter', 'index', 'lock', 'all',
- 'admin']}]
- elif typeOfPolicy == "hbase":
- policyObj['permMapList'] = [{'userList': [policy_user], 'permList': ['read', 'write', 'create', 'admin']}]
- elif typeOfPolicy == "knox":
- policyObj['permMapList'] = [{'userList': [policy_user], 'permList': ['allow', 'admin']}]
- elif typeOfPolicy == "storm":
- policyObj['permMapList'] = [{'userList': [policy_user],
- 'permList': ['submitTopology', 'fileUpload', 'getNimbusConf', 'getClusterInfo',
- 'fileDownload', 'killTopology', 'rebalance', 'activate', 'deactivate',
- 'getTopologyConf', 'getTopology', 'getUserTopology',
- 'getTopologyInfo', 'uploadNewCredential', 'admin']}]
- return policyObj
- @safe_retry(times=5, sleep_time=8, backoff_factor=1.5, err_class=Fail, return_on_fail=None)
- def create_ambari_admin_user(self,ambari_admin_username, ambari_admin_password,usernamepassword):
- """
- :param ambari_admin_username: username of user to be created
- :param ambari_admin_username: user password of user to be created
- :return Returns response code for successful user creation else None
- """
- flag_ambari_admin_present = False
- match = re.match('[a-zA-Z0-9_\S]+$', ambari_admin_password)
- if match is None:
- raise Fail('Invalid password given for Ranger Admin user for Ambari')
- try:
- url = self.urlUsers + '?name=' + str(ambari_admin_username)
- request = urllib2.Request(url)
- base64string = base64.encodestring(usernamepassword).replace('\n', '')
- request.add_header("Content-Type", "application/json")
- request.add_header("Accept", "application/json")
- request.add_header("Authorization", "Basic {0}".format(base64string))
- result = openurl(request, timeout=20)
- response_code = result.getcode()
- response = json.loads(result.read())
- if response_code == 200 and len(response['vXUsers']) >= 0:
- for vxuser in response['vXUsers']:
- if vxuser['name'] == ambari_admin_username:
- flag_ambari_admin_present = True
- break
- else:
- flag_ambari_admin_present = False
- if flag_ambari_admin_present:
- Logger.info(ambari_admin_username + ' user already exists.')
- return response_code
- else:
- Logger.info(ambari_admin_username + ' user is not present, creating user using given configurations')
- url = self.urlSecUsers
- admin_user = dict()
- admin_user['status'] = 1
- admin_user['userRoleList'] = ['ROLE_SYS_ADMIN']
- admin_user['name'] = ambari_admin_username
- admin_user['password'] = ambari_admin_password
- admin_user['description'] = ambari_admin_username
- admin_user['firstName'] = ambari_admin_username
- data = json.dumps(admin_user)
- base64string = base64.encodestring('{0}'.format(usernamepassword)).replace('\n', '')
- headers = {
- 'Accept': 'application/json',
- "Content-Type": "application/json"
- }
- request = urllib2.Request(url, data, headers)
- request.add_header("Authorization", "Basic {0}".format(base64string))
- result = openurl(request, timeout=20)
- response_code = result.getcode()
- response = json.loads(json.JSONEncoder().encode(result.read()))
- if response_code == 200 and response is not None:
- Logger.info('Ambari admin user creation successful.')
- return response_code
- else:
- Logger.info('Ambari admin user creation failed.')
- return None
- else:
- return None
- except urllib2.URLError, e:
- if isinstance(e, urllib2.HTTPError):
- raise Fail("Error creating ambari admin user. Http status code - {0}. \n {1}".format(e.code, e.read()))
- else:
- raise Fail("Error creating ambari admin user. Reason - {0}.".format(e.reason))
- except httplib.BadStatusLine:
- raise Fail("Ranger Admin service is not reachable, please restart the service and then try again")
- except TimeoutError:
- raise Fail("Connection to Ranger Admin failed. Reason - timeout")
|