package org.dataone.integration.it.testImplementations; import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import org.apache.commons.collections.IteratorUtils; import org.dataone.integration.ContextAwareTestCaseDataone; import org.dataone.integration.adapters.CNCallAdapter; import org.dataone.integration.adapters.MNCallAdapter; import org.dataone.integration.webTest.WebTestDescription; import org.dataone.integration.webTest.WebTestName; import org.dataone.service.types.v1.Node; import org.dataone.service.types.v1.NodeState; import org.dataone.service.types.v1.NodeType; import org.dataone.service.types.v1.Service; import org.dataone.service.types.v1.Services; import org.dataone.service.types.v2.NodeList; import org.junit.Before; import org.junit.Test; public class EnvironmentStatusTestImpl extends ContextAwareTestCaseDataone { private List cns; private NodeList cnNodeList; /** v1-ONLY MNs */ private List v1mns; /** v2-ONLY MNs */ private List v2mns; /** v1 AND v2 MNs */ private List v1v2mns; /** all MNs */ private List mns; private boolean setup = false; @Before public void setup() throws Exception { if(!setup) { // only run once, but still test assertions at end @Before each test case cns = new ArrayList(); mns = new ArrayList(); v1mns = new ArrayList(); v2mns = new ArrayList(); v1v2mns = new ArrayList(); Iterator cnIter = getCoordinatingNodeIterator(); if(cnIter != null) cns = IteratorUtils.toList(cnIter); assertTrue("Setup failed! Test requires at least one CN to function.", cns.size() > 0); CNCallAdapter cn = new CNCallAdapter(getSession(cnSubmitter), cns.get(0), "v2"); try { log.info("Fetching NodeList from CN: " + cn.getNodeBaseServiceUrl()); cnNodeList = cn.listNodes(); } catch (Exception e) { log.error("FAILED setup, unable to fetch node list from CN: " + cn.getNodeBaseServiceUrl(), e); throw e; } for(Node n : cnNodeList.getNodeList()) { if(n.getType() != NodeType.MN) continue; log.info("Checking capabilities for MN: " + n.getBaseURL()); MNCallAdapter v1MN = new MNCallAdapter(getSession(cnSubmitter), n, "v1"); MNCallAdapter v2MN = new MNCallAdapter(getSession(cnSubmitter), n, "v2"); Node v1Capabilities = null; Node v2Capabilities = null; try { v1Capabilities = v1MN.getCapabilities(); log.info("success for v1 MN.getCapabilities() on: " + v1MN.getLatestRequestUrl()); } catch (Exception v1e) { log.error("FAILED v1 MN.getCapabilities() on: " + v1MN.getLatestRequestUrl()); } try { v2Capabilities = v2MN.getCapabilities(); log.info("success for v2 MN.getCapabilities() on: " + v2MN.getLatestRequestUrl()); } catch (Exception v2e) { log.error("FAILED v2 MN.getCapabilities() on: " + v2MN.getLatestRequestUrl()); } if (v1Capabilities != null && v2Capabilities == null) { log.info("adding v1 MN: " + v1Capabilities.getBaseURL()); v1mns.add(v1Capabilities); mns.add(v1Capabilities); } if (v2Capabilities != null && v1Capabilities == null) { log.info("adding v2 MN: " + v2Capabilities.getBaseURL()); v2mns.add(v2Capabilities); mns.add(v2Capabilities); } if (v1Capabilities != null && v2Capabilities != null) { log.info("adding v1/v2 MN: " + v2Capabilities.getBaseURL()); v1v2mns.add(v2Capabilities); mns.add(v2Capabilities); } } setup = true; } assertTrue("FAILED setup, found zero CNs.", cns.size() != 0); } @Override protected String getTestDescription() { return "Various checks for the current environment - stuff like whether all nodes can be pinged, or CN / MN node doc consistency."; } @Test @WebTestName("ping environment nodes") @WebTestDescription("Tests whether the nodes listed for the environment can be pinged and are up. " + "For MNs, disregards whether they are registered as v1 or v2 nodes with the CN " + "and pings both endpoints.") public void checkNodes() { ArrayList errors = new ArrayList(); log.info("======================================================================"); log.info("pinging CNs..."); for (Node node : cnNodeList.getNodeList()) { if (node.getType() != NodeType.CN) continue; log.info("pinging CN: " + node.getBaseURL()); CNCallAdapter cn = new CNCallAdapter(getSession(cnSubmitter), node, "v2"); try { cn.ping(); log.info("success pinging " + node.getBaseURL()); } catch (Exception e) { log.error("ERROR: failed pinging " + node.getBaseURL()); errors.add("ERROR: failed pinging " + node.getBaseURL()); } } log.info("pinging MNs..."); for (Node node : cnNodeList.getNodeList()) { if (node.getType() != NodeType.MN) continue; if (node.getState() == NodeState.DOWN) { log.warn("WARNING: CN has Node state as DOWN for: " + node.getBaseURL()); errors.add("WARNING: CN has Node state as DOWN for: " + node.getBaseURL()); continue; } else if (node.getState() == NodeState.UNKNOWN) { log.warn("WARNING: CN has Node state as UNKNOWN for: " + node.getBaseURL()); errors.add("WARNING: CN has Node state as UNKNOWN for: " + node.getBaseURL()); } else if (node.getState() == NodeState.UP) { log.info("CN has Node state as UP for: " + node.getBaseURL()); } log.info("pinging MN: " + node.getBaseURL()); boolean pingV1 = true; boolean pingV2 = true; Services services = node.getServices(); boolean foundV1Service = false; boolean foundV2Service = false; if (services == null) { log.error("ERROR: null services for " + node.getBaseURL()); errors.add("ERROR: null services for " + node.getBaseURL()); } else { for (Service s : services.getServiceList()) { String ver = s.getVersion(); if (ver.equalsIgnoreCase("v1")) foundV1Service = true; else if (ver.equalsIgnoreCase("v2")) foundV2Service = true; } if (!foundV1Service) pingV1 = false; if (!foundV2Service) pingV2 = false; } if (pingV1) try { MNCallAdapter mn = new MNCallAdapter(getSession(cnSubmitter), node, "v1"); mn.ping(); log.info("success pinging v1 endpoint " + node.getBaseURL()); } catch (Exception e) { log.error("WARNING: failed pinging v1 endpoint " + node.getBaseURL()); errors.add("WARNING: failed pinging v1 endpoint " + node.getBaseURL()); } if (pingV2) try { MNCallAdapter mn = new MNCallAdapter(getSession(cnSubmitter), node, "v2"); mn.ping(); log.error("success pinging v2 endpoint " + node.getBaseURL()); } catch (Exception e) { log.error("WARNING: failed pinging v2 endpoint " + node.getBaseURL()); errors.add("WARNING: failed pinging v2 endpoint " + node.getBaseURL()); } } outputResults(errors); } @Test @WebTestName("replication enabled on MNs") @WebTestDescription("Tests whether replicate is enabled on the MNs in the environment. " + "Compares replicate status in CN NodeList to MN's Node capabilities for consistency.") public void replicationEnabled() { ArrayList errors = new ArrayList(); log.info("======================================================================"); for (Node mNode : cnNodeList.getNodeList()) { if (mNode.getType() != NodeType.MN) continue; log.info("checking replicate capabilities of MN: " + mNode.getBaseURL()); boolean replicateCnCap = mNode.isReplicate(); if (!replicateCnCap) errors.add("WARNING: replication is off for MN " + mNode.getBaseURL() + " in CN NodeList (" + cns.get(0).getBaseURL() + ")"); Node capabilities = null; for (Node n : mns) if (n.getIdentifier().equals(mNode.getIdentifier())) { capabilities = n; break; } if (capabilities == null) { log.error("ERROR: Unable to get Node capabilities from MN: " + mNode.getBaseURL()); errors.add("ERROR: Unable to get Node capabilities from MN: " + mNode.getBaseURL()); continue; } boolean replicateMnCap = capabilities.isReplicate(); if (!replicateMnCap) errors.add("WARNING: replication is off for MN " + mNode.getBaseURL() + " in MN's Node capabilities."); if (replicateCnCap != replicateMnCap) errors.add("ERROR: replication status is inconsistent between MN (" + mNode.getBaseURL() + ") and CN (" + cns.get(0).getBaseURL() + ")"); } outputResults(errors); } @Test @WebTestName("synchronize enabled on MNs") @WebTestDescription("Tests whether synchronize is enabled on the MNs in the environment. " + "Compares synchronize status in CN NodeList to MN's Node capabilities for consistency.") public void checkSynchronize() { ArrayList errors = new ArrayList(); log.info("======================================================================"); for (Node mNode : cnNodeList.getNodeList()) { if (mNode.getType() != NodeType.MN) continue; log.info("checking synchronize capabilities of MN: " + mNode.getBaseURL()); boolean synchronizeCnCap = mNode.isSynchronize(); if (!synchronizeCnCap) errors.add("WARNING: syncronize is off for MN " + mNode.getBaseURL() + " in CN NodeList (" + cns.get(0).getBaseURL() + ")"); Node capabilities = null; for (Node n : mns) if (n.getIdentifier().equals(mNode.getIdentifier())) { capabilities = n; break; } if (capabilities == null) { log.error("ERROR: Unable to get Node capabilities from MN: " + mNode.getBaseURL()); errors.add("ERROR: Unable to get Node capabilities from MN: " + mNode.getBaseURL()); continue; } boolean synchronizeMnCap = capabilities.isSynchronize(); if (!synchronizeMnCap) errors.add("WARNING: synchronization is off for MN " + mNode.getBaseURL() + " in MN's Node capabilities."); if (synchronizeCnCap != synchronizeMnCap) errors.add("ERROR: synchronize status is inconsistent between MN (" + mNode.getBaseURL() + ") and CN (" + cns.get(0).getBaseURL() + ")"); } outputResults(errors); } @Test @WebTestName("CN / MN service consistency") @WebTestDescription("Tests whether the copies of the Node documents on the CN match those on the MNs " + "in terms of the Services.") public void cnMnServiceConsistency() { ArrayList errors = new ArrayList(); log.info("======================================================================"); for (Node mNode : cnNodeList.getNodeList()) { if (mNode.getType() != NodeType.MN) continue; log.info("checking Services of MN: " + mNode.getBaseURL()); Services servicesCN = mNode.getServices(); if (servicesCN == null) { log.error("ERROR: Services are NULL for MN " + mNode.getBaseURL()); errors.add("ERROR: Services are NULL for MN " + mNode.getBaseURL()); } Node capabilities = null; for (Node n : mns) if (n.getIdentifier().equals(mNode.getIdentifier())) { capabilities = n; break; } if (capabilities == null) { log.error("ERROR: Unable to get Node capabilities from MN: " + mNode.getBaseURL()); errors.add("ERROR: Unable to get Node capabilities from MN: " + mNode.getBaseURL()); continue; } Services servicesMN = capabilities.getServices(); if (servicesMN == null) { log.error("ERROR: Services are NULL for MN " + mNode.getBaseURL()); errors.add("ERROR: Services are NULL for MN " + mNode.getBaseURL()); } if (servicesCN == null || servicesMN == null) continue; HashMap servicesMapCN = new HashMap(); HashMap servicesMapMN = new HashMap(); for (Service srvMN : servicesMN.getServiceList()) servicesMapMN.put(srvMN.getVersion() + "." + srvMN.getName(), srvMN.getAvailable()); for (Service srvCN : servicesCN.getServiceList()) servicesMapCN.put(srvCN.getVersion() + "." + srvCN.getName(), srvCN.getAvailable()); for (String s : servicesMapMN.keySet()) log.debug("MN service: " + s); for (String s : servicesMapCN.keySet()) log.debug("CN service: " + s); if (!servicesMapCN.keySet().containsAll(servicesMapMN.keySet())) { log.warn("WARNING: the CN (" + cns.get(0).getBaseURL() + ") does not contain all Services for MN (" + mNode.getBaseURL() + ") that the MN has listed in its Node document." ); errors.add("WARNING: the CN (" + cns.get(0).getBaseURL() + ") does not contain all Services for MN (" + mNode.getBaseURL() + ") that the MN has listed in its Node document." ); for (String s : servicesMapMN.keySet()) { if (!servicesMapCN.containsKey(s)) { log.warn("The CN (" + cns.get(0).getBaseURL() + ") does not contain " + "the " + s + " service from the MN (" + mNode.getBaseURL() + ")"); errors.add("The CN (" + cns.get(0).getBaseURL() + ") does not contain " + "the " + s + " service from the MN (" + mNode.getBaseURL() + ")"); } } } if (!servicesMapMN.keySet().containsAll(servicesMapCN.keySet())) { log.warn("WARNING: the MN (" + cns.get(0).getBaseURL() + ") does not contain all Services for MN (" + mNode.getBaseURL() + ") that the CN has listed."); errors.add("WARNING: the MN (" + cns.get(0).getBaseURL() + ") does not contain all Services for MN (" + mNode.getBaseURL() + ") that the CN has listed."); for (String s : servicesMapCN.keySet()) { if (!servicesMapMN.containsKey(s)) { log.warn("The MN (" + mNode.getBaseURL() + ") does not contain " + "the " + s + " service from the CN (" + cns.get(0).getBaseURL() + ")"); errors.add("The MN (" + mNode.getBaseURL() + ") does not contain " + "the " + s + " service from the CN (" + cns.get(0).getBaseURL() + ")"); } } } } outputResults(errors); } private void outputResults(ArrayList errors) { String results = ""; if (errors.size() > 0) { results += "----------------------------------------------------------------------\n"; results += "Results: \n"; for (String string : errors) { results += "\t" + string + "\n"; } log.error(results); } assertTrue("Test contained errors or warnings:\n" + results, errors.size() == 0); } }