[Branch,~linaro-validation/lava-scheduler/trunk] Rev 243: Add more xmlrpc APIs to make life easy.

Message ID 20130418084217.27313.53520.launchpad@ackee.canonical.com
State Accepted
Headers show

Commit Message

Senthil Kumaran April 18, 2013, 8:42 a.m.
Merge authors:
  Senthil Kumaran S (stylesen)
Related merge proposals:
  https://code.launchpad.net/~stylesen/lava-scheduler/more-xml-rpc-apis/+merge/158400
  proposed by: Senthil Kumaran S (stylesen)
  review: Approve - Antonio Terceiro (terceiro)
  review: Needs Fixing - Zygmunt Krynicki (zkrynicki)
------------------------------------------------------------
revno: 243 [merge]
committer: Senthil Kumaran <senthil.kumaran@linaro.org>
branch nick: trunk
timestamp: Thu 2013-04-18 14:10:44 +0530
message:
  Add more xmlrpc APIs to make life easy.
modified:
  lava_scheduler_app/api.py


--
lp:lava-scheduler
https://code.launchpad.net/~linaro-validation/lava-scheduler/trunk

You are subscribed to branch lp:lava-scheduler.
To unsubscribe from this branch go to https://code.launchpad.net/~linaro-validation/lava-scheduler/trunk/+edit-subscription

Patch

=== modified file 'lava_scheduler_app/api.py'
--- lava_scheduler_app/api.py	2012-05-09 05:57:15 +0000
+++ lava_scheduler_app/api.py	2013-04-18 00:58:20 +0000
@@ -1,15 +1,17 @@ 
 import xmlrpclib
-
 from simplejson import JSONDecodeError
-
+from django.db.models import Count
 from linaro_django_xmlrpc.models import ExposedAPI
-
 from lava_scheduler_app.models import (
     Device,
     DeviceType,
     JSONDataError,
     TestJob,
     )
+from lava_scheduler_app.views import (
+    SumIfSQL,
+    SumIf
+)
 
 
 class SchedulerAPI(ExposedAPI):
@@ -51,3 +53,148 @@ 
             raise xmlrpclib.Fault(403, "Permission denied.")
         job.cancel()
         return True
+
+    def job_output(self, job_id):
+        """
+        Name
+        ----
+        `job_output` (`job_id`)
+
+        Description
+        -----------
+        Get the output of given job id.
+
+        Arguments
+        ---------
+        `job_id`: string
+            Job id for which the output is required.
+
+        Return value
+        ------------
+        This function returns an XML-RPC binary data of output file, provided
+        the user is authenticated with an username and token.
+        """
+
+        if not self.user:
+            raise xmlrpclib.Fault(
+                401, "Authentication with user and token required for this "
+                "API.")
+
+        try:
+            job = TestJob.objects.accessible_by_principal(self.user).get(
+                pk=job_id)
+        except TestJob.DoesNotExist:
+            raise xmlrpclib.Fault(404, "Specified job not found.")
+
+        return xmlrpclib.Binary(job.output_file().read())
+
+    def all_devices(self):
+        """
+        Name
+        ----
+        `all_devices` ()
+
+        Description
+        -----------
+        Get all the available devices with their state and type information.
+
+        Arguments
+        ---------
+        None
+
+        Return value
+        ------------
+        This function returns an XML-RPC array in which each item is a list of
+        device hostname, device type and device state. For example:
+
+        [['panda01', 'panda', 'running'], ['qemu01', 'qemu', 'idle']]
+        """
+
+        devices = Device.objects.values_list('hostname',
+                                             'device_type__name',
+                                             'status')
+        devices = [list((x[0], x[1], Device.STATUS_CHOICES[x[2]][1].lower()))
+                   for x in devices]
+
+        return devices
+
+    def all_device_types(self):
+        """
+        Name
+        ----
+        `all_device_types` ()
+
+        Description
+        -----------
+        Get all the available device types with their state and count
+        information.
+
+        Arguments
+        ---------
+        None
+
+        Return value
+        ------------
+        This function returns an XML-RPC array in which each item is a dict
+        which contains name (device type), idle, busy, offline counts.
+        For example:
+
+        [{'idle': 1, 'busy': 0, 'name': 'panda', 'offline': 0},
+        {'idle': 1, 'busy': 0, 'name': 'qemu', 'offline': 0}]
+        """
+
+        device_type_list = []
+        keys = ['busy', 'name', 'idle', 'offline']
+
+        device_types = DeviceType.objects.filter(display=True).annotate(
+            idle=SumIf('device', condition='status=%s' % Device.IDLE),
+            offline=SumIf('device', condition='status in (%s,%s)' % (
+                    Device.OFFLINE, Device.OFFLINING)),
+            busy=SumIf('device', condition='status=%s' % Device.RUNNING),
+            ).order_by('name')
+
+        for dev_type in device_types:
+            device_type = {}
+            for key in keys:
+                device_type[key] = getattr(dev_type, key)
+            device_type_list.append(device_type)
+
+        return device_type_list
+
+    def pending_jobs_by_device_type(self):
+        """
+        Name
+        ----
+        `pending_jobs_by_device_type` ()
+
+        Description
+        -----------
+        Get number of pending jobs in each device type.
+
+        Arguments
+        ---------
+        None
+
+        Return value
+        ------------
+        This function returns a dict where the key is the device type and
+        the value is the number of jobs pending in that device type.
+        For example:
+
+        {'qemu': 0, 'panda': 3}
+        """
+
+        pending_jobs_by_device = {}
+
+        jobs = TestJob.objects.filter(status=TestJob.SUBMITTED).values_list(
+            'requested_device_type_id').annotate(
+            pending_jobs=(Count('id')))
+        pending_jobs_by_device.update(dict(jobs))
+
+        # Get rest of the devices and put number of pending jobs as 0.
+        device_types = DeviceType.objects.values_list('name', flat=True)
+        for device_type in device_types:
+            if device_type not in pending_jobs_by_device:
+                pending_jobs_by_device[device_type] = 0
+                
+        return pending_jobs_by_device