AMBARI-23945. Infra Solr Migration - helper command to enable/disable/fix solr kerberos config.
diff --git a/ambari-infra-solr-client/README.md b/ambari-infra-solr-client/README.md
index 2df113b..53c6a3e 100644
--- a/ambari-infra-solr-client/README.md
+++ b/ambari-infra-solr-client/README.md
@@ -764,9 +764,16 @@
 
 #### <a id="if-solr-restarted">What to do if Solr instances restarted right after Ambari upgrade but before upgrade Solr instance packages?</a>
 
-As Solr instances won't start with the new upgraded configs (only if kerberos is enabled), you can do a small fix to make it work to just add this line to `infra-solr-env/content`:
+If you restarted Solr before backup or upgrade Solr server packages, you can fix the Solr config with the following command:
 ```bash
-SOLR_KERB_NAME_RULES="{{infra_solr_kerberos_name_rules}}"
+/usr/bin/python /usr/lib/ambari-infra-solr-client/migrationHelper.py --ini-file $CONFIG_INI_LOCATION --action fix-solr5-kerberos-config
+```
+
+That is basically add `SOLR_KERB_NAME_RULES` back to `infra-solr-env/content` and disable authorization for Solr. (upload a /security.json to /infra-solr znode without the authorization config, then turn manually managed /security.json on in order to not override /security.json again on Solr restart) After the command finished successfully, you will need to restart Solr instances.
+
+But if you added `SOLR_KERB_NAME_RULES` config to the `infra-solr-env/content`, you will require to delete that after you upgraded Solr package (and before restarting them). You can do that with the `fix-solr7-kerberos-config` action:
+```bash
+/usr/bin/python /usr/lib/ambari-infra-solr-client/migrationHelper.py --ini-file $CONFIG_INI_LOCATION --action fix-solr7-kerberos-config
 ```
 
 #### <a id="get-core-/-shard-names-with-hosts">Get core / shard names with hosts</a>
@@ -775,24 +782,17 @@
 
 #### <a id="turn-off-infra-solr-authorization">Turn off Infra Solr Authorization</a>
 
-You can turn off Solr authorization plugin with setting `infra-solr-security-json/content` Ambari configuration to `{"authentication": {"class": "org.apache.solr.security.KerberosPlugin"}}` (with that authentication will be still enabled). Then you will need to restart Solr, as that config is uploaded to the `/infra-solr/security.json` znode during startup. Other option is to use zkcli.sh of an Infra Solr to upload the security.json to the right place:
-```bash
-# Setup env for zkcli.sh
-source /etc/ambari-infra-solr/conf/infra-solr-env.sh
-# Run that command only if kerberos is enabled.
-export SOLR_ZK_CREDS_AND_ACLS="${SOLR_AUTHENTICATION_OPTS}"
-ZK_CONN_STRING=... # connection string -> zookeeper server addresses with the znode, e.g.: c7401.ambari.apache.org:2181/infra-solr
-
-/usr/lib/ambari-infra-solr/server/scripts/cloud-scripts/zkcli.sh -zkhost $ZK_CONN_STRING -cmd put /security.json
-  '{"authentication": {"class": "org.apache.solr.security.KerberosPlugin"}}'
-```
-
-Or you can also use the `migationHelper.py` script to disable the Solr authorization (for that to keep this settings, you can disable the management of the security.json in `infra-solr-security-json` config type)
-
+You can turn off Solr authorization plugin with the `disable-solr-authorization` action (can be executed after config generation [step](#0-gather-params)):
 ```bash
 /usr/bin/python /usr/lib/ambari-infra-solr-client/migrationHelper.py --ini-file $CONFIG_INI_LOCATION --action disable-solr-authorization
 ```
 
+You can re-enable it with the following command: (or set `infra-solr-security-json/infra_solr_security_manually_managed` configuration to `false`, then restart Solr)
+
+```bash
+/usr/bin/python /usr/lib/ambari-infra-solr-client/migrationHelper.py --ini-file $CONFIG_INI_LOCATION --action enable-solr-authorization
+```
+
 #### <a id="">Solr Migration Helper Script</a>
 
 `/usr/lib/ambari-infra-solr-client/migrationHelper.py --help`
diff --git a/ambari-infra-solr-client/src/main/python/migrationHelper.py b/ambari-infra-solr-client/src/main/python/migrationHelper.py
index 4d63bdd..1e62b98 100755
--- a/ambari-infra-solr-client/src/main/python/migrationHelper.py
+++ b/ambari-infra-solr-client/src/main/python/migrationHelper.py
@@ -61,6 +61,8 @@
 
 REQUESTS_API_URL = '/requests'
 BATCH_REQUEST_API_URL = "/api/v1/clusters/{0}/request_schedules"
+GET_ACTUAL_CONFIG_URL = '/configurations/service_config_versions?service_name={0}&is_current=true'
+CREATE_CONFIGURATIONS_URL = '/configurations'
 
 LIST_SOLR_COLLECTION_URL = '{0}/admin/collections?action=LIST&wt=json'
 CREATE_SOLR_COLLECTION_URL = '{0}/admin/collections?action=CREATE&name={1}&collection.configName={2}&numShards={3}&replicationFactor={4}&maxShardsPerNode={5}&wt=json'
@@ -295,7 +297,6 @@
 
   return request_schedules
 
-
 def create_command_request(command, parameters, hosts, cluster, context, service=SOLR_SERVICE_NAME, component=SOLR_COMPONENT_NAME):
   request = {}
   request_info = {}
@@ -635,7 +636,84 @@
   else:
     return collections
 
-def get_solr_urls(options, config, collection, collections_json):
+def get_infra_solr_props(config, accessor):
+  cluster = config.get('ambari_server', 'cluster')
+  service_configs = get_json(accessor, CLUSTERS_URL.format(cluster) + GET_ACTUAL_CONFIG_URL.format(SOLR_SERVICE_NAME))
+  infra_solr_props = {}
+  infra_solr_env_properties = {}
+  infra_solr_security_json_properties = {}
+  if 'items' in service_configs and len(service_configs['items']) > 0:
+    if 'configurations' in service_configs['items'][0]:
+      for config in service_configs['items'][0]['configurations']:
+        if 'type' in config and config['type'] == 'infra-solr-env':
+          infra_solr_env_properties = config['properties']
+        if 'type' in config and config['type'] == 'infra-solr-security-json':
+          infra_solr_security_json_properties = config['properties']
+  infra_solr_props['infra-solr-env'] = infra_solr_env_properties
+  infra_solr_props['infra-solr-security-json'] = infra_solr_security_json_properties
+  return infra_solr_props
+
+def insert_string_before(full_str, sub_str, insert_str):
+  idx = full_str.index(sub_str)
+  return full_str[:idx] + insert_str + full_str[idx:]
+
+def set_solr_security_management(infra_solr_props, accessor, enable = True):
+  security_props =  infra_solr_props['infra-solr-security-json']
+  check_value = "false" if enable else "true"
+  set_value = "true" if enable else "false"
+  turn_status = "on" if enable else "off"
+  if 'infra_solr_security_manually_managed' in security_props and security_props['infra_solr_security_manually_managed'] == check_value:
+    security_props['infra_solr_security_manually_managed'] = set_value
+    post_configuration = create_configs('infra-solr-security-json', security_props, 'Turn {0} security.json manaul management by migrationHelper.py'.format(turn_status))
+    apply_configs(config, accessor, post_configuration)
+  else:
+    print "Configuration 'infra-solr-security-json/infra_solr_security_manually_managed' has already set to '{0}'".format(set_value)
+
+def set_solr_name_rules(infra_solr_props, accessor, add = False):
+  """
+  Set name rules in infra-solr-env/content if not set in add mode, in non-add mode, remove it if exists
+  :param add: solr kerb name rules needs to be added (if false, it needs to be removed)
+  """
+  infra_solr_env_props =  infra_solr_props['infra-solr-env']
+  name_rules_param = "SOLR_KERB_NAME_RULES=\"{{infra_solr_kerberos_name_rules}}\"\n"
+
+  if 'content' in infra_solr_env_props and (name_rules_param not in infra_solr_env_props['content']) is add:
+    if add:
+      print "Adding 'SOLR_KERB_NAME_RULES' to 'infra-solr-env/content'"
+      new_content = insert_string_before(infra_solr_env_props['content'], "SOLR_KERB_KEYTAB", name_rules_param)
+      infra_solr_env_props['content'] = new_content
+      post_configuration = create_configs('infra-solr-env', infra_solr_env_props, 'Add "SOLR_KERB_NAME_RULES" by migrationHelper.py')
+      apply_configs(config, accessor, post_configuration)
+    else:
+      print "Removing 'SOLR_KERB_NAME_RULES' from 'infra-solr-env/content'"
+      new_content = infra_solr_env_props['content'].replace(name_rules_param, '')
+      infra_solr_env_props['content'] = new_content
+      post_configuration = create_configs('infra-solr-env', infra_solr_env_props, 'Remove "SOLR_KERB_NAME_RULES" by migrationHelper.py')
+      apply_configs(config, accessor, post_configuration)
+  else:
+    if add:
+      print "'SOLR_KERB_NAME_RULES' has already set in configuration 'infra-solr-env/content'"
+    else:
+      print "Configuration 'infra-solr-env/content' does not contain 'SOLR_KERB_NAME_RULES'"
+
+def apply_configs(config, accessor, post_configuration):
+  cluster = config.get('ambari_server', 'cluster')
+  desired_configs_post_body = {}
+  desired_configs_post_body["Clusters"] = {}
+  desired_configs_post_body["Clusters"]["desired_configs"] = post_configuration
+  accessor(CLUSTERS_URL.format(cluster), 'PUT', json.dumps(desired_configs_post_body))
+
+def create_configs(config_type, properties, context):
+  configs_for_posts = {}
+  configuration = {}
+  configuration['type'] = config_type
+  configuration['tag'] = "version" + str(int(round(time.time() * 1000)))
+  configuration['properties'] = properties
+  configuration['service_config_version_note'] = context
+  configs_for_posts[config_type] = configuration
+  return configs_for_posts
+
+def get_solr_urls(options, config, collection, collections_json): # TODO: use proper url from collections.json
   solr_urls = []
   solr_hosts = None
   solr_port = "8886"
@@ -1521,7 +1599,7 @@
     else:
       print "Collection '{0}' does not exist or filtered out. Skipping update collection state operation.".format(backup_fulltext_index_name)
 
-def disable_solr_authorization(options, accessor, parser, config):
+def set_solr_authorization(options, accessor, parser, config, enable_authorization, fix_kerberos_config = False):
   solr_znode='/infra-solr'
   if config.has_section('infra_solr') and config.has_option('infra_solr', 'znode'):
     solr_znode=config.get('infra_solr', 'znode')
@@ -1529,11 +1607,24 @@
   if config.has_section('cluster') and config.has_option('cluster', 'kerberos_enabled'):
     kerberos_enabled=config.get('cluster', 'kerberos_enabled')
   if kerberos_enabled == 'true':
-    print "Disable Solr authorization by uploading a new security.json ..."
-    copy_znode(options, config, COLLECTIONS_DATA_JSON_LOCATION.format("security-without-authr.json"),
+    infra_solr_props = get_infra_solr_props(config, accessor)
+    if enable_authorization:
+      print "Enable Solr security.json management by Ambari ... "
+      set_solr_security_management(infra_solr_props, accessor, enable = False)
+      if fix_kerberos_config:
+        set_solr_name_rules(infra_solr_props, accessor, False)
+    else:
+      print "Disable Solr authorization by uploading a new security.json and turn on security.json management by Ambari..."
+      set_solr_security_management(infra_solr_props, accessor, enable = True)
+      copy_znode(options, config, COLLECTIONS_DATA_JSON_LOCATION.format("security-without-authr.json"),
              "{0}/security.json".format(solr_znode), copy_from_local=True)
+      if fix_kerberos_config:
+        set_solr_name_rules(infra_solr_props, accessor, True)
   else:
-    print "Security is not enabled. Skipping disable Solr authorization operation."
+    if fix_kerberos_config:
+      print "Security is not enabled. Skipping enable/disable Solr authorization + fix infra-solr-env kerberos config operation."
+    else:
+      print "Security is not enabled. Skipping enable/disable Solr authorization operation."
 
 def summarize_shard_check_result(check_results, skip_warnings = False, skip_index_size = False):
   warnings = 0
@@ -1611,8 +1702,9 @@
   parser = optparse.OptionParser("usage: %prog [options]")
 
   parser.add_option("-a", "--action", dest="action", type="string", help="delete-collections | backup | cleanup-znodes | backup-and-cleanup | migrate | restore |' \
-              ' rolling-restart-solr | rolling-restart-atlas | rolling-restart-ranger | check-shards | check-backup-shards | disable-solr-authorization |'\
-              ' upgrade-solr-clients | upgrade-solr-instances | upgrade-logsearch-portal | upgrade-logfeeders | stop-logsearch | restart-solr |restart-logsearch | restart-ranger | restart-atlas")
+              ' rolling-restart-solr | rolling-restart-atlas | rolling-restart-ranger | check-shards | check-backup-shards | enable-solr-authorization | disable-solr-authorization |'\
+              ' fix-solr5-kerberos-config | fix-solr7-kerberos-config | upgrade-solr-clients | upgrade-solr-instances | upgrade-logsearch-portal | upgrade-logfeeders | stop-logsearch |'\
+              ' restart-solr |restart-logsearch | restart-ranger | restart-atlas")
   parser.add_option("-i", "--ini-file", dest="ini_file", type="string", help="Config ini file to parse (required)")
   parser.add_option("-f", "--force", dest="force", default=False, action="store_true", help="force index upgrade even if it's the right version")
   parser.add_option("-v", "--verbose", dest="verbose", action="store_true", help="use for verbose logging")
@@ -1745,8 +1837,14 @@
           print "ATLAS service has not found in the config or filtered out."
       elif options.action.lower() == 'rolling-restart-solr':
         rolling_restart(options, accessor, parser, config, SOLR_SERVICE_NAME, SOLR_COMPONENT_NAME, "Rolling Restart Infra Solr Instances")
+      elif options.action.lower() == 'enable-solr-authorization':
+        set_solr_authorization(options, accessor, parser, config, True)
       elif options.action.lower() == 'disable-solr-authorization':
-        disable_solr_authorization(options, accessor, parser, config)
+        set_solr_authorization(options, accessor, parser, config, False)
+      elif options.action.lower() == 'fix-solr5-kerberos-config':
+        set_solr_authorization(options, accessor, parser, config, False, True)
+      elif options.action.lower() == 'fix-solr7-kerberos-config':
+        set_solr_authorization(options, accessor, parser, config, True, True)
       elif options.action.lower() == 'check-shards':
         check_shards(options, accessor, parser, config)
       elif options.action.lower() == 'check-backup-shards':
@@ -1756,11 +1854,10 @@
       else:
         parser.print_help()
         print 'action option is invalid (available actions: delete-collections | backup | cleanup-znodes | backup-and-cleanup | migrate | restore |' \
-              ' rolling-restart-solr | rolling-restart-ranger | rolling-restart-atlas | check-shards | check-backup-shards | check-docs | disable-solr-authorization |' \
-              ' upgrade-solr-clients | upgrade-solr-instances | upgrade-logsearch-portal | upgrade-logfeeders | stop-logsearch | restart-solr |' \
+              ' rolling-restart-solr | rolling-restart-ranger | rolling-restart-atlas | check-shards | check-backup-shards | check-docs | enable-solr-authorization |'\
+              ' disable-solr-authorization | fix-solr5-kerberos-config | fix-solr7-kerberos-config | upgrade-solr-clients | upgrade-solr-instances | upgrade-logsearch-portal |' \
+              ' upgrade-logfeeders | stop-logsearch | restart-solr |' \
               ' restart-logsearch | restart-ranger | restart-atlas)'
         sys.exit(1)
-      if options.verbose:
-        print "Migration helper command ({0}) {1}FINISHED{2}".format(str(args), colors.OKGREEN, colors.ENDC)
-      else:
-        print "Migration helper command {0}FINISHED{1}".format(colors.OKGREEN, colors.ENDC)
\ No newline at end of file
+
+      print "Migration helper command {0}FINISHED{1}".format(colors.OKGREEN, colors.ENDC)
\ No newline at end of file