blob: b386d8a3085ef8c854a33b8841f038ad32828f81 [file] [log] [blame]
#!flask/bin/python
# -*- coding: utf-8 -*-
# Copyright 2017 Google Inc.
#
# 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.
import ap_spec
import logging
import ndb_json
from flask import Flask, jsonify, abort, request, make_response
from google.appengine.ext import ndb
app = Flask(__name__)
# Chaos AP Device Methods
class ApDevice(ndb.Model):
"""Models an individual AP object with specs."""
hostname = ndb.StringProperty(indexed=True)
lock_status = ndb.BooleanProperty(indexed=True)
lock_status_updated = ndb.DateTimeProperty(auto_now=True)
locked_by = ndb.StringProperty()
router_name = ndb.StringProperty()
lab_label = ndb.StringProperty()
ap_label = ndb.StringProperty()
@app.route('/')
def greeting():
return 'Welcome to Chaos AP Page.\n'
@app.route('/devices/new', methods=['POST'])
def post():
"""
Create a new AP in the datastore.
Requires a hostname, lab_label, ap_label, and router_name.
curl -i -H "Content-Type: application/json" -X POST -d \
'{"hostname":"<HOSTNAME>"}' http://localhost:8080/devices/new
@returns string if success, error 400 if fails.
"""
if not request.json:
abort(400)
hostname = request.json['hostname']
new_device = ApDevice(
id = hostname,
hostname = hostname,
lock_status = False)
if 'router_name' in request.json and type(request.json['router_name']) != unicode:
make_response(jsonify({'error': 'Router name not unicode.'}), 400)
elif 'ap_label' in request.json and type(request.json['ap_label']) != unicode:
make_response(jsonify({'error': 'AP label not unicode.'}), 400)
elif 'lab_label' in request.json and type(request.json['lab_label']) != unicode:
make_response(jsonify({'error': 'Lab label not unicode.'}), 400)
else:
new_device.router_name = request.json['router_name']
new_device.ap_label = request.json['ap_label']
new_device.lab_label = request.json['lab_label']
new_device.put()
return jsonify(result=True, id=hostname)
@app.route('/devices/<hostname>', methods=['PUT', 'GET'])
def edit_ap_device(hostname):
"""Get and/or edit an AP.
curl -i -H "Content-Type: application/json" <URL>/devices/<HOSTNAME>
curl -i -H "Content-Type: application/json" -X PUT -d '{"ap_label":"<AP_LABEL>"}' \
<URL>/devices/<HOSTNAME>
"""
if request.method == 'GET':
device_key = ndb.Key(ApDevice, hostname)
device = device_key.get()
device_js = ndb_json.dumps(device, indent=0)
return device_js
if request.method == 'PUT':
device_key = ndb.Key(ApDevice, hostname)
device = device_key.get()
if 'router_name' in request.json:
device.router_name = request.json['router_name']
if 'ap_label' in request.json:
device.ap_label = request.json['ap_label']
if 'lab_label' in request.json:
device.lab_label = request.json['lab_label']
device.put()
return jsonify(result=True, id=hostname, ap_label=device.ap_label, \
lab_label=device.lab_label, router_name=device.router_name)
@app.route('/devices/lock', methods=['PUT'])
def lock_devices():
"""
Locks devices given either a list of hostnames or a hostname string.
curl -i -H "Content-Type: application/json" -X PUT \
-d '{"hostname":"<HOSTNAME>", "locked_by":"<LDAP>"}' \
<URL>/devices/lock
@returns Hosts locked message if success, error 400 if fails.
"""
if not request.json:
abort(400)
if type(request.json['hostname']) is list:
hostnames = request.json['hostname']
device_keys = [ndb.Key(ApDevice, x) for x in hostnames]
devices = ndb.get_multi(device_keys)
for d in devices:
d.lock_status = True
ndb.put_multi(devices)
return jsonify(result=True, id=hostnames)
elif 'hostname' in request.json and type(request.json['hostname']) != unicode:
return make_response(jsonify({'error': 'Hostname not unicode.'}), 400)
elif 'locked_by' in request.json and type(request.json['locked_by']) != unicode:
return make_response(jsonify({'error': 'Need locked_by name'}), 400)
else:
hostname = request.json['hostname']
device_key = ndb.Key(ApDevice, hostname)
device = device_key.get()
device.lock_status = True
device.locked_by = request.json['locked_by']
device.put()
return jsonify(result=True, id=hostname)
@app.route('/devices/unlock', methods=['PUT'])
def unlock_devices():
"""
Unlocks devices given either a list of hostnames or a hostname string.
curl -i -H "Content-Type: application/json" -X PUT \
-d '{"hostname":"<HOSTNAME>"}' <URL>/devices/unlock
@returns Hosts unlocked message if success, error 400 if fails.
"""
if not request.json:
return make_response(jsonify({'error': 'Need json dict.'}), 400)
elif 'hostname' in request.json and type(request.json['hostname']) != unicode:
return make_response(jsonify({'error': 'Hostname not unicode.'}), 400)
elif type(request.json['hostname']) is list:
hostnames = request.json['hostname']
device_keys = [ndb.Key(ApDevice, x) for x in hostnames]
devices = ndb.get_multi(device_keys)
for d in devices:
d.lock_status = False
ndb.put_multi(devices)
return jsonify(result=True, id=hostnames)
else:
hostname = request.json['hostname']
device_key = ndb.Key(ApDevice, hostname)
device = device_key.get()
device.lock_status = False
device.locked_by = None
device.put()
return jsonify(result=True, id=hostname)
@app.route('/devices/delete', methods=['PUT'])
def delete():
"""Deletes AP in datastore given a hostname.
curl -i -H "Content-Type: application/json" -X PUT \
-d '{"hostname":"<HOSTNAME>"}' <URL>/devices/delete
@returns Hosts deleted message if success.
"""
hostname = request.json['hostname']
device_key = ndb.Key(ApDevice, hostname)
device_key.delete()
return "%s deleted.\n" % hostname
# Querying devices.
@app.route('/devices/', methods=['GET'])
def get_devices():
"""Get list of devices in datastore.
curl -i -H "Content-Type: application/json" <URL>/devices/
@returns list of devices
"""
devices_query = ApDevice.query()
devices_entity = ndb_json.dumps(devices_query, indent=0, sort_keys=True)
return devices_entity
@app.route('/devices/<hostname>', methods=['GET'])
def show_device(hostname):
"""Show one device with all fields.
curl -i -H "Content-Type: application/json" <URL>/devices/<HOSTNAME>
@returns python dict of device
"""
device_key = ndb.Key(ApDevice, hostname)
device = device_key.get()
device_js = ndb_json.dumps(device, indent=0)
return device_js
@app.route('/unlocked_devices/', methods=['GET'])
def get_unlocked_devices():
"""Get list of unlocked devices in datastore.
curl -i -H "Content-Type: application/json" <URL>/unlocked_devices/
@returns list of devices
"""
devices_query = ApDevice.query(ApDevice.lock_status==False)
devices_entity = ndb_json.dumps(devices_query, indent=0, sort_keys=True)
return devices_entity
@app.route('/devices/location', methods=['PUT'])
def filter_by_location():
"""Get list of unlocked devices according to filter.
curl -i -H "Content-Type: application/json" -X PUT \
-d '{"ap_label":<AP_LABEL>, "lab_label":<LAB_LABEL>}' <URL>/location
@returns list of devices
"""
if not request.json:
return make_response(jsonify({'error': 'Need json dict.'}), 400)
devices_query = ApDevice.query(ApDevice.ap_label==request.json["ap_label"],
ApDevice.lab_label==request.json["lab_label"],
ApDevice.lock_status==False)
devices_entity = ndb_json.dumps(devices_query, indent=0, sort_keys=True)
return devices_entity
@app.errorhandler(404)
def not_found(error):
return make_response(jsonify({'error': 'Not found'}), 404)
if __name__ == '__main__':
app.run(host='127.0.0.1', port=8080, debug=True)