# Copyright 2015: Mirantis Inc. # All Rights Reserved. # # 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 copy from rally.common import validation from rally import exceptions import rally.task.context as context from rally_openstack.contexts.vm import custom_image from rally_openstack.scenarios.vm import utils as vm_utils @validation.add("required_platform", platform="openstack", users=True) @context.configure(name="image_command_customizer", platform="openstack", order=501) class ImageCommandCustomizerContext(custom_image.BaseCustomImageGenerator): """Context class for generating image customized by a command execution. Run a command specified by configuration to prepare image. Use this script e.g. to download and install something. """ CONFIG_SCHEMA = copy.deepcopy( custom_image.BaseCustomImageGenerator.CONFIG_SCHEMA) CONFIG_SCHEMA["definitions"] = { "stringOrStringList": { "anyOf": [ {"type": "string", "description": "just a string"}, { "type": "array", "description": "just a list of strings", "items": {"type": "string"} } ] }, "scriptFile": { "type": "object", "properties": { "script_file": {"$ref": "#/definitions/stringOrStringList"}, "interpreter": {"$ref": "#/definitions/stringOrStringList"}, "command_args": {"$ref": "#/definitions/stringOrStringList"} }, "required": ["script_file", "interpreter"], "additionalProperties": False, }, "scriptInline": { "type": "object", "properties": { "script_inline": {"type": "string"}, "interpreter": {"$ref": "#/definitions/stringOrStringList"}, "command_args": {"$ref": "#/definitions/stringOrStringList"} }, "required": ["script_inline", "interpreter"], "additionalProperties": False, }, "commandPath": { "type": "object", "properties": { "remote_path": {"$ref": "#/definitions/stringOrStringList"}, "local_path": {"type": "string"}, "command_args": {"$ref": "#/definitions/stringOrStringList"} }, "required": ["remote_path"], "additionalProperties": False, }, "commandDict": { "oneOf": [ {"$ref": "#/definitions/scriptFile"}, {"$ref": "#/definitions/scriptInline"}, {"$ref": "#/definitions/commandPath"}, ], } } CONFIG_SCHEMA["properties"]["command"] = { "$ref": "#/definitions/commandDict" } def _customize_image(self, server, fip, user): code, out, err = vm_utils.VMScenario(self.context)._run_command( fip["ip"], self.config["port"], self.config["username"], self.config.get("password"), command=self.config["command"], pkey=user["keypair"]["private"]) if code: raise exceptions.ScriptError( message="Command `%(command)s' execution failed," " code %(code)d:\n" "STDOUT:\n============================\n" "%(out)s\n" "STDERR:\n============================\n" "%(err)s\n" "============================\n" % {"command": self.config["command"], "code": code, "out": out, "err": err}) return code, out, err