#!/usr/bin/env python import datetime from suds.wsse import Security from suds.wsse import UsernameToken from suds.client import Client from dm.common.exceptions.objectNotFound import ObjectNotFound from dm.common.objects.runInfo import RunInfo from dm.common.objects.beamlineInfo import BeamlineInfo from dm.common.objects.proposalInfo import ProposalInfo from dm.common.objects.apsUserInfo import ApsUserInfo from dm.common.exceptions.dmException import DmException from dm.common.utility.loggingManager import LoggingManager class BssClient: WSDL_URL = 'https://schedule.aps.anl.gov/beamschedds/springws' CACHE_DURATION_IN_SECONDS = 10 def __init__(self, username, password): self.logger = LoggingManager.getInstance().getLogger(self.__class__.__name__) self.__configure(username, password) def __configure(self, username, password): beamlineScheduleServiceUrl = self.WSDL_URL + '/beamlineScheduleService/beamlineScheduleWebService.wsdl' runScheduleServiceUrl = self.WSDL_URL + '/runScheduleService/runScheduleWebService.wsdl' try: self.runScheduleServiceClient = Client(runScheduleServiceUrl) self.runScheduleServiceClient.options.cache.setduration(seconds=self.CACHE_DURATION_IN_SECONDS) self.setSoapHeader(self.runScheduleServiceClient, username, password) self.beamlineScheduleServiceClient = Client(beamlineScheduleServiceUrl) self.beamlineScheduleServiceClient.options.cache.setduration(seconds=self.CACHE_DURATION_IN_SECONDS) self.setSoapHeader(self.beamlineScheduleServiceClient, username, password) except Exception, ex: self.logger.error('Cannot open BSS connection: %s' % str(ex)) raise DmException(exception=ex) @classmethod def setSoapHeader(cls, client, username, password): security = Security() token = UsernameToken(username, password) token.setcreated() security.tokens.append(token) client.set_options(wsse=security) def listRuns(self): ''' Return list of all runs. ''' result = self.runScheduleServiceClient.service.findAllRuns() runArray = result.run runs = [] for run in runArray: runs.append(RunInfo({'name' : run.runName, 'startTime' : run.startTime, 'endTime' : run.endTime})) return runs def listRunsBetweenDates(self, startDate, endDate): ''' Find list of runs between given startDate and endDate. ''' result = self.runScheduleServiceClient.service.findAllRuns() runArray = result.run runs = [] for run in runArray: if run.startTime >= startDate and run.endTime <= endDate: runs.append(RunInfo({'name' : run.runName, 'startTime' : run.startTime, 'endTime' : run.endTime})) return runs def getRunForDates(self, startDate, endDate): ''' Find run that spans given startDate and endDate. ''' result = self.runScheduleServiceClient.service.findAllRuns() runArray = result.run for run in runArray: if startDate >= run.startTime and endDate <= run.endTime: return RunInfo({'name' : run.runName, 'startTime' : run.startTime, 'endTime' : run.endTime}) raise ObjectNotFound('No run found.') def getCurrentRun(self): ''' Find current run. ''' now = datetime.datetime.now() return self.getRunForDates(now, now) def listBeamlines(self): ''' Find list of all beamlines. ''' result = self.beamlineScheduleServiceClient.service.findAllBeamlines() beamlineArray = result.beamline beamlines = [] for beamline in beamlineArray: beamlines.append(BeamlineInfo({'name' : beamline.beamlineName, 'id' : beamline.id})) return beamlines def createProposalInfo(self, proposal): experimenterArray = proposal.experimenters.experimenter experimenters = [] for experimenter in experimenterArray: user = ApsUserInfo({ 'id' : experimenter.id, 'badge' : experimenter.badge, 'email' : experimenter.email, 'firstName' : experimenter.firstName, 'instId' : experimenter.instId, 'institution' : experimenter.institution, 'lastName' : experimenter.lastName }) if hasattr(experimenter, 'piFlag'): user['piFlag'] = experimenter.piFlag experimenters.append(user) proposalInfo = ProposalInfo({ 'title' : proposal.proposalTitle, 'id' : proposal.id, 'experimenters' : experimenters }) return proposalInfo def listBeamlineProposals(self, beamlineName, runName): ''' Find beamline schedule for a given beamlineName and runName. ''' schedule = self.beamlineScheduleServiceClient.service.findBeamlineSchedule(beamlineName, runName) activitiesArray = schedule.activities.activity proposals = [] for activity in activitiesArray: if hasattr(activity, 'beamtimeRequest'): proposal = activity.beamtimeRequest.proposal proposals.append(self.createProposalInfo(proposal)) return proposals def getBeamlineProposal(self, proposalId, beamlineName, runName): ''' Find proposal with a given id, beamlineName and runName. ''' schedule = self.beamlineScheduleServiceClient.service.findBeamlineSchedule(beamlineName, runName) activitiesArray = schedule.activities.activity proposals = [] for activity in activitiesArray: if hasattr(activity, 'beamtimeRequest'): proposal = activity.beamtimeRequest.proposal if proposal.id == proposalId: return self.createProposalInfo(proposal) raise ObjectNotFound('Proposal with id %s does not exist (beamline: %s; run: %s).' % (proposalId, beamlineName, runName)) if __name__ == '__main__': bss = BssClient('DMADMIN', 'A2Fxew@11:76am') now = datetime.datetime.now() days = datetime.timedelta(days=180) before = now - days print before, now runNames = bss.getRunsBetweenDates(before, now) print 'RUNS: ', runNames print 'CURRENT RUN: ', bss.getCurrentRun() print bss.listBeamlines() print bss.listBeamlineProposals('1-ID-B,C,E', '2017-1') print print bss.getBeamlineProposal(51190, '1-ID-B,C,E', '2017-1') print print bss.getBeamlineProposal(48258, '1-ID-B,C,E', '2017-1')