blob: 1e7c3e69511094d60c7982315930fe52342005c3 [file] [log] [blame]
# Copyright 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Module contains a simple implementation of the devices RPC."""
from cherrypy import tools
import common
from cros_lib.fake_device_server import common_util
from cros_lib.fake_device_server import resource_method
from cros_lib.fake_device_server import server_errors
# TODO(sosa): All access to this object should technically require auth. Create
# setters/getters for the auth token for testing.
class Devices(resource_method.ResourceMethod):
"""A simple implementation of the device interface.
A common workflow of using this API is:
POST .../ # Creates a new device with id <id>.
PATCH ..../<id> # Update device state.
GET .../<id> # Get device state.
DELETE .../<id> # Delete the device.
"""
# Needed for cherrypy to expose this to requests.
exposed = True
# Requires keys in device_config to create a device.
required_keys = ['systemName', 'deviceKind', 'channel']
def __init__(self, resource, commands_instance):
"""Initializes a registration ticket.
@param resource: A resource delegate for storing devices.
@param commands_instance: Instance of commands method class.
"""
super(Devices, self).__init__(resource)
self.commands_instance = commands_instance
def create_device(self, api_key, device_config):
"""Creates a new device given the device_config.
@param api_key: Api key for the application.
@param device_config: Json dict for the device.
@raises server_errors.HTTPError: if the config is missing a required key
"""
# Verify required keys exist in the device draft.
for key in self.required_keys:
if key not in device_config:
raise server_errors.HTTPError(400, 'Must specify %s' % key)
# Create default state.
device_config['kind'] = 'clouddevices#device'
device_config['state'] = { 'version': '',
'base': { 'connectionStatus': 'online'},
}
device_config['etag'] = '0' # SOMETHING RANDOM
device_config['owner'] = '0' # GET OWNER
new_device = self.resource.update_data_val(None, api_key,
data_in=device_config)
self.commands_instance.new_device(new_device['id'], api_key)
return new_device
@tools.json_out()
def GET(self, *args, **kwargs):
"""GET .../(device_id) gets device info or lists all devices.
Supports both the GET / LIST commands for devices. List lists all
devices a user has access to, however, this implementation just returns
all devices.
Raises:
server_errors.HTTPError if the device doesn't exist.
"""
id, api_key, _ = common_util.parse_common_args(args, kwargs)
if id:
return self.resource.get_data_val(id, api_key)
else:
# Returns listing (ignores optional parameters).
listing = {'kind': 'clouddevices#devicesListResponse'}
listing['devices'] = self.resource.get_data_vals()
return listing
@tools.json_out()
def POST(self, *args, **kwargs):
"""Creates a new device using the incoming json data."""
id, api_key, _ = common_util.parse_common_args(args, kwargs)
data = common_util.parse_serialized_json()
if id:
raise server_errors.HTTPError(400, 'Cannot pass an id to INSERT')
if not data:
data = {}
return self.create_device(api_key, data)
def DELETE(self, *args, **kwargs):
"""Deletes the given device.
Format of this call is:
DELETE .../device_id
Raises:
server_errors.HTTPError if the device doesn't exist.
"""
id, api_key, _ = common_util.parse_common_args(args, kwargs)
self.resource.del_data_val(id, api_key)
self.commands_instance.remove_device(id, api_key)