mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Merge branch 'dev-Silversthorn' into dev-Silversthorn-MVC
This commit is contained in:
commit
186dcdc616
87
.gitlab-ci.yml
Normal file
87
.gitlab-ci.yml
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
stages:
|
||||||
|
- buildx
|
||||||
|
- build-dev
|
||||||
|
- build-prod
|
||||||
|
|
||||||
|
buildx:
|
||||||
|
image: docker:git
|
||||||
|
services:
|
||||||
|
- docker:dind
|
||||||
|
stage: buildx
|
||||||
|
rules:
|
||||||
|
- if: $CI_COMMIT_BRANCH == 'dev'
|
||||||
|
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||||
|
variables:
|
||||||
|
GIT_STRATEGY: none
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- buildx
|
||||||
|
expire_in: 1 hour
|
||||||
|
script:
|
||||||
|
- export DOCKER_BUILDKIT=1
|
||||||
|
- git clone git://github.com/docker/buildx ./docker-buildx
|
||||||
|
- docker build --platform=local -o . ./docker-buildx
|
||||||
|
|
||||||
|
docker-build-dev:
|
||||||
|
image: docker:latest
|
||||||
|
services:
|
||||||
|
- name: docker:dind
|
||||||
|
command: ["--experimental"]
|
||||||
|
stage: build-dev
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
rules:
|
||||||
|
- if: $CI_COMMIT_BRANCH == 'dev'
|
||||||
|
environment:
|
||||||
|
name: development
|
||||||
|
before_script:
|
||||||
|
- mkdir -p ~/.docker/cli-plugins
|
||||||
|
- mv buildx ~/.docker/cli-plugins/docker-buildx
|
||||||
|
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||||
|
- echo $CI_BUILD_TOKEN | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
|
||||||
|
script:
|
||||||
|
- |
|
||||||
|
tag=":$CI_COMMIT_REF_SLUG"
|
||||||
|
echo "Running on branch '$CI_COMMIT_BRANCH': tag = $tag"
|
||||||
|
- docker buildx create --use
|
||||||
|
- docker buildx build
|
||||||
|
--cache-from type=registry,ref="$CI_REGISTRY_IMAGE${tag}"
|
||||||
|
--build-arg BUILDKIT_INLINE_CACHE=1
|
||||||
|
--tag "$CI_REGISTRY_IMAGE${tag}"
|
||||||
|
--platform linux/arm64/v8,linux/amd64
|
||||||
|
--push .
|
||||||
|
after_script:
|
||||||
|
- docker buildx imagetools inspect "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG"
|
||||||
|
|
||||||
|
docker-build-prod:
|
||||||
|
image: docker:latest
|
||||||
|
services:
|
||||||
|
- name: docker:dind
|
||||||
|
command: ["--experimental"]
|
||||||
|
stage: build-prod
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
rules:
|
||||||
|
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||||
|
environment:
|
||||||
|
name: production
|
||||||
|
before_script:
|
||||||
|
- mkdir -p ~/.docker/cli-plugins
|
||||||
|
- mv buildx ~/.docker/cli-plugins/docker-buildx
|
||||||
|
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||||
|
- echo $CI_BUILD_TOKEN | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
|
||||||
|
script:
|
||||||
|
- |
|
||||||
|
tag=""
|
||||||
|
echo "Running on default branch '$CI_DEFAULT_BRANCH': tag = 'latest'"
|
||||||
|
- docker buildx create --use
|
||||||
|
- docker buildx build
|
||||||
|
--cache-from type=registry,ref="$CI_REGISTRY_IMAGE${tag}"
|
||||||
|
--build-arg BUILDKIT_INLINE_CACHE=1
|
||||||
|
--tag "$CI_REGISTRY_IMAGE${tag}"
|
||||||
|
--platform linux/arm64/v8,linux/amd64
|
||||||
|
--push .
|
||||||
|
after_script:
|
||||||
|
- docker buildx imagetools inspect "$CI_REGISTRY_IMAGE${tag}"
|
79
README.md
79
README.md
@ -19,15 +19,57 @@ Git Repository - https://gitlab.com/crafty-controller/crafty-web
|
|||||||
|
|
||||||
## Basic Docker Usage
|
## Basic Docker Usage
|
||||||
|
|
||||||
A Docker image pipeline is still to be implimented but for example you can expect the image to be located: `crafty/cc-dashboard` and you would change the image in the below `docker run` to this image.
|
**To get started with docker**, all you need to do is pull the image from this git repository's registry.
|
||||||
|
This is done by using `docker-compose` or `docker run`(You don't need to clone the Repository and build, like in 3.x ).
|
||||||
|
|
||||||
If you are building from the `docker-compose` you can find it in `./docker/docker-compose.yml` just `cd` to the docker directory and `docker-compose up -d`
|
If you have a config folder already from previous local installation or docker setup, the image should mount this volume, if none is present then it will populate its own config folder for you.
|
||||||
|
|
||||||
If you'd rather not use `docker-compose` you can use the following `docker run`:
|
### Using the registry image:
|
||||||
|
The provided image supports both `arm64` and `amd64` out the box, if you have issues though you can build it yourself.
|
||||||
|
|
||||||
|
The image is located at: `registry.gitlab.com/crafty-controller/crafty-commander:latest`
|
||||||
|
| Branch | Status |
|
||||||
|
| ----------------- | ------------------------------------------------------------------ |
|
||||||
|
| :latest | [![pipeline status](https://gitlab.com/crafty-controller/crafty-commander/badges/master/pipeline.svg)](https://gitlab.com/crafty-controller/crafty-commander/-/commits/master) |
|
||||||
|
| :dev | [![pipeline status](https://gitlab.com/crafty-controller/crafty-commander/badges/dev/pipeline.svg)](https://gitlab.com/crafty-controller/crafty-commander/-/commits/dev) |
|
||||||
|
|
||||||
|
While the repository is still **private / pre-release**,
|
||||||
|
Before you can pull the image you must authenticate docker with the Container Registry.
|
||||||
|
|
||||||
|
To authenticate you will need a [personal access token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html)
|
||||||
|
with the minimum scope:
|
||||||
|
|
||||||
|
- For read (*pull*) access, `read_registry`.
|
||||||
|
- For write (*push*) access, `write_registry`.
|
||||||
|
|
||||||
|
When you have this just run:
|
||||||
|
```bash
|
||||||
|
$ docker login registry.gitlab.com -u <username> -p <token>
|
||||||
```
|
```
|
||||||
$ docker build . -t cc-dashboard
|
Then use one of the following methods:
|
||||||
# REMEMBER, Build your image!
|
#### docker-compose.yml
|
||||||
|
```yml
|
||||||
|
version: '3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
crafty:
|
||||||
|
container_name: crafty_commander
|
||||||
|
image: registry.gitlab.com/crafty-controller/crafty-commander:latest
|
||||||
|
ports:
|
||||||
|
- "8000:8000" # HTTP
|
||||||
|
- "8443:8443" # HTTPS
|
||||||
|
- "8123:8123" # DYNMAP
|
||||||
|
- "19132:19132/udp" # BEDROCK
|
||||||
|
- "24000-25600:24000-25600" # MC SERV PORT RANGE
|
||||||
|
volumes:
|
||||||
|
- ./docker/backups:/commander/backups
|
||||||
|
- ./docker/logs:/commander/logs
|
||||||
|
- ./docker/servers:/commander/servers
|
||||||
|
- ./docker/config:/commander/app/config
|
||||||
|
```
|
||||||
|
|
||||||
|
#### docker run
|
||||||
|
```sh
|
||||||
$ docker run \
|
$ docker run \
|
||||||
--name crafty_commander \
|
--name crafty_commander \
|
||||||
-p 8000:8000 \
|
-p 8000:8000 \
|
||||||
@ -39,8 +81,29 @@ $ docker run \
|
|||||||
-v "/$(pwd)/docker/logs:/commander/logs" \
|
-v "/$(pwd)/docker/logs:/commander/logs" \
|
||||||
-v "/$(pwd)/docker/servers:/commander/servers" \
|
-v "/$(pwd)/docker/servers:/commander/servers" \
|
||||||
-v "/$(pwd)/docker/config:/commander/app/config" \
|
-v "/$(pwd)/docker/config:/commander/app/config" \
|
||||||
cc-dashboard
|
registry.gitlab.com/crafty-controller/crafty-commander:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building from the cloned repository:
|
||||||
|
|
||||||
|
If you are building from `docker-compose` you can find the compose file in `./docker/docker-compose.yml` just `cd` to the docker directory and `docker-compose up -d`
|
||||||
|
|
||||||
|
If you'd rather not use `docker-compose` you can use the following `docker run`in the directory where the *Dockerfile* is:
|
||||||
|
```sh
|
||||||
|
# REMEMBER, Build your image first!
|
||||||
|
$ docker build . -t crafty
|
||||||
|
|
||||||
|
$ docker run \
|
||||||
|
--name crafty_commander \
|
||||||
|
-p 8000:8000 \
|
||||||
|
-p 8443:8443 \
|
||||||
|
-p 8123:8123 \
|
||||||
|
-p 19132:19132/udp \
|
||||||
|
-p 24000-25600:24000-25600 \
|
||||||
|
-v "/$(pwd)/docker/backups:/commander/backups" \
|
||||||
|
-v "/$(pwd)/docker/logs:/commander/logs" \
|
||||||
|
-v "/$(pwd)/docker/servers:/commander/servers" \
|
||||||
|
-v "/$(pwd)/docker/config:/commander/app/config" \
|
||||||
|
crafty
|
||||||
```
|
```
|
||||||
A fresh build will take several minutes depending on your system, but will be rapid there after.
|
A fresh build will take several minutes depending on your system, but will be rapid there after.
|
||||||
|
|
||||||
If you have a config folder already from previous local installation or docker setup, the image should mount this volume, if none is present then it will populate its own config folder for you.
|
|
||||||
|
@ -175,8 +175,8 @@ class Stats:
|
|||||||
|
|
||||||
|
|
||||||
# TODO: search server properties file for possible override of 127.0.0.1
|
# TODO: search server properties file for possible override of 127.0.0.1
|
||||||
internal_ip = server_data.get('server_ip', "127.0.0.1")
|
internal_ip = server['server_ip']
|
||||||
server_port = server_settings.get('server-port', "25565")
|
server_port = server['server_port']
|
||||||
|
|
||||||
logger.debug("Pinging {} on port {}".format(internal_ip, server_port))
|
logger.debug("Pinging {} on port {}".format(internal_ip, server_port))
|
||||||
int_mc_ping = ping(internal_ip, int(server_port))
|
int_mc_ping = ping(internal_ip, int(server_port))
|
||||||
@ -201,6 +201,8 @@ class Stats:
|
|||||||
for s in servers:
|
for s in servers:
|
||||||
|
|
||||||
server_id = s.get('server_id', None)
|
server_id = s.get('server_id', None)
|
||||||
|
server = db_helper.get_server_data_by_id(server_id)
|
||||||
|
|
||||||
|
|
||||||
logger.debug('Getting stats for server: {}'.format(server_id))
|
logger.debug('Getting stats for server: {}'.format(server_id))
|
||||||
|
|
||||||
@ -208,7 +210,7 @@ class Stats:
|
|||||||
server_obj = s.get('server_obj', None)
|
server_obj = s.get('server_obj', None)
|
||||||
server_obj.reload_server_settings()
|
server_obj.reload_server_settings()
|
||||||
server_settings = s.get('server_settings', {})
|
server_settings = s.get('server_settings', {})
|
||||||
server_data = s.get('server_data_obj', {})
|
server_data = self.controller.get_server_data(server_id)
|
||||||
|
|
||||||
# world data
|
# world data
|
||||||
world_name = server_settings.get('level-name', 'Unknown')
|
world_name = server_settings.get('level-name', 'Unknown')
|
||||||
@ -218,8 +220,8 @@ class Stats:
|
|||||||
p_stats = self._get_process_stats(server_obj.PID)
|
p_stats = self._get_process_stats(server_obj.PID)
|
||||||
|
|
||||||
# TODO: search server properties file for possible override of 127.0.0.1
|
# TODO: search server properties file for possible override of 127.0.0.1
|
||||||
internal_ip = server_data.get('server_ip', "127.0.0.1")
|
internal_ip = server['server_ip']
|
||||||
server_port = server_settings.get('server-port', "25565")
|
server_port = server['server_port']
|
||||||
|
|
||||||
logger.debug("Pinging server '{}' on {}:{}".format(s.get('server_name', "ID#{}".format(server_id)), internal_ip, server_port))
|
logger.debug("Pinging server '{}' on {}:{}".format(s.get('server_name', "ID#{}".format(server_id)), internal_ip, server_port))
|
||||||
int_mc_ping = ping(internal_ip, int(server_port))
|
int_mc_ping = ping(internal_ip, int(server_port))
|
||||||
@ -276,8 +278,8 @@ class Stats:
|
|||||||
p_stats = self._get_process_stats(server_obj.PID)
|
p_stats = self._get_process_stats(server_obj.PID)
|
||||||
|
|
||||||
# TODO: search server properties file for possible override of 127.0.0.1
|
# TODO: search server properties file for possible override of 127.0.0.1
|
||||||
internal_ip = server_data.get('server_ip', "127.0.0.1")
|
internal_ip = server['server_ip']
|
||||||
server_port = server_settings.get('server-port', "25565")
|
server_port = server['server_port']
|
||||||
|
|
||||||
logger.debug("Pinging server '{}' on {}:{}".format(server.name, internal_ip, server_port))
|
logger.debug("Pinging server '{}' on {}:{}".format(server.name, internal_ip, server_port))
|
||||||
int_mc_ping = ping(internal_ip, int(server_port))
|
int_mc_ping = ping(internal_ip, int(server_port))
|
||||||
|
@ -14,6 +14,7 @@ import html
|
|||||||
import zipfile
|
import zipfile
|
||||||
import pathlib
|
import pathlib
|
||||||
import shutil
|
import shutil
|
||||||
|
from requests import get
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from socket import gethostname
|
from socket import gethostname
|
||||||
@ -75,6 +76,25 @@ class Helpers:
|
|||||||
logger.error("{} does not exist".format(file))
|
logger.error("{} does not exist".format(file))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def check_internet():
|
||||||
|
try:
|
||||||
|
requests.get('https://google.com', timeout=1)
|
||||||
|
return True
|
||||||
|
except Exception as err:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def check_port(server_port):
|
||||||
|
host_public = get('https://api.ipify.org').text
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
result = sock.connect_ex((host_public ,server_port))
|
||||||
|
sock.close()
|
||||||
|
if result == 0:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def get_setting(self, key, default_return=False):
|
def get_setting(self, key, default_return=False):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -100,6 +100,14 @@ class Controller:
|
|||||||
# add this temp object to the list of init servers
|
# add this temp object to the list of init servers
|
||||||
self.servers_list.append(temp_server_dict)
|
self.servers_list.append(temp_server_dict)
|
||||||
|
|
||||||
|
if s['auto_start']:
|
||||||
|
db_helper.set_waiting_start(s['server_id'], True)
|
||||||
|
|
||||||
|
db_helper.get_waiting_start(s['server_id'])
|
||||||
|
|
||||||
|
server_stats = db_helper.get_all_servers_stats()
|
||||||
|
self.refresh_server_settings(s['server_id'])
|
||||||
|
|
||||||
console.info("Loaded Server: ID {} | Name: {} | Autostart: {} | Delay: {} ".format(
|
console.info("Loaded Server: ID {} | Name: {} | Autostart: {} | Delay: {} ".format(
|
||||||
s['server_id'],
|
s['server_id'],
|
||||||
s['server_name'],
|
s['server_name'],
|
||||||
|
@ -21,6 +21,7 @@ from app.classes.shared.console import console
|
|||||||
from app.classes.models.servers import Servers, servers_helper
|
from app.classes.models.servers import Servers, servers_helper
|
||||||
from app.classes.models.management import management_helper
|
from app.classes.models.management import management_helper
|
||||||
from app.classes.web.websocket_helper import websocket_helper
|
from app.classes.web.websocket_helper import websocket_helper
|
||||||
|
from app.classes.shared.translation import translation
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -183,19 +184,31 @@ class Server:
|
|||||||
logger.info("Linux Detected")
|
logger.info("Linux Detected")
|
||||||
|
|
||||||
logger.info("Starting server in {p} with command: {c}".format(p=self.server_path, c=self.server_command))
|
logger.info("Starting server in {p} with command: {c}".format(p=self.server_path, c=self.server_command))
|
||||||
|
|
||||||
|
db_helper.set_waiting_start(self.server_id, False)
|
||||||
try:
|
try:
|
||||||
self.process = pexpect.spawn(self.server_command, cwd=self.server_path, timeout=None, encoding=None)
|
self.process = pexpect.spawn(self.server_command, cwd=self.server_path, timeout=None, encoding='utf-8')
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
msg = "Server {} failed to start with error code: {}".format(self.name, ex)
|
msg = "Server {} failed to start with error code: {}".format(self.name, ex)
|
||||||
logger.error(msg)
|
logger.error(msg)
|
||||||
websocket_helper.broadcast('send_start_error', {
|
websocket_helper.broadcast('send_start_error', {
|
||||||
'error': msg
|
'error': translation.translate('error', 'start-error').format(self.name, ex)
|
||||||
})
|
})
|
||||||
return False
|
return False
|
||||||
websocket_helper.broadcast('send_start_reload', {
|
if helper.check_internet():
|
||||||
})
|
loc_server_port = db_helper.get_server_stats_by_id(self.server_id)['server_port']
|
||||||
|
if helper.check_port(loc_server_port):
|
||||||
|
websocket_helper.broadcast('send_start_reload', {
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
websocket_helper.broadcast('send_start_error', {
|
||||||
|
'error': translation.translate('error', 'closedPort').format(loc_server_port)
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
websocket_helper.broadcast('send_start_error', {
|
||||||
|
'error': translation.translate('error', 'internet')
|
||||||
|
})
|
||||||
|
|
||||||
self.process = pexpect.spawn(self.server_command, cwd=self.server_path, timeout=None, encoding='utf-8')
|
|
||||||
out_buf = ServerOutBuf(self.process, self.server_id)
|
out_buf = ServerOutBuf(self.process, self.server_id)
|
||||||
|
|
||||||
logger.debug('Starting virtual terminal listener for server {}'.format(self.name))
|
logger.debug('Starting virtual terminal listener for server {}'.format(self.name))
|
||||||
@ -351,6 +364,9 @@ class Server:
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def get_pid(self):
|
||||||
|
return self.PID
|
||||||
|
|
||||||
def detect_crash(self):
|
def detect_crash(self):
|
||||||
|
|
||||||
logger.info("Detecting possible crash for server: {} ".format(self.name))
|
logger.info("Detecting possible crash for server: {} ".format(self.name))
|
||||||
|
@ -2,6 +2,7 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
|
from typing import Container
|
||||||
import zipfile
|
import zipfile
|
||||||
|
|
||||||
import tornado.web
|
import tornado.web
|
||||||
@ -153,6 +154,8 @@ class AjaxHandler(BaseHandler):
|
|||||||
if srv_obj.check_running():
|
if srv_obj.check_running():
|
||||||
srv_obj.send_command(command)
|
srv_obj.send_command(command)
|
||||||
|
|
||||||
|
db_helper.add_to_audit_log(user_data['user_id'], "Sent command to {} terminal: {}".format(db_helper.get_server_friendly_name(server_id), command), server_id, self.get_remote_ip())
|
||||||
|
|
||||||
elif page == "create_file":
|
elif page == "create_file":
|
||||||
file_parent = self.get_body_argument('file_parent', default=None, strip=True)
|
file_parent = self.get_body_argument('file_parent', default=None, strip=True)
|
||||||
file_name = self.get_body_argument('file_name', default=None, strip=True)
|
file_name = self.get_body_argument('file_name', default=None, strip=True)
|
||||||
@ -196,6 +199,18 @@ class AjaxHandler(BaseHandler):
|
|||||||
self.redirect("/panel/server_detail?id={}&subpage=files".format(server_id))
|
self.redirect("/panel/server_detail?id={}&subpage=files".format(server_id))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
elif page == "kill":
|
||||||
|
server_id = self.get_argument('id', None)
|
||||||
|
svr = self.controller.get_server_obj(server_id)
|
||||||
|
if svr.get_pid():
|
||||||
|
try:
|
||||||
|
svr.killpid(svr.get_pid())
|
||||||
|
except Exception as e:
|
||||||
|
logger.error("Could not find PID for requested termsig. Full error: {}".format(e))
|
||||||
|
else:
|
||||||
|
logger.error("Could not find PID for requested termsig. Full error: {}".format(e))
|
||||||
|
return
|
||||||
|
|
||||||
@tornado.web.authenticated
|
@tornado.web.authenticated
|
||||||
def delete(self, page):
|
def delete(self, page):
|
||||||
if page == "del_file":
|
if page == "del_file":
|
||||||
|
@ -74,6 +74,7 @@ class PanelHandler(BaseHandler):
|
|||||||
'error': error,
|
'error': error,
|
||||||
'time': formatted_time
|
'time': formatted_time
|
||||||
}
|
}
|
||||||
|
page_data['super_user'] = exec_user['superuser']
|
||||||
|
|
||||||
# if no servers defined, let's go to the build server area
|
# if no servers defined, let's go to the build server area
|
||||||
if page_data['server_stats']['total'] == 0 and page != "error" and page != "credits" and page != "contribute":
|
if page_data['server_stats']['total'] == 0 and page != "error" and page != "credits" and page != "contribute":
|
||||||
@ -127,10 +128,17 @@ class PanelHandler(BaseHandler):
|
|||||||
elif page == 'dashboard':
|
elif page == 'dashboard':
|
||||||
if exec_user['superuser'] == 1:
|
if exec_user['superuser'] == 1:
|
||||||
page_data['servers'] = self.controller.servers.get_all_servers_stats()
|
page_data['servers'] = self.controller.servers.get_all_servers_stats()
|
||||||
|
for data in page_data['servers']:
|
||||||
|
data['stats']['waiting_start'] = db_helper.get_waiting_start(int(data['stats']['server_id']['server_id']))
|
||||||
else:
|
else:
|
||||||
user_auth = self.controller.servers.get_authorized_servers_stats(exec_user_id)
|
user_auth = self.controller.servers.get_authorized_servers_stats(exec_user_id)
|
||||||
logger.debug("ASFR: {}".format(user_auth))
|
logger.debug("ASFR: {}".format(user_auth))
|
||||||
page_data['servers'] = user_auth
|
page_data['servers'] = user_auth
|
||||||
|
|
||||||
|
total_players = 0
|
||||||
|
for server in db_helper.get_all_defined_servers():
|
||||||
|
total_players += len(self.controller.stats.get_server_players(server['server_id']))
|
||||||
|
page_data['num_players'] = total_players
|
||||||
|
|
||||||
for s in page_data['servers']:
|
for s in page_data['servers']:
|
||||||
try:
|
try:
|
||||||
@ -171,6 +179,7 @@ class PanelHandler(BaseHandler):
|
|||||||
# server_data isn't needed since the server_stats also pulls server data
|
# server_data isn't needed since the server_stats also pulls server data
|
||||||
page_data['server_data'] = self.controller.servers.get_server_data_by_id(server_id)
|
page_data['server_data'] = self.controller.servers.get_server_data_by_id(server_id)
|
||||||
page_data['server_stats'] = self.controller.servers.get_server_stats_by_id(server_id)
|
page_data['server_stats'] = self.controller.servers.get_server_stats_by_id(server_id)
|
||||||
|
page_data['waiting_start'] = self.controller.servers.get_waiting_start(server_id)
|
||||||
page_data['get_players'] = lambda: self.controller.stats.get_server_players(server_id)
|
page_data['get_players'] = lambda: self.controller.stats.get_server_players(server_id)
|
||||||
page_data['active_link'] = subpage
|
page_data['active_link'] = subpage
|
||||||
page_data['permissions'] = {
|
page_data['permissions'] = {
|
||||||
@ -637,7 +646,10 @@ class PanelHandler(BaseHandler):
|
|||||||
server_id = self.get_argument('id', None)
|
server_id = self.get_argument('id', None)
|
||||||
backup_path = bleach.clean(self.get_argument('backup_path', None))
|
backup_path = bleach.clean(self.get_argument('backup_path', None))
|
||||||
max_backups = bleach.clean(self.get_argument('max_backups', None))
|
max_backups = bleach.clean(self.get_argument('max_backups', None))
|
||||||
enabled = int(float(bleach.clean(self.get_argument('auto_enabled'), '0')))
|
try:
|
||||||
|
enabled = int(float(bleach.clean(self.get_argument('auto_enabled'), '0')))
|
||||||
|
except Exception as e:
|
||||||
|
enabled = '0'
|
||||||
|
|
||||||
if not exec_user['superuser']:
|
if not exec_user['superuser']:
|
||||||
self.redirect("/panel/error?error=Unauthorized access: not superuser")
|
self.redirect("/panel/error?error=Unauthorized access: not superuser")
|
||||||
@ -652,10 +664,16 @@ class PanelHandler(BaseHandler):
|
|||||||
return
|
return
|
||||||
|
|
||||||
if backup_path is not None:
|
if backup_path is not None:
|
||||||
Servers.update({
|
if enabled == '0':
|
||||||
Servers.backup_path: backup_path
|
Servers.update({
|
||||||
}).where(Servers.server_id == server_id).execute()
|
Servers.backup_path: backup_path
|
||||||
self.controller.management.set_backup_config(server_id, max_backups=max_backups)
|
}).where(Servers.server_id == server_id).execute()
|
||||||
|
self.controller.management.set_backup_config(server_id, max_backups=max_backups, auto_enabled=False)
|
||||||
|
else:
|
||||||
|
Servers.update({
|
||||||
|
Servers.backup_path: backup_path
|
||||||
|
}).where(Servers.server_id == server_id).execute()
|
||||||
|
self.controller.management.set_backup_config(server_id, max_backups=max_backups, auto_enabled=True)
|
||||||
|
|
||||||
self.controller.management.add_to_audit_log(exec_user['user_id'],
|
self.controller.management.add_to_audit_log(exec_user['user_id'],
|
||||||
"Edited server {}: updated backups".format(server_id),
|
"Edited server {}: updated backups".format(server_id),
|
||||||
|
@ -228,7 +228,12 @@ if (webSocket) {
|
|||||||
var x = document.querySelector('.modal-backdrop');
|
var x = document.querySelector('.modal-backdrop');
|
||||||
if(x){
|
if(x){
|
||||||
x.remove()}
|
x.remove()}
|
||||||
bootbox.alert(start_error.error);
|
bootbox.alert({
|
||||||
|
message: start_error.error,
|
||||||
|
callback: function () {
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,9 @@
|
|||||||
<p class="font-weight-light text-muted mb-0">{{ r }}</p>
|
<p class="font-weight-light text-muted mb-0">{{ r }}</p>
|
||||||
{% end %}
|
{% end %}
|
||||||
</div>
|
</div>
|
||||||
|
{% if "Super User" in data['user_role'] %}
|
||||||
<a class="dropdown-item" href="/panel/activity_logs"><i class="dropdown-item-icon mdi mdi-calendar-check-outline text-primary"></i> Activity</a>
|
<a class="dropdown-item" href="/panel/activity_logs"><i class="dropdown-item-icon mdi mdi-calendar-check-outline text-primary"></i> Activity</a>
|
||||||
|
{% end %}
|
||||||
<a class="dropdown-item" href="/public/logout"><i class="dropdown-item-icon mdi mdi-power text-primary"></i>Sign Out</a>
|
<a class="dropdown-item" href="/public/logout"><i class="dropdown-item-icon mdi mdi-power text-primary"></i>Sign Out</a>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<h5 class="mb-1 font-weight-medium text-primary">{{ translate('dashboard', 'players') }}</h5>
|
<h5 class="mb-1 font-weight-medium text-primary">{{ translate('dashboard', 'players') }}</h5>
|
||||||
<h3 class="mb-0 font-weight-semibold">18</h3>
|
<h3 class="mb-0 font-weight-semibold">{{ data['num_players'] }}</h3>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="wrapper my-auto ml-auto ml-lg-4">
|
<div class="wrapper my-auto ml-auto ml-lg-4">
|
||||||
@ -126,13 +126,17 @@
|
|||||||
<td id="controls{{server['server_data']['server_id']}}" class="actions_serverlist">
|
<td id="controls{{server['server_data']['server_id']}}" class="actions_serverlist">
|
||||||
{% if server['user_command_permission'] %}
|
{% if server['user_command_permission'] %}
|
||||||
{% if server['stats']['running'] %}
|
{% if server['stats']['running'] %}
|
||||||
<a class="stop_button" data-id="{{server['server_data']['server_id']}}"> <i class="fas fa-stop"></i></a>
|
<a class="stop_button" data-id="{{server['server_data']['server_id']}}" data-toggle="tooltip" title={{ translate('dashboard', 'stop') }}> <i class="fas fa-stop"></i></a>
|
||||||
<a class="restart_button" data-id="{{server['server_data']['server_id']}}"> <i class="fas fa-sync"></i></a>
|
<a class="restart_button" data-id="{{server['server_data']['server_id']}}" data-toggle="tooltip" title={{ translate('dashboard', 'restart') }}> <i class="fas fa-sync"></i></a>
|
||||||
|
<a class="kill_button" data-id="{{server['server_data']['server_id']}}" class="kill_button" data-toggle="tooltip" title={{ translate('dashboard', 'kill') }}> <i class="fas fa-skull"></i></a>
|
||||||
{% elif server['stats']['updating']%}
|
{% elif server['stats']['updating']%}
|
||||||
<a data-id="{{server['server_data']['server_id']}}" class=""> UPDATING...</i></a>
|
<a data-id="{{server['server_data']['server_id']}}" class="">{{ translate('serverTerm', 'updating') }}</i></a>
|
||||||
|
{% elif server['stats']['waiting_start']%}
|
||||||
|
<a data-id="{{server['server_data']['server_id']}}" class="" title={{ translate('dashboard', 'delay-explained')}}>{{ translate('dashboard', 'starting') }}</i></a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a data-id="{{server['server_data']['server_id']}}" class="play_button"><i class="fas fa-play"></i></a>
|
<a data-id="{{server['server_data']['server_id']}}" class="play_button"><i class="fas fa-play" data-toggle="tooltip" title={{ translate('dashboard', 'start') }}></i></a>
|
||||||
<a data-id="{{server['server_data']['server_id']}}" class="clone_button"> <i class="fas fa-clone"></i></a>
|
<a data-id="{{server['server_data']['server_id']}}" class="clone_button"> <i class="fas fa-clone" data-toggle="tooltip" title={{ translate('dashboard', 'clone') }}></i></a>
|
||||||
|
<a class="kill_button" data-id="{{server['server_data']['server_id']}}" class="kill_button" data-toggle="tooltip" title={{ translate('dashboard', 'kill') }}> <i class="fas fa-skull"></i></a>
|
||||||
{% end %}
|
{% end %}
|
||||||
{% end %}
|
{% end %}
|
||||||
</td>
|
</td>
|
||||||
@ -240,6 +244,25 @@ function send_command (server_id, command){
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function send_kill (server_id){
|
||||||
|
/* this getCookie function is in base.html */
|
||||||
|
var token = getCookie("_xsrf");
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
headers: {'X-XSRFToken': token},
|
||||||
|
url: '/ajax/kill?id=' + server_id,
|
||||||
|
success: function(data){
|
||||||
|
console.log("got response:");
|
||||||
|
console.log(data);
|
||||||
|
setTimeout(function(){
|
||||||
|
location.reload();
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
$( document ).ready(function() {
|
$( document ).ready(function() {
|
||||||
console.log('ready for JS!')
|
console.log('ready for JS!')
|
||||||
|
|
||||||
@ -272,6 +295,37 @@ $( document ).ready(function() {
|
|||||||
title: '{% raw translate("dashboard", "sendingCommand") %}',
|
title: '{% raw translate("dashboard", "sendingCommand") %}',
|
||||||
message: '<div align="center"><i class="fas fa-spin fa-spinner"></i> {% raw translate("dashboard", "bePatientRestart") %} </div>'
|
message: '<div align="center"><i class="fas fa-spin fa-spinner"></i> {% raw translate("dashboard", "bePatientRestart") %} </div>'
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
$( ".kill_button" ).click(function() {
|
||||||
|
server_id = $(this).attr("data-id");
|
||||||
|
bootbox.confirm({
|
||||||
|
message: "This will kill the server process and all it's subprocesses. Killing a process can potentially corrupt files. Only do this in extreme circumstances. Are you sure you would like to continue?",
|
||||||
|
buttons: {
|
||||||
|
confirm: {
|
||||||
|
label: '{% raw translate("dashboard", "kill") %}',
|
||||||
|
className: 'btn-danger'
|
||||||
|
},
|
||||||
|
cancel: {
|
||||||
|
label: '{% raw translate("panelConfig", "cancel") %}',
|
||||||
|
className: 'btn-secondary'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
callback: function (result) {
|
||||||
|
if(result){
|
||||||
|
send_kill(server_id);
|
||||||
|
var dialog = bootbox.dialog({
|
||||||
|
title: '{% raw translate("dashboard", "killing") %}',
|
||||||
|
message: '<p><i class="fa fa-spin fa-spinner"></i> Loading...</p>'
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.init(function(){
|
||||||
|
setTimeout(function(){
|
||||||
|
location.reload();
|
||||||
|
}, 15000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
if (webSocket) {
|
if (webSocket) {
|
||||||
cpu_data = document.getElementById('cpu_data');
|
cpu_data = document.getElementById('cpu_data');
|
||||||
|
@ -54,6 +54,12 @@
|
|||||||
<button onclick="" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1 disabled">{% raw translate('serverTerm', 'restart') %}</button>
|
<button onclick="" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1 disabled">{% raw translate('serverTerm', 'restart') %}</button>
|
||||||
<button onclick="" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate('serverTerm', 'stop') }}</button>
|
<button onclick="" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate('serverTerm', 'stop') }}</button>
|
||||||
</div>
|
</div>
|
||||||
|
{% elif data['waiting_start'] %}
|
||||||
|
<div id="control_buttons" class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0" style="visibility: visible">
|
||||||
|
<button onclick="" id="start-btn" style="max-width: 7rem; white-space: nowrap;" class="btn btn-secondary m-1 flex-grow-1 disabled" data-toggle="tooltip" title="{{ translate('serverTerm', 'delay-explained')}}">{{ translate('serverTerm', 'starting') }}</button>
|
||||||
|
<button onclick="" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1 disabled">{% raw translate('serverTerm', 'restart') %}</button>
|
||||||
|
<button onclick="" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate('serverTerm', 'stop') }}</button>
|
||||||
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div id="control_buttons" class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0" style="visibility: visible">
|
<div id="control_buttons" class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0" style="visibility: visible">
|
||||||
<button onclick="send_command(server_id, 'start_server');" id="start-btn" style="max-width: 7rem;" class="btn btn-primary m-1 flex-grow-1">{{ translate('serverTerm', 'start') }}</button>
|
<button onclick="send_command(server_id, 'start_server');" id="start-btn" style="max-width: 7rem;" class="btn btn-primary m-1 flex-grow-1">{{ translate('serverTerm', 'start') }}</button>
|
||||||
|
16
app/migrations/20210915205501_waiting_start_1.py
Normal file
16
app/migrations/20210915205501_waiting_start_1.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Generated by database migrator
|
||||||
|
import peewee
|
||||||
|
|
||||||
|
def migrate(migrator, database, **kwargs):
|
||||||
|
migrator.add_columns('server_stats', waiting_start=peewee.BooleanField(default=False))
|
||||||
|
"""
|
||||||
|
Write your migrations here.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def rollback(migrator, database, **kwargs):
|
||||||
|
migrator.drop_columns('server_stats', ['waiting_start'])
|
||||||
|
"""
|
||||||
|
Write your rollback migrations here.
|
||||||
|
"""
|
@ -10,7 +10,10 @@
|
|||||||
"contact": "Contact Crafty Control Support via Discord",
|
"contact": "Contact Crafty Control Support via Discord",
|
||||||
"terribleFailure": "What a Terrible Failure!",
|
"terribleFailure": "What a Terrible Failure!",
|
||||||
"embarassing": "Oh my, well, this is embarrassing.",
|
"embarassing": "Oh my, well, this is embarrassing.",
|
||||||
"error": "Error!"
|
"error": "Error!",
|
||||||
|
"start-error": "Server {} failed to start with error code: {}",
|
||||||
|
"closedPort": "We have detected port {} may not be open on the host network or a firewall is blocking it. Remote client connections to the server may be limited.",
|
||||||
|
"internet": "We have detected the machine running Crafty has no connection to the internet. Client connections to the server may be limited."
|
||||||
},
|
},
|
||||||
"404": {
|
"404": {
|
||||||
"contact": "Contact Crafty Control Support via Discord",
|
"contact": "Contact Crafty Control Support via Discord",
|
||||||
@ -89,7 +92,15 @@
|
|||||||
"sendingCommand": "Sending your command",
|
"sendingCommand": "Sending your command",
|
||||||
"cpuCurFreq": "CPU Current Clock",
|
"cpuCurFreq": "CPU Current Clock",
|
||||||
"cpuMaxFreq": "CPU Maximum Clock",
|
"cpuMaxFreq": "CPU Maximum Clock",
|
||||||
"cpuCores": "CPU Cores"
|
"cpuCores": "CPU Cores",
|
||||||
|
"start": "Start",
|
||||||
|
"stop": "Stop",
|
||||||
|
"clone": "Clone",
|
||||||
|
"kill": "Kill Process",
|
||||||
|
"restart": "Restart",
|
||||||
|
"killing": "Killing process...",
|
||||||
|
"starting": "Delayed-Start",
|
||||||
|
"delay-explained": "The service/agent has recently started and is delaying the start of the minecraft server instance"
|
||||||
},
|
},
|
||||||
"accessDenied": {
|
"accessDenied": {
|
||||||
"accessDenied": "Access Denied",
|
"accessDenied": "Access Denied",
|
||||||
@ -129,7 +140,9 @@
|
|||||||
"start": "Start",
|
"start": "Start",
|
||||||
"restart": "Restart",
|
"restart": "Restart",
|
||||||
"stop": "Stop",
|
"stop": "Stop",
|
||||||
"updating": "Updating..."
|
"updating": "Updating...",
|
||||||
|
"starting": "Delayed-Start",
|
||||||
|
"delay-explained": "The service/agent has recently started and is delaying the start of the minecraft server instance"
|
||||||
},
|
},
|
||||||
"serverPlayerManagement": {
|
"serverPlayerManagement": {
|
||||||
"players": "Players",
|
"players": "Players",
|
||||||
|
@ -10,7 +10,10 @@
|
|||||||
"contact": "Ota yhteyttä Crafty Control -tukeen Discordin kautta",
|
"contact": "Ota yhteyttä Crafty Control -tukeen Discordin kautta",
|
||||||
"terribleFailure": "Mikä kauhea epäonnistuminen!",
|
"terribleFailure": "Mikä kauhea epäonnistuminen!",
|
||||||
"embarassing": "No, tämähän on noloa.",
|
"embarassing": "No, tämähän on noloa.",
|
||||||
"error": "Virhe!"
|
"error": "Virhe!",
|
||||||
|
"start-error": "Palvelin {} ei käynnistynyt virhekoodilla: {}",
|
||||||
|
"closedPort": "Olemme havainneet, että portti {} ei ehkä ole auki isäntäverkossa tai palomuuri estää sen. Etäasiakkaan yhteydet palvelimeen voivat olla rajallisia.",
|
||||||
|
"internet": "Olemme havainneet, että Crafty -koneella ei ole Internet -yhteyttä. Asiakasyhteydet palvelimelle voivat olla rajalliset."
|
||||||
},
|
},
|
||||||
"404": {
|
"404": {
|
||||||
"contact": "Ota yhteyttä Crafty Control -tukeen Discordin kautta",
|
"contact": "Ota yhteyttä Crafty Control -tukeen Discordin kautta",
|
||||||
@ -89,7 +92,15 @@
|
|||||||
"sendingCommand": "Lähetämme komentoasi",
|
"sendingCommand": "Lähetämme komentoasi",
|
||||||
"cpuCurFreq": "Nykyinen kellotaajuus",
|
"cpuCurFreq": "Nykyinen kellotaajuus",
|
||||||
"cpuMaxFreq": "Maksimi kellotaajuus",
|
"cpuMaxFreq": "Maksimi kellotaajuus",
|
||||||
"cpuCores": "Suorittimen ytimet"
|
"cpuCores": "Suorittimen ytimet",
|
||||||
|
"start": "Alkaa",
|
||||||
|
"stop": "Lopettaa",
|
||||||
|
"clone": "Klooni",
|
||||||
|
"kill": "Tapa prosessi",
|
||||||
|
"restart": "Uudelleenkäynnistää",
|
||||||
|
"killing": "Tappamisprosessi ...",
|
||||||
|
"starting": "Myöhästynyt lähtö",
|
||||||
|
"delay-explained": "Palvelu/agentti on äskettäin aloittanut ja viivästyttää minecraft -palvelimen ilmentymän alkua"
|
||||||
},
|
},
|
||||||
"accessDenied": {
|
"accessDenied": {
|
||||||
"accessDenied": "Käyttö estetty",
|
"accessDenied": "Käyttö estetty",
|
||||||
@ -128,7 +139,10 @@
|
|||||||
"sendCommand": "Lähetä komento",
|
"sendCommand": "Lähetä komento",
|
||||||
"start": "Käynnistä",
|
"start": "Käynnistä",
|
||||||
"restart": "Uudelleen­käynnistä",
|
"restart": "Uudelleen­käynnistä",
|
||||||
"stop": "Sammuta"
|
"stop": "Sammuta",
|
||||||
|
"updating": "Updating",
|
||||||
|
"starting": "Myöhästynyt lähtö",
|
||||||
|
"delay-explained": "Palvelu/agentti on äskettäin aloittanut ja viivästyttää minecraft -palvelimen ilmentymän alkua"
|
||||||
},
|
},
|
||||||
"serverPlayerManagement": {
|
"serverPlayerManagement": {
|
||||||
"players": "Pelaajat",
|
"players": "Pelaajat",
|
||||||
|
@ -10,7 +10,10 @@
|
|||||||
"contact": "Contacter le Support de Crafty Control via Discord",
|
"contact": "Contacter le Support de Crafty Control via Discord",
|
||||||
"terribleFailure": "C'est une Terrible Erreur !",
|
"terribleFailure": "C'est une Terrible Erreur !",
|
||||||
"embarassing": "Oulà, c'est embarrassant.",
|
"embarassing": "Oulà, c'est embarrassant.",
|
||||||
"error": "Erreur !"
|
"error": "Erreur !",
|
||||||
|
"start-error": "Le serveur {} n'a pas pu démarrer avec le code d'erreur : {}",
|
||||||
|
"closedPort": "Nous avons détecté que le port {} n'est peut-être pas ouvert sur le réseau hôte ou qu'un pare-feu le bloque. Les connexions des clients distants au serveur peuvent être limitées.",
|
||||||
|
"internet": "Nous avons détecté que la machine exécutant Crafty n'a pas de connexion à Internet. Les connexions client au serveur peuvent être limitées."
|
||||||
},
|
},
|
||||||
"404": {
|
"404": {
|
||||||
"contact": "Contacter le Support de Crafty Control via Discord",
|
"contact": "Contacter le Support de Crafty Control via Discord",
|
||||||
@ -89,7 +92,15 @@
|
|||||||
"sendingCommand": "Envoi de votre commande",
|
"sendingCommand": "Envoi de votre commande",
|
||||||
"cpuCurFreq": "Fréquence CPU actuelle",
|
"cpuCurFreq": "Fréquence CPU actuelle",
|
||||||
"cpuMaxFreq": "Fréquence CPU Maximum",
|
"cpuMaxFreq": "Fréquence CPU Maximum",
|
||||||
"cpuCores": "Coeurs CPU"
|
"cpuCores": "Coeurs CPU",
|
||||||
|
"start": "Début",
|
||||||
|
"stop": "Arrêter",
|
||||||
|
"clone": "Cloner",
|
||||||
|
"kill": "Tuer le processus",
|
||||||
|
"restart": "Redémarrage",
|
||||||
|
"killing": "Processus de mise à mort...",
|
||||||
|
"starting": "Démarrage retardé",
|
||||||
|
"delay-explained": "Le service/agent a récemment démarré et retarde le démarrage de l'instance du serveur minecraft"
|
||||||
},
|
},
|
||||||
"accessDenied": {
|
"accessDenied": {
|
||||||
"accessDenied": "Accès Interdit",
|
"accessDenied": "Accès Interdit",
|
||||||
@ -129,7 +140,9 @@
|
|||||||
"start": "Démarrer",
|
"start": "Démarrer",
|
||||||
"restart": "Redémarrer",
|
"restart": "Redémarrer",
|
||||||
"stop": "Arrêter",
|
"stop": "Arrêter",
|
||||||
"updating": "Mise à Jour ..."
|
"updating": "Mise à Jour ...",
|
||||||
|
"starting": "Démarrage retardé",
|
||||||
|
"delay-explained": "Le service/agent a récemment démarré et retarde le démarrage de l'instance du serveur minecraft"
|
||||||
},
|
},
|
||||||
"serverPlayerManagement": {
|
"serverPlayerManagement": {
|
||||||
"players": "Joueurs",
|
"players": "Joueurs",
|
||||||
|
17
docker-compose.yml.example
Normal file
17
docker-compose.yml.example
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
crafty:
|
||||||
|
container_name: crafty_commander
|
||||||
|
image: registry.gitlab.com/crafty-controller/crafty-commander:latest
|
||||||
|
ports:
|
||||||
|
- "8000:8000" # HTTP
|
||||||
|
- "8443:8443" # HTTPS
|
||||||
|
- "8123:8123" # DYNMAP
|
||||||
|
- "19132:19132/udp" # BEDROCK
|
||||||
|
- "24000-25600:24000-25600" # MC SERV PORT RANGE
|
||||||
|
volumes:
|
||||||
|
- ./docker/backups:/commander/backups
|
||||||
|
- ./docker/logs:/commander/logs
|
||||||
|
- ./docker/servers:/commander/servers
|
||||||
|
- ./docker/config:/commander/app/config
|
@ -1,7 +1,7 @@
|
|||||||
version: '3'
|
version: '3'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
cc-dashboard:
|
crafty:
|
||||||
container_name: crafty_commander
|
container_name: crafty_commander
|
||||||
build: ..
|
build: ..
|
||||||
ports:
|
ports:
|
||||||
|
8
main.py
8
main.py
@ -131,6 +131,14 @@ if __name__ == '__main__':
|
|||||||
# this should always be last
|
# this should always be last
|
||||||
tasks_manager.start_main_kill_switch_watcher()
|
tasks_manager.start_main_kill_switch_watcher()
|
||||||
|
|
||||||
|
logger.info("Checking Internet/Port Service. This may take a minute.")
|
||||||
|
console.info("Checking Internet/Port Service. This may take a minute.")
|
||||||
|
|
||||||
|
if not helper.check_internet():
|
||||||
|
console.error("We have detected the machine running Crafty has no connection to the internet. Client connections to the server may be limited.")
|
||||||
|
elif not helper.check_port(helper.get_setting('https_port')):
|
||||||
|
console.error("We have detected Crafty's port, {} may not be open on the host network or a firewall is blocking it. Remote client connections to Crafty may be limited.".format(helper.get_setting('https_port')))
|
||||||
|
|
||||||
Crafty = MainPrompt(tasks_manager, migration_manager)
|
Crafty = MainPrompt(tasks_manager, migration_manager)
|
||||||
|
|
||||||
def sigterm_handler(signum, current_stack_frame):
|
def sigterm_handler(signum, current_stack_frame):
|
||||||
|
Loading…
Reference in New Issue
Block a user