# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you 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. # brooklyn.catalog: id: minecraft-server-cuberite version: 0.1.0 itemType: template iconUrl: http://images.wikia.com/yogbox/images/d/dd/Minecraft_Block.svg name: Minecraft Server (Cuberite) description: | Cuberite Minecraft Server with a choice of plugins. license: Apache-2.0 maintainer_name: John McCabe maintainer_email: john@johnmccabe.net issues_url: https://github.com/johnmccabe/brooklyn-minecraft/issues publish: license_code: Apache-2.0 overview: README.md reference: reference.json item: origin: http://cuberite.org/ brooklyn.parameters: - name: cuberite.url label: Cuberite Download URL description: URL pointing at the Cuberite release archive (defaults to latest) default: https://builds.cuberite.org/job/Cuberite%20Linux%20x64%20Master/lastSuccessfulBuild/artifact/Cuberite.tar.gz - name: cuberite.port label: Cuberite Server Port description: Port number the Cuberite server will listen on default: 25565 - name: cuberite.webadmin.port label: WebAdmin HTTP Port description: Port number the Cuberite WebAdmin server will listen on default: 8080 - name: cuberite.motd.url label: MOTD URL (optional) description: URL pointing at motd.txt file with Message of the Day show to players on joining your server - name: plugin.worldedit label: Install WorldEdit Plugin description: Install WorldEdit Plugin type: java.lang.Boolean default: true - name: plugin.essentials label: Install Essentials Plugin description: Install Essentials Plugin type: java.lang.Boolean default: true - name: plugin.magiccarpet label: Install MagicCarpet Plugin description: Install MagicCarpet Plugin type: java.lang.Boolean default: true - name: plugin.hungergames label: Install HungerGames Plugin description: Install HungerGames Plugin type: java.lang.Boolean default: false - name: plugin.skyblock label: Install SkyBlock Plugin description: Install SkyBlock Plugin type: java.lang.Boolean default: false - name: plugin.login label: Install Login Plugin description: Install Login Plugin type: java.lang.Boolean default: false - name: cuberite.maintenance.duration label: Maintenance Duration description: Time, in seconds, during which the absence of a running Cuberite process will be ignored. default: 300 - name: cuberite.maintenance.warning.duration label: Maintenance Warning Duration description: Time, in seconds, during which shutdown warning messages are broadcast to the server. default: 300 services: - type: org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess brooklyn.config: cuberite.server.command.delay: 2 cuberite.server.post.launch.delay: 5 cuberite.backup.directory: /var/cuberite/backup cuberite.maintenance.warning.interval: 10 provisioning.properties: osFamily: ubuntu osVersionRegex: 15.10 shell.env: CUBERITE_BACKUP_DIRECTORY: $brooklyn:config("cuberite.backup.directory") CUBERITE_URL: $brooklyn:config("cuberite.url") CUBERITE_MOTD_URL: $brooklyn:config("cuberite.motd.url") CUBERITE_PORT: $brooklyn:config("cuberite.port") CUBERITE_WEBADMIN_PORT: $brooklyn:config("cuberite.webadmin.port") CUBERITE_WEBADMIN_PASSWORD: $brooklyn:attributeWhenReady("cuberite.webadmin.password") MAINTENANCE_DURATION: $brooklyn:config("cuberite.maintenance.duration") MAINTENANCE_WARNING_DURATION: $brooklyn:config("cuberite.maintenance.warning.duration") MAINTENANCE_WARNING_INTERVAL: $brooklyn:config("cuberite.maintenance.warning.interval") PLUGIN_WORLDEDIT: $brooklyn:config("plugin.worldedit") PLUGIN_ESSENTIALS: $brooklyn:config("plugin.essentials") PLUGIN_MAGICCARPET: $brooklyn:config("plugin.magiccarpet") PLUGIN_HUNGERGAMES: $brooklyn:config("plugin.hungergames") PLUGIN_SKYBLOCK: $brooklyn:config("plugin.skyblock") PLUGIN_LOGIN: $brooklyn:config("plugin.login") INSTALL_DIR: $brooklyn:attributeWhenReady("install.dir") RUN_DIR: $brooklyn:attributeWhenReady("run.dir") SERVER_COMMAND_DELAY: $brooklyn:config("cuberite.server.command.delay") SERVER_POST_LAUNCH_DELAY: $brooklyn:config("cuberite.server.post.launch.delay") install.command: | echo "Installing Cuberite" curl -O ${CUBERITE_URL} tar zxf Cuberite.tar.gz sudo apt-get --yes install git echo "Installing Plugins" cd ${INSTALL_DIR}/Server/Plugins # Non-core plugins if [ "$PLUGIN_WORLDEDIT" = "true" ]; then echo "Installing WorldEdit Plugin" git clone https://github.com/cuberite/WorldEdit fi if [ "$PLUGIN_ESSENTIALS" = "true" ]; then echo "Installing Essentials Plugin" git clone https://github.com/mc-server/Essentials fi if [ "$PLUGIN_HUNGERGAMES" = "true" ]; then echo "Installing HungerGames Plugin" git clone https://github.com/mc-server/HungerGames fi if [ "$PLUGIN_SKYBLOCK" = "true" ]; then echo "Installing SkyBlock Plugin" git clone https://github.com/Seadragon91/SkyBlock fi if [ "$PLUGIN_LOGIN" = "true" ]; then echo "Installing Login Plugin" git clone https://github.com/NiLSPACE/Login fi echo "Create backup directory: ${CUBERITE_BACKUP_DIRECTORY}" sudo mkdir -p ${CUBERITE_BACKUP_DIRECTORY} sudo chmod a+rwx ${CUBERITE_BACKUP_DIRECTORY} echo "Create functions script" cat <<'EOF' >> ${INSTALL_DIR}/Server/_brooklyn-minecraft-fns.sh #### variables ### _TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S") #### function definitions #### _enable_plugin() { plugin=$1 enabled=$2 echo $1 echo $2 echo "Sleeping for ${SERVER_COMMAND_DELAY} seconds" sleep $SERVER_COMMAND_DELAY if [ "${enabled}" = "true" ]; then if [ ! "x${plugin}" = "x" ]; then echo "Enabling plugin - ${plugin}" # note that : == true curl --data "PluginFolder=${plugin}&EnablePlugin=Enable" \ -g -s -u admin:${CUBERITE_WEBADMIN_PASSWORD} \ http://localhost:${CUBERITE_WEBADMIN_PORT}/webadmin/Core/Plugins || : echo $? else echo "Plugin ${plugin} not found, unable to enable" fi else echo "Plugin ${plugin} not enabled" fi } _reload_server() { echo "Triggering server reload" sleep $SERVER_COMMAND_DELAY curl --data "ReloadServer=Reload+Server" \ -g -s -u admin:${CUBERITE_WEBADMIN_PASSWORD} \ http://localhost:${CUBERITE_WEBADMIN_PORT}/webadmin/Core/Manage_Server \ 2>&1 >/dev/null } _broadcast() { msg=$1 echo "Broadcasting message to server: ${msg}" curl --data "ChatMessage=@4@l${msg}" \ -g -s -u admin:${CUBERITE_WEBADMIN_PASSWORD} \ http://localhost:${CUBERITE_WEBADMIN_PORT}/webadmin/Core/Chat \ 2>&1 >/dev/null } _start_maintenance(){ countdown=${MAINTENANCE_WARNING_DURATION} while [ "$countdown" -ge 5 ]; do _broadcast "Server will restart in ${countdown} seconds." sleep ${MAINTENANCE_WARNING_INTERVAL} let countdown-=${MAINTENANCE_WARNING_INTERVAL} done for i in {5..1}; do _broadcast "Restarting in ${i}...." sleep 1 done touch ${RUN_DIR}/.maintenance_mode echo "Killing Cuberite Server" pkill Cuberite || true echo "Wait for Cuberite daemon to exit" until ! pgrep Cuberite; do echo "... sleeping" sleep ${SERVER_COMMAND_DELAY} done } _exit_maintenance() { echo "Restarting Cuberite Daemon" cd ${INSTALL_DIR}/Server ./Cuberite -d echo "Exiting Maintenance mode" rm ${RUN_DIR}/.maintenance_mode } ############################## EOF customize.command: | echo "Configuring Cuberite" echo " - Motd" if [ -z "$CUBERITE_MOTD_URL" ]; then echo "Using default motd" # Note the weird indentation is deliberate cat > ${INSTALL_DIR}/Server/motd.txt <<- EOMOTD @6@lWelcome to Brooklyn Installed Cuberite @6http://www.cuberite.org/ @6Type /help for all commands EOMOTD else echo "ensure MOTD URL is accessible, does not validate contents" curl --head ${CUBERITE_MOTD_URL} | head -n 1 | grep 200 echo "Downloading motd from - ${CUBERITE_MOTD_URL}" curl -o ${INSTALL_DIR}/Server/motd.txt ${CUBERITE_MOTD_URL} fi echo " - Webadmin" cat > ${INSTALL_DIR}/Server/webadmin.ini <<- EOWEBADMIN #!/bin/bash [User:admin] Password=${CUBERITE_WEBADMIN_PASSWORD} [WebAdmin] Ports=${CUBERITE_WEBADMIN_PORT} Enabled=1 EOWEBADMIN launch.command: | # Start Cuberite Daemon cd ${INSTALL_DIR}/Server ./Cuberite -d -p ${CUBERITE_PORT} post.launch.command: | # Load functions source ${INSTALL_DIR}/Server/_brooklyn-minecraft-fns.sh # echo "Waiting for WebAdmin server startup to complete - ${SERVER_POST_LAUNCH_DELAY} seconds" sleep $SERVER_POST_LAUNCH_DELAY until $(curl -o /dev/null -s -I -f http://localhost:${CUBERITE_WEBADMIN_PORT}); do echo "... sleeping" sleep $SERVER_COMMAND_DELAY done ## Note order of plugin enablement can be significant, refer to the plugin docs # Core bundled plugins _enable_plugin MagicCarpet $PLUGIN_MAGICCARPET # Non-core plugins _enable_plugin WorldEdit $PLUGIN_WORLDEDIT _enable_plugin Essentials $PLUGIN_ESSENTIALS _enable_plugin HungerGames $PLUGIN_HUNGERGAMES _enable_plugin SkyBlock $PLUGIN_SKYBLOCK _enable_plugin Login $PLUGIN_LOGIN echo "Reloading Server Config" _reload_server checkRunning.command: | if [ -e ${RUN_DIR}/.maintenance_mode ] && test `find ".${RUN_DIR}/maintenance_mode" -mmin -${MAINTENANCE_DURATION}`; then echo "Active maintenance window detected, ignoring Cuberite process state" exit 0 elif [ -e ${RUN_DIR}/.maintenance_mode ]; then echo "Maintenance window has expired" fi # Check for the Cuberite process and pgrep Cuberite stop.command: | # Kill Cuberite process pkill Cuberite || true sudo rm -rf ${INSTALL_DIR} sudo rm -rf ${RUN_DIR} brooklyn.initializers: - type: org.apache.brooklyn.core.sensor.StaticSensor brooklyn.config: name: cuberite.port targetType: string static.value: $brooklyn:config("cuberite.port") - type: org.apache.brooklyn.core.sensor.password.CreatePasswordSensor brooklyn.config: name: cuberite.webadmin.password password.length: 10 - type: org.apache.brooklyn.core.effector.ssh.SshCommandEffector brooklyn.config: name: backupWorld description: Backup the current world to a 7zip archive command: | # Load functions source ${INSTALL_DIR}/Server/_brooklyn-minecraft-fns.sh FILE_TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S") # Regex converts non-[A-Za-z0-9_-] characters to _ # For example: "test invalid / name" will be converted to "test_invalid___name" BACKUP_FILENAME=${BACKUP_PREFIX//[^[:alnum:]_-]/_}-world-${FILE_TIMESTAMP}.tar.gz _start_maintenance echo "Backing up worlds" cd ${INSTALL_DIR}/Server/ tar czvf ${CUBERITE_BACKUP_DIRECTORY}/${BACKUP_FILENAME} world* _exit_maintenance parameters: BACKUP_PREFIX: label: Backup Prefix description: | Memorable prefix for world backup archive, any characters other than [A-Za-z0-9_-] will be converted to _ defaultValue: brooklyn-cuberite-backup - type: org.apache.brooklyn.core.effector.ssh.SshCommandEffector brooklyn.config: name: backupFull description: Backup the current world and config to a 7zip archive. command: | # Load functions source ${INSTALL_DIR}/Server/_brooklyn-minecraft-fns.sh FILE_TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S") # Regex converts non-[A-Za-z0-9_-] characters to _ # For example: "test invalid / name" will be converted to "test_invalid___name" BACKUP_FILENAME=${BACKUP_PREFIX//[^[:alnum:]_-]/_}-full-${FILE_TIMESTAMP}.tar.gz _start_maintenance echo "Backing up worlds" # TODO - plugin file backup? cuberite binary backup? migrations? cd ${INSTALL_DIR}/Server/ tar --ignore-failed-read -z -v -cf ${CUBERITE_BACKUP_DIRECTORY}/${BACKUP_FILENAME} world* *.ini players schematics itemblacklist *.sqlite motd.txt _exit_maintenance parameters: BACKUP_PREFIX: label: Backup Prefix description: | Memorable prefix for world backup archive, any characters other than [A-Za-z0-9_-] will be converted to _ defaultValue: brooklyn-cuberite-backup - type: org.apache.brooklyn.core.effector.ssh.SshCommandEffector brooklyn.config: name: showLogs description: Display the last n lines of Cuberite log output command: | cd ${INSTALL_DIR}/Server/logs tail -n ${NUM_LINES} $(ls -1t | head -1) parameters: NUM_LINES: label: Number of lines description: Number of lines to return defaultValue: 500 - type: org.apache.brooklyn.core.effector.ssh.SshCommandEffector brooklyn.config: name: listBackups description: Display a list of backups command: | cd ${CUBERITE_BACKUP_DIRECTORY} ls -hgot | awk '{if(! match($1 , /^total$/)) printf("%s %s %s %s %s\n", $7,$4,$5,$6,$3)}' - type: org.apache.brooklyn.core.effector.ssh.SshCommandEffector brooklyn.config: name: restoreBackup description: Restore a specified backup command: | # Load functions source ${INSTALL_DIR}/Server/_brooklyn-minecraft-fns.sh if [! -e ${CUBERITE_BACKUP_DIRECTORY}/${BACKUP_NAME} ]; then echo "Backup not found: ${BACKUP_NAME}" exit 1 fi _start_maintenance echo "Restoring worlds" tar -zxvf ${CUBERITE_BACKUP_DIRECTORY}/${BACKUP_NAME} -C ${INSTALL_DIR}/Server echo "Setting password to value in cuberite.webadmin.password sensor" sed -i "/Password=/c\Password=${CUBERITE_WEBADMIN_PASSWORD}" ${INSTALL_DIR}/Server/webadmin.ini _exit_maintenance parameters: BACKUP_NAME: label: Backup name description: | Filename of the backup to restore, use the listBackups effector to get a list of available backups - type: org.apache.brooklyn.core.effector.ssh.SshCommandEffector brooklyn.config: name: regenerateWorlds description: Delete the current world and generate a new one command: | # Load functions source ${INSTALL_DIR}/Server/_brooklyn-minecraft-fns.sh _start_maintenance echo "Deleting current worlds" rm -rf ${INSTALL_DIR}/Server/world* _exit_maintenance - type: org.apache.brooklyn.core.effector.ssh.SshCommandEffector brooklyn.config: name: broadcastMessage description: Broadcast a message to the minecraft server command: | # Load functions source ${INSTALL_DIR}/Server/_brooklyn-minecraft-fns.sh _broadcast "${MESSAGE}" parameters: MESSAGE: label: Message to broadcast description: | Message to broadcast to the Minecraft server, you can use standard Minecraft text formatting codes. - type: org.apache.brooklyn.core.effector.ssh.SshCommandEffector brooklyn.config: name: deleteBackups description: Delete old backup files command: | rm -v ${CUBERITE_BACKUP_DIRECTORY}/${BACKUP_NAME} parameters: BACKUP_NAME: label: Backup to delete description: | Files to delete, you can pass wildcards to delete multiple files. brooklyn.enrichers: # publish URLs when service is up # `cuberite.webadmin.url` for public access, `cuberite.webadmin.subnet.url` for internal access - type: brooklyn.enricher.basic.Transformer brooklyn.config: enricher.sourceSensor: $brooklyn:sensor("service.isUp") enricher.targetSensor: $brooklyn:sensor("cuberite.webadmin.url") enricher.targetValue: | $brooklyn:formatString("http://%s:%s", $brooklyn:attributeWhenReady("host.address"), $brooklyn:config("cuberite.webadmin.port")) - type: brooklyn.enricher.basic.Transformer brooklyn.config: enricher.sourceSensor: $brooklyn:sensor("service.isUp") enricher.targetSensor: $brooklyn:sensor("cuberite.webadmin.subnet.url") enricher.targetValue: $brooklyn:formatString("http://%s:%s", $brooklyn:attributeWhenReady("host.subnet.address"), $brooklyn:config("cuberite.webadmin.port")) - type: brooklyn.enricher.basic.Transformer brooklyn.config: enricher.sourceSensor: $brooklyn:sensor("service.isUp") enricher.targetSensor: $brooklyn:sensor("main.uri") enricher.targetValue: $brooklyn:formatString("http://%s:%s/", $brooklyn:attributeWhenReady("host.address"), $brooklyn:config("cuberite.webadmin.port"))