From: vrovachev Date: Fri, 24 Jul 2015 08:26:45 +0000 (+0400) Subject: Add python script for validation erratum files X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=dc01470edf474c75c04fafed19d0b1e0c9111eb7;p=tools%2Fsustaining.git Add python script for validation erratum files Closes-Bug: #1477694 Change-Id: Ie3677ceae35e6b9174946a9c3a3dae2ac42df046 --- diff --git a/scripts/erratumvalidation.py b/scripts/erratumvalidation.py new file mode 100644 index 0000000..7616ad7 --- /dev/null +++ b/scripts/erratumvalidation.py @@ -0,0 +1,321 @@ +# Copyright 2015 Mirantis, 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. + +from jsonschema import validate +import yaml +import sys +import urllib2 + +SCHEMA = "http://json-schema.org/draft-04/schema" + +CVE_URL = "https://cve.mitre.org/cgi-bin/cvename.cgi?name={bug}" + +CONFIG_SCHEMA = { + "type": "object", + "$schema": SCHEMA, + "definitions": { + "short_string_schema": { + "type": "string", + "maxLength": 200 + }, + "array_schema": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "uniqueItems": True + }, + "target_schema": { + "enum": ["master", "slaves", "controller_role", "compute_role", + "cinder_role", "ceph-osd_role", "mongo_role", + "zabbix-server_role", "base-os_role"] + }, + "bool_schema": { + "type": "boolean", + "default": False + }, + "os_step_upload_script_schema": { + "type": "object", + "$schema": SCHEMA, + "properties": { + "id": { + "type": "integer", + }, + "type": { + "enum": ["upload_script"] + }, + "target": { + "type": "array", + "items": { + "$ref": "#/definitions/target_schema" + }, + "minItems": 1, + "uniqueItems": True + }, + "script": { + "type": "string", + "minLength": 1 + }, + "upload_path": { + "type": "string", + "minLength": 1 + }, + }, + "required": ["id", "type", "target", "script", "upload_path"], + "additionalProperties": False, + }, + "os_step_run_command_schema": { + "type": "object", + "$schema": SCHEMA, + "properties": { + "id": { + "type": "integer", + }, + "type": { + "enum": ["run_command"] + }, + "target": { + "type": "array", + "items": { + "$ref": "#/definitions/target_schema" + }, + "minItems": 1, + "uniqueItems": True + }, + "command": { + "type": "string", + "minLength": 1 + }, + }, + "required": ["id", "type", "target", "command"], + "additionalProperties": False, + }, + "os_step_run_tasks_schema": { + "type": "object", + "$schema": SCHEMA, + "properties": { + "id": { + "type": "integer", + }, + "type": { + "enum": ["run_tasks"] + }, + "target": { + "type": "array", + "items": { + "$ref": "#/definitions/target_schema" + }, + "minItems": 1, + "uniqueItems": True + }, + "tasks": { + "type": "string", + "minLength": 1 + }, + }, + "required": ["id", "type", "target", "tasks"], + "additionalProperties": False, + }, + "os_step_text_schema": { + "type": "object", + "$schema": SCHEMA, + "properties": { + "id": { + "type": "integer", + }, + "type": { + "enum": ["text"] + }, + "target": { + "type": "array", + "items": { + "$ref": "#/definitions/target_schema" + }, + "minItems": 1, + "uniqueItems": True + }, + "text": { + "type": "string", + "minLength": 1 + }, + }, + "required": ["id", "type", "text"], + "additionalProperties": False, + }, + "os_step_server_action_schema": { + "type": "object", + "$schema": SCHEMA, + "properties": { + "id": { + "type": "integer", + }, + "type": { + "enum": ["server_down", "server_up", "server_reboot"] + }, + "target": { + "type": "array", + "items": { + "$ref": "#/definitions/target_schema" + }, + "minItems": 1, + "uniqueItems": True + }, + }, + "required": ["id", "type", "target"], + "additionalProperties": False, + }, + "os_step_schema": { + "type": "array", + "items": { + "oneOf": [ + {"$ref": "#/definitions/os_step_upload_script_schema"}, + {"$ref": "#/definitions/os_step_run_command_schema"}, + {"$ref": "#/definitions/os_step_run_tasks_schema"}, + {"$ref": "#/definitions/os_step_text_schema"}, + {"$ref": "#/definitions/os_step_server_action_schema"} + ] + } + }, + "scenario_schema": { + "type": "object", + "$schema": SCHEMA, + "patternProperties": { + 'ubuntu|centos': { + "$ref": "#/definitions/os_step_schema" + } + }, + "anyOf": [{"required": ['ubuntu']}, {"required": ['centos']}], + "additionalProperties": False + }, + }, + "properties": { + "title": { + "$ref": "#/definitions/short_string_schema" + }, + "description": { + "type": "string", + "maxLength": 1000 + }, + "cve": { + "$ref": "#/definitions/short_string_schema" + }, + "ossa": { + "$ref": "#/definitions/short_string_schema" + }, + "regenerate_image_ubuntu": { + "$ref": "#/definitions/bool_schema" + }, + "regenerate_image_centos": { + "$ref": "#/definitions/bool_schema" + }, + "regenerate_bootstrap": { + "$ref": "#/definitions/bool_schema" + }, + "regenerate_containers": { + "$ref": "#/definitions/bool_schema" + }, + "security": { + "$ref": "#/definitions/bool_schema" + }, + "verify_visible": { + "$ref": "#/definitions/bool_schema" + }, + "tests": { + "$ref": "#/definitions/array_schema" + }, + "rally": { + "$ref": "#/definitions/array_schema" + }, + "affected-pkgs": { + "type": "object", + "$schema": SCHEMA, + "patternProperties": { + 'ubuntu|centos': { + "$ref": "#/definitions/array_schema" + } + }, + "anyOf": [{"required": ['ubuntu']}, {"required": ['centos']}], + "additionalProperties": False + }, + "targets": { + "type": "array", + "items": { + "type": "object", + "$schema": SCHEMA, + "properties": { + "type": { + "enum": ["master", "environment"] + }, + "patch-scenario": { + "$ref": "#/definitions/scenario_schema" + }, + "verify-scenario": { + "$ref": "#/definitions/scenario_schema" + } + }, + "additionalProperties": False, + "required": ["type", "patch-scenario"] + } + + } + }, + "required": ["title", "affected-pkgs"], + "additionalProperties": False +} + +# TODO(vrovachev): TBD after create general schema for erratum version 2 +CONFIG_SCHEMA_V2 = {} + + +def validate_schema(erratum_file): + + with open(erratum_file) as f: + content = f.read() + dict_content = yaml.load(content) + validate_schema = CONFIG_SCHEMA + + if dict_content.get('version') == 2: + validate_schema = CONFIG_SCHEMA_V2 + + # validate schema + validate(dict_content, validate_schema) + + # Check that OS in affected-pkgs has in patch-scenario and + # in verify-scenario if verify-scenario specified + os_error_msg = ("{system} OS specified in affected-pkgs but not " + "specified in {vol}-scenario steps") + for distro in dict_content['affected-pkgs']: + for target in dict_content['targets']: + if not target['patch-scenario'].get(distro): + raise Exception(os_error_msg.format(system=distro, + vol="patch")) + if target.get('verify-scenario'): + if not target['verify-scenario'].get(distro): + raise Exception(os_error_msg.format(system=distro, + vol="verify")) + + # Check CVE bug if cve bug number specified + cve_error_msg = ("CVE bub with number: {number} specified in erratum" + " file but this bug not found." + " URL for search: {search_url}") + if dict_content.get("cve"): + url_for_cve = CVE_URL.format(bug=dict_content["cve"]) + resp = urllib2.urlopen(url_for_cve) + if resp.read().find("ERROR:") != -1: + raise Exception(cve_error_msg.format( + number=dict_content['cve'], search_url=url_for_cve)) + +if __name__ == "__main__": + validate_schema(sys.argv[1])