Browse Source

Merge branch 'trunk' into branch-alerts-dev

Jonathan Hurley 11 years ago
parent
commit
9919b3f4fa
21 changed files with 322 additions and 94 deletions
  1. 12 5
      ambari-agent/src/main/python/ambari_agent/Facter.py
  2. 17 0
      ambari-common/src/main/python/ambari_commons/os_check.py
  3. 1 0
      ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
  4. 4 1
      ambari-server/src/main/java/org/apache/ambari/server/api/resources/ViewInstanceResourceDefinition.java
  5. 1 1
      ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
  6. 15 20
      ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
  7. 3 1
      ambari-server/src/main/python/ambari_server/utils.py
  8. 6 0
      ambari-server/src/main/resources/os_family.json
  9. 1 1
      ambari-server/src/main/resources/stacks/HDP/2.0.6/services/OOZIE/package/scripts/oozie.py
  10. 0 2
      ambari-server/src/main/resources/stacks/HDP/2.0.6/services/OOZIE/package/scripts/params.py
  11. 1 0
      ambari-server/src/main/resources/stacks/HDP/2.0.6/services/ZOOKEEPER/configuration/zookeeper-env.xml
  12. 2 0
      ambari-server/src/main/resources/stacks/HDP/2.0.6/services/ZOOKEEPER/package/scripts/params.py
  13. 75 0
      ambari-server/src/main/resources/stacks/HDP/2.2/services/OOZIE/configuration/oozie-site.xml
  14. 17 11
      ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
  15. 10 0
      ambari-server/src/test/python/stacks/2.0.6/OOZIE/test_oozie_server.py
  16. 1 1
      ambari-web/app/templates/main/service/services/storm.hbs
  17. 8 0
      ambari-web/app/views/main/service/services/storm.js
  18. 55 34
      contrib/views/slider/src/main/resources/ui/app/controllers/slider_app_controller.js
  19. 17 16
      contrib/views/slider/src/main/resources/ui/app/models/slider_app.js
  20. 12 1
      contrib/views/slider/src/main/resources/ui/test/integration/pages/index_test.js
  21. 64 0
      contrib/views/slider/src/main/resources/ui/test/unit/controllers/slider_app_controller_test.js

+ 12 - 5
ambari-agent/src/main/python/ambari_agent/Facter.py

@@ -189,8 +189,10 @@ class Facter():
 
   # Return first ip adress
   def getIpAddress(self):
-    result = self.data_return_first("(?: inet addr:)(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})",
-                                    self.DATA_IFCONFIG_OUTPUT)
+    ip_pattern="(?: inet addr:)(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})"
+    if OSCheck.is_redhat7():
+      ip_pattern="(?: inet )(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})"
+    result = self.data_return_first(ip_pattern,self.DATA_IFCONFIG_OUTPUT)
     if result == '':
       log.warn("Can't get an ip address from {0}".format(self.DATA_IFCONFIG_OUTPUT))
       return socket.gethostbyname(socket.gethostname())
@@ -199,8 +201,10 @@ class Facter():
 
   # Return  netmask
   def getNetmask(self):
-    result = self.data_return_first("(?: Mask:)(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})",
-                                    self.DATA_IFCONFIG_OUTPUT)
+    mask_pattern="(?: Mask:)(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})"
+    if OSCheck.is_redhat7():
+      mask_pattern="(?: netmask )(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})"
+    result = self.data_return_first(mask_pattern,self.DATA_IFCONFIG_OUTPUT)
     if result == '':
       log.warn("Can't get a netmask from {0}".format(self.DATA_IFCONFIG_OUTPUT))
       return 'OS NOT SUPPORTED'
@@ -209,7 +213,10 @@ class Facter():
 
   # Return interfaces
   def getInterfaces(self):
-    result = self.data_return_list("(\w+)(?:.*Link encap:)", self.DATA_IFCONFIG_OUTPUT)
+    interface_pattern="(\w+)(?:.*Link encap:)"
+    if OSCheck.is_redhat7():
+      interface_pattern="(\w+)(?:.*flags=)"
+    result = self.data_return_list(interface_pattern, self.DATA_IFCONFIG_OUTPUT)
     if result == '':
       log.warn("Can't get a network interfaces list from {0}".format(self.DATA_IFCONFIG_OUTPUT))
       return 'OS NOT SUPPORTED'

+ 17 - 0
ambari-common/src/main/python/ambari_commons/os_check.py

@@ -28,6 +28,8 @@ def linux_distribution():
 
   if PYTHON_VER < 26:
     linux_distribution = platform.dist()
+  elif os.path.exists('/etc/redhat-release'):
+    linux_distribution = platform.dist()
   else:
     linux_distribution = platform.linux_distribution()
 
@@ -212,3 +214,18 @@ class OSCheck:
     except Exception:
       pass
     return False
+
+  @staticmethod
+  def is_redhat7():
+    """
+     Return true if it is so or false if not
+
+     This is safe check for redhat7 , doesn't generate exception
+    """
+    try:
+      ostemp=OSCheck.get_os_family()+OSCheck().get_os_major_version()
+      if ostemp == 'redhat7':
+        return True
+    except Exception:
+      pass
+    return False

+ 1 - 0
ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java

@@ -685,6 +685,7 @@ public class HeartBeatHandler {
 
     String agentOsType = getOsType(register.getHardwareProfile().getOS(),
         register.getHardwareProfile().getOSRelease());
+    LOG.info("agentOsType = "+agentOsType );
     if (!ambariMetaInfo.isOsSupported(agentOsType)) {
       LOG.warn("Received registration request from host with not supported"
           + " os type"

+ 4 - 1
ambari-server/src/main/java/org/apache/ambari/server/api/resources/ViewInstanceResourceDefinition.java

@@ -41,7 +41,10 @@ public class ViewInstanceResourceDefinition extends BaseResourceDefinition {
    */
   public ViewInstanceResourceDefinition(Set<SubResourceDefinition> subResourceDefinitions) {
     super(Resource.Type.ViewInstance);
-    this.subResourceDefinitions = new HashSet<SubResourceDefinition>(subResourceDefinitions);
+
+    this.subResourceDefinitions = subResourceDefinitions == null ? new HashSet<SubResourceDefinition>() :
+        new HashSet<SubResourceDefinition>(subResourceDefinitions);
+
     this.subResourceDefinitions.add(new SubResourceDefinition(Resource.Type.ViewPrivilege));
   }
 

+ 1 - 1
ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java

@@ -122,7 +122,7 @@ public class AmbariMetaInfo {
   public static final String REPOSITORY_XML_PROPERTY_BASEURL = "baseurl";
   // all the supported OS'es
   private static final List<String> ALL_SUPPORTED_OS = Arrays.asList(
-      "centos5", "redhat5", "centos6", "redhat6", "oraclelinux5",
+      "redhat7","centos7","centos5", "redhat5", "centos6", "redhat6", "oraclelinux5",
       "oraclelinux6", "suse11", "sles11", "ubuntu12");
 
   private final ActionDefinitionManager adManager = new ActionDefinitionManager();

+ 15 - 20
ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java

@@ -124,7 +124,7 @@ public class ViewRegistry {
    * Mapping of view names to sub-resources.
    */
   private final Map<String, Set<SubResourceDefinition>> subResourceDefinitionsMap =
-      new HashMap<String, Set<SubResourceDefinition>>();
+      new ConcurrentHashMap<String, Set<SubResourceDefinition>>();
 
   /**
    * Mapping of view types to resource providers.
@@ -403,27 +403,13 @@ public class ViewRegistry {
    *
    * @return the set of sub-resource definitions
    */
-  public synchronized Set<SubResourceDefinition> getSubResourceDefinitions(
+  public Set<SubResourceDefinition> getSubResourceDefinitions(
       String viewName, String version) {
 
     viewName = ViewEntity.getViewName(viewName, version);
 
-    Set<SubResourceDefinition> subResourceDefinitions =
-        subResourceDefinitionsMap.get(viewName);
-
-    if (subResourceDefinitions == null) {
-      subResourceDefinitions = new HashSet<SubResourceDefinition>();
-      ViewEntity definition = getDefinition(viewName);
-      if (definition != null) {
-        for (Resource.Type type : definition.getViewResourceTypes()) {
-          subResourceDefinitions.add(new SubResourceDefinition(type));
-        }
-      }
-      subResourceDefinitionsMap.put(viewName, subResourceDefinitions);
-    }
-    return subResourceDefinitions;
+    return subResourceDefinitionsMap.get(viewName);
   }
-
   /**
    * Read all view archives.
    */
@@ -773,10 +759,13 @@ public class ViewRegistry {
     List<ParameterConfig> parameterConfigurations = viewConfig.getParameters();
 
     Collection<ViewParameterEntity> parameters = new HashSet<ViewParameterEntity>();
+
+    String viewName = viewDefinition.getName();
+
     for (ParameterConfig parameterConfiguration : parameterConfigurations) {
       ViewParameterEntity viewParameterEntity =  new ViewParameterEntity();
 
-      viewParameterEntity.setViewName(viewDefinition.getName());
+      viewParameterEntity.setViewName(viewName);
       viewParameterEntity.setName(parameterConfiguration.getName());
       viewParameterEntity.setDescription(parameterConfiguration.getDescription());
       viewParameterEntity.setRequired(parameterConfiguration.isRequired());
@@ -803,7 +792,7 @@ public class ViewRegistry {
     for (ResourceConfig resourceConfiguration : resourceConfigurations) {
       ViewResourceEntity viewResourceEntity = new ViewResourceEntity();
 
-      viewResourceEntity.setViewName(viewDefinition.getName());
+      viewResourceEntity.setViewName(viewName);
       viewResourceEntity.setName(resourceConfiguration.getName());
       viewResourceEntity.setPluralName(resourceConfiguration.getPluralName());
       viewResourceEntity.setIdProperty(resourceConfiguration.getIdProperty());
@@ -837,7 +826,7 @@ public class ViewRegistry {
     }
 
     ResourceTypeEntity resourceTypeEntity = new ResourceTypeEntity();
-    resourceTypeEntity.setName(viewDefinition.getName());
+    resourceTypeEntity.setName(viewName);
 
     viewDefinition.setResourceType(resourceTypeEntity);
 
@@ -860,6 +849,12 @@ public class ViewRegistry {
     viewDefinition.setView(view);
     viewDefinition.setMask(viewConfig.getMasker());
 
+    Set<SubResourceDefinition> subResourceDefinitions = new HashSet<SubResourceDefinition>();
+    for (Resource.Type type : viewDefinition.getViewResourceTypes()) {
+      subResourceDefinitions.add(new SubResourceDefinition(type));
+    }
+    subResourceDefinitionsMap.put(viewName, subResourceDefinitions);
+
     return viewDefinition;
   }
 

+ 3 - 1
ambari-server/src/main/python/ambari_server/utils.py

@@ -23,7 +23,7 @@ import sys
 import time
 import glob
 import subprocess
-from ambari_commons import OSConst
+from ambari_commons import OSConst,OSCheck
 
 # PostgreSQL settings
 PG_STATUS_RUNNING_DEFAULT = "running"
@@ -192,6 +192,8 @@ def get_postgre_hba_dir(OS_FAMILY):
     # Like: /etc/postgresql/9.1/main/
     return os.path.join(PG_HBA_INIT_FILES[OS_FAMILY], get_ubuntu_pg_version(),
                         "main")
+  elif OSCheck.is_redhat7():
+    return PG_HBA_ROOT_DEFAULT
   else:
     if not os.path.isfile(PG_HBA_INIT_FILES[OS_FAMILY]):
       # Link: /etc/init.d/postgresql --> /etc/init.d/postgresql-9.1

+ 6 - 0
ambari-server/src/main/resources/os_family.json

@@ -1,4 +1,10 @@
 {
+  "redhat7": [
+    "redhat7",
+    "centos7",
+    "oraclelinux7",
+    "rhel7"
+  ],
   "redhat6": [
     "redhat6",
     "centos6",

+ 1 - 1
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/OOZIE/package/scripts/oozie.py

@@ -121,7 +121,7 @@ def oozie_server_specific(
     not_if="ls {pid_file} >/dev/null 2>&1 && !(ps `cat {pid_file}` >/dev/null 2>&1)"
   )
   
-  oozie_server_directorties = [params.oozie_pid_dir, params.oozie_log_dir, params.oozie_tmp_dir, params.oozie_data_dir, params.oozie_lib_dir, params.oozie_webapps_dir, params.oozie_webapps_conf_dir]
+  oozie_server_directorties = [params.oozie_pid_dir, params.oozie_log_dir, params.oozie_tmp_dir, params.oozie_data_dir, params.oozie_lib_dir, params.oozie_webapps_dir, params.oozie_webapps_conf_dir, params.oozie_server_dir]
   Directory( oozie_server_directorties,
     owner = params.oozie_user,
     mode = 0755,

+ 0 - 2
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/OOZIE/package/scripts/params.py

@@ -33,7 +33,6 @@ rpm_version = default("/configurations/cluster-env/rpm_version", None)
 if rpm_version:
   hadoop_bin_dir = "/usr/hdp/current/hadoop/bin"
   hadoop_lib_home = "/usr/hdp/current/hadoop/lib"
-  mapreduce_libs_path = "/usr/hdp/current/hadoop-mapreduce/*"
   oozie_lib_dir = "/usr/hdp/current/oozie/"
   oozie_setup_sh = "/usr/hdp/current/oozie/bin/oozie-setup.sh"
   oozie_webapps_dir = "/usr/hdp/current/oozie/oozie-server/webapps"
@@ -47,7 +46,6 @@ if rpm_version:
 else:
   hadoop_bin_dir = "/usr/bin"
   hadoop_lib_home = "/usr/lib/hadoop/lib"
-  mapreduce_libs_path = "/usr/lib/hadoop-mapreduce/*"
   oozie_lib_dir = "/var/lib/oozie/"
   oozie_setup_sh = "/usr/lib/oozie/bin/oozie-setup.sh"
   oozie_webapps_dir = "/var/lib/oozie/oozie-server/webapps/"

+ 1 - 0
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/ZOOKEEPER/configuration/zookeeper-env.xml

@@ -69,6 +69,7 @@
     <description>This is the jinja template for zookeeper-env.sh file</description>
     <value>
 export JAVA_HOME={{java64_home}}
+export ZOOKEEPER_HOME={{zk_home}}
 export ZOO_LOG_DIR={{zk_log_dir}}
 export ZOOPIDFILE={{zk_pid_file}}
 export SERVER_JVMFLAGS={{zk_server_heapsize}}

+ 2 - 0
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/ZOOKEEPER/package/scripts/params.py

@@ -31,9 +31,11 @@ rpm_version = default("/configurations/cluster-env/rpm_version", None)
 
 #hadoop params
 if rpm_version:
+  zk_home = '/usr/hdp/current/zookeeper'
   zk_bin = '/usr/hdp/current/zookeeper/bin'
   smoke_script = '/usr/hdp/current/zookeeper/bin/zkCli.sh'
 else:
+  zk_home = '/usr'
   zk_bin = '/usr/lib/zookeeper/bin'
   smoke_script = "/usr/lib/zookeeper/bin/zkCli.sh"
 

+ 75 - 0
ambari-server/src/main/resources/stacks/HDP/2.2/services/OOZIE/configuration/oozie-site.xml

@@ -28,5 +28,80 @@
       additional system stress.
     </description>
   </property>
+  <property>
+    <name>oozie.services</name>
+    <value>
+      org.apache.oozie.service.SchedulerService,
+      org.apache.oozie.service.InstrumentationService,
+      org.apache.oozie.service.MemoryLocksService,
+      org.apache.oozie.service.UUIDService,
+      org.apache.oozie.service.ELService,
+      org.apache.oozie.service.AuthorizationService,
+      org.apache.oozie.service.UserGroupInformationService,
+      org.apache.oozie.service.HadoopAccessorService,
+      org.apache.oozie.service.JobsConcurrencyService,
+      org.apache.oozie.service.URIHandlerService,
+      org.apache.oozie.service.DagXLogInfoService,
+      org.apache.oozie.service.SchemaService,
+      org.apache.oozie.service.LiteWorkflowAppService,
+      org.apache.oozie.service.JPAService,
+      org.apache.oozie.service.StoreService,
+      org.apache.oozie.service.CoordinatorStoreService,
+      org.apache.oozie.service.SLAStoreService,
+      org.apache.oozie.service.DBLiteWorkflowStoreService,
+      org.apache.oozie.service.CallbackService,
+      org.apache.oozie.service.ShareLibService,
+      org.apache.oozie.service.CallableQueueService,
+      org.apache.oozie.service.ActionService,
+      org.apache.oozie.service.ActionCheckerService,
+      org.apache.oozie.service.RecoveryService,
+      org.apache.oozie.service.PurgeService,
+      org.apache.oozie.service.CoordinatorEngineService,
+      org.apache.oozie.service.BundleEngineService,
+      org.apache.oozie.service.DagEngineService,
+      org.apache.oozie.service.CoordMaterializeTriggerService,
+      org.apache.oozie.service.StatusTransitService,
+      org.apache.oozie.service.PauseTransitService,
+      org.apache.oozie.service.GroupsService,
+      org.apache.oozie.service.ProxyUserService,
+      org.apache.oozie.service.XLogStreamingService,
+      org.apache.oozie.service.JvmPauseMonitorService
+    </value>
+    <description>
+      All services to be created and managed by Oozie Services singleton.
+      Class names must be separated by commas.
+    </description>
+  </property>
+
+  <property>
+    <name>oozie.service.SchemaService.wf.ext.schemas</name>
+    <value>shell-action-0.1.xsd,shell-action-0.2.xsd,shell-action-0.3.xsd,email-action-0.1.xsd,email-action-0.2.xsd,hive-action-0.2.xsd,hive-action-0.3.xsd,hive-action-0.4.xsd,hive-action-0.5.xsd,sqoop-action-0.2.xsd,sqoop-action-0.3.xsd,sqoop-action-0.4.xsd,ssh-action-0.1.xsd,ssh-action-0.2.xsd,distcp-action-0.1.xsd,distcp-action-0.2.xsd,oozie-sla-0.1.xsd,oozie-sla-0.2.xsd</value>
+  </property>
+
+  <property>
+    <name>oozie.service.AuthorizationService.security.enabled</name>
+    <value>false</value>
+    <description>
+      Specifies whether security (user name/admin role) is enabled or not.
+      If disabled any user can manage Oozie system and manage any job.
+    </description>
+  </property>
+
+  <property>
+    <name>oozie.service.HadoopAccessorService.kerberos.enabled</name>
+    <value>false</value>
+    <description>
+      Indicates if Oozie is configured to use Kerberos.
+    </description>
+  </property>
+
+  <property>
+    <name>oozie.authentication.simple.anonymous.allowed</name>
+    <value>true</value>
+    <description>
+      Indicates if anonymous requests are allowed.
+      This setting is meaningful only when using 'simple' authentication.
+    </description>
+  </property>
 
 </configuration>

+ 17 - 11
ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java

@@ -40,6 +40,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
@@ -74,8 +75,6 @@ import org.apache.ambari.server.security.authorization.AmbariGrantedAuthority;
 import org.apache.ambari.server.view.configuration.InstanceConfig;
 import org.apache.ambari.server.view.configuration.InstanceConfigTest;
 import org.apache.ambari.server.view.configuration.PropertyConfig;
-import org.apache.ambari.server.view.configuration.ResourceConfig;
-import org.apache.ambari.server.view.configuration.ResourceConfigTest;
 import org.apache.ambari.server.view.configuration.ViewConfig;
 import org.apache.ambari.server.view.configuration.ViewConfigTest;
 import org.apache.ambari.server.view.events.EventImpl;
@@ -600,21 +599,28 @@ public class ViewRegistryTest {
 
   @Test
   public void testGetSubResourceDefinitions() throws Exception {
+    ViewConfig config = ViewConfigTest.getConfig();
+
     ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
+
     ViewRegistry registry = ViewRegistry.getInstance();
 
-    ResourceConfig config = ResourceConfigTest.getResourceConfigs().get(0);
-    Resource.Type type1 = new Resource.Type("myType");
+    registry.setupViewDefinition(viewDefinition, config, getClass().getClassLoader());
+
+    Set<SubResourceDefinition> subResourceDefinitions =
+        registry.getSubResourceDefinitions(viewDefinition.getCommonName(), viewDefinition.getVersion());
 
-    ResourceProvider provider1 = createNiceMock(ResourceProvider.class);
-    viewDefinition.addResourceProvider(type1, provider1);
 
-    viewDefinition.addResourceConfiguration(type1, config);
-    registry.addDefinition(viewDefinition);
-    Set<SubResourceDefinition> subResourceDefinitions = registry.getSubResourceDefinitions("MY_VIEW", "1.0.0");
+    Assert.assertEquals(3, subResourceDefinitions.size());
+
+    Set<String> names = new HashSet<String>();
+    for (SubResourceDefinition definition : subResourceDefinitions) {
+      names.add(definition.getType().name());
+    }
 
-    Assert.assertEquals(1, subResourceDefinitions.size());
-    Assert.assertEquals("myType", subResourceDefinitions.iterator().next().getType().name());
+    Assert.assertTrue(names.contains("MY_VIEW{1.0.0}/resources"));
+    Assert.assertTrue(names.contains("MY_VIEW{1.0.0}/resource"));
+    Assert.assertTrue(names.contains("MY_VIEW{1.0.0}/subresource"));
   }
 
   @Test

+ 10 - 0
ambari-server/src/test/python/stacks/2.0.6/OOZIE/test_oozie_server.py

@@ -209,6 +209,11 @@ class TestOozieServer(RMFTestCase):
                               recursive = True,
                               mode = 0755,
                               )
+    self.assertResourceCalled('Directory', '/var/lib/oozie/oozie-server',
+                              owner = 'oozie',
+                              recursive = True,
+                              mode = 0755,
+                              )
     self.assertResourceCalled('Execute', 'cd /usr/lib/oozie && tar -xvf oozie-sharelib.tar.gz',
                               not_if = 'ls /var/run/oozie/oozie.pid >/dev/null 2>&1 && ps `cat /var/run/oozie/oozie.pid` >/dev/null 2>&1',
                               )
@@ -319,6 +324,11 @@ class TestOozieServer(RMFTestCase):
                               recursive = True,
                               mode = 0755,
                               )
+    self.assertResourceCalled('Directory', '/var/lib/oozie/oozie-server',
+                              owner = 'oozie',
+                              recursive = True,
+                              mode = 0755,
+                              )
     self.assertResourceCalled('Execute', 'cd /usr/lib/oozie && tar -xvf oozie-sharelib.tar.gz',
                               not_if = 'ls /var/run/oozie/oozie.pid >/dev/null 2>&1 && ps `cat /var/run/oozie/oozie.pid` >/dev/null 2>&1',
                               )

+ 1 - 1
ambari-web/app/templates/main/service/services/storm.hbs

@@ -19,7 +19,7 @@
 {{view App.SummaryMasterComponentsView mastersCompBinding="view.parentView.mastersObj"}}
 <tr>
   <td>
-    <a href="#" {{action filterHosts view.superVisorComponents.[0]}}>
+    <a href="#" {{action filterHosts view.filterComponent}}>
       {{t dashboard.services.storm.supervisors}}
     </a>
   </td>

+ 8 - 0
ambari-web/app/views/main/service/services/storm.js

@@ -23,6 +23,14 @@ App.MainDashboardServiceStormView = App.MainDashboardServiceView.extend({
   templateName: require('templates/main/service/services/storm'),
   serviceName: 'STORM',
 
+  /**
+   * this parameter is used to fiter hosts by component name
+   * used in mainHostController.filterByComponent() method
+   */
+  filterComponent: function() {
+    return Em.Object.create({componentName: 'SUPERVISOR'});
+  }.property(),
+
   freeSlotsPercentage: function() {
     return Math.round(this.get('service.freeSlots')/this.get('service.totalSlots')*100);
   }.property('service.freeSlots', 'service.totalSlots'),

+ 55 - 34
contrib/views/slider/src/main/resources/ui/app/controllers/slider_app_controller.js

@@ -41,6 +41,49 @@ App.SliderAppController = Ember.ObjectController.extend(App.AjaxErrorHandler, {
     return (Em.get(this.get('model'), 'quickLinks.content.content.length') > 0);
   }.property('model.quickLinks.content.content.length'),
 
+  /**
+   * List of all possible actions for slider app
+   * @type {Em.Object}
+   */
+  appActions: Em.Object.create({
+    stop: {
+      title: 'Stop',
+      action: 'freeze',
+      confirm: true
+    },
+    flex: {
+      title: 'Flex',
+      action: 'flex',
+      confirm: false
+    },
+    destroy: {
+      title: 'Destroy',
+      action: 'destroy',
+      customConfirm: 'confirmDestroy'
+    },
+    start: {
+      title: 'Start',
+      action: 'thaw',
+      confirm: false
+    }
+  }),
+
+  /**
+   * map of available action for slider app according to its status
+   * key - status, value - list of actions
+   * @type {Em.Object}
+   */
+  statusActionsMap: Em.Object.create({
+    NEW: ['stop'],
+    NEW_SAVING: ['stop'],
+    ACCEPTED: ['stop'],
+    RUNNING: ['stop', 'flex'],
+    FINISHED: ['start', 'destroy'],
+    FAILED: ['destroy'],
+    KILLED: ['destroy'],
+    FROZEN: ['start', 'destroy']
+  }),
+
   /**
    * List of available for model actions
    * Based on <code>model.status</code>
@@ -49,40 +92,19 @@ App.SliderAppController = Ember.ObjectController.extend(App.AjaxErrorHandler, {
   availableActions: function() {
     var actions = Em.A([]),
       advanced = Em.A([]),
+      appActions = this.get('appActions'),
+      statusActionsMap = this.get('statusActionsMap'),
       status = this.get('model.status');
-    if ('RUNNING' === status) {
-      actions.pushObject({
-        title: 'Stop',
-        action: 'freeze',
-        confirm: true
-      });
-    }
-    if ('RUNNING' == status) {
-      actions.push({
-        title: 'Flex',
-        action: 'flex',
-        confirm: false
-      });
-    }
-    if ('FROZEN' === status) {
-      actions.pushObject({
-        title: 'Start',
-        action: 'thaw',
-        confirm: false
-      });
-      advanced.pushObject({
-        title: 'Destroy',
-        action: 'destroy',
-        customConfirm: 'confirmDestroy'
-      });
-    }
-    if ('FAILED' === status) {
-      advanced.pushObject({
-        title: 'Destroy',
-        action: 'destroy',
-        customConfirm: 'confirmDestroy'
-      });
-    }
+
+    statusActionsMap[status].forEach(function(action) {
+      if ('destroy' === action) {
+        advanced.pushObject(appActions[action]);
+      }
+      else {
+        actions.pushObject(appActions[action]);
+      }
+    });
+
     if (advanced.length) {
       actions.pushObject({
         title: 'Advanced',
@@ -405,7 +427,6 @@ App.SliderAppController = Ember.ObjectController.extend(App.AjaxErrorHandler, {
           this.tryDoAction();
         }
       }
-      return true;
     }
   }
 

+ 17 - 16
contrib/views/slider/src/main/resources/ui/app/models/slider_app.js

@@ -71,22 +71,22 @@ App.SliderApp = DS.Model.extend({
   /**
    * @type {App.SliderAppComponent[]}
    */
-  components: DS.hasMany('sliderAppComponent', {async:true}),
+  components: DS.hasMany('sliderAppComponent', {async: true}),
 
   /**
    * @type {App.QuickLink[]}
    */
-  quickLinks: DS.hasMany('quickLink', {async:true}),
+  quickLinks: DS.hasMany('quickLink', {async: true}),
 
   /**
    * @type {App.SliderAppAlert[]}
    */
-  alerts: DS.hasMany('sliderAppAlert', {async:true}),
+  alerts: DS.hasMany('sliderAppAlert', {async: true}),
 
   /**
    * @type {App.TypedProperty[]}
    */
-  runtimeProperties: DS.hasMany('typedProperty', {async:true}),
+  runtimeProperties: DS.hasMany('typedProperty', {async: true}),
 
   /**
    * @type {object}
@@ -117,7 +117,7 @@ App.SliderApp = DS.Model.extend({
   /**
    * @type {boolean}
    */
-  doNotShowComponentsAndAlerts: function(){
+  doNotShowComponentsAndAlerts: function () {
     return this.get('status') == "FROZEN" || this.get('status') == "FAILED";
   }.property('status', 'components', 'alerts'),
 
@@ -125,7 +125,7 @@ App.SliderApp = DS.Model.extend({
    * Display metrics only for running apps
    * @type {boolean}
    */
-  showMetrics: function() {
+  showMetrics: function () {
     var global = this.get('configs')['global'];
     if (App.get('gangliaHost') != null) {
       return true;
@@ -138,9 +138,9 @@ App.SliderApp = DS.Model.extend({
    * @param {object} o
    * @returns {{key: string, value: *}[]}
    */
-  mapObject: function(o) {
+  mapObject: function (o) {
     if (Ember.typeOf(o) !== 'object') return [];
-    return Ember.keys(o).map(function(key) {
+    return Ember.keys(o).map(function (key) {
       return {
         key: key,
         value: o[key],
@@ -154,12 +154,13 @@ App.SliderApp = DS.Model.extend({
 App.SliderApp.FIXTURES = [];
 
 App.SliderApp.Status = {
-    accepted: "ACCEPTED",
-    failed: "FAILED",
-    finished: "FINISHED",
-    killed: "KILLED",
-    new: "NEW",
-    new_saving: "NEW_SAVING",
-    running: "RUNNING" ,
-    submitted:"SUBMITTED"
+  accepted: "ACCEPTED",
+  failed: "FAILED",
+  finished: "FINISHED",
+  killed: "KILLED",
+  new: "NEW",
+  new_saving: "NEW_SAVING",
+  running: "RUNNING",
+  submitted: "SUBMITTED",
+  frozen: "FROZEN"
 };

+ 12 - 1
contrib/views/slider/src/main/resources/ui/test/integration/pages/index_test.js

@@ -44,7 +44,7 @@ test('sliderConfigs', function () {
 
   visit('/');
   // configs count may be changed by adding new slider-configs
-  equal(App.SliderApp.store.all('sliderConfig').content.length, 2, 'slider configs should be set');
+  equal(App.SliderApp.store.all('sliderConfig').content.length, 3, 'slider configs should be set');
 
 });
 
@@ -59,4 +59,15 @@ test('Create-App button', function () {
     equal(currentURL(), '/createAppWizard/step1', 'url is valid');
   });
 
+});
+
+test('Create-App button visible/hidden', function () {
+
+  Em.run(function () {
+    App.__container__.lookup('controller:application').set('hasConfigErrors', true);
+  });
+
+  visit('/');
+  equal(find('.create-app').length, 0, 'Create App button should be hidden if some config errors');
+
 });

+ 64 - 0
contrib/views/slider/src/main/resources/ui/test/unit/controllers/slider_app_controller_test.js

@@ -0,0 +1,64 @@
+/**
+ * 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.
+ */
+
+moduleFor('controller:sliderApp', 'App.SliderAppController');
+
+test('availableActions', function () {
+
+  var controller = this.subject({model: Em.Object.create({status: ''})});
+  controller.set('model.status', App.SliderApp.Status.accepted);
+  deepEqual(controller.get('availableActions').mapBy('action'), ['freeze'], 'actions for ACCEPTED');
+
+  Em.run(function () {
+    controller.set('model.status', App.SliderApp.Status.failed);
+  });
+  deepEqual(controller.get('availableActions').findBy('title', 'Advanced').submenu.mapBy('action'), ['destroy'], 'actions for FAILED');
+
+  Em.run(function () {
+    controller.set('model.status', App.SliderApp.Status.finished);
+  });
+  deepEqual(controller.get('availableActions').findBy('title', 'Advanced').submenu.mapBy('action'), ['destroy'], 'actions for FINISHED');
+  ok(controller.get('availableActions').mapBy('action').contains('thaw'), 'actions for FINISHED (2)');
+
+  Em.run(function () {
+    controller.set('model.status', App.SliderApp.Status.killed);
+  });
+  deepEqual(controller.get('availableActions').findBy('title', 'Advanced').submenu.mapBy('action'), ['destroy'], 'actions for KILLED');
+
+  Em.run(function () {
+    controller.set('model.status', App.SliderApp.Status.new);
+  });
+  deepEqual(controller.get('availableActions').mapBy('action'), ['freeze'], 'actions for NEW');
+
+  Em.run(function () {
+    controller.set('model.status', App.SliderApp.Status.new_saving);
+  });
+  deepEqual(controller.get('availableActions').mapBy('action'), ['freeze'], 'actions for NEW_SAVING');
+
+  Em.run(function () {
+    controller.set('model.status', App.SliderApp.Status.running);
+  });
+  deepEqual(controller.get('availableActions').mapBy('action'), ['freeze', 'flex'], 'actions for RUNNING');
+
+  Em.run(function () {
+    controller.set('model.status', App.SliderApp.Status.frozen);
+  });
+  deepEqual(controller.get('availableActions').findBy('title', 'Advanced').submenu.mapBy('action'), ['destroy'], 'actions for FROZEN');
+  ok(controller.get('availableActions').mapBy('action').contains('thaw'), 'actions for FROZEN (2)');
+
+});