<commit_before>#__BEGIN_LICENSE__
# Copyright (c) 2015, United States Government, as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All rights reserved.
#
# The xGDS platform is licensed 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.
#__END_LICENSE__
import datetime
#import time
import logging
import os
import stat
import traceback
import time
import json

from django.utils import timezone
from django.conf import settings
from django.contrib import messages
from django.shortcuts import redirect
from django.core.urlresolvers import reverse

from django.db.models.aggregates import Max

from geocamPycroraptor2.views import getPyraptordClient, stopPyraptordServiceIfRunning
from geocamUtil.datetimeJsonEncoder import DatetimeJsonEncoder

from geocamUtil.loader import LazyGetModelByName, getClassByName

from django.core.cache import caches
_cache = caches['default']

# if settings.XGDS_CORE_REDIS:
#     from xgds_core.redisUtil import publishRedisSSE

SETTINGS_MODEL = LazyGetModelByName(settings.XGDS_VIDEO_SETTINGS_MODEL)
SEGMENT_MODEL = LazyGetModelByName(settings.XGDS_VIDEO_SEGMENT_MODEL)
EPISODE_MODEL = LazyGetModelByName(settings.XGDS_VIDEO_EPISODE_MODEL)
VIDEO_SOURCE_MODEL = LazyGetModelByName(settings.XGDS_VIDEO_SOURCE_MODEL)

SSE_TYPE = "video"

def makedirsIfNeeded(path):
    """
    Helper for displayEpisodeRecordedVideo
    """
    if not os.path.exists(path):
        currentUmask = os.umask(0)  # Save current umask and set to 0 so we can control permissions
        os.makedirs(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IROTH | stat.S_IXOTH)
        os.umask(currentUmask)  # Restore process umask
#        os.chmod(path, (stat.S_IRWXO | stat.S_IRWXG | stat.S_IRWXU))

def emptySegmentDir(recordedVideoDir):
    ''' check if this segment directory is empty
    '''
    try:
        if not os.listdir(recordedVideoDir):
            return True
    except:
        return True
    return False

def getVideoSource(sourceName):
    videoSource = VIDEO_SOURCE_MODEL.get().objects.get(shortName=sourceName)
    return videoSource

def splitFlightName(flightName):
    #this assumes flight name of episodeName_sourceName
    splits = flightName.split('_')
    episodeName = splits[0]
    sourceName = splits[1]
    return (episodeName, sourceName)

def startFlightRecording(request, flightName):
    (episodeName, sourceName) = splitFlightName(flightName)
    startTime=timezone.now()   #TODO: This is not true - we should lookup timecode from Wowza playlist
    try:
        videoEpisode = EPISODE_MODEL.get().objects.get(shortName=episodeName)
        if videoEpisode.endTime:
            videoEpisode.endTime = None
            videoEpisode.save()
            messages.info(request, 'Cleared end time for episode ' + episodeName)
    except:
        videoEpisode = EPISODE_MODEL.get()(shortName=episodeName, startTime=startTime)
        videoEpisode.save()
        messages.info(request, 'Created video episode ' + episodeName)

    videoEpisode.broadcast('start')

    recordingDir = getRecordedVideoDir(flightName)
    recordingUrl = getRecordedVideoUrl(flightName)
    videoSource = getVideoSource(sourceName)
    commands = startRecording(videoSource, recordingDir,
                              recordingUrl, startTime,
                              episode=videoEpisode)
    messages.info(request, commands)
    return redirect(reverse('error'))

def stopFlightRecording(request, flightName, endEpisode = False):
    (episodeName, sourceName) = splitFlightName(flightName)
    stopTime = timezone.now()
    commands = stopRecording(getVideoSource(sourceName), stopTime)

    if endEpisode:
        videoEpisode = EPISODE_MODEL.get().objects.get(shortName=episodeName)
        videoEpisode.endTime = stopTime
        videoEpisode.save()
        videoEpisode.broadcast('end')
        commands = commands + ' & set episode end time ' + str(stopTime)
    messages.info(request, commands)
    return redirect(reverse('error'))

def makeNewSegment(source, recordingDir, recordingUrl, startTime, episode):
    if not source.videofeed_set.all():
        logging.info("video feeds set is empty")
        return
    videoFeed = source.videofeed_set.all()[0]

    # figure out next segment number for this source and episode
    try:
        maxSegmentNumber = SEGMENT_MODEL.get().objects.filter(episode=episode, source=source).aggregate(Max('segNumber'))
        segmentNumber = maxSegmentNumber['segNumber__max']
        if not segmentNumber:
            segmentNumber = 0
        recordedVideoDir = os.path.join(recordingDir, 'Segment%03d' % segmentNumber)
        if not emptySegmentDir(recordedVideoDir):
            segmentNumber = segmentNumber + 1
            recordedVideoDir = os.path.join(recordingDir, 'Segment%03d' % segmentNumber)

        # adjust start and end times for all prio segments
        existingSegments = SEGMENT_MODEL.get().objects.filter(source=source,episode=episode)
#         for segment in existingSegments:
#             segment.adjustSegmentTimes()
    except:
        traceback.print_exc()
        segmentNumber = 0
        recordedVideoDir = os.path.join(recordingDir, 'Segment%03d' % segmentNumber)

    makedirsIfNeeded(recordedVideoDir)
    try:
        videoSettingses = SETTINGS_MODEL.get().objects.filter(width=videoFeed.settings.width,
                                                              height=videoFeed.settings.height)
        videoSettings = videoSettingses.first()
    except:
        # make a new one
        videoSettings = SETTINGS_MODEL.get()()
        videoSettings.width = videoFeed.settings.width
        videoSettings.height = videoFeed.settings.height
        videoSettings.save()

    videoSegment, created = SEGMENT_MODEL.get().objects.get_or_create(directoryName="Segment",
                                                                      segNumber=segmentNumber,
                                                                      indexFileName=settings.XGDS_VIDEO_INDEX_FILE_NAME,
                                                                      endTime=None,
                                                                      settings=videoSettings,
                                                                      source=source,
                                                                      episode=episode)
    videoSegment.startTime = startTime
    videoSegment.save()
    videoSegment.broadcast('start')

    return {'videoFeed': videoFeed,
            'recordedVideoDir': recordedVideoDir,
            'segmentObj': videoSegment}

def invokeMakeNewSegment(sourcePK, recordingDir, recordingUrl, startTime, episodePK):
    ''' call makeNewSegment after we look up the source and episode '''
    source = VIDEO_SOURCE_MODEL.get().objects.get(pk=sourcePK)
    episode = EPISODE_MODEL.get().objects.get(pk=episodePK)
    return makeNewSegment(source, recordingDir, recordingUrl, startTime, episode)

def getCurrentSegmentForSource(sourcePK, episodePK):
    ''' Look for latest segment for given source and episode '''
    source = VIDEO_SOURCE_MODEL.get().objects.get(pk=sourcePK)
    episode = EPISODE_MODEL.get().objects.get(pk=episodePK)
    open_segments = source.videosegment_set.filter(episode=episode).filter(endTime=None)
    if open_segments.count() != 1:
        print "*** WARNING: there should be exactly one unfinished segment during recording! Found %d for source %s" % (open_segments.count(), source.shortName)
    return open_segments[0]

def startRecording(source, recordingDir, recordingUrl, startTime, episode):
    segmentInfo = makeNewSegment(source, recordingDir, recordingUrl, startTime, episode)

    if settings.PYRAPTORD_SERVICE is True:
        pyraptord = getPyraptordClient()

    assetName = source.shortName
    recorderService = '%s_recorder' % assetName
    recorderCommand = ''
    if settings.XGDS_VIDEO_RECORDING_METHOD == 'VLC':
        recorderCommand = ("%s %s --sout='#duplicate{dst=std{access=livehttp{seglen=6,splitanywhere=false,delsegs=false,numsegs=0,index=prog_index.m3u8,index-url=prog_index-#####.ts},mux=ts,dst=prog_index-#####.ts}}'"
                           % (settings.XGDS_VIDEO_VLC_PATH,
                              segmentInfo['videoFeed'].url))
    elif settings.XGDS_VIDEO_RECORDING_METHOD == 'HLS':
        scriptPath = os.path.join(settings.PROJ_ROOT, 'apps', 'xgds_video', 'scripts', 'recordHLS2.py')
        recorderCommand = ('%s --sourceUrl=%s --outputDir=%s --recorderId=%s --episodePK=%d --sourcePK=%d' % (scriptPath, segmentInfo['videoFeed'].url, segmentInfo['recordedVideoDir'], assetName, episode.pk, source.pk))

    print recorderCommand
    if settings.PYRAPTORD_SERVICE is True:
        #(pyraptord, recorderService)
        #stopPyraptordServiceIfRunning(pyraptord, recorderService)
        # the old process will suicide so let us look to see if it is done
        running = True
        count = 0
        while running and count < 10:
            oldStatus = pyraptord.getStatus(recorderService)
            if 'procStatus' not in oldStatus or oldStatus['procStatus'] != 'running':
                running = False
            time.sleep(0.5)

        pyraptord.updateServiceConfig(recorderService,
                                      {'command': recorderCommand,
                                       'cwd': segmentInfo['recordedVideoDir']})
        pyraptord.restart(recorderService)
        return recorderCommand
    return 'NO PYRAPTORD: ' + recorderCommand

def endSegment(segment, endTime):
    segment.endTime = endTime
    segment.save()
    segment.broadcast('end')

def stopRecording(source, endTime):
    assetName = source.shortName
    recorderService = '%s_recorder' % assetName

    if settings.XGDS_VIDEO_RECORDING_METHOD == 'HLS':
        # set the persistent flag to stop.
        #TODO make this better
        _cache.set("recordHLS:%s:stopRecording" % assetName, True)
        return 'SET MEMCACHE TO STOP HLS RECORDING FOR %s' % (assetName)

    else:
        # we need to set the endtime
        unended_segments = source.videosegment_set.filter(endTime=None)
        for segment in unended_segments:
            endSegment(segment, endTime)

        if settings.PYRAPTORD_SERVICE is True:
            pyraptord = getPyraptordClient('pyraptord')
            stopPyraptordServiceIfRunning(pyraptord, recorderService)
            return 'STOPPED PYCRORAPTOR SERVICES: ' + recorderService
    return 'NO PYRAPTORD: ' + recorderService

def stopRecordingAndCleanSegments(source, videoChunks):
    # call method to clear out giant file and kill recorder if needed
    stopRecording(source, timezone.now())
    for chunk in videoChunks:
        os.remove(chunk)

def getRecordedVideoDir(name):
    recordedVideoDir = ("%s/%s/Video/Recordings/" %
                        (settings.RECORDED_VIDEO_DIR_BASE,
                         name))
    return recordedVideoDir

def getRecordedVideoUrl(name):
    recordedVideoUrl = "%s%s/Video/Recordings/" % \
        (settings.RECORDED_VIDEO_URL_BASE,
         name)
    return recordedVideoUrl

def endActiveEpisode(end_time):
    episode = getClassByName(settings.XGDS_VIDEO_GET_ACTIVE_EPISODE)()
    if episode:
        episode.endTime = end_time
        episode.save()
        episode.broadcast('end')

# def publishSSE(channel, status, data):
#     if settings.XGDS_SSE and settings.XGDS_CORE_REDIS:
#         result = {'status': status,
#                   'data': data}
#         json_string = json.dumps(result, cls=DatetimeJsonEncoder)
#         publishRedisSSE(channel, SSE_TYPE, json_string)
#         return json_string

def setFudgeForSource(sourceName, seconds):
    key = 'VIDEO_FUDGE_' + sourceName;
    _cache.set(key, seconds)

def getFudgeForSource(sourceName):
    # use memcache to retrieve the frational seconds fudge factor for this video source
    key = 'VIDEO_FUDGE_' + sourceName;
    fudge = _cache.get(key)
    if not fudge:
        fudge = settings.XGDS_VIDEO_BUFFER_FUDGE_FACTOR
    return fudge
<commit_msg>Improve splitFlightName() to work with names having uderscores before vehicle name<commit_after>#__BEGIN_LICENSE__
# Copyright (c) 2015, United States Government, as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All rights reserved.
#
# The xGDS platform is licensed 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.
#__END_LICENSE__
import datetime
#import time
import logging
import os
import stat
import traceback
import time
import json

from django.utils import timezone
from django.conf import settings
from django.contrib import messages
from django.shortcuts import redirect
from django.core.urlresolvers import reverse

from django.db.models.aggregates import Max

from geocamPycroraptor2.views import getPyraptordClient, stopPyraptordServiceIfRunning
from geocamUtil.datetimeJsonEncoder import DatetimeJsonEncoder

from geocamUtil.loader import LazyGetModelByName, getClassByName

from django.core.cache import caches
_cache = caches['default']

# if settings.XGDS_CORE_REDIS:
#     from xgds_core.redisUtil import publishRedisSSE

SETTINGS_MODEL = LazyGetModelByName(settings.XGDS_VIDEO_SETTINGS_MODEL)
SEGMENT_MODEL = LazyGetModelByName(settings.XGDS_VIDEO_SEGMENT_MODEL)
EPISODE_MODEL = LazyGetModelByName(settings.XGDS_VIDEO_EPISODE_MODEL)
VIDEO_SOURCE_MODEL = LazyGetModelByName(settings.XGDS_VIDEO_SOURCE_MODEL)

SSE_TYPE = "video"

def makedirsIfNeeded(path):
    """
    Helper for displayEpisodeRecordedVideo
    """
    if not os.path.exists(path):
        currentUmask = os.umask(0)  # Save current umask and set to 0 so we can control permissions
        os.makedirs(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IROTH | stat.S_IXOTH)
        os.umask(currentUmask)  # Restore process umask
#        os.chmod(path, (stat.S_IRWXO | stat.S_IRWXG | stat.S_IRWXU))

def emptySegmentDir(recordedVideoDir):
    ''' check if this segment directory is empty
    '''
    try:
        if not os.listdir(recordedVideoDir):
            return True
    except:
        return True
    return False

def getVideoSource(sourceName):
    videoSource = VIDEO_SOURCE_MODEL.get().objects.get(shortName=sourceName)
    return videoSource

def splitFlightName(flightName):
    #this assumes flight name of episodeName_sourceName - source cannot have underscores in name.
    splits = flightName.rsplit("_", 1)
    episodeName = splits[0]
    sourceName = splits[1]
    return (episodeName, sourceName)

def startFlightRecording(request, flightName):
    (episodeName, sourceName) = splitFlightName(flightName)
    startTime=timezone.now()   #TODO: This is not true - we should lookup timecode from Wowza playlist
    try:
        videoEpisode = EPISODE_MODEL.get().objects.get(shortName=episodeName)
        if videoEpisode.endTime:
            videoEpisode.endTime = None
            videoEpisode.save()
            messages.info(request, 'Cleared end time for episode ' + episodeName)
    except:
        videoEpisode = EPISODE_MODEL.get()(shortName=episodeName, startTime=startTime)
        videoEpisode.save()
        messages.info(request, 'Created video episode ' + episodeName)

    videoEpisode.broadcast('start')

    recordingDir = getRecordedVideoDir(flightName)
    recordingUrl = getRecordedVideoUrl(flightName)
    videoSource = getVideoSource(sourceName)
    commands = startRecording(videoSource, recordingDir,
                              recordingUrl, startTime,
                              episode=videoEpisode)
    messages.info(request, commands)
    return redirect(reverse('error'))

def stopFlightRecording(request, flightName, endEpisode = False):
    (episodeName, sourceName) = splitFlightName(flightName)
    stopTime = timezone.now()
    commands = stopRecording(getVideoSource(sourceName), stopTime)

    if endEpisode:
        videoEpisode = EPISODE_MODEL.get().objects.get(shortName=episodeName)
        videoEpisode.endTime = stopTime
        videoEpisode.save()
        videoEpisode.broadcast('end')
        commands = commands + ' & set episode end time ' + str(stopTime)
    messages.info(request, commands)
    return redirect(reverse('error'))

def makeNewSegment(source, recordingDir, recordingUrl, startTime, episode):
    if not source.videofeed_set.all():
        logging.info("video feeds set is empty")
        return
    videoFeed = source.videofeed_set.all()[0]

    # figure out next segment number for this source and episode
    try:
        maxSegmentNumber = SEGMENT_MODEL.get().objects.filter(episode=episode, source=source).aggregate(Max('segNumber'))
        segmentNumber = maxSegmentNumber['segNumber__max']
        if not segmentNumber:
            segmentNumber = 0
        recordedVideoDir = os.path.join(recordingDir, 'Segment%03d' % segmentNumber)
        if not emptySegmentDir(recordedVideoDir):
            segmentNumber = segmentNumber + 1
            recordedVideoDir = os.path.join(recordingDir, 'Segment%03d' % segmentNumber)

        # adjust start and end times for all prio segments
        existingSegments = SEGMENT_MODEL.get().objects.filter(source=source,episode=episode)
#         for segment in existingSegments:
#             segment.adjustSegmentTimes()
    except:
        traceback.print_exc()
        segmentNumber = 0
        recordedVideoDir = os.path.join(recordingDir, 'Segment%03d' % segmentNumber)

    makedirsIfNeeded(recordedVideoDir)
    try:
        videoSettingses = SETTINGS_MODEL.get().objects.filter(width=videoFeed.settings.width,
                                                              height=videoFeed.settings.height)
        videoSettings = videoSettingses.first()
    except:
        # make a new one
        videoSettings = SETTINGS_MODEL.get()()
        videoSettings.width = videoFeed.settings.width
        videoSettings.height = videoFeed.settings.height
        videoSettings.save()

    videoSegment, created = SEGMENT_MODEL.get().objects.get_or_create(directoryName="Segment",
                                                                      segNumber=segmentNumber,
                                                                      indexFileName=settings.XGDS_VIDEO_INDEX_FILE_NAME,
                                                                      endTime=None,
                                                                      settings=videoSettings,
                                                                      source=source,
                                                                      episode=episode)
    videoSegment.startTime = startTime
    videoSegment.save()
    videoSegment.broadcast('start')

    return {'videoFeed': videoFeed,
            'recordedVideoDir': recordedVideoDir,
            'segmentObj': videoSegment}

def invokeMakeNewSegment(sourcePK, recordingDir, recordingUrl, startTime, episodePK):
    ''' call makeNewSegment after we look up the source and episode '''
    source = VIDEO_SOURCE_MODEL.get().objects.get(pk=sourcePK)
    episode = EPISODE_MODEL.get().objects.get(pk=episodePK)
    return makeNewSegment(source, recordingDir, recordingUrl, startTime, episode)

def getCurrentSegmentForSource(sourcePK, episodePK):
    ''' Look for latest segment for given source and episode '''
    source = VIDEO_SOURCE_MODEL.get().objects.get(pk=sourcePK)
    episode = EPISODE_MODEL.get().objects.get(pk=episodePK)
    open_segments = source.videosegment_set.filter(episode=episode).filter(endTime=None)
    if open_segments.count() != 1:
        print "*** WARNING: there should be exactly one unfinished segment during recording! Found %d for source %s" % (open_segments.count(), source.shortName)
    return open_segments[0]

def startRecording(source, recordingDir, recordingUrl, startTime, episode):
    segmentInfo = makeNewSegment(source, recordingDir, recordingUrl, startTime, episode)

    if settings.PYRAPTORD_SERVICE is True:
        pyraptord = getPyraptordClient()

    assetName = source.shortName
    recorderService = '%s_recorder' % assetName
    recorderCommand = ''
    if settings.XGDS_VIDEO_RECORDING_METHOD == 'VLC':
        recorderCommand = ("%s %s --sout='#duplicate{dst=std{access=livehttp{seglen=6,splitanywhere=false,delsegs=false,numsegs=0,index=prog_index.m3u8,index-url=prog_index-#####.ts},mux=ts,dst=prog_index-#####.ts}}'"
                           % (settings.XGDS_VIDEO_VLC_PATH,
                              segmentInfo['videoFeed'].url))
    elif settings.XGDS_VIDEO_RECORDING_METHOD == 'HLS':
        scriptPath = os.path.join(settings.PROJ_ROOT, 'apps', 'xgds_video', 'scripts', 'recordHLS2.py')
        recorderCommand = ('%s --sourceUrl=%s --outputDir=%s --recorderId=%s --episodePK=%d --sourcePK=%d' % (scriptPath, segmentInfo['videoFeed'].url, segmentInfo['recordedVideoDir'], assetName, episode.pk, source.pk))

    print recorderCommand
    if settings.PYRAPTORD_SERVICE is True:
        #(pyraptord, recorderService)
        #stopPyraptordServiceIfRunning(pyraptord, recorderService)
        # the old process will suicide so let us look to see if it is done
        running = True
        count = 0
        while running and count < 10:
            oldStatus = pyraptord.getStatus(recorderService)
            if 'procStatus' not in oldStatus or oldStatus['procStatus'] != 'running':
                running = False
            time.sleep(0.5)

        pyraptord.updateServiceConfig(recorderService,
                                      {'command': recorderCommand,
                                       'cwd': segmentInfo['recordedVideoDir']})
        pyraptord.restart(recorderService)
        return recorderCommand
    return 'NO PYRAPTORD: ' + recorderCommand

def endSegment(segment, endTime):
    segment.endTime = endTime
    segment.save()
    segment.broadcast('end')

def stopRecording(source, endTime):
    assetName = source.shortName
    recorderService = '%s_recorder' % assetName

    if settings.XGDS_VIDEO_RECORDING_METHOD == 'HLS':
        # set the persistent flag to stop.
        #TODO make this better
        _cache.set("recordHLS:%s:stopRecording" % assetName, True)
        return 'SET MEMCACHE TO STOP HLS RECORDING FOR %s' % (assetName)

    else:
        # we need to set the endtime
        unended_segments = source.videosegment_set.filter(endTime=None)
        for segment in unended_segments:
            endSegment(segment, endTime)

        if settings.PYRAPTORD_SERVICE is True:
            pyraptord = getPyraptordClient('pyraptord')
            stopPyraptordServiceIfRunning(pyraptord, recorderService)
            return 'STOPPED PYCRORAPTOR SERVICES: ' + recorderService
    return 'NO PYRAPTORD: ' + recorderService

def stopRecordingAndCleanSegments(source, videoChunks):
    # call method to clear out giant file and kill recorder if needed
    stopRecording(source, timezone.now())
    for chunk in videoChunks:
        os.remove(chunk)

def getRecordedVideoDir(name):
    recordedVideoDir = ("%s/%s/Video/Recordings/" %
                        (settings.RECORDED_VIDEO_DIR_BASE,
                         name))
    return recordedVideoDir

def getRecordedVideoUrl(name):
    recordedVideoUrl = "%s%s/Video/Recordings/" % \
        (settings.RECORDED_VIDEO_URL_BASE,
         name)
    return recordedVideoUrl

def endActiveEpisode(end_time):
    episode = getClassByName(settings.XGDS_VIDEO_GET_ACTIVE_EPISODE)()
    if episode:
        episode.endTime = end_time
        episode.save()
        episode.broadcast('end')

# def publishSSE(channel, status, data):
#     if settings.XGDS_SSE and settings.XGDS_CORE_REDIS:
#         result = {'status': status,
#                   'data': data}
#         json_string = json.dumps(result, cls=DatetimeJsonEncoder)
#         publishRedisSSE(channel, SSE_TYPE, json_string)
#         return json_string

def setFudgeForSource(sourceName, seconds):
    key = 'VIDEO_FUDGE_' + sourceName;
    _cache.set(key, seconds)

def getFudgeForSource(sourceName):
    # use memcache to retrieve the frational seconds fudge factor for this video source
    key = 'VIDEO_FUDGE_' + sourceName;
    fudge = _cache.get(key)
    if not fudge:
        fudge = settings.XGDS_VIDEO_BUFFER_FUDGE_FACTOR
    return fudge
<|endoftext|>


<commit_before># coding: utf-8
'''
File: validate.py
Author: Oliver Zscheyge
Description:
    Contains validate method to check whether a given XML document conforms
    to the Confopy data model.
'''

import os.path as op
from lxml import etree

def validate(files):
    """Validates XML files according to the Confopy data model XML schema.
    Args:
        files: A list of file paths. The XML documents to validate.
    Return:
        A string message indicating the successful validation or listing all errors.
    """
    xsd_path = u"%s/c"""onfopy_document.xsd" % op.dirname(op.realpath(__file__))
    output = u""
    for f in files:
        xsd_doc = etree.parse(xsd_path)
        xml_schema = etree.XMLSchema(xsd_doc)
        doc = etree.parse(f)
        if xml_schema.validate(doc):
            output = output + "%s is a valid instance of %s!\n" % (f, xsd_path)
        else:
            output = output + "%s is invalid according to %s!\n\nError(s):\n%s\n" % (f, xsd_path, xml_schema.error_log)
    return output
<commit_msg>Fix incorrectly delimited string<commit_after># coding: utf-8
'''
File: validate.py
Author: Oliver Zscheyge
Description:
    Contains validate method to check whether a given XML document conforms
    to the Confopy data model.
'''

import os.path as op
from lxml import etree

def validate(files):
    """Validates XML files according to the Confopy data model XML schema.
    Args:
        files: A list of file paths. The XML documents to validate.
    Return:
        A string message indicating the successful validation or listing all errors.
    """
    xsd_path = u"%s/confopy_document.xsd" % op.dirname(op.realpath(__file__))
    output = u""
    for f in files:
        xsd_doc = etree.parse(xsd_path)
        xml_schema = etree.XMLSchema(xsd_doc)
        doc = etree.parse(f)
        if xml_schema.validate(doc):
            output = output + "%s is a valid instance of %s!\n" % (f, xsd_path)
        else:
            output = output + "%s is invalid according to %s!\n\nError(s):\n%s\n" % (f, xsd_path, xml_schema.error_log)
    return output
<|endoftext|>


<commit_before>import IPython

import ts_charting.lab.lab as tslab
import ipycli.standalone as sa

from workbench import sharedx

class ID3Lab(tslab.Lab):
    def get_varname(self):
        """
        Try to get the variable that this lab is
        bound to in the IPython kernel
        """
        inst = IPython.InteractiveShell._instance
        for k,v in inst.user_ns.iteritems():
            if v is self and not k.startswith('_'):
                return k

    def link(self):
        name = self.get_varname()
        return sa.link(name)

    def _repr_html_(self):
        out = 'stations:
'
        out += '
'.join(self.stations.keys())
        link = self.link().data
        out += '
' + link
        return out

    @property
    def html_obj(self):
        # for now default to sharedx
        return sharedx
<commit_msg>converted notebook repr to use Javascript<commit_after>import IPython

import ts_charting.lab.lab as tslab
import ipycli.standalone as sa

from workbench import sharedx

class ID3Lab(tslab.Lab):
    def get_varname(self):
        """
        Try to get the variable that this lab is
        bound to in the IPython kernel
        """
        inst = IPython.InteractiveShell._instance
        for k,v in inst.user_ns.iteritems():
            if v is self and not k.startswith('_'):
                return k

    def link(self):
        name = self.get_varname()
        return sa.link(name)

    def _repr_javascript_(self):
        """
        Output:

        stations:
        AAPL
        IBM

        <link>

        Note:
            Uses Javascript because sa.link() returns javascript. This is
            because sa.link needs to use the location.href to get the notebook_id
            since we cannot grab that from within the notebook kernel.
        """
        js = """
        element.append('{0}');
        container.show();
        """
        station_text = 'stations:
'
        station_text += '
'.join(self.stations.keys())
        out = js.format(station_text)

        link = self.link().data
        out += 'elemenet.append("
");' + link
        return out

    @property
    def html_obj(self):
        # for now default to sharedx
        return sharedx

    def __str__(self):
        return
<|endoftext|>


<commit_before>#!/usr/bin/env python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Entry point for the dartium buildbots.

This script is called from buildbot and reports results using the buildbot
annotation scheme.
"""

import os
import sys

from common import chromium_utils

def main():
  builder_name = os.getenv('BUILDBOT_BUILDERNAME', default='')

  # Temporary until 1.6 ships on stable.
  if builder_name.endswith('-be') or builder_name.endswith("-dev"):
    script = 'src/dart/tools/dartium/buildbot_annotated_steps.py'
  else:
    script = 'src/dartium_tools/buildbot_annotated_steps.py'
  chromium_utils.RunCommand([sys.executable, script])

  # BIG HACK
  # Normal ninja clobbering does not work due to symlinks/python on windows
  # Full clobbering before building does not work since it will destroy
  # the ninja build files
  # So we basically clobber at the end here
  if chromium_utils.IsWindows() and 'full' in builder_name:
    chromium_utils.RemoveDirectory('src/out')
  return 0

if __name__ == '__main__':
  sys.exit(main())
<commit_msg>Use exitcode of running the annotated steps script<commit_after>#!/usr/bin/env python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Entry point for the dartium buildbots.

This script is called from buildbot and reports results using the buildbot
annotation scheme.
"""

import os
import sys

from common import chromium_utils

def main():
  builder_name = os.getenv('BUILDBOT_BUILDERNAME', default='')

  # Temporary until 1.6 ships on stable.
  if builder_name.endswith('-be') or builder_name.endswith("-dev"):
    script = 'src/dart/tools/dartium/buildbot_annotated_steps.py'
  else:
    script = 'src/dartium_tools/buildbot_annotated_steps.py'
  result = chromium_utils.RunCommand([sys.executable, script])

  if result:
    print 'Running annotated steps % failed' % script
    return 1
  # BIG HACK
  # Normal ninja clobbering does not work due to symlinks/python on windows
  # Full clobbering before building does not work since it will destroy
  # the ninja build files
  # So we basically clobber at the end here
  if chromium_utils.IsWindows() and 'full' in builder_name:
    chromium_utils.RemoveDirectory('src/out')
  return 0

if __name__ == '__main__':
  sys.exit(main())
<|endoftext|>


<commit_before>"""Command exports."""
from .simple import (add_ftp_user, authorize_ip, delete_ftp_user, fix_rtorrent,
                     mirror_main, start_torrents)

__all__ = [
    'add_ftp_user', 'authorize_ip', 'delete_ftp_user', 'fix_rtorrent',
    'mirror_main', 'start_torrents'
]
<commit_msg>xirvik/commands/__init__: remove old import<commit_after>"""Command exports."""
from .simple import (add_ftp_user, authorize_ip, delete_ftp_user, fix_rtorrent,
                     start_torrents)

__all__ = ('add_ftp_user', 'authorize_ip', 'delete_ftp_user', 'fix_rtorrent',
           'start_torrents')
<|endoftext|>


<commit_before>from twisted.application import service
from twisted.python import components, failure
from twisted.internet import defer, reactor

class IBackendService(components.Interface):
	""" Interface to a backend service of a pubsub service """

	def do_publish(self, node, publisher, item):
		""" Returns a deferred that returns """

class BackendException(Exception):
	def __init__(self, msg = ''):
		self.msg = msg

	def __str__(self):
		return self.msg

class NodeNotFound(BackendException):
	def __init__(self, msg = 'Node not found'):
		BackendException.__init__(self, msg)

class NotAuthorized(BackendException):
	pass

class PayloadExpected(BackendException):
	def __init__(self, msg = 'Payload expected'):
		BackendException.__init__(self, msg)

class NoPayloadAllowed(BackendException):
	def __init__(self, msg = 'No payload allowed'):
		BackendException.__init__(self, msg)

class MemoryBackendService(service.Service):

	__implements__ = IBackendService,

	def __init__(self):
		self.nodes = {
			"ralphm/mood/ralphm@ik.nu": {
				"persist_items": True,
				"deliver_payloads": True,
			}
		}
		self.subscribers = {
			"ralphm/mood/ralphm@ik.nu": [
				"notify@ik.nu/mood_monitor"
			]
		}
		self.affiliations = {
			"ralphm/mood/ralphm@ik.nu": {
				"ralphm@ik.nu": "owner",
				"ralphm@doe.ik.nu": "publisher"
			}
		}

	def do_publish(self, node, publisher, items):
		try:
			try:
				config = self.nodes[node]
				persist_items = config["persist_items"]
				deliver_payloads = config["deliver_payloads"]
			except KeyError:
				raise NodeNotFound

			try:
				affiliation = self.affiliations[node][publisher]
				if affiliation not in ['owner', 'publisher']:
					raise NotAuthorized
			except KeyError:
				raise NotAuthorized()

			# the following is under the assumption that the publisher
			# has to provide an item when the node is persistent, but
			# an empty notification is to be sent.

			if items and not persist_items and not deliver_payloads:
				raise NoPayloadAllowed
			elif not items and (persist_items or deliver_payloads):
				raise PayloadExpected

			print "publish by %s to %s" % (publisher, node)

			if persist_items or deliver_payloads:
				for item in items:
					if item["id"] is None:
						item["id"] = 'random'

			if persist_items:
				self.storeItems(node, publisher, items)

			if items and not deliver_payloads:
				for item in items:
					item.children = []

			recipients = self.get_subscribers(node)
			recipients.addCallback(self.magic_filter, node, items)
			recipients.addCallback(self.pubsub_service.do_notification, node)

			return defer.succeed(None)
		except:
			f = failure.Failure()
			return defer.fail(f)

	def magic_filter(self, subscribers, node, items):
		list = {}
		for subscriber in subscribers:
			list[subscriber] = items

		return list

	def get_subscribers(self, node):
		d = defer.Deferred()
		try:
			result = self.subscribers[node]
		except:
			f = failure.Failure()
			reactor.callLater(0, d.errback, f)
		else:
			reactor.callLater(0, d.callback, result)

		return d

	def storeItems(self, node, publisher, items):
		for item in items:
			print "Storing item %s" % item.toXml()

<commit_msg>Redone memory storage of nodes. Created a few classes for memory storage of nodes. Implemented basic subscription. Implemented item storage.<commit_after>from twisted.application import service
from twisted.python import components, failure
from twisted.internet import defer, reactor
from twisted.protocols.jabber import jid

class IBackendService(components.Interface):
	""" Interface to a backend service of a pubsub service """

	def do_publish(self, node, publisher, item):
		""" Returns a deferred that returns """

class BackendException(Exception):
	def __init__(self, msg = ''):
		self.msg = msg

	def __str__(self):
		return self.msg

class NodeNotFound(BackendException):
	def __init__(self, msg = 'Node not found'):
		BackendException.__init__(self, msg)

class NotAuthorized(BackendException):
	pass

class PayloadExpected(BackendException):
	def __init__(self, msg = 'Payload expected'):
		BackendException.__init__(self, msg)

class NoPayloadAllowed(BackendException):
	def __init__(self, msg = 'No payload allowed'):
		BackendException.__init__(self, msg)

class Subscription:
	def __init__(self, state):
		self.state = state

class NodeConfiguration:
	def __init__(self):
		self.persist_items = False
		self.deliver_payloads = False

class Node:
	def __init__(self, name):
		self.name = name
		self.configuration = NodeConfiguration()
		self.subscriptions = {}
		self.affiliations = {}
		self.items = {}

class MemoryBackendService(service.Service):

	__implements__ = IBackendService,

	def __init__(self):
		self.nodes = {}

		node = Node("ralphm/mood/ralphm@ik.nu")
		node.subscriptions["ralphm@doe.ik.nu"] = Subscription("subscribed")
		node.affiliations["ralphm@ik.nu"] = "owner"
		node.affiliations["ralphm@doe.ik.nu"] = "publisher"
		node.configuration.persist_items = True
		node.configuration.deliver_payloads = True
		self.nodes[node.name] = node

	def do_publish(self, node_id, publisher, items):
		try:
			try:
				node = self.nodes[node_id]
				persist_items = node.configuration.persist_items
				deliver_payloads = node.configuration.deliver_payloads
			except KeyError:
				raise NodeNotFound

			try:
				if node.affiliations[publisher] not in ['owner', 'publisher']:
					raise NotAuthorized
			except KeyError:
				raise NotAuthorized()

			# the following is under the assumption that the publisher
			# has to provide an item when the node is persistent, but
			# an empty notification is to be sent.

			if items and not persist_items and not deliver_payloads:
				raise NoPayloadAllowed
			elif not items and (persist_items or deliver_payloads):
				raise PayloadExpected

			print "publish by %s to %s" % (publisher, node_id)

			if persist_items or deliver_payloads:
				for item in items:
					if item["id"] is None:
						item["id"] = 'random'

			if persist_items:
				self.storeItems(node_id, publisher, items)

			if items and not deliver_payloads:
				for item in items:
					item.children = []

			recipients = self.get_subscribers(node_id)
			recipients.addCallback(self.magic_filter, node_id, items)
			recipients.addCallback(self.pubsub_service.do_notification, node_id)

			return defer.succeed(None)
		except:
			f = failure.Failure()
			return defer.fail(f)

	def do_subscribe(self, node_id, subscriber, requestor):
		# expect subscriber and requestor to be a jid.JID
		try:
			try:
				node = self.nodes[node_id]
			except KeyError:
				raise NodeNotFound

			affiliation = node.affiliations.get(requestor.full(), 'none')

			if affiliation == 'banned':
				raise NotAuthorized

			print subscriber.full()
			print subscriber.userhostJID().full()
			print requestor.full()

			if subscriber.userhostJID() != requestor:
				raise NotAuthorized

			try:
				subscription = node.subscriptions[subscriber.full()]
			except KeyError:
				subscription = Subscription('subscribed')
				node.subscriptions[subscriber.full()] = subscription

			print node.subscriptions

			return defer.succeed({
					'affiliation': affiliation,
					'node': node_id,
					'jid': subscriber,
					'subscription': subscription.state})
		except:
			f = failure.Failure()
			return defer.fail(f)

	def magic_filter(self, subscribers, node_id, items):
		list = {}
		for subscriber in subscribers:
			list[subscriber] = items

		return list

	def get_subscribers(self, node_id):
		d = defer.Deferred()
		try:
			result = self.nodes[node_id].subscriptions.keys()
		except:
			f = failure.Failure()
			reactor.callLater(0, d.errback, f)
		else:
			reactor.callLater(0, d.callback, result)

		return d

	def storeItems(self, node_id, publisher, items):
		for item in items:
			self.nodes[node_id].items[item["id"]] = item

		print self.nodes[node_id].items
<|endoftext|>


<commit_before>"""
File:           defines.py
Author:         Andreas Poehlmann

Some definitions
"""

VendorId = 0x2457
ModelNames = {
    0x1002: 'USB2000',
    0x100a: 'HR2000',
    0x1012: 'HR4000',
    0x1014: 'USB650',
    0x1016: 'HR2000PLUS',
    0x1018: 'QE65000',
    0x101E: 'USB2000PLUS',
    0x1022: 'USB4000',
    0x1026: 'NIRQUEST512',
    0x1028: 'NIRQUEST256',
    0x102a: 'MAYA2000PRO',
    0x102c: 'MAYA2000',
    0x1040: 'TORUS',
    0x1044: 'APEX',
    0x1046: 'MAYALSL',
    0x2000: 'JAZ',
    0x4000: 'STS',
    0x4004: 'QEPRO',
    0x5000: 'VENTANA',
}
ProductIds = list(ModelNames.keys())
SpectrometerClasses = list(ModelNames.values())

DarkPixels = {
    'USB2000'	  : list(range(2, 24)),
    'HR2000'	  : list(range(2, 24)),
    'HR4000'	  : list(range(2, 13)),
    'USB650'	  : [],  # ??? unkown
    'HR2000PLUS'  : list(range(2, 24)),
    'QE65000'	  : list(range(0, 4)) + list(range(1040, 1044)),  # as in seabreeze-3.0.5
    'USB2000PLUS' : list(range(2, 24)),
    'USB4000'	  : list(range(2, 13)),
    'NIRQUEST512' : [],
    'NIRQUEST256' : [],
    'MAYA2000PRO' : list(range(0, 4)) + list(range(2064, 2068)),
    'MAYA2000'	  : list(range(0, 8)) + list(range(2072, 2080)),
    'TORUS'	  : [],
    'APEX'	  : list(range(0, 4)) + list(range(2064, 2068)),
    'MAYALSL'     : list(range(0, 4)) + list(range(2064, 2068)),
    'JAZ'	  : list(range(2, 24)),
    'STS'	  : [],
    'QEPRO'	  : list(range(0, 4)) + list(range(1040, 1044)),
    'VENTANA'	  : [],
}

class _EndPointMap(object):
    def __init__(self, ep_out=None, lowspeed_in=None,
                 highspeed_in=None, highspeed_in2=None):
        self.ep_out = ep_out
        self.lowspeed_in = lowspeed_in
        self.highspeed_in = highspeed_in
        self.highspeed_in2 = highspeed_in2

_EML2K = _EndPointMap(ep_out=0x02, lowspeed_in=0x87, highspeed_in=0x82)
_EMFPGA = _EndPointMap(ep_out=0x01, lowspeed_in=0x81, highspeed_in=0x82, highspeed_in2=0x86)
_EMDUAL = _EndPointMap(ep_out=0x01, lowspeed_in=0x81)  # XXX: we'll ignore the alternative EPs
_EMVENT = _EndPointMap(ep_out=0x01, lowspeed_in=0x82)
_EMJAZ = _EndPointMap(ep_out=0x01, lowspeed_in=0x81, highspeed_in=0x82)

EndPoints= {
     'USB2000'	   : _EML2K,
     'HR2000'	   : _EML2K,
     'HR4000'	   : _EMFPGA,  # usbspeed  ^0x2000
     'USB650'	   : _EML2K,  # ??? assumed
     'HR2000PLUS'  : _EMFPGA,  # usbspeed  ^0x2000
     'QE65000'	   : _EMFPGA,  # usbspeed  ^0x8000
     'USB2000PLUS' : _EMFPGA,  # usbspeed
     'USB4000'	   : _EMFPGA,  # usbspeed
     'NIRQUEST512' : _EMFPGA,
     'NIRQUEST256' : _EMFPGA,
     'MAYA2000PRO' : _EMFPGA,  # usbspeed
     'MAYA2000'	   : _EMFPGA,  # usbspeed
     'TORUS'	   : _EMFPGA,  # usbspeed
     'APEX'	   : _EMFPGA,  # usbspeed
     'MAYALSL'     : _EMFPGA,  # usbspeed
     'JAZ'	   : _EMJAZ,
     'STS'	   : _EMDUAL,
     'QEPRO'	   : _EMDUAL,
     'VENTANA'	   : _EMVENT,
}

TriggerModes = {
    'USB2000' : {
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'EXT_HW'       : 3,
    },
    'HR2000' : {
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'EXT_HW'       : 3,
    },
    'HR4000'	   : {
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'EXT_HW'       : 3,
       'EXT_HW_SYNC'  : 2,
    },
    'HR2000PLUS'  : {
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'EXT_HW'       : 2,
       'EXT_HW_SYNC'  : 3,
       'EXT_HW_EDGE'  : 4,
        },
    'QE65000'	   : {
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'EXT_HW'       : 3,
       'EXT_HW_SYNC'  : 2,
        },
    'USB2000PLUS' : {
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'EXT_HW'       : 2,
       'EXT_HW_SYNC'  : 3,
       'EXT_HW_EDGE'  : 4,
        },
    'USB4000'	   : {
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'EXT_HW'       : 3,
       'EXT_HW_SYNC'  : 2,
        },
    'NIRQUEST512' : {
       'FREE_RUNNING' : 0,
       'EXT_HW'       : 2,
        },
    'NIRQUEST256' : {
       'FREE_RUNNING' : 0,
       'EXT_HW'       : 2,
        },
    'MAYA2000PRO' : {
       'FREE_RUNNING' : 0,
       'EXT_HW'       : 1,
       'EXT_HW_SYNC'  : 2,
       'EXT_HW_EDGE'  : 3,
        },
    'MAYA2000'	   : {
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'REALTIME'     : 3,
        },
    'MAYALSL'	   : {
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'REALTIME'     : 3,
        },
    'TORUS'	   : {
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'EXT_HW'       : 2,
       'EXT_HW_SYNC'  : 3,
       'EXT_HW_EDGE'  : 4,
        },
    'APEX'	   : dict(),
    'JAZ'	   : dict(),  # FIXME
    'STS'	   : {
       'FREE_RUNNING' : 2,
       'SOFTWARE'     : 0,
       'EXT_HW'       : 1,
        },
    'QEPRO'	   : dict(),  # FIXME
    'VENTANA'	   : dict(),  # FIXME
    'USB650'	   : {  # ??? assumed.
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'EXT_HW'       : 3,
        },
}

<commit_msg>Update electric dark pixels in pyseabreeze<commit_after>"""
File:           defines.py
Author:         Andreas Poehlmann

Some definitions
"""

VendorId = 0x2457
ModelNames = {
    0x1002: 'USB2000',
    0x100a: 'HR2000',
    0x1012: 'HR4000',
    0x1014: 'USB650',
    0x1016: 'HR2000PLUS',
    0x1018: 'QE65000',
    0x101E: 'USB2000PLUS',
    0x1022: 'USB4000',
    0x1026: 'NIRQUEST512',
    0x1028: 'NIRQUEST256',
    0x102a: 'MAYA2000PRO',
    0x102c: 'MAYA2000',
    0x1040: 'TORUS',
    0x1044: 'APEX',
    0x1046: 'MAYALSL',
    0x2000: 'JAZ',
    0x4000: 'STS',
    0x4004: 'QEPRO',
    0x5000: 'VENTANA',
}
ProductIds = list(ModelNames.keys())
SpectrometerClasses = list(ModelNames.values())

DarkPixels = {
    'USB2000'	  : list(range(2, 24)),
    'HR2000'	  : list(range(2, 24)),
    'HR4000'	  : list(range(2, 13)),
    'USB650'	  : [],  # ??? unkown
    'HR2000PLUS'  : list(range(2, 24)),
    'QE65000'	  : list(range(0, 4)) + list(range(1040, 1044)),  # as in seabreeze-3.0.5
    'USB2000PLUS' : list(range(6, 21)),  # as in seabreeze-3.0.9
    'USB4000'	  : list(range(5, 16)),  # as in seabreeze-3.0.9
    'NIRQUEST512' : [],
    'NIRQUEST256' : [],
    'MAYA2000PRO' : list(range(0, 4)) + list(range(2064, 2068)),
    'MAYA2000'	  : list(range(0, 8)) + list(range(2072, 2080)),
    'TORUS'	  : [],
    'APEX'	  : list(range(0, 4)) + list(range(2064, 2068)),
    'MAYALSL'     : list(range(0, 4)) + list(range(2064, 2068)),
    'JAZ'	  : list(range(2, 24)),
    'STS'	  : [],
    'QEPRO'	  : list(range(0, 4)) + list(range(1040, 1044)),
    'VENTANA'	  : [],
}

class _EndPointMap(object):
    def __init__(self, ep_out=None, lowspeed_in=None,
                 highspeed_in=None, highspeed_in2=None):
        self.ep_out = ep_out
        self.lowspeed_in = lowspeed_in
        self.highspeed_in = highspeed_in
        self.highspeed_in2 = highspeed_in2

_EML2K = _EndPointMap(ep_out=0x02, lowspeed_in=0x87, highspeed_in=0x82)
_EMFPGA = _EndPointMap(ep_out=0x01, lowspeed_in=0x81, highspeed_in=0x82, highspeed_in2=0x86)
_EMDUAL = _EndPointMap(ep_out=0x01, lowspeed_in=0x81)  # XXX: we'll ignore the alternative EPs
_EMVENT = _EndPointMap(ep_out=0x01, lowspeed_in=0x82)
_EMJAZ = _EndPointMap(ep_out=0x01, lowspeed_in=0x81, highspeed_in=0x82)

EndPoints= {
     'USB2000'	   : _EML2K,
     'HR2000'	   : _EML2K,
     'HR4000'	   : _EMFPGA,  # usbspeed  ^0x2000
     'USB650'	   : _EML2K,  # ??? assumed
     'HR2000PLUS'  : _EMFPGA,  # usbspeed  ^0x2000
     'QE65000'	   : _EMFPGA,  # usbspeed  ^0x8000
     'USB2000PLUS' : _EMFPGA,  # usbspeed
     'USB4000'	   : _EMFPGA,  # usbspeed
     'NIRQUEST512' : _EMFPGA,
     'NIRQUEST256' : _EMFPGA,
     'MAYA2000PRO' : _EMFPGA,  # usbspeed
     'MAYA2000'	   : _EMFPGA,  # usbspeed
     'TORUS'	   : _EMFPGA,  # usbspeed
     'APEX'	   : _EMFPGA,  # usbspeed
     'MAYALSL'     : _EMFPGA,  # usbspeed
     'JAZ'	   : _EMJAZ,
     'STS'	   : _EMDUAL,
     'QEPRO'	   : _EMDUAL,
     'VENTANA'	   : _EMVENT,
}

TriggerModes = {
    'USB2000' : {
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'EXT_HW'       : 3,
    },
    'HR2000' : {
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'EXT_HW'       : 3,
    },
    'HR4000'	   : {
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'EXT_HW'       : 3,
       'EXT_HW_SYNC'  : 2,
    },
    'HR2000PLUS'  : {
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'EXT_HW'       : 2,
       'EXT_HW_SYNC'  : 3,
       'EXT_HW_EDGE'  : 4,
        },
    'QE65000'	   : {
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'EXT_HW'       : 3,
       'EXT_HW_SYNC'  : 2,
        },
    'USB2000PLUS' : {
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'EXT_HW'       : 2,
       'EXT_HW_SYNC'  : 3,
       'EXT_HW_EDGE'  : 4,
        },
    'USB4000'	   : {
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'EXT_HW'       : 3,
       'EXT_HW_SYNC'  : 2,
        },
    'NIRQUEST512' : {
       'FREE_RUNNING' : 0,
       'EXT_HW'       : 2,
        },
    'NIRQUEST256' : {
       'FREE_RUNNING' : 0,
       'EXT_HW'       : 2,
        },
    'MAYA2000PRO' : {
       'FREE_RUNNING' : 0,
       'EXT_HW'       : 1,
       'EXT_HW_SYNC'  : 2,
       'EXT_HW_EDGE'  : 3,
        },
    'MAYA2000'	   : {
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'REALTIME'     : 3,
        },
    'MAYALSL'	   : {
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'REALTIME'     : 3,
        },
    'TORUS'	   : {
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'EXT_HW'       : 2,
       'EXT_HW_SYNC'  : 3,
       'EXT_HW_EDGE'  : 4,
        },
    'APEX'	   : dict(),
    'JAZ'	   : dict(),  # FIXME
    'STS'	   : {
       'FREE_RUNNING' : 2,
       'SOFTWARE'     : 0,
       'EXT_HW'       : 1,
        },
    'QEPRO'	   : dict(),  # FIXME
    'VENTANA'	   : dict(),  # FIXME
    'USB650'	   : {  # ??? assumed.
       'FREE_RUNNING' : 0,
       'SOFTWARE'     : 1,
       'EXT_HW'       : 3,
        },
}

<|endoftext|>


<commit_before>import os
import json
import socket
import sys
import time
import traceback
import xmlrpclib

from core.models import Slice, Instance, ServiceClass, Reservation, Tag, Network, User, Node, Image, Deployment, Site, NetworkTemplate, NetworkSlice

from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

def ps_id_to_pl_id(x):
    # Since we don't want the XOS object IDs to conflict with existing
    # PlanetLab object IDs in the CMI, just add 100000 to the XOS object
    # IDs.
    return 100000 + x

def pl_id_to_ps_id(x):
    return x - 100000

# slice_remap is a dict of ps_slice_name -> (pl_slice_name, pl_slice_id)

def pl_slice_id(slice, slice_remap={}):
    if slice.name in slice_remap:
        return int(slice_remap[slice.name][1])
    else:
        return ps_id_to_pl_id(slice.id)

def pl_slicename(slice, slice_remap={}):
    if slice.name in slice_remap:
        return slice_remap[slice.name][0]
    else:
        return slice.name

def filter_fields(src, fields):
    dest = {}
    for (key,value) in src.items():
        if (not fields) or (key in fields):
            dest[key] = value
    return dest

def GetSlices(filter={}, slice_remap={}):
    #ps_slices = Slice.objects.filter(**filter)
    ps_slices = Slice.objects.all()
    slices = []
    for ps_slice in ps_slices:
        if (filter) and ("name" in filter):
            remapped_name = slice_remap.get(ps_slice.name, (ps_slice.name,))[0]
            if (remapped_name != filter["name"]):
                continue

        node_ids=[]
        for ps_instance in ps_slice.instances.all():
            node_ids.append(ps_id_to_pl_id(ps_instance.node.id))

        slice = {"instantiation": "plc-instantiated",
                 "description": "XOS slice",
                 "slice_id": pl_slice_id(ps_slice, slice_remap),
                 "node_ids": node_ids,
                 "url": "xos",
                 "max_nodes": 1000,
                 "peer_slice_id": None,
                 "slice_tag_ids": [],
                 "peer_id": None,
                 "site_id": ps_id_to_pl_id(ps_slice.site_id),
                 "name": pl_slicename(ps_slice, slice_remap),
                 "planetstack_name": ps_slice.name}     # keeping planetstack_name for now, to match the modified config.py

                 # creator_person_id, person_ids, expires, created

        slices.append(slice)
    return slices

def GetNodes(node_ids=None, fields=None, slice_remap={}):
    if node_ids:
        ps_nodes = Node.objects.filter(id__in=[pl_id_to_ps_id(nid) for nid in node_ids])
    else:
        ps_nodes = Node.objects.all()
    nodes = []
    for ps_node in ps_nodes:
        slice_ids=[]
        for ps_instance in ps_node.instances.all():
            slice_ids.append(pl_slice_id(ps_instance.slice, slice_remap))

        node = {"node_id": ps_id_to_pl_id(ps_node.id),
                "site_id": ps_id_to_pl_id(ps_node.site_id),
                "node_type": "regular",
                "peer_node_id": None,
                "hostname": ps_node.name.lower(),
                "conf_file_ids": [],
                "slice_ids": slice_ids,
                "model": "xos",
                "peer_id": None,
                "node_tag_ids": []}

                # last_updated, key, boot_state, pcu_ids, node_type, session, last_boot,
                # interface_ids, slice_ids_whitelist, run_level, ssh_rsa_key, last_pcu_reboot,
                # nodegroup_ids, verified, last_contact, boot_nonce, version,
                # last_pcu_configuration, last_download, date_created, ports

        nodes.append(node)

    nodes = [filter_fields(node, fields) for node in nodes]

    return nodes

def GetTags(slicename,node_id):
    return {}

def GetSites(slice_remap={}):
    ps_sites = Site.objects.all()
    sites = []
    for ps_site in ps_sites:
        slice_ids=[]
        for ps_slice in ps_site.slices.all():
            slice_ids.append(pl_slice_id(ps_slice, slice_remap))

        node_ids=[]
        for ps_node in ps_site.nodes.all():
            node_ids.append(ps_id_to_pl_id(ps_node.id))

        site = {"site_id": ps_id_to_pl_id(ps_site.id),
                "node_ids": node_ids,
                "pcu_ids": [],
                "max_slices": 100,
                "max_instances": 1000,
                "is_public": False,
                "peer_site_id": None,
                "abbrebiated_name": ps_site.abbreviated_name,
                "address_ids": [],
                "name": ps_site.name,
                "url": None,
                "site_tag_ids": [],
                "enabled": True,
                "longitude": float(ps_site.location.longitude),
                "latitude": float(ps_site.location.latitude),
                "slice_ids": slice_ids,
                "login_base": ps_site.login_base,
                "peer_id": None}

                # last_updated, ext_consortium_id, person_ids, date_created

        sites.append(site)

    return sites

def GetInterfaces(slicename, node_ids, return_nat=False, return_private=False):
    interfaces = []
    ps_slices = Slice.objects.filter(name=slicename)
    for ps_slice in ps_slices:
        for ps_instance in ps_slice.instances.all():
            node_id = ps_id_to_pl_id(ps_instance.node_id)
            if node_id in node_ids:
                ps_node = ps_instance.node

                ip = socket.gethostbyname(ps_node.name.strip())

                # If the slice has a network that's labeled for hpc_client, then
                # return that network.
                found_labeled_network = False
                for port in ps_instance.ports.all():
                    if (not port.ip):
                        continue
                    if (port.network.owner != ps_slice):
                        continue
                    if port.network.labels and ("hpc_client" in port.network.labels):
                        ip=port.ip
                        found_labeled_network = True

                if not found_labeled_network:
                    # search for a dedicated public IP address
                    for port in ps_instance.ports.all():
                        if (not port.ip):
                            continue
                        template = port.network.template
                        if (template.visibility=="public") and (template.translation=="none"):
                            ip=port.ip

                if return_nat:
                    ip = None
                    for port in ps_instance.ports.all():
                        if (not port.ip):
                            continue
                        template = port.network.template
                        if (template.visibility=="private") and (template.translation=="NAT"):
                            ip=port.ip
                    if not ip:
                        continue

                if return_private:
                    ip = None
                    for port in ps_instance.ports.all():
                        if (not port.ip):
                            continue
                        template = port.network.template
                        if (template.visibility=="private") and (template.translation=="none"):
                            ip=port.ip
                    if not ip:
                        continue

                interface = {"node_id": node_id,
                             "ip": ip,
                             "broadcast": None,
                             "mac": "11:22:33:44:55:66",
                             "bwlimit": None,
                             "network": None,
                             "is_primary": True,
                             "dns1": None,
                             "hostname": None,
                             "netmask": None,
                             "interface_tag_ids": [],
                             "interface_id": node_id,     # assume each node has only one interface
                             "gateway": None,
                             "dns2": None,
                             "type": "ipv4",
                             "method": "dhcp"}
                interfaces.append(interface)
    return interfaces

def GetConfiguration(name, slice_remap={}):
    slicename = name["name"]
    if "node_id" in name:
        node_id = name["node_id"]
    else:
        node_id = 0

    node_instance_tags = GetTags(slicename, node_id)

    slices = GetSlices({"name": slicename}, slice_remap=slice_remap)
    perhost = {}
    allinterfaces = {}
    hostprivmap = {}
    hostipmap = {}
    hostnatmap = {}
    nodes = []
    if len(slices)==1:
        slice = slices[0]
        node_ids = slice['node_ids']
        nodes = GetNodes(node_ids, ['hostname', 'node_id', 'site_id'], slice_remap=slice_remap)
        nodemap = {}
        for node in nodes:
            nodemap[node['node_id']]=node['hostname']

        interfaces = GetInterfaces(slice["planetstack_name"], node_ids)
        hostipmap = {}
        for interface in interfaces:
            if nodemap[interface['node_id']] not in allinterfaces:
                allinterfaces[nodemap[interface['node_id']]] = []
            interface['interface_tags'] = []
            allinterfaces[nodemap[interface['node_id']]].append(interface)
            if interface['is_primary']:
                hostipmap[nodemap[interface['node_id']]] = interface['ip']

        hostnatmap = {}
        interfaces = GetInterfaces(slice["planetstack_name"], node_ids, return_nat=True)
        for interface in interfaces:
            interface['interface_tags'] = []
            hostnatmap[nodemap[interface['node_id']]] = interface['ip']

        hostprivmap = {}
        interfaces = GetInterfaces(slice["planetstack_name"], node_ids, return_private=True)
        for interface in interfaces:
            interface['interface_tags'] = []
            hostprivmap[nodemap[interface['node_id']]] = interface['ip']

        for nid in node_ids:
            instance_tags = GetTags(slicename,nid)
            perhost[nodemap[nid]] = instance_tags

    instances = GetSlices(slice_remap=slice_remap)
    if node_id != 0:
        instances = [slice for slice in instances if (node_id in slice.node_ids)]

    sites = GetSites(slice_remap=slice_remap)
    for site in sites:
        site["site_tags"] = []

    timestamp = int(time.time())
    return {'version': 3,
            'timestamp': timestamp,
            'configuration': node_instance_tags,
            'allconfigurations':perhost,
            'hostipmap':hostipmap,
            'hostnatmap':hostnatmap,
            'hostprivmap':hostprivmap,
            'instances': instances,
            'interfaces': allinterfaces,
            'sites': sites,
            'nodes': nodes}

DEFAULT_REMAP = {"princeton_vcoblitz2": ["princeton_vcoblitz", 70]}

def HandleGetConfiguration1():
    configs={}
    for slicename in ["princeton_vcoblitz"]:
        configs[slicename] = GetConfiguration({"name": slicename}, DEFAULT_REMAP)
    return configs

def HandleGetNodes1():
    return GetNodes(slice_remap=DEFAULT_REMAP)

def HandleGetSlices1():
    return GetSlices(slice_remap=DEFAULT_REMAP)

def HandleGetConfiguration2(name, slice_remap):
    return GetConfiguration(name, slice_remap=slice_remap)

def HandleGetNodes2(slice_remap):
    return GetNodes(slice_remap=slice_remap)

def HandleGetSlices2(slice_remap):
    return GetSlices(slice_remap=slice_remap)

FUNCS = {"GetConfiguration": HandleGetConfiguration1,
         "GetNodes": HandleGetNodes1,
         "GetSlices": HandleGetSlices1,
         "GetConfiguration2": HandleGetConfiguration2,
         "GetNodes2": HandleGetNodes2,
         "GetSlices2": HandleGetSlices2}

@csrf_exempt
def LegacyXMLRPC(request):
    if request.method == "POST":
        try:
            (args, method) = xmlrpclib.loads(request.body)
            result = None
            if method in FUNCS:
                result = FUNCS[method](*args)
            return HttpResponse(xmlrpclib.dumps((result,), methodresponse=True, allow_none=1))
        except:
            traceback.print_exc()
            return HttpResponseServerError()
    else:
        return HttpResponse("Not Implemented")

if __name__ == '__main__':
    slices = GetSlices(slice_remap = DEFAULT_REMAP)
    nodes = GetNodes(slice_remap = DEFAULT_REMAP)

    config = GetConfiguration({"name": "princeton_vcoblitz"}, slice_remap = DEFAULT_REMAP)
    print config
    print slices
    print nodes

<commit_msg>compatibility api expects to access instances using the sliver keyword<commit_after>import os
import json
import socket
import sys
import time
import traceback
import xmlrpclib

from core.models import Slice, Instance, ServiceClass, Reservation, Tag, Network, User, Node, Image, Deployment, Site, NetworkTemplate, NetworkSlice

from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

def ps_id_to_pl_id(x):
    # Since we don't want the XOS object IDs to conflict with existing
    # PlanetLab object IDs in the CMI, just add 100000 to the XOS object
    # IDs.
    return 100000 + x

def pl_id_to_ps_id(x):
    return x - 100000

# slice_remap is a dict of ps_slice_name -> (pl_slice_name, pl_slice_id)

def pl_slice_id(slice, slice_remap={}):
    if slice.name in slice_remap:
        return int(slice_remap[slice.name][1])
    else:
        return ps_id_to_pl_id(slice.id)

def pl_slicename(slice, slice_remap={}):
    if slice.name in slice_remap:
        return slice_remap[slice.name][0]
    else:
        return slice.name

def filter_fields(src, fields):
    dest = {}
    for (key,value) in src.items():
        if (not fields) or (key in fields):
            dest[key] = value
    return dest

def GetSlices(filter={}, slice_remap={}):
    #ps_slices = Slice.objects.filter(**filter)
    ps_slices = Slice.objects.all()
    slices = []
    for ps_slice in ps_slices:
        if (filter) and ("name" in filter):
            remapped_name = slice_remap.get(ps_slice.name, (ps_slice.name,))[0]
            if (remapped_name != filter["name"]):
                continue

        node_ids=[]
        for ps_instance in ps_slice.instances.all():
            node_ids.append(ps_id_to_pl_id(ps_instance.node.id))

        slice = {"instantiation": "plc-instantiated",
                 "description": "XOS slice",
                 "slice_id": pl_slice_id(ps_slice, slice_remap),
                 "node_ids": node_ids,
                 "url": "xos",
                 "max_nodes": 1000,
                 "peer_slice_id": None,
                 "slice_tag_ids": [],
                 "peer_id": None,
                 "site_id": ps_id_to_pl_id(ps_slice.site_id),
                 "name": pl_slicename(ps_slice, slice_remap),
                 "planetstack_name": ps_slice.name}     # keeping planetstack_name for now, to match the modified config.py

                 # creator_person_id, person_ids, expires, created

        slices.append(slice)
    return slices

def GetNodes(node_ids=None, fields=None, slice_remap={}):
    if node_ids:
        ps_nodes = Node.objects.filter(id__in=[pl_id_to_ps_id(nid) for nid in node_ids])
    else:
        ps_nodes = Node.objects.all()
    nodes = []
    for ps_node in ps_nodes:
        slice_ids=[]
        for ps_instance in ps_node.instances.all():
            slice_ids.append(pl_slice_id(ps_instance.slice, slice_remap))

        node = {"node_id": ps_id_to_pl_id(ps_node.id),
                "site_id": ps_id_to_pl_id(ps_node.site_id),
                "node_type": "regular",
                "peer_node_id": None,
                "hostname": ps_node.name.lower(),
                "conf_file_ids": [],
                "slice_ids": slice_ids,
                "model": "xos",
                "peer_id": None,
                "node_tag_ids": []}

                # last_updated, key, boot_state, pcu_ids, node_type, session, last_boot,
                # interface_ids, slice_ids_whitelist, run_level, ssh_rsa_key, last_pcu_reboot,
                # nodegroup_ids, verified, last_contact, boot_nonce, version,
                # last_pcu_configuration, last_download, date_created, ports

        nodes.append(node)

    nodes = [filter_fields(node, fields) for node in nodes]

    return nodes

def GetTags(slicename,node_id):
    return {}

def GetSites(slice_remap={}):
    ps_sites = Site.objects.all()
    sites = []
    for ps_site in ps_sites:
        slice_ids=[]
        for ps_slice in ps_site.slices.all():
            slice_ids.append(pl_slice_id(ps_slice, slice_remap))

        node_ids=[]
        for ps_node in ps_site.nodes.all():
            node_ids.append(ps_id_to_pl_id(ps_node.id))

        site = {"site_id": ps_id_to_pl_id(ps_site.id),
                "node_ids": node_ids,
                "pcu_ids": [],
                "max_slices": 100,
                "max_slivers": 1000,
                "is_public": False,
                "peer_site_id": None,
                "abbrebiated_name": ps_site.abbreviated_name,
                "address_ids": [],
                "name": ps_site.name,
                "url": None,
                "site_tag_ids": [],
                "enabled": True,
                "longitude": float(ps_site.location.longitude),
                "latitude": float(ps_site.location.latitude),
                "slice_ids": slice_ids,
                "login_base": ps_site.login_base,
                "peer_id": None}

                # last_updated, ext_consortium_id, person_ids, date_created

        sites.append(site)

    return sites

def GetInterfaces(slicename, node_ids, return_nat=False, return_private=False):
    interfaces = []
    ps_slices = Slice.objects.filter(name=slicename)
    for ps_slice in ps_slices:
        for ps_instance in ps_slice.instances.all():
            node_id = ps_id_to_pl_id(ps_instance.node_id)
            if node_id in node_ids:
                ps_node = ps_instance.node

                ip = socket.gethostbyname(ps_node.name.strip())

                # If the slice has a network that's labeled for hpc_client, then
                # return that network.
                found_labeled_network = False
                for port in ps_instance.ports.all():
                    if (not port.ip):
                        continue
                    if (port.network.owner != ps_slice):
                        continue
                    if port.network.labels and ("hpc_client" in port.network.labels):
                        ip=port.ip
                        found_labeled_network = True

                if not found_labeled_network:
                    # search for a dedicated public IP address
                    for port in ps_instance.ports.all():
                        if (not port.ip):
                            continue
                        template = port.network.template
                        if (template.visibility=="public") and (template.translation=="none"):
                            ip=port.ip

                if return_nat:
                    ip = None
                    for port in ps_instance.ports.all():
                        if (not port.ip):
                            continue
                        template = port.network.template
                        if (template.visibility=="private") and (template.translation=="NAT"):
                            ip=port.ip
                    if not ip:
                        continue

                if return_private:
                    ip = None
                    for port in ps_instance.ports.all():
                        if (not port.ip):
                            continue
                        template = port.network.template
                        if (template.visibility=="private") and (template.translation=="none"):
                            ip=port.ip
                    if not ip:
                        continue

                interface = {"node_id": node_id,
                             "ip": ip,
                             "broadcast": None,
                             "mac": "11:22:33:44:55:66",
                             "bwlimit": None,
                             "network": None,
                             "is_primary": True,
                             "dns1": None,
                             "hostname": None,
                             "netmask": None,
                             "interface_tag_ids": [],
                             "interface_id": node_id,     # assume each node has only one interface
                             "gateway": None,
                             "dns2": None,
                             "type": "ipv4",
                             "method": "dhcp"}
                interfaces.append(interface)
    return interfaces

def GetConfiguration(name, slice_remap={}):
    slicename = name["name"]
    if "node_id" in name:
        node_id = name["node_id"]
    else:
        node_id = 0

    node_instance_tags = GetTags(slicename, node_id)

    slices = GetSlices({"name": slicename}, slice_remap=slice_remap)
    perhost = {}
    allinterfaces = {}
    hostprivmap = {}
    hostipmap = {}
    hostnatmap = {}
    nodes = []
    if len(slices)==1:
        slice = slices[0]
        node_ids = slice['node_ids']
        nodes = GetNodes(node_ids, ['hostname', 'node_id', 'site_id'], slice_remap=slice_remap)
        nodemap = {}
        for node in nodes:
            nodemap[node['node_id']]=node['hostname']

        interfaces = GetInterfaces(slice["planetstack_name"], node_ids)
        hostipmap = {}
        for interface in interfaces:
            if nodemap[interface['node_id']] not in allinterfaces:
                allinterfaces[nodemap[interface['node_id']]] = []
            interface['interface_tags'] = []
            allinterfaces[nodemap[interface['node_id']]].append(interface)
            if interface['is_primary']:
                hostipmap[nodemap[interface['node_id']]] = interface['ip']

        hostnatmap = {}
        interfaces = GetInterfaces(slice["planetstack_name"], node_ids, return_nat=True)
        for interface in interfaces:
            interface['interface_tags'] = []
            hostnatmap[nodemap[interface['node_id']]] = interface['ip']

        hostprivmap = {}
        interfaces = GetInterfaces(slice["planetstack_name"], node_ids, return_private=True)
        for interface in interfaces:
            interface['interface_tags'] = []
            hostprivmap[nodemap[interface['node_id']]] = interface['ip']

        for nid in node_ids:
            instance_tags = GetTags(slicename,nid)
            perhost[nodemap[nid]] = instance_tags

    instances = GetSlices(slice_remap=slice_remap)
    if node_id != 0:
        instances = [slice for slice in instances if (node_id in slice.node_ids)]

    sites = GetSites(slice_remap=slice_remap)
    for site in sites:
        site["site_tags"] = []

    timestamp = int(time.time())
    return {'version': 3,
            'timestamp': timestamp,
            'configuration': node_instance_tags,
            'allconfigurations':perhost,
            'hostipmap':hostipmap,
            'hostnatmap':hostnatmap,
            'hostprivmap':hostprivmap,
            'slivers': instances,
            'interfaces': allinterfaces,
            'sites': sites,
            'nodes': nodes}

DEFAULT_REMAP = {"princeton_vcoblitz2": ["princeton_vcoblitz", 70]}

def HandleGetConfiguration1():
    configs={}
    for slicename in ["princeton_vcoblitz"]:
        configs[slicename] = GetConfiguration({"name": slicename}, DEFAULT_REMAP)
    return configs

def HandleGetNodes1():
    return GetNodes(slice_remap=DEFAULT_REMAP)

def HandleGetSlices1():
    return GetSlices(slice_remap=DEFAULT_REMAP)

def HandleGetConfiguration2(name, slice_remap):
    return GetConfiguration(name, slice_remap=slice_remap)

def HandleGetNodes2(slice_remap):
    return GetNodes(slice_remap=slice_remap)

def HandleGetSlices2(slice_remap):
    return GetSlices(slice_remap=slice_remap)

FUNCS = {"GetConfiguration": HandleGetConfiguration1,
         "GetNodes": HandleGetNodes1,
         "GetSlices": HandleGetSlices1,
         "GetConfiguration2": HandleGetConfiguration2,
         "GetNodes2": HandleGetNodes2,
         "GetSlices2": HandleGetSlices2}

@csrf_exempt
def LegacyXMLRPC(request):
    if request.method == "POST":
        try:
            (args, method) = xmlrpclib.loads(request.body)
            result = None
            if method in FUNCS:
                result = FUNCS[method](*args)
            return HttpResponse(xmlrpclib.dumps((result,), methodresponse=True, allow_none=1))
        except:
            traceback.print_exc()
            return HttpResponseServerError()
    else:
        return HttpResponse("Not Implemented")

if __name__ == '__main__':
    slices = GetSlices(slice_remap = DEFAULT_REMAP)
    nodes = GetNodes(slice_remap = DEFAULT_REMAP)

    config = GetConfiguration({"name": "princeton_vcoblitz"}, slice_remap = DEFAULT_REMAP)
    print config
    print slices
    print nodes

<|endoftext|>


<commit_before>from decimal import Decimal

from lib.connectwise_py.connectwise.activity import Activity
from lib.connectwise_py.connectwise.member import Member
from lib.connectwise_py.connectwise.ticket import Ticket
from .connectwise import Connectwise

class TimeEntry:
    def __init__(self, chargeToId, chargeToType, **kwargs):
        self.chargeToId = chargeToId
        self.chargeToType = chargeToType
        self.estHourlyCost = 0
        self.estCost = 0
        for kwarg in kwargs:
            setattr(self, kwarg, kwargs[kwarg])
        self.actualHours = Decimal(kwargs['actualHours'])

    def __repr__(self):
        return "<Time Entry {}>".format(self.chargeToId)

    @classmethod
    def fetch_by_member_identifier(cls, member_identifier, on_or_after=None, before=None):
        conditions = ['member/identifier="{}"'.format(member_identifier)]
        if on_or_after:
            conditions.append('timeStart>=[{}]'.format(on_or_after))
        if before:
            conditions.append('timeStart<[{}]'.format(before))
        return [cls(**time_entry) for time_entry in Connectwise.submit_request('time/entries', conditions)]

    @classmethod
    def fetch_vacation_by_member_identifier(cls, member_identifier):
        conditions = ['member/identifier="{}"'.format(member_identifier), 'workType/id=7']  # Vacation work type
        return [cls(**time_entry) for time_entry in Connectwise.submit_request('time/entries', conditions)]

    @classmethod
    def fetch_pd(cls):
        conditions = ['workType/id=29']  # PD work type
        return [cls(**time_entry) for time_entry in Connectwise.submit_request('time/entries', conditions)]

    @classmethod
    def fetch_pd_by_member_identifier(cls, member_identifier):
        conditions = ['member/identifier="{}"'.format(member_identifier), 'workType/id=29']  # PD work type
        return [cls(**time_entry) for time_entry in Connectwise.submit_request('time/entries', conditions)]

    @classmethod
    def fetch_by_date_range(cls, on_or_after=None, before=None, fields=None):
        conditions = []
        if on_or_after:
            conditions.append('timeStart>=[{}]'.format(on_or_after))
        if before:
            conditions.append('timeStart<[{}]'.format(before))

        return [cls(**time_entry) for time_entry in
                Connectwise.submit_request('time/entries', conditions, fields=fields)]

    @classmethod
    def fetch_by_company_id(cls, company_id, on_or_after=None, before=None):
        conditions = ['company/id={}'.format(company_id)]
        if on_or_after:
            conditions.append('timeStart>=[{}]'.format(on_or_after))
        if before:
            conditions.append('timeStart<[{}]'.format(before))

        return [cls(**time_entry) for time_entry in
                Connectwise.submit_request('time/entries', conditions)]

    @classmethod
    def fetch_by_charge_to_id(cls, charge_to_id, charge_to_type=None):
        conditions = ['chargeToId={}'.format(charge_to_id)]
        if charge_to_type: conditions.append('chargeToType="{}"'.format(charge_to_type))
        return [cls(**time_entry) for time_entry in
                Connectwise.submit_request('time/entries', conditions)]

    @classmethod
    def fetch_by_charge_to_ids(cls, charge_to_ids, on_or_after=None, before=None):
        if len(charge_to_ids) > 10:
            raise IOError('Cannot lookup more than 10 chargeToIds at once')
        conditions = ['({})'.format(
            'chargeToId={}'.format(' or chargeToId='.join('{}'.format(_id) for _id in charge_to_ids)))]
        if on_or_after: conditions.append('timeStart>=[{}]'.format(on_or_after))
        if before: conditions.append('timeStart<[{}]'.format(before))
        return [cls(**time_entry) for time_entry in
                Connectwise.submit_request('time/entries', conditions)]

    def service_location(self, schedule_entries=[], tickets=[]):
        if Connectwise.get_custom_field_value(self, 'Where'): return Connectwise.get_custom_field_value(self, 'Where')
        schedule_entry = [s.where['name'] for s in schedule_entries
                          if s.dateStart[:10] == self.timeStart[:10]
                          and s.objectId == self.chargeToId]
        if schedule_entry: return schedule_entry[0]

        ticket = [t.serviceLocation['name'] for t in tickets if t.id == self.chargeToId]
        if ticket: return ticket[0]

        return 'On-Site'

    def actual_days(self):
        return round(self.actualHours / 8, 2)

    def daily_rate(self):
        return Decimal(self.hourlyRate * 8)

    def billable_amount(self):
        if self.billableOption != 'Billable':
            return Decimal(0)
        return Decimal(self.hoursBilled * self.hourlyRate)

    def fetch_estimated_cost(self, members=None):

        if members:
            try:
                member = [member for member in members if member.identifier == self.member['identifier']][0]
            except IndexError:
                return 0
        else:
            try:
                member = Member.fetch_member_by_identifier(self.member['identifier'])
            except IndexError:
                return 0

        self.estHourlyCost = Decimal(member.hourly_cost(self.timeStart[:10]))

        if member.identifier.lower() == 'ktooredman' or member.identifier.lower() == 'psoldwedel':
            if self.billableOption == 'Billable':
                self.estHourlyCost = Decimal(150)
            else:
                self.estHourlyCost = Decimal(125)
        elif member.identifier.lower() == 'mvanclay':
            if self.billableOption == 'Billable':
                self.estHourlyCost = Decimal(137.5)
            else:
                self.estHourlyCost = Decimal(125)

        if self.workType['name'] == 'Professional Development':
            self.estHourlyCost = round(self.estHourlyCost / 2, 2)

        self.estCost = round(self.estHourlyCost * self.actualHours, 2)
        return self.estCost

    def get_charge_to_info(self, tickets=[], activities=[], charge_codes=[], return_type='string'):
        if self.chargeToType == 'Activity':
            if activities:
                self.activity = [activity for activity in activities if self.chargeToId == activity.id]
                if self.activity:
                    self.activity = self.activity[0]
                else:
                    self.activity = Activity.fetch_by_id(self.chargeToId)
                # if not self.activity:
                #     self.activity = Activity.fetch_by_id(self.chargeToId)
            else:
                # print('about to get activity')
                self.activity = Activity.fetch_by_id(self.chargeToId)
                # print('just got activity')
            # print('activity', self.activity)
            output = [self.company['name']]
            if hasattr(self.activity, 'opportunity'): output.append('{}'.format(self.activity.opportunity['name']))
            output.append('Activity #{}: {}'.format(self.activity.id, self.activity.name))

        elif self.chargeToType == 'ProjectTicket' or self.chargeToType == 'ServiceTicket':
            if tickets:
                # print('about to check haystack for ticket')
                self.ticket = [ticket for ticket in tickets if self.chargeToId == ticket.id]
                if self.ticket:
                    self.ticket = self.ticket[0]
                    # print('just found ticket in the haystack')
                else:
                    # print('couldnt find ticket in haystack, so getting it separately')
                    self.ticket = Ticket.fetch_by_id(self.chargeToId)
            else:
                # print('about to get ticket')
                self.ticket = Ticket.fetch_by_id(self.chargeToId)
                # print('just got ticket')
            # print('ticket', self.ticket)
            output = [self.company['name']]
            if self.ticket.project: output.append(self.ticket.project['name'])
            if self.ticket.phase: output.append(self.ticket.phase['name'])
            output.append('Ticket #{}: {}'.format(self.ticket.id, self.ticket.summary))
        else:
            output = [self.company['name'], self.chargeToType, '{}'.format(self.chargeToId)]

        if return_type == 'string':
            return ' / '.join(output)
        elif return_type == 'list':
            return output

        return output
<commit_msg>Added override_specific_member_hourly_cost method. It doesn't do anything here, but it can be used in a child class in your own project to modify self.estHourlyCost if you need to apply some custom business logic, as we did<commit_after>from decimal import Decimal

from lib.connectwise_py.connectwise.activity import Activity
from lib.connectwise_py.connectwise.member import Member
from lib.connectwise_py.connectwise.ticket import Ticket
from .connectwise import Connectwise

class TimeEntry:
    def __init__(self, chargeToId, chargeToType, **kwargs):
        self.chargeToId = chargeToId
        self.chargeToType = chargeToType
        self.estHourlyCost = 0
        self.estCost = 0
        for kwarg in kwargs:
            setattr(self, kwarg, kwargs[kwarg])
        self.actualHours = Decimal(kwargs['actualHours'])

    def __repr__(self):
        return "<Time Entry {}>".format(self.chargeToId)

    @classmethod
    def fetch_by_member_identifier(cls, member_identifier, on_or_after=None, before=None):
        conditions = ['member/identifier="{}"'.format(member_identifier)]
        if on_or_after:
            conditions.append('timeStart>=[{}]'.format(on_or_after))
        if before:
            conditions.append('timeStart<[{}]'.format(before))
        return [cls(**time_entry) for time_entry in Connectwise.submit_request('time/entries', conditions)]

    @classmethod
    def fetch_vacation_by_member_identifier(cls, member_identifier):
        conditions = ['member/identifier="{}"'.format(member_identifier), 'workType/id=7']  # Vacation work type
        return [cls(**time_entry) for time_entry in Connectwise.submit_request('time/entries', conditions)]

    @classmethod
    def fetch_pd(cls):
        conditions = ['workType/id=29']  # PD work type
        return [cls(**time_entry) for time_entry in Connectwise.submit_request('time/entries', conditions)]

    @classmethod
    def fetch_pd_by_member_identifier(cls, member_identifier):
        conditions = ['member/identifier="{}"'.format(member_identifier), 'workType/id=29']  # PD work type
        return [cls(**time_entry) for time_entry in Connectwise.submit_request('time/entries', conditions)]

    @classmethod
    def fetch_by_date_range(cls, on_or_after=None, before=None, fields=None):
        conditions = []
        if on_or_after:
            conditions.append('timeStart>=[{}]'.format(on_or_after))
        if before:
            conditions.append('timeStart<[{}]'.format(before))

        return [cls(**time_entry) for time_entry in
                Connectwise.submit_request('time/entries', conditions, fields=fields)]

    @classmethod
    def fetch_by_company_id(cls, company_id, on_or_after=None, before=None):
        conditions = ['company/id={}'.format(company_id)]
        if on_or_after:
            conditions.append('timeStart>=[{}]'.format(on_or_after))
        if before:
            conditions.append('timeStart<[{}]'.format(before))

        return [cls(**time_entry) for time_entry in
                Connectwise.submit_request('time/entries', conditions)]

    @classmethod
    def fetch_by_charge_to_id(cls, charge_to_id, charge_to_type=None):
        conditions = ['chargeToId={}'.format(charge_to_id)]
        if charge_to_type: conditions.append('chargeToType="{}"'.format(charge_to_type))
        return [cls(**time_entry) for time_entry in
                Connectwise.submit_request('time/entries', conditions)]

    @classmethod
    def fetch_by_charge_to_ids(cls, charge_to_ids, on_or_after=None, before=None):
        if len(charge_to_ids) > 10:
            raise IOError('Cannot lookup more than 10 chargeToIds at once')
        conditions = ['({})'.format(
            'chargeToId={}'.format(' or chargeToId='.join('{}'.format(_id) for _id in charge_to_ids)))]
        if on_or_after: conditions.append('timeStart>=[{}]'.format(on_or_after))
        if before: conditions.append('timeStart<[{}]'.format(before))
        return [cls(**time_entry) for time_entry in
                Connectwise.submit_request('time/entries', conditions)]

    def service_location(self, schedule_entries=[], tickets=[]):
        if Connectwise.get_custom_field_value(self, 'Where'): return Connectwise.get_custom_field_value(self, 'Where')
        schedule_entry = [s.where['name'] for s in schedule_entries
                          if s.dateStart[:10] == self.timeStart[:10]
                          and s.objectId == self.chargeToId]
        if schedule_entry: return schedule_entry[0]

        ticket = [t.serviceLocation['name'] for t in tickets if t.id == self.chargeToId]
        if ticket: return ticket[0]

        return 'On-Site'

    def actual_days(self):
        return round(self.actualHours / 8, 2)

    def daily_rate(self):
        return Decimal(self.hourlyRate * 8)

    def billable_amount(self):
        if self.billableOption != 'Billable':
            return Decimal(0)
        return Decimal(self.hoursBilled * self.hourlyRate)

    def fetch_estimated_cost(self, members=None):

        if members:
            try:
                member = [member for member in members if member.identifier == self.member['identifier']][0]
            except IndexError:
                return 0
        else:
            try:
                member = Member.fetch_member_by_identifier(self.member['identifier'])
            except IndexError:
                return 0

        self.estHourlyCost = Decimal(member.hourly_cost(self.timeStart[:10]))

        self.override_specific_member_hourly_cost(member)

        if self.workType['name'] == 'Professional Development':
            self.estHourlyCost = round(self.estHourlyCost / 2, 2)

        self.estCost = round(self.estHourlyCost * self.actualHours, 2)
        return self.estCost

    def override_specific_member_hourly_cost(self, member):
        # override this method in a child class in your own project if you need to override self.estHourlyCost
        # for certain Members under specific custom business logic, such as whether or not the Time Entry is
        # Billable and/or occurred during a specific time period
        pass

    def get_charge_to_info(self, tickets=[], activities=[], charge_codes=[], return_type='string'):
        if self.chargeToType == 'Activity':
            if activities:
                self.activity = [activity for activity in activities if self.chargeToId == activity.id]
                if self.activity:
                    self.activity = self.activity[0]
                else:
                    self.activity = Activity.fetch_by_id(self.chargeToId)
                # if not self.activity:
                #     self.activity = Activity.fetch_by_id(self.chargeToId)
            else:
                # print('about to get activity')
                self.activity = Activity.fetch_by_id(self.chargeToId)
                # print('just got activity')
            # print('activity', self.activity)
            output = [self.company['name']]
            if hasattr(self.activity, 'opportunity'): output.append('{}'.format(self.activity.opportunity['name']))
            output.append('Activity #{}: {}'.format(self.activity.id, self.activity.name))

        elif self.chargeToType == 'ProjectTicket' or self.chargeToType == 'ServiceTicket':
            if tickets:
                # print('about to check haystack for ticket')
                self.ticket = [ticket for ticket in tickets if self.chargeToId == ticket.id]
                if self.ticket:
                    self.ticket = self.ticket[0]
                    # print('just found ticket in the haystack')
                else:
                    # print('couldnt find ticket in haystack, so getting it separately')
                    self.ticket = Ticket.fetch_by_id(self.chargeToId)
            else:
                # print('about to get ticket')
                self.ticket = Ticket.fetch_by_id(self.chargeToId)
                # print('just got ticket')
            # print('ticket', self.ticket)
            output = [self.company['name']]
            if self.ticket.project: output.append(self.ticket.project['name'])
            if self.ticket.phase: output.append(self.ticket.phase['name'])
            output.append('Ticket #{}: {}'.format(self.ticket.id, self.ticket.summary))
        else:
            output = [self.company['name'], self.chargeToType, '{}'.format(self.chargeToId)]

        if return_type == 'string':
            return ' / '.join(output)
        elif return_type == 'list':
            return output

        return output
<|endoftext|>