/*
 * 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.
 */

package org.apache.slider.providers.hbase.minicluster.freezethaw

import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs.FileSystem as HadoopFS
import org.apache.hadoop.fs.Path
import org.apache.hadoop.hbase.ClusterStatus
import org.apache.hadoop.yarn.conf.YarnConfiguration
import org.apache.slider.api.InternalKeys
import org.apache.slider.core.main.ServiceLauncher
import org.apache.slider.api.ClusterDescription
import org.apache.slider.core.build.InstanceIO
import org.apache.slider.providers.hbase.HBaseKeys
import org.apache.slider.common.tools.ConfigHelper
import org.apache.slider.common.tools.SliderFileSystem
import org.apache.slider.common.tools.SliderUtils
import org.apache.slider.client.SliderClient
import org.apache.slider.providers.hbase.minicluster.HBaseMiniClusterTestBase
import org.junit.Test

/**
 * Test of RM creation. This is so the later test's prereq's can be met
 */
@CompileStatic
@Slf4j
class TestFreezeReconfigureThawLiveRegionService
    extends HBaseMiniClusterTestBase {

  @Test
  public void testFreezeReconfigureThawLiveRegionService() throws Throwable {
    int regionServerCount = 4
    int nodemanagers = 3
    YarnConfiguration conf = configuration
    //one vcore per node
    conf.setInt("yarn.nodemanager.resource.cpu-vcores", 1)
    String clustername = createMiniCluster("", conf, nodemanagers, true)
    describe(
        "Create a $regionServerCount node cluster, stop it, patch the configuration files," +
        " start it and verify that it came back with the new settings")

    ServiceLauncher<SliderClient> launcher = createHBaseCluster(
        clustername,
        regionServerCount,
        [],
        true,
        true)
    SliderClient sliderClient = launcher.service
    addToTeardown(sliderClient);
    ClusterDescription status = sliderClient.getClusterDescription(clustername)
    log.info("${status.toJsonString()}")

    ClusterStatus clustat = basicHBaseClusterStartupSequence(sliderClient)

    clustat = waitForHBaseRegionServerCount(
        sliderClient,
        clustername,
        regionServerCount,
        hbaseClusterStartupToLiveTime)
    describe("Cluster status")
    log.info(hbaseStatusToString(clustat));


    clusterActionFreeze(sliderClient, clustername)
    killAllRegionServers();

    //reconfigure time

    //get the location of the cluster
    HadoopFS dfs = HadoopFS.get(new URI(fsDefaultName), miniCluster.config)
    SliderFileSystem sliderFileSystem = new SliderFileSystem(dfs, miniCluster.config)
    Path clusterDir = sliderFileSystem.buildClusterDirPath(clustername);
    def instanceDefinition = InstanceIO.loadInstanceDefinitionUnresolved(
        sliderFileSystem,
        clusterDir)

    def snapshotPath = instanceDefinition.internalOperations.get(
        InternalKeys.INTERNAL_SNAPSHOT_CONF_PATH)
    assert snapshotPath != null

    Path confdir = new Path(snapshotPath);
    Path hbaseSiteXML = new Path(confdir, HBaseKeys.SITE_XML)
    Configuration originalConf = ConfigHelper.loadTemplateConfiguration(
        dfs,
        hbaseSiteXML,
        "");
    //patch
    String patchedText = "patched-after-freeze"
    originalConf.setBoolean(patchedText, true);
    //save
    ConfigHelper.saveConfig(dfs, hbaseSiteXML, originalConf);

    //now let's start the cluster up again
    ServiceLauncher<SliderClient> launcher2 = thawCluster(clustername, [], true);
    SliderClient thawed = launcher2.service
    clustat = basicHBaseClusterStartupSequence(thawed)

    //get the options
    ClusterDescription stat = thawed.clusterDescription
    Map<String, String> properties = stat.clientProperties
    log.info("Cluster properties: \n" + SliderUtils.stringifyMap(properties));
    assert properties[patchedText] == "true";

  }


}
