def __call__(self, request): """WSGI method that controls (de)serialization and method dispatch.""" try: action_args = self.get_action_args(request.environ) action = action_args.pop('action', None) deserialized_request = self.deserialize_request(request) action_args.update(deserialized_request) except exception.InvalidContentType: msg = _("Unsupported Content-Type") return webob.exc.HTTPUnsupportedMediaType(explanation=msg) except exception.MalformedRequestBody: msg = _("Malformed request body") return webob.exc.HTTPBadRequest(explanation=msg) action_result = self.execute_action(action, request, **action_args) try: response = webob.Response(request=request) self.dispatch(self.serializer, action, response, action_result) return response # return unserializable result (typically a webob exc) except Exception: try: err_body = action_result.get_unserialized_body() self.serializer.default(action_result, err_body) except Exception: LOG.warning(_LW("Unable to serialize exception response")) return action_result
def cookbook_deploy_test(self, cookbook): """Try to deploy the given cookbook through an serial connection :param cookbook: cookbook to deploy :return: dict message with results """ LOG.debug("Sending cookbook to %s" % self._ip) b_success = True msg = {} self.connect_session() msg['install'] = self.run_install(cookbook) b_success &= msg['install']['success'] msg['test'] = self.run_test(cookbook) b_success &= msg['test']['success'] msg['deploy'] = self.run_deploy(cookbook) b_success &= msg['deploy']['success'] # check execution output if b_success: msg['result'] = { 'success': True, 'result': "Cookbook %s successfully deployed\n" % cookbook } else: msg['result'] = { 'success': False, 'result': "Error deploying cookbook {}\n".format(cookbook) } LOG.error(_LW("%s") % msg) self.disconnect_session() return msg
def connect_session(self): """ Connect to a session with the internal parameters :return: """ self.ssh.set_missing_host_key_policy(AutoAddPolicy()) try: self.ssh.connect( self._ip, username=self._username, password=self._password ) except Exception as e: LOG.error(_LW("SSH connect exception %s") % e) raise SshConnectException(host=self._ip)
def cookbook_deployment_test(self, cookbook, recipe, image=CONF.clients_docker.image): """ Try to process a cookbook and return results :param cookbook: cookbook to deploy :param recipe: recipe to deploy :param image: image to deploy to :return: dictionary with results """ LOG.debug("Sending cookbook to docker server in %s" % self._url) b_success = True msg = {} self.run_container(image) # inject custom solo.json/solo.rb file json_cont = CONF.clients_chef.cmd_config.format( cookbook_name=cookbook, recipe_name=recipe) cmd_inject = CONF.clients_chef.cmd_inject.format(config=json_cont) self.execute_command(cmd_inject) msg['install'] = self.run_install(cookbook) b_success &= msg['install']['success'] msg['test'] = self.run_test(cookbook) b_success &= msg['test']['success'] msg['deploy'] = self.run_deploy(cookbook, recipe) b_success &= msg['deploy']['success'] # check execution output if b_success: msg['result'] = { 'success': True, 'result': "Cookbook %s successfully deployed\n" % cookbook } else: msg['result'] = { 'success': False, 'result': "Error deploying cookbook {}\n".format(cookbook) } LOG.error(_LW("%s") % msg) self.remove_container() return msg
def run_install(self, cookbook): """Run download and install command :param cookbook: cookbook to process :return msg: operation result """ try: cmd_install = CONF.clients_chef.cmd_install.format(cookbook) resp_install = self.execute_command(cmd_install) msg = { 'success': True, 'response': resp_install } for line in resp_install.splitlines(): if "ERROR" in line: msg['success'] = False except Exception as e: self.disconnect_session() LOG.error(_LW("Chef install exception %s") % e) raise CookbookInstallException(cookbook=cookbook) return msg
def run_test(self, cookbook): """Test cookbook syntax :param cookbook: cookbook to test :return msg: dictionary with results and state """ try: cmd_test = CONF.clients_chef.cmd_test.format(cookbook) resp_test = self.execute_command(cmd_test) msg = { 'success': True, 'response': resp_test } for line in resp_test.splitlines(): if "ERROR" in line: msg['success'] = False except Exception as e: self.disconnect_session() LOG.error(_LW("Cookbook syntax exception %s") % e) raise CookbookSyntaxException(cookbook=cookbook) return msg
def run_container(self, image): """Run and start a container based on the given image :param image: image to run :return: """ contname = "{}-validate".format(image).replace("/", "_") try: try: self.dc.remove_container(contname, force=True) LOG.info(_LI('Removing old %s container') % contname) except NotFound: pass self.container = self.dc.create_container( image, tty=True, name=contname ).get('Id') self.dc.start(container=self.container) except AttributeError as e: LOG.error(_LW("Error creating container: %s") % e) raise DockerContainerException(image=image)
def run_deploy(self, cookbook, recipe): """Run cookbook deployment :param cookbook: cookbook to deploy :param recipe: recipe to deploy :return msg: dictionary with results and state """ try: # launch execution cmd_launch = CONF.clients_chef.cmd_launch resp_launch = self.execute_command(cmd_launch) msg = { 'success': True, 'response': resp_launch } LOG.debug(_("Launch result: %s") % resp_launch) if resp_launch is None or "FATAL" in resp_launch: msg['success'] = False except Exception as e: self.remove_container(self.container) LOG.error(_LW("Cookbook deployment exception %s") % e) raise CookbookDeploymentException(cookbook=cookbook) return msg
def run_install(self, cookbook): """Run download and install command :param cookbook: cookbook to process :return msg: operation result """ try: cmd_install = CONF.clients_chef.cmd_install.format( cookbook_name=cookbook) resp_install = self.execute_command(cmd_install) msg = { 'success': True, 'response': resp_install } for line in resp_install.splitlines(): if "ERROR" in line: msg['success'] = False LOG.debug(_("Install result: %s") % resp_install) except Exception as e: LOG.error(_LW("Chef install exception: %s") % e) self.remove_container(self.container) raise CookbookInstallException(cookbook=cookbook) return msg
def run_deploy(self, cookbook): """Run cookbook deployment :param cookbook: cookbook to deploy :return msg: dictionary with results and state """ try: # inject custom solo.json file json_cont = CONF.clients_chef.cmd_config.format(cookbook) cmd_inject = CONF.clients_chef.cmd_inject.format(json_cont) self.execute_command(cmd_inject) # launch execution cmd_launch = CONF.clients_chef.cmd_launch resp_launch = self.execute_command(cmd_launch) msg = { 'success': True, 'response': resp_launch } if resp_launch is None or "FATAL" in resp_launch: msg['success'] = False except Exception as e: self.disconnect_session() LOG.error(_LW("Cookbook deployment exception %s") % e) raise CookbookDeploymentException(cookbook=cookbook) return msg