Beispiel #1
0
def puppet_nodes():
    """Handles the Puppet nodes list page"""

    # Check user permissions
    if not does_user_have_permission("puppet.nodes.view"):
        abort(403)

        # Get a cursor to the database
    curd = g.db.cursor(mysql.cursors.DictCursor)

    # Get Puppet nodes from the database
    curd.execute(
        "SELECT `puppet_nodes`.`certname` AS `certname`, `puppet_nodes`.`env` AS `env`, `systems`.`id` AS `id`, `systems`.`name` AS `name`  FROM `puppet_nodes` LEFT JOIN `systems` ON `puppet_nodes`.`id` = `systems`.`id` ORDER BY `puppet_nodes`.`certname` "
    )
    results = curd.fetchall()

    # Get node statuses
    try:
        statuses = cortex.lib.puppet.puppetdb_get_node_statuses()
    except Exception as ex:
        return stderr(
            "Unable to connect to PuppetDB",
            "Unable to connect to the Puppet database. The error was: " + type(ex).__name__ + " - " + str(ex),
        )

    for row in results:
        if row["certname"] in statuses:
            row["status"] = statuses[row["certname"]]
        else:
            row["status"] = "unknown"

            # Render
    return render_template("puppet/nodes.html", active="puppet", data=results, title="Puppet Nodes")
Beispiel #2
0
def puppet_dashboard_status(status):
    """This view is responsible for listing puppet nodes but only those matching
	a certain status in PuppetDB."""

    # Check user permissions (note this is the nodes permission rather than dashboard)
    if not does_user_have_permission("puppet.nodes.view"):
        abort(403)

        # For the purposes of the dashboard, unreported is the same as unknown
    if status == "unreported":
        status = "unknown"

        # Page Titles to use
    page_title_map = {
        "unchanged": "Normal",
        "changed": "Changed",
        "noop": "Disabled",
        "failed": "Failed",
        "unknown": "Unknown/Unreported",
        "all": "Registered",
    }

    # If we have an invalid status, return 404
    if status not in page_title_map:
        abort(404)

        # Connect to PuppetDB
    try:
        db = cortex.lib.puppet.puppetdb_connect()
    except Exception as ex:
        return stderr(
            "Unable to connect to PuppetDB",
            "Unable to connect to the Puppet database. The error was: " + type(ex).__name__ + " - " + str(ex),
        )

        # Get information about all the nodes, including their status
    nodes = db.nodes(with_status=True)

    # Create a filterd array
    nodes_of_type = []

    # Iterate over nodes and do the filtering
    if status != "all":
        for node in nodes:
            # If the status matches...
            if node.status == status:
                nodes_of_type.append(node)
                # Or if the required status is 'unknown' and it's not one of the normal statii
            elif status == "unknown" and node.status not in ["unchanged", "changed", "noop", "failed"]:
                nodes_of_type.append(node)
    else:
        nodes_of_type = nodes

    return render_template(
        "puppet/dashboard-status.html",
        active="puppet",
        title="Puppet Dashboard",
        nodes=nodes_of_type,
        status=page_title_map[status],
    )
Beispiel #3
0
def error500(error):
	
	# Record the error in the log
	logerr()	

	# Return a standard error page		
	return stderr("Internal Error","An internal server error occured",500)
Beispiel #4
0
def puppet_radiator():
    """Handles the Puppet radiator view page. Similar to the dashboard."""

    ## No permissions check: this is accessible without logging in
    try:
        stats = cortex.lib.puppet.puppetdb_get_node_stats()
    except Exception as ex:
        return stderr(
            "Unable to connect to PuppetDB",
            "Unable to connect to the Puppet database. The error was: " + type(ex).__name__ + " - " + str(ex),
        )

    return render_template("puppet/radiator.html", stats=stats, active="puppet")
Beispiel #5
0
def puppet_dashboard():
    """Handles the Puppet dashboard page."""

    # Check user permissions
    if not does_user_have_permission("puppet.dashboard.view"):
        abort(403)

    try:
        stats = cortex.lib.puppet.puppetdb_get_node_stats()
    except Exception as ex:
        return stderr(
            "Unable to connect to PuppetDB",
            "Unable to connect to the Puppet database. The error was: " + type(ex).__name__ + " - " + str(ex),
        )

    return render_template("puppet/dashboard.html", stats=stats, active="puppet", title="Puppet Dashboard")
Beispiel #6
0
def puppet_report(report_hash):
    """Displays an individual report for a Puppet node"""

    # Connect to Puppet DB and query for a report with the given hash
    try:
        db = cortex.lib.puppet.puppetdb_connect()
    except Exception as ex:
        return stderr(
            "Unable to connect to PuppetDB",
            "Unable to connect to the Puppet database. The error was: " + type(ex).__name__ + " - " + str(ex),
        )

    reports = db.reports(query='["=", "hash", "' + report_hash + '"]')

    # 'reports' is a generator. Get the next (first and indeed, only item) from the generator
    try:
        report = next(reports)
    except StopIteration, e:
        # If we get a StopIteration error, then we've not got any data
        # returned from the reports generator, so the report didn't
        # exist, hence we should 404
        return abort(404)
Beispiel #7
0
def puppet_radiator():
    """Handles the Puppet radiator view page. Similar to the dashboard."""

    ## No permissions check: this is accessible without logging in
    try:
        stats = cortex.lib.puppet.puppetdb_get_node_stats()

    except Exception as e:
        return stderr(
            "Unable to connect to PuppetDB",
            "Unable to connect to the Puppet database. The error was: " +
            type(e).__name__ + " - " + str(e))

    # create dictionary to hold the values the radiator needs
    top_level_stats = {}
    for s in stats:
        #'count' value in the dictionary is the value we need
        top_level_stats[s] = stats[s]['count']

    return render_template('puppet/radiator.html',
                           stats=top_level_stats,
                           active='puppet')
Beispiel #8
0
def puppet_dashboard():
    """Handles the Puppet dashboard page."""

    # Check user permissions
    if not does_user_have_permission("puppet.dashboard.view"):
        abort(403)

    environments = cortex.lib.puppet.get_puppet_environments()

    try:
        stats = cortex.lib.puppet.puppetdb_get_node_stats(
            environments=[env["environment_name"] for env in environments], )
    except Exception as ex:
        return stderr(
            "Unable to connect to PuppetDB",
            "Unable to connect to the Puppet database. The error was: " +
            type(ex).__name__ + " - " + str(ex))

    return render_template('puppet/dashboard.html',
                           title="Puppet Dashboard",
                           active="puppet",
                           stats=stats)
Beispiel #9
0
def puppet_reports(node):
    """Handles the Puppet reports page for a node"""

    # Get the system (we need to know the ID for permissions checking)
    system = cortex.lib.systems.get_system_by_puppet_certname(node)
    if system is None:
        abort(404)

    ## Check if the user is allowed to view the reports of this node
    if not does_user_have_system_permission(system['id'], "view.puppet",
                                            "systems.all.view.puppet"):
        abort(403)

    try:
        # Connect to PuppetDB and get the reports
        db = cortex.lib.puppet.puppetdb_connect()
        reports = db.node(node).reports()

    except HTTPError as he:
        # If we get a 404 response from PuppetDB
        if he.response.status_code == 404:
            # Still display the page but with a nice error
            reports = None
        else:
            raise (he)
    except Exception as e:
        return stderr(
            "Unable to connect to PuppetDB",
            "Unable to connect to the Puppet database. The error was: " +
            type(e).__name__ + " - " + str(e))

    return render_template('puppet/reports.html',
                           reports=reports,
                           active='puppet',
                           title=node + " - Puppet Reports",
                           nodename=node,
                           pactive="reports",
                           system=system)
Beispiel #10
0
def error_handler(error):
	"""Handles generic exceptions within the application, displaying the
	traceback if the application is running in debug mode."""

	# Record the error in the log
	logerr()

	## If we're handling a workflow view handler we don't need to show the fatal
	## error screen, instead we'll use a standard error screen. the fatal error
	## screen exists in case a flaw occurs which prevents rendering of the 
	## layout - but that can't happen with a workflow.
	if 'workflow' in g:
		if g.workflow:
			app.logger.warn("Workflow error occured")
			return stderr("Workflow error","An error occured in the workflow function - " + type(error).__name__ + ": " + str(error))

	# Get the traceback
	if app.debug:
		debug = traceback.format_exc()
	else:
		debug = "Ask your system administrator to consult the error log for this application."

	# Output a fatal error
	return fatalerr(debug=debug)
Beispiel #11
0
	dbnode = None
	facts = None
	try:
		# Connect to PuppetDB, get the node information and then it's related facts
		db     = cortex.lib.puppet.puppetdb_connect()
		dbnode = db.node(node)
		facts  = dbnode.facts()
	except HTTPError, he:
		# If we get a 404 from the PuppetDB API
		if he.response.status_code == 404:
			# We will continue to render the page, just with no facts and display a nice error
			facts = None
		else:
			raise(he)
	except Exception, e:
		return stderr("Unable to connect to PuppetDB","Unable to connect to the Puppet database. The error was: " + type(ex).__name__ + " - " + str(ex))


	# Turn the facts generator in to a dictionary
	facts_dict = {}

	if facts != None:
		for fact in facts:
			facts_dict[fact.name] = fact.value

	# Load the system data - we don't care if it fails (i.e its not in the systems table)
	system = cortex.lib.systems.get_system_by_puppet_certname(node)

	# Render
	return render_template('puppet/facts.html', facts=facts_dict, node=dbnode, active='puppet', title=node + " - Puppet Facts", nodename=node, pactive="facts", system=system)
Beispiel #12
0
def error403(error):
    return stderr(
        "Permission Denied",
        "You do not have permission to access that page or perform that action.",
        403,
        template="no.html")
Beispiel #13
0
def error400(error):
    return stderr("Bad Request", "Your request was invalid", 400)
Beispiel #14
0
def error405(error):
    return stderr("Not allowed",
                  "Your web browser sent the wrong HTTP method",
                  405,
                  template="no.html")
Beispiel #15
0
def error404(error):
    return stderr("Not found", "I could not find what you requested", 404)
Beispiel #16
0
    facts = None
    try:
        # Connect to PuppetDB, get the node information and then it's related facts
        db = cortex.lib.puppet.puppetdb_connect()
        dbnode = db.node(node)
        facts = dbnode.facts()
    except HTTPError, he:
        # If we get a 404 from the PuppetDB API
        if he.response.status_code == 404:
            # We will continue to render the page, just with no facts and display a nice error
            facts = None
        else:
            raise (he)
    except Exception, e:
        return stderr(
            "Unable to connect to PuppetDB",
            "Unable to connect to the Puppet database. The error was: " + type(ex).__name__ + " - " + str(ex),
        )

        # Turn the facts generator in to a dictionary
    facts_dict = {}

    if facts != None:
        for fact in facts:
            facts_dict[fact.name] = fact.value

            # Load the system data - we don't care if it fails (i.e its not in the systems table)
    system = cortex.lib.systems.get_system_by_puppet_certname(node)

    # Render
    return render_template(
        "puppet/facts.html",
Beispiel #17
0
def error400(error):
	return stderr("Bad Request","Your request was invalid",400)
Beispiel #18
0
def error403(error):
	return stderr("Permission Denied","You do not have permission to access that page or perform that action.",403,template="no.html")
Beispiel #19
0
def error404(error):
	return stderr("Not found","I could not find what you requested",404)
Beispiel #20
0
def puppet_nodes(status=None):
    """Handles the Puppet nodes list page"""

    # Check user permissions
    if not does_user_have_permission("puppet.nodes.view"):
        abort(403)

    # Get a cursor to the database
    curd = g.db.cursor(mysql.cursors.DictCursor)

    # Get Puppet nodes from the database
    curd.execute(
        'SELECT `puppet_nodes`.`certname` AS `certname`, `puppet_nodes`.`env` AS `env`, `systems`.`id` AS `id`, `systems`.`name` AS `name`, `systems`.`allocation_comment` AS `allocation_comment` FROM `puppet_nodes` LEFT JOIN `systems` ON `puppet_nodes`.`id` = `systems`.`id` ORDER BY `puppet_nodes`.`certname` '
    )
    results = curd.fetchall()

    # Get node statuses
    try:
        statuses = cortex.lib.puppet.puppetdb_get_node_statuses()
    except Exception as e:
        return stderr(
            "Unable to connect to PuppetDB",
            "Unable to connect to the Puppet database. The error was: " +
            type(e).__name__ + " - " + str(e))

    data = []
    for row in results:
        if row['certname'] in statuses:
            row['status'] = statuses[row['certname']]['status']
            row['clientnoop'] = statuses[row['certname']]['clientnoop']
        else:
            row['status'] = 'unknown'
            row['clientnoop'] = 'unknown'

        if status == None or status == 'all':
            data.append(row)
        elif status == 'unchanged' and row['status'] == 'unchanged':
            data.append(row)
        elif status == 'changed' and row['status'] == 'changed':
            data.append(row)
        elif status == 'noop' and row['status'] == 'noop':
            data.append(row)
        elif status == 'failed' and row['status'] == 'failed':
            data.append(row)
        elif status == 'unknown' and row['status'] not in [
                'unchanged', 'changed', 'noop', 'failed'
        ]:
            data.append(row)

    # Page Title Map
    title = 'Puppet Nodes'
    page_title_map = {
        'unchanged': 'Normal',
        'changed': 'Changed',
        'noop': 'Disabled',
        'failed': 'Failed',
        'unknown': 'Unknown/Unreported',
        'all': 'Registered'
    }

    if status != None and status in page_title_map:
        title = title + ' - {}'.format(page_title_map.get(status))

    # Render
    return render_template('puppet/nodes.html',
                           active='puppet',
                           data=data,
                           title=title,
                           hide_unknown=True)
Beispiel #21
0
def puppet_environments(environment_id=None):
    """Show the Puppet documentation"""

    # Handle POST request
    if request.method == "POST" and all(k in request.form
                                        for k in ["action", "environment_id"]):
        environment_id = request.form["environment_id"]
        if request.form["action"] == "delete_environment":
            if not does_user_have_puppet_permission(
                    environment_id, "delete",
                    "puppet.environments.all.delete"):
                abort(403)
            elif "puppet" not in app.workflows:
                return stderr(
                    "Unable to delete Puppet environment",
                    "Error deleting Puppet environment, the workflow 'puppet' is required in order to delete Puppet environments, but was not found in app.workflows."
                )
            else:
                # Task Options
                options = {
                    "actions": [{
                        "id": "environment.delete",
                        "desc": "Deleting Puppet Environment"
                    }],
                    "values": {
                        "environment_id": environment_id
                    },
                }
                # Everything should be good - start a task.
                neocortex = cortex.lib.core.neocortex_connect()
                task_id = neocortex.create_task(
                    "puppet",
                    session["username"],
                    options,
                    description="Delete Puppet Environment")
                # Redirect to the status page for the task
                return redirect(url_for("task_status", task_id=task_id))
        else:
            abort(400)

    # Handle GET request
    # Get the database cursor
    curd = g.db.cursor(mysql.cursors.DictCursor)

    environments, permissions, nodes = [], [], []
    if environment_id and does_user_have_puppet_permission(
            environment_id, "view", "puppet.environments.all.view"):
        curd.execute(
            "SELECT * FROM `puppet_environments` WHERE `id`=%s LIMIT 1",
            (environment_id, ))
        environments = curd.fetchall()
        curd.execute(
            "SELECT * FROM `p_puppet_perms_view` WHERE `environment_id`=%s ORDER BY `who`",
            (environment_id, ))
        permissions = curd.fetchall()
    elif environment_id is None:
        if does_user_have_permission("puppet.environments.all.view"):
            environments = cortex.lib.puppet.get_puppet_environments()
        elif does_user_have_any_puppet_permission("view"):
            environments = cortex.lib.puppet.get_puppet_environments(
                environment_permission="view")
        else:
            abort(403)
    else:
        abort(403)

    # If no results could be found
    if not environments:
        abort(404)

    # If

    if environment_id:
        curd.execute(
            "SELECT `puppet_nodes`.`certname` AS `certname`, `puppet_nodes`.`env` AS `env`, `systems`.`id` AS `id`, `systems`.`name` AS `name`, `systems`.`allocation_comment` AS `allocation_comment` FROM `puppet_nodes` LEFT JOIN `systems` ON `puppet_nodes`.`id` = `systems`.`id` WHERE `puppet_nodes`.`env`=%s ORDER BY `puppet_nodes`.`certname`",
            (environments[0]["environment_name"], ))
        nodes = curd.fetchall()

    return render_template("puppet/environments.html",
                           active="puppet",
                           title="Puppet Environments",
                           environment_id=environment_id,
                           environments=environments,
                           permissions=permissions,
                           nodes=nodes)
Beispiel #22
0
def error405(error):
	return stderr("Not allowed","Your web browser sent the wrong HTTP method",405,template="no.html")