from org.codehaus.jettison.json import JSONObject, JSONArray
import sys;
import AdminTask;  # @UnresolvedImport
from WASConfLog import Log;
from utilities import Util
from ClusterMember import ClusterMember
from Server import Server
from Property import Property

__name_att__ = "websphere.dynamiccluster.name"

def export(objid, parentcontainmentpath, parentrespath):

  name = Util.getRequiredAttribute(objid, "name", 'DynamicCluster');

  containmentpath = "%(parentconpath)sDynamicCluster:%(name)s/" % {'parentconpath':parentcontainmentpath, 'name':name }
  if not containmentpath.startswith("/"):
    containmentpath = "/" + containmentpath;

  dict = _export(objid, parentrespath, parentcontainmentpath);
  dict['conpath'] = containmentpath;
  return dict

def _export(objid, parentrespath, containmentpath):
  Util.pushPathElement('DynamicCluster')

  name = Util.getRequiredAttribute(objid, "name", 'DynamicCluster');


  if parentrespath == "/":
    parentrespath = "";
  respath = "%(parentrespath)s/%(name)s" % { 'parentrespath':parentrespath, 'name':name }
  if not respath.startswith("/"):
    respath = "/" + respath;

  exportedObject = JSONObject();
  exportedObject.put("name", name);
  exportedObject.put("path", respath);
  exportedObject.put("teamMappings", JSONArray());
  exportedObject.put("inheritTeam", "true");
  exportedObject.put("description", "Discovered WebSphereDynamicCluster");
  exportedObject.put("roleName", "WebSphereDynamicCluster");

  roleProperties = JSONObject();

  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.dynamiccluster.minnodes", objid, "minNodes","DynamicCluster");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.dynamiccluster.name", objid, "name","DynamicCluster");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.dynamiccluster.membershippolicy", objid, "membershipPolicy","DynamicCluster");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.dynamiccluster.mininstances", objid, "minInstances","DynamicCluster");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.dynamiccluster.isolationgroup", objid, "isolationGroup","DynamicCluster");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.dynamiccluster.maxinstances", objid, "maxInstances","DynamicCluster");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.dynamiccluster.strictisolationenabled", objid, "strictIsolationEnabled","DynamicCluster");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.dynamiccluster.servertype", objid, "serverType","DynamicCluster");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.dynamiccluster.serverinactivitytime", objid, "serverInactivityTime","DynamicCluster");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.dynamiccluster.operationalmode", objid, "operationalMode","DynamicCluster");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.dynamiccluster.maxnodes", objid, "maxNodes","DynamicCluster");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.dynamiccluster.numverticalinstances", objid, "numVerticalInstances","DynamicCluster");
  exportedObject.put("roleProperties", roleProperties);
  result = { 'object': exportedObject, 'respath':respath }
  extraObjects = [];
  typeFolders = {};

  # get the server template, which is a Server object
  dcServerTemplate = Util.getAssociatedObjects(objid, "Server");
  if dcServerTemplate is not None and len(dcServerTemplate) > 0:
    Log.logMsg("Found a dynamic cluster server template: " + str(dcServerTemplate[0]), Log.LogLevelDebug);
    returndict = Util.createTypeFolder(respath, "DynamicClusterServerTemplate", typeFolders);
    currespath = returndict['path'];
    if returndict.has_key('object'):
      Util.addFromExport(extraObjects, returndict['object']);
    Util.addAllFromExport(extraObjects, Server.export(dcServerTemplate[0], containmentpath, currespath, 1));

  extraObjects = Property.exportProperties(objid, respath, extraObjects, typeFolders, 'properties',"DynamicCluster");

  members = Util.parseConfigIdListAttribute(objid, 'members', "DynamicCluster");
  for member in members:
    if len(member) > 0:
      returndict = Util.createTypeFolder(respath, "ClusterMember", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, ClusterMember._export(member, currespath));

  if len(extraObjects) != 0:
    result['extraObjects'] = extraObjects;
  Util.popPathElement('DynamicCluster');
  return result;



def doImport(containmentpath, roleName, jsonobject):
  if not jsonobject.has("roleProperties"):
    raise Exception("DynamicCluster resource has no role properties!");

  roleProperties = jsonobject.getJSONObject("roleProperties");
  if not roleProperties.has("websphere.dynamiccluster.name"):
    raise Exception("Resource role properties does not contain websphere.dynamiccluster.name!");

  objid = Util.getid(containmentpath);
  if objid == None or len(objid) == 0:
    parentconpath = "/Cell:/";
    parentid = Util.getid(parentconpath);
    if parentid == None or len(parentid) == 0:
      raise Exception("Parent does not exist to create DynamicCluster on.");
    objid = create(parentid, jsonobject, containmentpath);
  else:
    update(objid,jsonobject, containmentpath);
  return objid;



def create(parentid, jsonobject, containmentpath = None):
  Util.pushPathElement('DynamicCluster')
  if not jsonobject.has("roleProperties"):
    raise Exception("DynamicCluster resource has no role properties!");


  roleProperties = jsonobject.getJSONObject("roleProperties");

  if not roleProperties.has("websphere.dynamiccluster.name"):
    raise Exception("Resource role properties does not contain websphere.dynamiccluster.name!");

  clusterName = roleProperties.optString("websphere.dynamiccluster.name", None);

  membershipPolicy = roleProperties.optString("websphere.dynamiccluster.membershippolicy", None);
  if (membershipPolicy is None or len(membershipPolicy)==0):
    membershipPolicy = "\"node_nodegroup = \'DefaultNodeGroup\'\"";
  else:
    groupnameIndex = membershipPolicy.index("=");
    groupname = membershipPolicy[groupnameIndex+1:len(membershipPolicy)];
    groupname.strip();
    membershipPolicy = "\"node_nodegroup =%s\"" % groupname;

  properties = [];
  operationalMode = roleProperties.optString("websphere.dynamiccluster.operationalmode", None);
  if (operationalMode is None or len(operationalMode)==0):
     Util.addIfNotNone(properties, "operationalMode", "automatic");
  else:
     Util.addIfNotNone(properties, "operationalMode", operationalMode);
  Util.addIfNotNone(properties, "minInstances", roleProperties.optString("websphere.dynamiccluster.mininstances", None));
  Util.addIfNotNone(properties, "maxInstances", roleProperties.optString("websphere.dynamiccluster.maxinstances", None));
  Util.addIfNotNone(properties, "serverInactivityTime", roleProperties.optString("websphere.dynamiccluster.serverinactivitytime", None));
  Util.addIfNotNone(properties, "numVerticalInstances", roleProperties.optString("websphere.dynamiccluster.numverticalinstances", None));

  finString = Util._genStringFromPropertiesNoQuotes(properties);
  Log.log("Creating dynamic cluster with name %(name)s, membershipPolicy set to %(policy)s and dynamicClusterProperties of %(finalProps)s" % {'name':clusterName, 'policy':membershipPolicy, 'finalProps':finString} );
  AdminTask.createDynamicCluster(clusterName,'[-membershipPolicy %(policy)s \
                                          -dynamicClusterProperties "%(finalProps)s"]' % {'policy':membershipPolicy, 'finalProps':finString} );
  objid = Util.getid("/DynamicCluster:%s/" % clusterName);
  Log.log("Dynmamic Cluster objid: %s" % objid);

  #The following properties are not supported by the AdminTask approach to creating dynamic clusters so we will update them using a modify command.
  atts = [];
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.dynamiccluster.minnodes", None), "minNodes","DynamicCluster");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.dynamiccluster.isolationgroup", None), "isolationGroup","DynamicCluster");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.dynamiccluster.strictisolationenabled", None), "strictIsolationEnabled","DynamicCluster");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.dynamiccluster.servertype", None), "serverType","DynamicCluster");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.dynamiccluster.maxnodes", None), "maxNodes","DynamicCluster");
  if len(atts) != 0:
    print "Modifying DynamicCluster with attributes:"
    for prop in atts:
      print "%(name)s = %(value)s" % { 'name': prop[0], 'value': prop[1] };

    Util.modify(objid, atts);

  if jsonobject.has('children'):
    for curjsonobject in Util.getHighestChildrenWithRole(jsonobject.getJSONArray('children')):
      currole = curjsonobject.getString("roleName");
      if currole == "WebSphereClusterMember":
        ClusterMember.create(objid, curjsonobject);
      elif currole == "WebSphereDynamicClusterServerTemplate":
          # Usually, a server template is specified as part of the AdminTask.createDynamicCluster command.
          # We currently don't do that when creating a dynamic cluster.
          # If we don't specify a server template, it appears we get a default server template.
          # Let's modify that server template with our configuration data for our server template.
          # A dynamic server template is an object of type Server in WCCM
          # More info: https://www.ibm.com/support/knowledgecenter/SSEQTP_8.5.5/com.ibm.websphere.nd.doc/ae/rwve_adtaskdc.html
          #
          # get the objid of the server template
          dcServerTemplateContainmentPath = "/DynamicCluster:%(clusterName)s/Server:%(clusterName)s/" % {'clusterName':clusterName}
          dcServerTemplate = Util.getid(dcServerTemplateContainmentPath);
          Server.update(dcServerTemplate, curjsonobject, containmentpath, 1, dcServerTemplateContainmentPath);
      else:
        propertyObject = Property.createObjIfRole(objid, curjsonobject, currole);

  Util.popPathElement('DynamicCluster');

  return objid;

def update(objid,jsonobject, containmentpath = None):
  Util.pushPathElement('DynamicCluster')
  if not jsonobject.has("roleProperties"):
    raise Exception("DynamicCluster resource has no role properties!");

  roleProperties = jsonobject.getJSONObject("roleProperties");

  if not roleProperties.has("websphere.dynamiccluster.name"):
    raise Exception("Resource role properties does not contain websphere.dynamiccluster.name!");

  clusterName = roleProperties.optString("websphere.dynamiccluster.name", None);

  atts = [];
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.dynamiccluster.minnodes", None), "minNodes","DynamicCluster");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.dynamiccluster.name", None), "name","DynamicCluster");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.dynamiccluster.membershippolicy", None), "membershipPolicy","DynamicCluster");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.dynamiccluster.mininstances", None), "minInstances","DynamicCluster");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.dynamiccluster.isolationgroup", None), "isolationGroup","DynamicCluster");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.dynamiccluster.maxinstances", None), "maxInstances","DynamicCluster");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.dynamiccluster.strictisolationenabled", None), "strictIsolationEnabled","DynamicCluster");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.dynamiccluster.servertype", None), "serverType","DynamicCluster");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.dynamiccluster.serverinactivitytime", None), "serverInactivityTime","DynamicCluster");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.dynamiccluster.operationalmode", None), "operationalMode","DynamicCluster");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.dynamiccluster.maxnodes", None), "maxNodes","DynamicCluster");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.dynamiccluster.numverticalinstances", None), "numVerticalInstances","DynamicCluster");
  if len(atts) != 0:
    print "Modifying DynamicCluster with attributes:"
    for prop in atts:
      print "%(name)s = %(value)s" % { 'name': prop[0], 'value': prop[1] };

    Util.modify(objid, atts);
  else:
    print "DynamicCluster configuration up to date.";

  Property.removeProperties(objid, 'properties',"DynamicCluster");

  if jsonobject.has('children'):
    for curjsonobject in Util.getHighestChildrenWithRole(jsonobject.getJSONArray('children')):
      currole = curjsonobject.getString("roleName");
      if currole == "WebSphereClusterMember":
        # We can't delete all ClusterMembers and recreate them.
        # Instead, we need to update existing ones.
        # However, multiple cluster members can have the same name.
        # So, we have to do some ugly stuff to see if our ClusterMember already exist.
        # If they do exist, update them. If they don't exist, create them.
        cmobjid = "";
        roleProperties = curjsonobject.getJSONObject("roleProperties");
        targetNodeName = roleProperties.optString("websphere.clustermember.nodename", None);
        targetMemberName = roleProperties.optString("websphere.clustermember.membername", None);
        if targetNodeName != None and len(targetNodeName) > 0:
          # get all ClusterMembers
          members = Util.parseConfigIdListAttribute(objid, 'members', 'DynamicCluster');
          for member in members:
            # see if the nodeName and membername attribute matches
            actualNodeName = Util.getRequiredAttribute(member, "nodeName", 'ClusterMember');
            actualMemberName = Util.getRequiredAttribute(member, "memberName", 'ClusterMember');
            if actualNodeName == targetNodeName and targetMemberName == actualMemberName:
              cmobjid = member;
              break;
        if cmobjid != "":
          ClusterMember.update(cmobjid, curjsonobject);
        else:
          ClusterMember.create(objid, curjsonobject);
      elif currole == "WebSphereDynamicClusterServerTemplate":
          # Usually, a server template is specified as part of the AdminTask.createDynamicCluster command.
          # We currently don't do that when creating a dynamic cluster.
          # If we don't specify a server template, it appears we get a default server template.
          # Let's modify that server template with our configuration data for our server template.
          # A dynamic server template is an object of type Server in WCCM
          # More info: https://www.ibm.com/support/knowledgecenter/SSEQTP_8.5.5/com.ibm.websphere.nd.doc/ae/rwve_adtaskdc.html
          #
          # get the objid of the server template, then update it
          dcServerTemplateContainmentPath = "/DynamicCluster:%(clusterName)s/Server:%(clusterName)s/" % {'clusterName':clusterName}
          dcServerTemplate = Util.getid(dcServerTemplateContainmentPath);
          Server.update(dcServerTemplate, curjsonobject, containmentpath, 1, dcServerTemplateContainmentPath);
      else:
        propertyObject = Property.createObjIfRole(objid, curjsonobject, currole);
  Util.popPathElement('DynamicCluster');
