Initial commit of PVC Bootstrap system
Adds the PVC Bootstrap system, which allows the automated deployment of one or more PVC clusters.
This commit is contained in:
241
bootstrap-daemon/pvcbootstrapd/flaskapi.py
Executable file
241
bootstrap-daemon/pvcbootstrapd/flaskapi.py
Executable file
@ -0,0 +1,241 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# pvcbootstrapd.py - PVC Cluster Auto-bootstrap
|
||||
# Part of the Parallel Virtual Cluster (PVC) system
|
||||
#
|
||||
# Copyright (C) 2018-2021 Joshua M. Boniface <joshua@boniface.me>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
import flask
|
||||
import json
|
||||
|
||||
from pvcbootstrapd.Daemon import config
|
||||
|
||||
import pvcbootstrapd.lib.lib as lib
|
||||
|
||||
from flask_restful import Resource, Api
|
||||
from celery import Celery
|
||||
from celery.utils.log import get_task_logger
|
||||
|
||||
|
||||
logger = get_task_logger(__name__)
|
||||
|
||||
|
||||
# Create Flask app and set config values
|
||||
app = flask.Flask(__name__)
|
||||
blueprint = flask.Blueprint("api", __name__, url_prefix="")
|
||||
api = Api(blueprint)
|
||||
app.register_blueprint(blueprint)
|
||||
|
||||
app.config[
|
||||
"CELERY_BROKER_URL"
|
||||
] = f"redis://{config['queue_address']}:{config['queue_port']}{config['queue_path']}"
|
||||
|
||||
celery = Celery(app.name, broker=app.config["CELERY_BROKER_URL"])
|
||||
celery.conf.update(app.config)
|
||||
|
||||
|
||||
#
|
||||
# Celery functions
|
||||
#
|
||||
@celery.task(bind=True)
|
||||
def dnsmasq_checkin(self, data):
|
||||
lib.dnsmasq_checkin(config, data)
|
||||
|
||||
|
||||
@celery.task(bind=True)
|
||||
def host_checkin(self, data):
|
||||
lib.host_checkin(config, data)
|
||||
|
||||
|
||||
#
|
||||
# API routes
|
||||
#
|
||||
class API_Root(Resource):
|
||||
def get(self):
|
||||
"""
|
||||
Return basic details of the API
|
||||
---
|
||||
tags:
|
||||
- root
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
schema:
|
||||
type: object
|
||||
id: Message
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
description: A text message describing the result
|
||||
example: "The foo was successfully maxed"
|
||||
"""
|
||||
return {"message": "pvcbootstrapd API"}, 200
|
||||
|
||||
|
||||
api.add_resource(API_Root, "/")
|
||||
|
||||
|
||||
class API_Checkin(Resource):
|
||||
def get(self):
|
||||
"""
|
||||
Return checkin details of the API
|
||||
---
|
||||
tags:
|
||||
- checkin
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
schema:
|
||||
type: object
|
||||
id: Message
|
||||
"""
|
||||
return {"message": "pvcbootstrapd API Checkin interface"}, 200
|
||||
|
||||
|
||||
api.add_resource(API_Checkin, "/checkin")
|
||||
|
||||
|
||||
class API_Checkin_DNSMasq(Resource):
|
||||
def post(self):
|
||||
"""
|
||||
Register a checkin from the DNSMasq subsystem
|
||||
---
|
||||
tags:
|
||||
- checkin
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- in: body
|
||||
name: dnsmasq_checkin_event
|
||||
description: An event checkin from an external bootstrap tool component.
|
||||
schema:
|
||||
type: object
|
||||
required:
|
||||
- action
|
||||
properties:
|
||||
action:
|
||||
type: string
|
||||
description: The action of the event.
|
||||
example: "add"
|
||||
macaddr:
|
||||
type: string
|
||||
description: (add, old) The MAC address from a DHCP request.
|
||||
example: "ff:ff:ff:ab:cd:ef"
|
||||
ipaddr:
|
||||
type: string
|
||||
description: (add, old) The IP address from a DHCP request.
|
||||
example: "10.199.199.10"
|
||||
hostname:
|
||||
type: string
|
||||
description: (add, old) The client hostname from a DHCP request.
|
||||
example: "pvc-installer-live"
|
||||
client_id:
|
||||
type: string
|
||||
description: (add, old) The client ID from a DHCP request.
|
||||
example: "01:ff:ff:ff:ab:cd:ef"
|
||||
vendor_class:
|
||||
type: string
|
||||
description: (add, old) The DHCP vendor-class option from a DHCP request.
|
||||
example: "CPQRIB3 (HP Proliant DL360 G6 iLO)"
|
||||
user_class:
|
||||
type: string
|
||||
description: (add, old) The DHCP user-class option from a DHCP request.
|
||||
example: None
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
schema:
|
||||
type: object
|
||||
id: Message
|
||||
"""
|
||||
try:
|
||||
data = json.loads(flask.request.data)
|
||||
except Exception as e:
|
||||
logger.warn(e)
|
||||
data = {"action": None}
|
||||
logger.info(f"Handling DNSMasq checkin for: {data}")
|
||||
|
||||
task = dnsmasq_checkin.delay(data)
|
||||
logger.debug(task)
|
||||
return {"message": "received checkin from DNSMasq"}, 200
|
||||
|
||||
|
||||
api.add_resource(API_Checkin_DNSMasq, "/checkin/dnsmasq")
|
||||
|
||||
|
||||
class API_Checkin_Host(Resource):
|
||||
def post(self):
|
||||
"""
|
||||
Register a checkin from the Host subsystem
|
||||
---
|
||||
tags:
|
||||
- checkin
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- in: body
|
||||
name: host_checkin_event
|
||||
description: An event checkin from an external bootstrap tool component.
|
||||
schema:
|
||||
type: object
|
||||
required:
|
||||
- action
|
||||
properties:
|
||||
action:
|
||||
type: string
|
||||
description: The action of the event.
|
||||
example: "begin"
|
||||
hostname:
|
||||
type: string
|
||||
description: The system hostname.
|
||||
example: "hv1.mydomain.tld"
|
||||
host_macaddr:
|
||||
type: string
|
||||
description: The MAC address of the system provisioning interface.
|
||||
example: "ff:ff:ff:ab:cd:ef"
|
||||
host_ipaddr:
|
||||
type: string
|
||||
description: The IP address of the system provisioning interface.
|
||||
example: "10.199.199.11"
|
||||
bmc_macaddr:
|
||||
type: string
|
||||
description: The MAC address of the system BMC interface.
|
||||
example: "ff:ff:ff:01:23:45"
|
||||
bmc_ipaddr:
|
||||
type: string
|
||||
description: The IP addres of the system BMC interface.
|
||||
example: "10.199.199.10"
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
schema:
|
||||
type: object
|
||||
id: Message
|
||||
"""
|
||||
try:
|
||||
data = json.loads(flask.request.data)
|
||||
except Exception as e:
|
||||
logger.warning(f"Invalid JSON data, setting action to None: {e}")
|
||||
data = {"action": None}
|
||||
logger.info(f"Handling Host checkin for: {data}")
|
||||
|
||||
task = host_checkin.delay(data)
|
||||
logger.debug(task)
|
||||
return {"message": "received checkin from Host"}, 200
|
||||
|
||||
|
||||
api.add_resource(API_Checkin_Host, "/checkin/host")
|
Reference in New Issue
Block a user