Example #1
0
int main(void) {

  Arc::Logger logger(Arc::Logger::rootLogger, "Test");
  Arc::LogStream logcerr(std::cerr);
  Arc::Logger::rootLogger.addDestination(logcerr);
  logger.msg(Arc::INFO, "Creating client side chain");

  std::string id;
  std::string url("https://localhost/arex");
  Arc::NS ns("a-rex", "http://www.nordugrid.org/schemas/a-rex");
  Arc::MCCConfig cfg;
  Arc::UserConfig uc;
  uc.ApplyToConfig(cfg);

  Arc::ClientSOAP client(cfg, url, 60);
  std::string faultstring;

  Arc::PayloadSOAP request(ns);
  Arc::XMLNode req = request.NewChild("a-rex:CacheCheck").NewChild("a-rex:TheseFilesNeedToCheck");
  req.NewChild("a-rex:FileURL") = "http://example.org/test.txt";

  Arc::PayloadSOAP* response;

  Arc::MCC_Status status = client.process(&request, &response);

  if (!status) {
    std::cerr << "Request failed" << std::endl;
  }

  std::string str;
  response->GetDoc(str, true);
  std::cout << str << std::endl;

  return 0;
}
Example #2
0
Arc::MCC_Status ARexService::ESWipeActivity(ARexGMConfig& config,Arc::XMLNode in,Arc::XMLNode out) {
  /*
    esmanag:WipeActivity
      estypes:ActivityID

    esmanag:WipeActivityResponse
      esmanag:WipeActivityResponseItem
        estypes:ActivityID
        .
          esmanag:EstimatedTime (xsd:unsignedLong)
          estypes:InternalBaseFault
          OperationNotPossibleFault
          OperationNotAllowedFault
          ActivityNotFoundFault
          AccessControlFault

    estypes:VectorLimitExceededFault
    estypes:AccessControlFault
    estypes:InternalBaseFault
  */
  Arc::XMLNode id = in["ActivityID"];
  unsigned int n = 0;
  for(;(bool)id;++id) {
    if((++n) > MAX_ACTIVITIES) {
       Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"");
      ESVectorLimitExceededFault(fault,MAX_ACTIVITIES,"Too many ActivityID");
      out.Destroy();
      return Arc::MCC_Status(Arc::STATUS_OK);
    };
  };
  id = in["ActivityID"];
  for(;(bool)id;++id) {
    std::string jobid = id;
    Arc::XMLNode item = out.NewChild("esmanag:WipeActivityResponseItem");
    item.NewChild("estypes:ActivityID") = jobid;
    ARexJob job(jobid,config,logger_);
    if(!job) {
      // There is no such job
      logger_.msg(Arc::ERROR, "EMIES:WipeActivity: job %s - %s", jobid, job.Failure());
      ESActivityNotFoundFault(item.NewChild("dummy"),job.Failure());
    } else {
      if((job.State() != "FINISHED") &&
         (job.State() != "DELETED")) {
        logger_.msg(Arc::ERROR, "EMIES:WipeActivity: job %s - state is %s, not terminal", jobid, job.State());
        ESOperationNotAllowedFault(item.NewChild("dummy"),"Not in terminal state");
      } else if(!job.Clean()) {
        // Probably wrong current state
        logger_.msg(Arc::ERROR, "EMIES:WipeActivity: job %s - %s", jobid, job.Failure());
        // TODO: check for real reason
        ESOperationNotAllowedFault(item.NewChild("dummy"),job.Failure());
      } else {
        item.NewChild("esmanag:EstimatedTime") = Arc::tostring(config.GmConfig().WakeupPeriod());
      };
    };
  };
  return Arc::MCC_Status(Arc::STATUS_OK);
}
Example #3
0
Arc::MCC_Status ARexService::ESCancelActivity(ARexGMConfig& config,Arc::XMLNode in,Arc::XMLNode out) {
  /*
    CancelActivity
      estypes:ActivityID 1-

    CancelActivityResponse
      CancelActivityResponseItem 1-
        estypes:ActivityID
        .
          EstimatedTime 0-1
          estypes:InternalBaseFault
          OperationNotPossibleFault
          OperationNotAllowedFault
          ActivityNotFoundFault
          AccessControlFault

    estypes:VectorLimitExceededFault
    estypes:AccessControlFault
    estypes:InternalBaseFault
   */
  Arc::XMLNode id = in["ActivityID"];
  unsigned int n = 0;
  for(;(bool)id;++id) {
    if((++n) > MAX_ACTIVITIES) {
      Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"");
      ESVectorLimitExceededFault(fault,MAX_ACTIVITIES,"Too many ActivityID");
      out.Destroy();
      return Arc::MCC_Status(Arc::STATUS_OK);
    };
  };
  id = in["ActivityID"];
  for(;(bool)id;++id) {
    std::string jobid = id;
    Arc::XMLNode item = out.NewChild("esmanag:CancelActivityResponseItem");
    item.NewChild("estypes:ActivityID") = jobid;
    ARexJob job(jobid,config,logger_);
    if(!job) {
      // There is no such job
      logger_.msg(Arc::ERROR, "EMIES:CancelActivity: job %s - %s", jobid, job.Failure());
      ESActivityNotFoundFault(item.NewChild("dummy"),job.Failure());
    } else {
      if(!job.Cancel()) {
        // Probably wrong current state
        logger_.msg(Arc::ERROR, "EMIES:CancelActivity: job %s - %s", jobid, job.Failure());
        // TODO: check for real reason
        ESOperationNotAllowedFault(item.NewChild("dummy"),job.Failure());
      } else {
        // It may take "wakeup period" for cancel mark to be detected.
        // And same time till result of cancel script is processed.
        // Currently it is not possible to estimate how long canceling
        // would happen.
        item.NewChild("esmanag:EstimatedTime") = Arc::tostring(config.GmConfig().WakeupPeriod()*2);
      };
    };
  };
  return Arc::MCC_Status(Arc::STATUS_OK);
}
Example #4
0
CacheConfig::CacheConfig(const GMConfig& config):
    _cache_max(100),
    _cache_min(100),
    _log_file("/var/log/arc/cache-clean.log"),
    _log_level("INFO") ,
    _lifetime("0"),
    _clean_timeout(0) {
  // Load conf file
  std::ifstream cfile;
  if(!config_open(cfile,config.ConfigFile())) throw CacheConfigException("Can't open configuration file");
  
  /* detect type of file */
  switch(config_detect(cfile)) {
    case config_file_XML: {
      Arc::XMLNode cfg;
      if(!cfg.ReadFromStream(cfile)) {
        config_close(cfile);
        throw CacheConfigException("Can't interpret configuration file as XML");
      };
      config_close(cfile);
      try {
        parseXMLConf(cfg);
      } catch (CacheConfigException& e) {
        config_close(cfile);
        throw;
      }
    }; break;
    case config_file_INI: {
      ConfigSections cf(cfile);
      try {
        parseINIConf(cf);
      } catch (CacheConfigException& e) {
        config_close(cfile);
        throw;
      }
    }; break;
    default: {
      config_close(cfile);
      throw CacheConfigException("Can't recognize type of configuration file");
    }; break;
  };
  config_close(cfile);
}
Example #5
0
Arc::MCC_Status ARexService::ESResumeActivity(ARexGMConfig& config,Arc::XMLNode in,Arc::XMLNode out) {
  /*
    ResumeActivity
      estypes:ActivityID 1-

    ResumeActivityResponse
      ResumeActivityResponseItem 1-
        estypes:ActivityID
        .
          EstimatedTime 0-1
          estypes:InternalBaseFault
          OperationNotPossibleFault
          OperationNotAllowedFault
          ActivityNotFoundFault
          AccessControlFault

    estypes:VectorLimitExceededFault
    estypes:AccessControlFault
    estypes:InternalBaseFault
   */
  Arc::XMLNode id = in["ActivityID"];
  unsigned int n = 0;
  for(;(bool)id;++id) {
    if((++n) > MAX_ACTIVITIES) {
      Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"");
      ESVectorLimitExceededFault(fault,MAX_ACTIVITIES,"Too many ActivityID");
      out.Destroy();
      return Arc::MCC_Status(Arc::STATUS_OK);
    };
  };
  id = in["ActivityID"];
  for(;(bool)id;++id) {
    std::string jobid = id;
    Arc::XMLNode item = out.NewChild("esmanag:ResumeActivityResponseItem");
    item.NewChild("estypes:ActivityID") = jobid;
    ARexJob job(jobid,config,logger_);
    if(!job) {
      // There is no such job
      logger_.msg(Arc::ERROR, "EMIES:ResumeActivity: job %s - %s", jobid, job.Failure());
      ESActivityNotFoundFault(item.NewChild("dummy"),job.Failure());
    } else {
      // Pause not implemented hence job can't be resumed too
      logger_.msg(Arc::ERROR, "EMIES:ResumeActivity: job %s - %s", jobid, "pause not implemented");
      ESOperationNotAllowedFault(item.NewChild("dummy"),"pause not implemented");
    };
  };
  return Arc::MCC_Status(Arc::STATUS_OK);
}
Example #6
0
void test1(void) {
  std::cout<<"------ Testing simple file download ------"<<std::endl;

  Arc::URL url("http://grid.uio.no/index.html");

  Arc::NS ns;
  Arc::Config c(ns);
  Arc::XMLNode cfg = c;
  Arc::XMLNode mgr = cfg.NewChild("ModuleManager");
  Arc::XMLNode pth1 = mgr.NewChild("Path");
  pth1 = "../tcp/.libs";
  Arc::XMLNode pth2 = mgr.NewChild("Path");
  pth2 = ".libs";
  Arc::XMLNode plg1 = cfg.NewChild("Plugins");
  Arc::XMLNode mcctcp = plg1.NewChild("Name");
  mcctcp = "mcctcp";
  Arc::XMLNode plg2 = cfg.NewChild("Plugins");
  Arc::XMLNode mcchttp = plg2.NewChild("Name");
  mcchttp = "mcchttp";
  Arc::XMLNode chn = cfg.NewChild("Chain");

  Arc::XMLNode tcp = chn.NewChild("Component");
  Arc::XMLNode tcpname = tcp.NewAttribute("name");
  tcpname = "tcp.client";
  Arc::XMLNode tcpid = tcp.NewAttribute("id");
  tcpid = "tcp";
  Arc::XMLNode tcpcnt = tcp.NewChild("Connect");
  Arc::XMLNode tcphost = tcpcnt.NewChild("Host");
  tcphost = url.Host();
  Arc::XMLNode tcpport = tcpcnt.NewChild("Port");
  tcpport = Arc::tostring(url.Port());

  Arc::XMLNode http = chn.NewChild("Component");
  Arc::XMLNode httpname = http.NewAttribute("name");
  httpname = "http.client";
  Arc::XMLNode httpid = http.NewAttribute("id");
  httpid = "http";
  Arc::XMLNode httpentry = http.NewAttribute("entry");
  httpentry = "http";
  Arc::XMLNode httpnext = http.NewChild("next");
  Arc::XMLNode httpnextid = httpnext.NewAttribute("id");
  httpnextid = "tcp";
  Arc::XMLNode httpmeth = http.NewChild("Method");
  httpmeth = "GET";
  Arc::XMLNode httpep = http.NewChild("Endpoint");
  httpep = url.str();

  std::cout<<"------ Configuration ------"<<std::endl;
  std::string cfgstr;
  c.GetXML(cfgstr);
  std::cerr << cfgstr << std::endl;

  Arc::Loader l(c);

  Arc::Message request;
  Arc::PayloadRaw msg;
  Arc::MessageAttributes attributes;
  Arc::MessageContext context;
  request.Payload(&msg);
  request.Attributes(&attributes);
  request.Context(&context);
  Arc::Message response;

//!!  l["http"]->process(request,response);

  std::cout<<"*** RESPONSE ***"<<std::endl;
  Arc::PayloadRaw& payload =
    dynamic_cast<Arc::PayloadRaw&>(*response.Payload());
  for(int n = 0;n<payload.Size();++n) std::cout<<payload[n];
  std::cout<<std::endl;
}
Example #7
0
Arc::MCC_Status ARexService::MigrateActivity(ARexGMConfig& config,Arc::XMLNode in,Arc::XMLNode out,const std::string& clientid) {
  /*
  MigrateActivity
    ActivityIdentifier (wsa:EndpointReferenceType)
    ActivityDocument
      jsdl:JobDefinition
    ForceMigration

  MigrateActivityResponse
    ActivityIdentifier (wsa:EndpointReferenceType)
    ActivityDocument
      jsdl:JobDefinition

  NotAuthorizedFault
  NotAcceptingNewActivitiesFault
  UnsupportedFeatureFault
  InvalidRequestMessageFault
  */
  {
    std::string s;
    in.GetXML(s);
    logger_.msg(Arc::VERBOSE, "MigrateActivity: request = \n%s", s);
  };
  Arc::WSAEndpointReference id(in["ActivityIdentifier"]);
  if(!(Arc::XMLNode)id) {
    // Wrong request
    logger_.msg(Arc::ERROR, "MigrateActivitys: no ActivityIdentifier found");
    Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"Can't find ActivityIdentifier element in request");
    InvalidRequestMessageFault(fault,"jsdl:ActivityIdentifier","Element is missing");
    out.Destroy();
    return Arc::MCC_Status();
  };
  std::string migrateid = Arc::WSAEndpointReference(id).Address() + "/" + (std::string)Arc::WSAEndpointReference(id).ReferenceParameters()["a-rex:JobID"];
  if(migrateid.empty()) {
    // EPR is wrongly formated or not an A-REX EPR
    logger_.msg(Arc::ERROR, "MigrateActivity: EPR contains no JobID");
    Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"Can't find JobID element in ActivityIdentifier");
    InvalidRequestMessageFault(fault,"a-rex:JobID","Element is missing");
    out.Destroy();
    return Arc::MCC_Status();
  };

  // HPC Basic Profile 1.0 comply (these fault handlings are defined in the KnowARC standards 
  // conformance roadmap 2nd release)

 // End of the HPC BP 1.0 fault handling part

  std::string delegation;
  Arc::XMLNode delegated_token = in["arcdeleg:DelegatedToken"];
  if(delegated_token) {
    // Client wants to delegate credentials
    if(!delegation_stores_.DelegatedToken(config.GmConfig().DelegationDir(),delegated_token,config.GridName(),delegation)) {
      // Failed to accept delegation (report as bad request)
      logger_.msg(Arc::ERROR, "MigrateActivity: Failed to accept delegation");
      Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"Failed to accept delegation");
      InvalidRequestMessageFault(fault,"arcdeleg:DelegatedToken","This token does not exist");
      out.Destroy();
      return Arc::MCC_Status();
    };
  };

  if( !(in["ActivityDocument"]["JobDefinition"])) {
    /*
    // First try to get job desc from old cluster
    logger_.msg(Arc::VERBOSE, "MigrateActivity: no job description found try to get it from old cluster");
    Arc::MCCConfig cfg;
    // TODO:
    //if (!proxyPath.empty())
    cfg.AddProxy(delegation);
    //if (!certificatePath.empty())
      //cfg.AddCertificate(certificatePath);
    //if (!keyPath.empty())
      //cfg.AddPrivateKey(keyPath);
    //if (!caCertificatesDir.empty())
      //cfg.AddCADir(caCertificatesDir);
    Arc::URL url(migrateid);
    Arc::PathIterator pi(url.Path(), true);
    url.ChangePath(*pi);
    Arc::AREXClient ac(url, cfg);
    Arc::NS ns;
    ns["a-rex"] = "http://www.nordugrid.org/schemas/a-rex";
    ns["bes-factory"] = "http://schemas.ggf.org/bes/2006/08/bes-factory";
    ns["wsa"] = "http://www.w3.org/2005/08/addressing";
    ns["jsdl"] = "http://schemas.ggf.org/jsdl/2005/11/jsdl";
    ns["jsdl-posix"] = "http://schemas.ggf.org/jsdl/2005/11/jsdl-posix";
    ns["jsdl-arc"] = "http://www.nordugrid.org/ws/schemas/jsdl-arc";
    ns["jsdl-hpcpa"] = "http://schemas.ggf.org/jsdl/2006/07/jsdl-hpcpa";
    Arc::XMLNode id(ns, "ActivityIdentifier");
    id.NewChild("wsa:Address") = url.str();
    id.NewChild("wsa:ReferenceParameters").NewChild("a-rex:JobID") = pi.Rest();
    std::string idstr;
    id.GetXML(idstr);
    std::string desc_str;
    if (ac.getdesc(idstr,desc_str)){
      Arc::JobDescription desc;
      desc.setSource(desc_str);
      if (desc.isValid()) {
        logger_.msg(Arc::INFO,"Valid job description obtained");
        if ( !( in["ActivityDocument"] ) ) in.NewChild("bes-factory:ActivityDocument");
        Arc::XMLNode XMLdesc;
        desc.getXML(XMLdesc);
        in["ActivityDocument"].NewChild(XMLdesc);
      } else {
        // Wrongly formatted job description
        logger_.msg(Arc::ERROR, "MigrateActivity: job description could not be fetch from old cluster");
        Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"Can't find JobDefinition element in request");
        InvalidRequestMessageFault(fault,"jsdl:JobDefinition","Element is missing");
        out.Destroy();
        return Arc::MCC_Status();
      }
    }
    */
    //else {
      // Not able to get job description
      logger_.msg(Arc::ERROR, "MigrateActivity: no job description found");
      //logger_.msg(Arc::ERROR, "MigrateActivity: job description could not be fetch from old cluster");
      Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"Can't find JobDefinition element in request");
      InvalidRequestMessageFault(fault,"jsdl:JobDefinition","Element is missing");
      out.Destroy();
      return Arc::MCC_Status();
    //}
  };

  Arc::XMLNode jsdl = in["ActivityDocument"]["JobDefinition"];

  Arc::NS ns;
  // Creating migration XMLNode
  Arc::XMLNode migration(ns, "Migration");
  migration.NewChild("ActivityIdentifier") = migrateid;
  if( (bool)in["ForceMigration"]){
    migration.NewChild("ForceMigration") = (std::string)in["ForceMigration"];
  } else {
    migration.NewChild("ForceMigration") = "true";
  }

  std::string migrationStr;
  migration.GetDoc(migrationStr, true);
  logger_.msg(Arc::INFO, "Migration XML sent to AREXJob: %s", migrationStr);

  JobIDGeneratorARC idgenerator(config.Endpoint());
  ARexJob job(jsdl,config,delegation,clientid,logger_,idgenerator,migration);
  if(!job) {
    ARexJobFailure failure_type = job;
    std::string failure = job.Failure();
    switch(failure_type) {
      case ARexJobDescriptionUnsupportedError: {
        Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"Unsupported feature in job description");
        UnsupportedFeatureFault(fault,failure);
      }; break;
      case ARexJobDescriptionMissingError: {
        Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"Missing needed element in job description");
        UnsupportedFeatureFault(fault,failure);
      }; break;
      case ARexJobDescriptionLogicalError: {
        std::string element;
        std::string::size_type pos = failure.find(' ');
        if(pos != std::string::npos) {
          element=failure.substr(0,pos);
          failure=failure.substr(pos+1);
        };
        Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"Logical error in job description");
        InvalidRequestMessageFault(fault,element,failure);
      }; break;
      default: {
        logger_.msg(Arc::ERROR, "MigrateActivity: Failed to migrate new job: %s",failure);
        // Failed to migrate new job (no corresponding BES fault defined - using generic SOAP error)
        logger_.msg(Arc::ERROR, "MigrateActivity: Failed to migrate new job");
        Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,("Failed to migrate new activity: "+failure).c_str());
        GenericFault(fault);
      }; break;
    };
    out.Destroy();
    return Arc::MCC_Status();
  };

  // Make SOAP response
  Arc::WSAEndpointReference identifier(out.NewChild("bes-factory:ActivityIdentifier"));
  // Make job's ID
  identifier.Address(config.Endpoint()); // address of service
  identifier.ReferenceParameters().NewChild("a-rex:JobID")=job.ID();
  identifier.ReferenceParameters().NewChild("a-rex:JobSessionDir")=config.Endpoint()+"/"+job.ID();
  out.NewChild(in["ActivityDocument"]);
  logger_.msg(Arc::VERBOSE, "MigrateActivity finished successfully");
  {
    std::string s;
    out.GetXML(s);
    logger_.msg(Arc::VERBOSE, "MigrateActivity: response = \n%s", s);
  };
  /* Needs to kill old job */

  return Arc::MCC_Status(Arc::STATUS_OK);
}
Example #8
0
int main(void) {
  signal(SIGTTOU,SIG_IGN);
  signal(SIGTTIN,SIG_IGN);
  Arc::Logger logger(Arc::Logger::rootLogger, "Test");
  Arc::LogStream logcerr1(std::cerr);
  Arc::Logger::rootLogger.addDestination(logcerr1);
  // Load service chain
  logger.msg(Arc::INFO, "Creating service side chain");
  Arc::Config service_config("service.xml");
  if(!service_config) {
    logger.msg(Arc::ERROR, "Failed to load service configuration");
    return -1;
  };
  Arc::MCCLoader service_loader(service_config);
  logger.msg(Arc::INFO, "Service side MCCs are loaded");

  logger.msg(Arc::INFO, "Creating client interface");
  Arc::MCCConfig client_cfg;
  // Paths to plugins in source tree
  client_cfg.AddPluginsPath("../../hed/mcc/http/.libs");
  client_cfg.AddPluginsPath("../../hed/mcc/soap/.libs");
  client_cfg.AddPluginsPath("../../hed/mcc/tls/.libs");
  client_cfg.AddPluginsPath("../../hed/mcc/tcp/.libs");
  client_cfg.AddPluginsPath("../../hed/shc/.libs");
  // Specify credentials
  client_cfg.AddPrivateKey("./testkey-nopass.pem");
  client_cfg.AddCertificate("./testcert.pem");
  client_cfg.AddCAFile("./testcacert.pem");
  // Create client instance for contacting echo service
  Arc::ClientSOAP client(client_cfg,Arc::URL("https://127.0.0.1:60000/echo"),60);
  // Add SecHandler to chain at TLS location to accept only
  // connection to server with specified DN
  std::list<std::string> dns;
  // Making a list of allowed hosts. To make this test
  // fail change DN below.
  dns.push_back("/O=Grid/O=Test/CN=localhost");
  // Creating SecHandler configuration with allowed DNs
  Arc::DNListHandlerConfig dncfg(dns,"outgoing");
  // Adding SecHandler to client at TLS level.
  // We have to explicitely specify method of ClientTCP 
  // class to attach SecHandler at proper location.
  client.Arc::ClientTCP::AddSecHandler(dncfg,Arc::TLSSec); 
  logger.msg(Arc::INFO, "Client side MCCs are loaded");

  for(int n = 0;n<1;n++) {
  // Create and send echo request
  logger.msg(Arc::INFO, "Creating and sending request");
  Arc::NS echo_ns;
  Arc::PayloadSOAP req(echo_ns);
  // Making echo namespace appear at operation level only
  // This is probably not needed and is here for demonstration
  // purposes only.
  echo_ns["echo"]="http://www.nordugrid.org/schemas/echo";
  Arc::XMLNode op = req.NewChild("echo:echo",echo_ns);
  op.NewChild("echo:say")="HELLO";
  Arc::PayloadSOAP* resp = NULL;
  Arc::MCC_Status status = client.process(&req,&resp);
  if(!status) {
    logger.msg(Arc::ERROR, "Request failed");
    if(resp) delete resp;
    return -1;
  };
  if(resp == NULL) {
    logger.msg(Arc::ERROR, "There is no response");
    return -1;
  };
  logger.msg(Arc::INFO, "Request succeed!!!");
  std::cout << "Response: " << (std::string)((*resp)["echoResponse"]["hear"])
	    << std::endl;
  delete resp;
  };
 
  return 0;
}
Example #9
0
Arc::MCC_Status ARexService::ChangeActivityStatus(ARexGMConfig& config,Arc::XMLNode in,Arc::XMLNode out) {
  /*
  ChangeActivityStatus
    ActivityIdentifier (wsa:EndpointReferenceType)
    OldStatus (a-rex,optional)
        attribute = state (bes-factory:ActivityStateEnumeration)
    NewStatus (a-rex)
        attribute = state (bes-factory:ActivityStateEnumeration)

  ChangeActivityStatusResponse
    NewStatus (a-rex)
        attribute = state (bes-factory:ActivityStateEnumeration)

  NotAuthorizedFault
  InvalidActivityIdentifierFault
  CantApplyOperationToCurrentStateFault
  */
  {
    std::string s;
    in.GetXML(s);
    logger_.msg(Arc::VERBOSE, "ChangeActivityStatus: request = \n%s", s);
  };
  Arc::WSAEndpointReference id(in["ActivityIdentifier"]);
  if(!(Arc::XMLNode)id) {
    // Wrong request
    logger_.msg(Arc::ERROR, "ChangeActivityStatus: no ActivityIdentifier found");
    Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"Can't find ActivityIdentifier element in request");
    InvalidRequestMessageFault(fault,"jsdl:ActivityIdentifier","Element is missing");
    out.Destroy();
    return Arc::MCC_Status(Arc::STATUS_OK);
  };
  std::string jobid = Arc::WSAEndpointReference(id).ReferenceParameters()["a-rex:JobID"];
  if(jobid.empty()) {
    // EPR is wrongly formated or not an A-REX EPR
    logger_.msg(Arc::ERROR, "ChangeActivityStatus: EPR contains no JobID");
    Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"Can't find JobID element in ActivityIdentifier");
    InvalidRequestMessageFault(fault,"a-rex:JobID","Element is missing");
    out.Destroy();
    return Arc::MCC_Status(Arc::STATUS_OK);
  };
  ARexJob job(jobid,config,logger_);
  if(!job) {
    // There is no such job
    std::string failure = job.Failure();
    logger_.msg(Arc::ERROR, "ChangeActivityStatus: no job found: %s",failure);
    Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"Can't find requested Activity");
    UnknownActivityIdentifierFault(fault,"No corresponding Activity found");
    out.Destroy();
    return Arc::MCC_Status(Arc::STATUS_OK);
  };

  // Old State
  Arc::XMLNode old_state = in["OldStatus"];
  std::string old_bes_state = old_state.Attribute("state");
  std::string old_arex_state = old_state["a-rex:state"];

  // New state
  Arc::XMLNode new_state = in["NewStatus"];
  if(!new_state) {
    // Wrong request
    logger_.msg(Arc::ERROR, "ChangeActivityStatus: missing NewStatus element");
    Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"Missing NewStatus element in request");
    InvalidRequestMessageFault(fault,"a-rex:NewStatus","Element is missing");
    out.Destroy();
    return Arc::MCC_Status(Arc::STATUS_OK);
  };
  std::string new_bes_state = new_state.Attribute("state");
  std::string new_arex_state = new_state["a-rex:state"];
  // Take renewed proxy if supplied
  std::string delegation;
  Arc::XMLNode delegated_token = new_state["arcdeleg:DelegatedToken"];
  if(delegated_token) {
    if(!delegation_stores_.DelegatedToken(config.GmConfig().DelegationDir(),delegated_token,config.GridName(),delegation)) {
      // Failed to accept delegation (report as bad request)
      logger_.msg(Arc::ERROR, "ChangeActivityStatus: Failed to accept delegation");
      Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"Failed to accept delegation");
      InvalidRequestMessageFault(fault,"arcdeleg:DelegatedToken","This token does not exist");
      out.Destroy();
      return Arc::MCC_Status(Arc::STATUS_OK);
    };
  };

  bool pending = false;
  std::string gm_state = job.State(pending);
  bool failed = job.Failed();
  std::string bes_state("");
  std::string arex_state("");
  convertActivityStatus(gm_state,bes_state,arex_state,failed,pending);
  // Old state in request must be checked against current one
  if((!old_bes_state.empty()) && (old_bes_state != bes_state)) {
    logger_.msg(Arc::ERROR, "ChangeActivityStatus: old BES state does not match");
    Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"OldStatus is not same as current status");
    CantApplyOperationToCurrentStateFault(fault,gm_state,failed,"OldStatus does not match");
    out.Destroy();
    return Arc::MCC_Status(Arc::STATUS_OK);
  };
  if((!old_arex_state.empty()) && (old_arex_state != arex_state)) {
    logger_.msg(Arc::ERROR, "ChangeActivityStatus: old A-REX state does not match");
    Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"OldStatus is not same as current status");
    CantApplyOperationToCurrentStateFault(fault,gm_state,failed,"OldStatus does not match");
    out.Destroy();
    return Arc::MCC_Status(Arc::STATUS_OK);
  };

  // Check for allowed combinations
  if((new_bes_state == "Finished") &&
     ((new_arex_state.empty()) || (new_arex_state == "Killing"))) {
    // Request to cancel job
    if((gm_state != "FINISHED") &&
       (gm_state != "CANCELING") &&
       (gm_state != "DELETED")) job.Cancel();
  } else
  if((new_bes_state == "Finished") &&
     (new_arex_state == "Deleted")) {
     // Request to clean job
    if((gm_state != "FINISHED") &&
       (gm_state != "CANCELING") &&
       (gm_state != "DELETED")) job.Cancel();
    job.Clean();
  } else 
  if((new_bes_state == "Running") &&
     (new_arex_state.empty())) { // Not supporting resume into user-defined state
    // Request to resume job
    if(!job.UpdateCredentials(delegation)) {
      logger_.msg(Arc::ERROR, "ChangeActivityStatus: Failed to update credentials");
      Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"Internal error: Failed to update credentials");
      out.Destroy();
      return Arc::MCC_Status(Arc::STATUS_OK);
    };
    if(!job.Resume()) {
      logger_.msg(Arc::ERROR, "ChangeActivityStatus: Failed to resume job");
      Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"Internal error: Failed to resume activity");
      out.Destroy();
      return Arc::MCC_Status(Arc::STATUS_OK);
    };
  } else {
    logger_.msg(Arc::ERROR, "ChangeActivityStatus: State change not allowed: from %s/%s to %s/%s",
                bes_state.c_str(),arex_state.c_str(),new_bes_state.c_str(),new_arex_state.c_str());
    Arc::SOAPFault fault(out.Parent(),Arc::SOAPFault::Sender,"Requested status transition is not supported");
    CantApplyOperationToCurrentStateFault(fault,gm_state,failed,"Requested status transition is not supported");
    out.Destroy();
    return Arc::MCC_Status(Arc::STATUS_OK);
  };
  // Make response
  // TODO: 
  // Updating currenst job state
  gm_state=job.State(pending);
  failed=job.Failed();
  convertActivityStatus(gm_state,bes_state,arex_state,failed,pending);
  Arc::XMLNode state = out.NewChild("a-rex:NewStatus");
  state.NewAttribute("bes-factory:state")=bes_state;
  state.NewChild("a-rex:state")=arex_state;
  {
    std::string s;
    out.GetXML(s);
    logger_.msg(Arc::VERBOSE, "ChangeActivityStatus: response = \n%s", s);
  };
  return Arc::MCC_Status(Arc::STATUS_OK);
}