def import_server(self, **raw_args): args = {k: str(v) for k, v in raw_args.iteritems()} server_name = args.pop('server_name') retval = None response = {'result': None, 'cmd': 'import_server', 'payload': None} from pwd import getpwnam from grp import getgrgid try: instance = mc(server_name, self.login, self.base_directory) instance.import_server(**args) instance = mc(server_name, None, self.base_directory) instance.chown(self.login) instance.chgrp(getgrgid(getpwnam(self.login).pw_gid).gr_name) except (RuntimeError, KeyError, OSError, ValueError) as ex: response['result'] = 'error' retval = ex.message except CalledProcessError as ex: response['result'] = 'error' retval = ex.output except RuntimeWarning as ex: response['result'] = 'warning' retval = ex.message else: response['result'] = 'success' retval = "Server '%s' successfully imported" % server_name response['payload'] = to_jsonable_type(retval) return response
def test_bare_environment(self): with self.assertRaises(TypeError): instance = mc() for s in (False, ): with self.assertRaises(ValueError): instance = mc(s)
def test_create(self): instance = mc('one', **self.instance_arguments) instance.create() for d in ('cwd','bwd','awd'): self.assertTrue(os.path.exists(instance.env[d])) for f in ('sp', 'sc'): self.assertTrue(os.path.isfile(instance.env[f])) self.assertTrue(instance.server_properties[:]) self.assertTrue(instance.server_config[:]) with self.assertRaises(RuntimeError): self.assertTrue(instance.command_start) with self.assertRaises(RuntimeError): self.assertIsNone(instance.command_kill) self.assertTrue(instance.command_backup) self.assertTrue(instance.command_archive) self.assertTrue(instance.command_restore) ''' FIXME: how should prune/apply_profile/wget_profile respond? ''' instance = mc('two', **self.instance_arguments) instance.create({'java':{'java_xmx':2048}}, {'server-port':'27000'}) self.assertEqual(instance.server_properties['server-port'], '27000') self.assertEqual(instance.server_config['java':'java_xmx'], '2048') instance = mc('three', **self.instance_arguments) instance.create(sc={'java':{'java_bogus': 'wow!'}}, sp={'bogus-value':'abcd'}) self.assertEqual(instance.server_properties['bogus-value'], 'abcd') self.assertEqual(instance.server_config['java':'java_bogus'], 'wow!')
def display_crontabs(): print ''' <script type="text/javascript"> $('.sc').one("click", (function(event){ event.preventDefault(); $.post("cgi-bin/server.py", { command: "display", server: $(this).attr("id"), page: 'server.config' }, function(data){ $('#main').html(data); }); })); </script> ''' print '<h2>System Crontabs</h2>' print '<p><span class="green">%s</span> servers were located in <span class="green">%s</a>:</p>' % (len(mineos.mc.ports_reserved()), mineos.mc().mineos_config['paths']['world_path']) print '<pre><b>%s%s%s%s</b><br>' % ('{:<20}'.format('server'), '{:<14}'.format('archive'), '{:<14}'.format('backup'), '{:<14}'.format('map')) for server, port, status in mineos.mc.ports_reserved(): instance = mineos.mc(server) print '<a href="#" class="sc stats" id="%s">%s</a>%s%s%s' % (server, '{:<20}'.format(server), '{:<14}'.format(instance.server_config['crontabs']['freq_archive']), '{:<14}'.format(instance.server_config['crontabs']['freq_backup']), '{:<14}'.format(instance.server_config['crontabs']['freq_map']))
def import_server(self, **raw_args): args = {k:str(v) for k,v in raw_args.iteritems()} server_name = args.pop('server_name') retval = None response = { 'result': None, 'cmd': 'import_server', 'payload': None } from pwd import getpwnam from grp import getgrgid try: instance = mc(server_name, self.login, self.base_directory) instance.import_server(**args) instance = mc(server_name, None, self.base_directory) instance.chown(self.login) instance.chgrp(getgrgid(getpwnam(self.login).pw_gid).gr_name) except (RuntimeError, KeyError, OSError) as ex: response['result'] = 'error' retval = ex.message except CalledProcessError as ex: response['result'] = 'error' retval = ex.output except RuntimeWarning as ex: response['result'] = 'warning' retval = ex.message else: response['result'] = 'success' retval = "Server '%s' successfully imported" % server_name response['payload'] = to_jsonable_type(retval) return response
def check_interval(self): from procfs_reader import path_owner from time import sleep crons = [] for action in ('backup','archive'): for server in mc.list_servers_to_act(action, self.base_directory): crons.append( (action, server) ) for action, server in crons: try: path_ = os.path.join(self.base_directory, mc.DEFAULT_PATHS['servers'], server) getattr(mc(server, path_owner(path_), self.base_directory), 'commit')() except Exception: pass else: sleep(len(crons) * mc.COMMIT_DELAY) for action, server in crons: try: path_ = os.path.join(self.base_directory, mc.DEFAULT_PATHS['servers'], server) getattr(mc(server, path_owner(path_), self.base_directory), action)() sleep(mc.COMMIT_DELAY) except Exception: pass
def test_sc_defaults(self): from conf_reader import config_file instance = mc('one', **self.instance_arguments) instance.create(sc={'java':{'java-bin':'isworking'}}) conf = config_file(instance.env['sc']) self.assertTrue(conf._use_sections) self.assertEqual(conf['java':'java-bin'], 'isworking') instance = mc('one', **self.instance_arguments) self.assertTrue(conf._use_sections) self.assertEqual(instance.server_config['java':'java-bin'], 'isworking')
def test_sp_defaults(self): from conf_reader import config_file instance = mc('one', **self.instance_arguments) instance.create(sp={'server-ip':'127.0.0.1'}) conf = config_file(instance.env['sp']) self.assertFalse(conf._use_sections) self.assertEqual(conf['server-ip'],'127.0.0.1') instance = mc('one', **self.instance_arguments) self.assertFalse(conf._use_sections) self.assertEqual(instance.server_properties['server-ip'], '127.0.0.1')
def test_sp_defaults(self): from conf_reader import config_file instance = mc('one', **self.instance_arguments) instance.create(sp={'server-ip': '127.0.0.1'}) conf = config_file(instance.env['sp']) self.assertFalse(conf._use_sections) self.assertEqual(conf['server-ip'], '127.0.0.1') instance = mc('one', **self.instance_arguments) self.assertFalse(conf._use_sections) self.assertEqual(instance.server_properties['server-ip'], '127.0.0.1')
def test_sc_defaults(self): from conf_reader import config_file instance = mc('one', **self.instance_arguments) instance.create(sc={'java': {'java-bin': 'isworking'}}) conf = config_file(instance.env['sc']) self.assertTrue(conf._use_sections) self.assertEqual(conf['java':'java-bin'], 'isworking') instance = mc('one', **self.instance_arguments) self.assertTrue(conf._use_sections) self.assertEqual(instance.server_config['java':'java-bin'], 'isworking')
def test_profiles(self): global VANILLA_PROFILE mc._make_skeleton(self.instance_arguments['base_directory']) instance = mc('one', **self.instance_arguments) instance.create() self.assertIsNone(instance.profile) with self.assertRaises(KeyError): instance.profile = 'vanilla' instance.define_profile(VANILLA_PROFILE) instance.update_profile(VANILLA_PROFILE['name']) self.assertTrue(os.path.exists(os.path.join(instance.env['pwd'], VANILLA_PROFILE['name']))) self.assertFalse(os.path.isfile(os.path.join(instance.env['pwd'], VANILLA_PROFILE['save_as']))) self.assertTrue(os.path.isfile(os.path.join(instance.env['pwd'], VANILLA_PROFILE['name'], VANILLA_PROFILE['run_as']))) from copy import copy newprofile = copy(VANILLA_PROFILE) newprofile['run_as'] = 'minecraft_server.1.6.2.jar' instance.define_profile(newprofile) self.assertEqual(instance.profile_config['vanilla':'run_as'], 'minecraft_server.1.6.2.jar')
def change_pc_group(self, **raw_args): args = {k: str(v) for k, v in raw_args.iteritems()} group = args.pop('group') retval = None response = {'result': None, 'cmd': 'chgrp_pc', 'payload': None} try: if self.login == 'root': instance = mc('throwaway', None, self.base_directory) instance.chgrp_pc(group) else: raise OSError( 'Group assignment to %s failed. Only the superuser may make change groups.' % group) except (RuntimeError, KeyError, OSError) as ex: response['result'] = 'error' retval = ex.message except CalledProcessError as ex: response['result'] = 'error' retval = ex.output except RuntimeWarning as ex: response['result'] = 'warning' retval = ex.message else: response['result'] = 'success' retval = "profile.config group ownership granted to '%s'" % group response['payload'] = to_jsonable_type(retval) return response
def display_stats(server_name): print ''' <script type="text/javascript"> $('.rename').one("click", (function(event){ event.preventDefault(); $.post("cgi-bin/server.py", { command: "display", server: $(this).attr("id"), page: "rename" }, function(data){ $('#main').html(data); }); })); $('.update').one("click", (function(event){ event.preventDefault(); $.post("cgi-bin/server.py", { command: "display", server: $(this).attr("id"), page: $(this).html() }, function(data){ $('#main').html(data); }); })); </script>''' print '<h2>%s</h2>' % 'Server Status' instance = mineos.mc(server_name) if instance.status() in ['down', 'foreign', 'unclean']: print "<h3>%s %s</h3>" % (server_name, '<a href="#" class="rename" id="%s">(rename)</a><br>' % server_name) else: print "<h3>%s</h3>" % server_name print "<h4>server is currently: %s</h4>" % instance.status() print '<ul>' print '<li><a href="#" class="update" id="%s">%s</a></li>' % (server_name, 'server.properties') print '<li><a href="#" class="update" id="%s">%s</a></li>' % (server_name, 'server.config') print '</ul>'
def change_group(self, **raw_args): args = {k: str(v) for k, v in raw_args.iteritems()} server_name = args.pop('server_name') group = args.pop('group') retval = None response = {'result': None, 'cmd': 'chgrp', 'payload': None} try: if self.login == mc.has_server_rights(self.login, server_name, self.base_directory) or \ self.login == 'root': instance = mc(server_name, None, self.base_directory) instance.chgrp(group) else: raise OSError( 'Group assignment to %s failed. Only the owner make change groups.' % group) except (RuntimeError, KeyError, OSError) as ex: response['result'] = 'error' retval = ex.message except CalledProcessError as ex: response['result'] = 'error' retval = ex.output except RuntimeWarning as ex: response['result'] = 'warning' retval = ex.message else: response['result'] = 'success' retval = "Server '%s' group ownership granted to '%s'" % ( server_name, group) response['payload'] = to_jsonable_type(retval) return response
def test_prune(self): instance = mc('one', **self.instance_arguments) instance.create() for d in ('cwd','bwd','awd'): self.assertTrue(os.path.exists(instance.env[d])) instance.backup() #0 incr self.assertEqual(len(instance.list_increments().increments), 0) instance._command_direct('touch me', instance.env['cwd']) self.assertTrue(os.path.isfile(os.path.join(instance.env['cwd'], 'me'))) time.sleep(1.1) instance.backup() #1 incr self.assertEqual(len(instance.list_increments().increments), 1) instance._command_direct('touch you', instance.env['cwd']) self.assertTrue(os.path.isfile(os.path.join(instance.env['cwd'], 'you'))) time.sleep(1.2) instance.backup() #2 incr self.assertEqual(len(instance.list_increments().increments), 2) instance.prune(1) self.assertEqual(len(instance.list_increments().increments), 1) instance.prune('now') self.assertEqual(len(instance.list_increments().increments), 0)
def change_group(self, **raw_args): args = {k:str(v) for k,v in raw_args.iteritems()} server_name = args.pop('server_name') group = args.pop('group') retval = None response = { 'result': None, 'cmd': 'chgrp', 'payload': None } try: if self.login == mc.has_server_rights(self.login, server_name, self.base_directory) or \ self.login == 'root': instance = mc(server_name, None, self.base_directory) instance.chgrp(group) else: raise OSError('Group assignment to %s failed. Only the owner make change groups.' % group) except (RuntimeError, KeyError, OSError) as ex: response['result'] = 'error' retval = ex.message except CalledProcessError as ex: response['result'] = 'error' retval = ex.output except RuntimeWarning as ex: response['result'] = 'warning' retval = ex.message else: response['result'] = 'success' retval = "Server '%s' group ownership granted to '%s'" % (server_name, group) response['payload'] = to_jsonable_type(retval) return response
def change_pc_group(self, **raw_args): args = {k:str(v) for k,v in raw_args.iteritems()} group = args.pop('group') retval = None response = { 'result': None, 'cmd': 'chgrp_pc', 'payload': None } try: if self.login == 'root': instance = mc('throwaway', None, self.base_directory) instance.chgrp_pc(group) else: raise OSError('Group assignment to %s failed. Only the superuser may make change groups.' % group) except (RuntimeError, KeyError, OSError) as ex: response['result'] = 'error' retval = ex.message except CalledProcessError as ex: response['result'] = 'error' retval = ex.output except RuntimeWarning as ex: response['result'] = 'warning' retval = ex.message else: response['result'] = 'success' retval = "profile.config group ownership granted to '%s'" % group response['payload'] = to_jsonable_type(retval) return response
def delete_server(self, **raw_args): args = {k:str(v) for k,v in raw_args.iteritems()} server_name = args.pop('server_name') retval = None response = { 'result': None, 'cmd': 'delete_server', 'payload': None } try: if mc.has_server_rights(self.login, server_name, self.base_directory): instance = mc(server_name, None, self.base_directory) instance.delete_server() else: raise OSError('Server deletion failed. Only the server owner or root may delete servers.') except (RuntimeError, KeyError, OSError) as ex: response['result'] = 'error' retval = ex.message except CalledProcessError as ex: response['result'] = 'error' retval = ex.output except RuntimeWarning as ex: response['result'] = 'warning' retval = ex.message else: response['result'] = 'success' retval = "Server '%s' deleted" % server_name response['payload'] = to_jsonable_type(retval) return response
def delete_server(self, **raw_args): args = {k: str(v) for k, v in raw_args.iteritems()} server_name = args.pop('server_name') retval = None response = {'result': None, 'cmd': 'delete_server', 'payload': None} try: if mc.has_server_rights(self.login, server_name, self.base_directory): instance = mc(server_name, None, self.base_directory) instance.delete_server() else: raise OSError( 'Server deletion failed. Only the server owner or root may delete servers.' ) except (RuntimeError, KeyError, OSError) as ex: response['result'] = 'error' retval = ex.message except CalledProcessError as ex: response['result'] = 'error' retval = ex.output except RuntimeWarning as ex: response['result'] = 'warning' retval = ex.message else: response['result'] = 'success' retval = "Server '%s' deleted" % server_name response['payload'] = to_jsonable_type(retval) return response
def test_valid_server_name(self): bad_names = ['this!', 'another,server', '"hello"', '.minecraft', 'top^sirloin', 'me@you', 'server-with-hyphens','`', '\t', 'minecraft 1.6', ''] ok_names = ['server', 'pvp', '21324', 'server_one', 'minecraft1.6', '_a_server'] for server_name in bad_names: with self.assertRaises(ValueError): instance = mc(server_name, **self.instance_arguments) for server_name in ok_names: instance = mc(server_name, **self.instance_arguments) self.assertIsNotNone(instance.server_name)
def act_update_sp(form): sp = os.path.join(mineos.mc().mineos_config['paths']['world_path'], form['server'], 'server.properties') sc = os.path.join(mineos.mc().mineos_config['paths']['world_path'], form['server'], 'server.config') for key in form.keys(): mineos.mc.attribute_change(sp, key.replace('_', '-'), form[key], form['server']) if key == 'server_port': mineos.mc.config_alter(sc, 'minecraft', 'port', form[key], form['server']) elif key == 'max_players': mineos.mc.config_alter(sc, 'minecraft', key, form[key], form['server']) print '<pre>' for key, value in mineos.mc.attribute_list(sp): print '{:<15}'.format(key), '{:<15}'.format(value) print '</pre>'
def display_server_properties(server_name): print ''' <script type="text/javascript"> $('.updatesp').one("click", (function(event){ event.preventDefault(); $.post("cgi-bin/server.py", $('#changevalues').serialize(), function(data){ $('#main').html(data); }); })); </script>''' print '<h2>server.properties for %s</h2>' % server_name instance = mineos.mc(server_name) filename = os.path.join(instance.mineos_config['paths']['world_path'], server_name, 'server.properties') status = instance.status() if status in ['up', 'down', 'foreign', 'unclean']: print '''<form name="changevalues" id="changevalues"> <input name="command" type="hidden" value="act"> <input name="action" type="hidden" value="update_sp"> <input name="server" type="hidden" value="%s"> <table>''' % server_name for key, value in mineos.mc.attribute_list(filename): print ''' <tr> <td colspan="2"><label for="%s">%s</label></td> <td colspan="2"><input type="text" name="%s" id="%s" value="%s" /></td> </tr>''' % (key.replace('-', '_'), key, key.replace('-', '_'), key.replace('-', '_'), value) print ''' <tr>
def test_profiles(self): global VANILLA_PROFILE mc._make_skeleton(self.instance_arguments['base_directory']) instance = mc('one', **self.instance_arguments) instance.create() self.assertIsNone(instance.profile) with self.assertRaises(KeyError): instance.profile = 'vanilla' instance.define_profile(VANILLA_PROFILE) instance.update_profile(VANILLA_PROFILE['name']) self.assertTrue( os.path.exists( os.path.join(instance.env['pwd'], VANILLA_PROFILE['name']))) self.assertFalse( os.path.isfile( os.path.join(instance.env['pwd'], VANILLA_PROFILE['save_as']))) self.assertTrue( os.path.isfile( os.path.join(instance.env['pwd'], VANILLA_PROFILE['name'], VANILLA_PROFILE['run_as']))) from copy import copy newprofile = copy(VANILLA_PROFILE) newprofile['run_as'] = 'minecraft_server.1.6.2.jar' instance.define_profile(newprofile) self.assertEqual(instance.profile_config['vanilla':'run_as'], 'minecraft_server.1.6.2.jar')
def check_interval(self): from procfs_reader import path_owner for action in ('backup','archive'): for i in mc.list_servers_to_act(action, self.base_directory): path_ = os.path.join(self.base_directory, mc.DEFAULT_PATHS['servers'], i) getattr(mc(i, path_owner(path_), self.base_directory), action)()
def test_prune(self): instance = mc('one', **self.instance_arguments) instance.create() for d in ('cwd', 'bwd', 'awd'): self.assertTrue(os.path.exists(instance.env[d])) instance.backup() #0 incr self.assertEqual(len(instance.list_increments().increments), 0) instance._command_direct('touch me', instance.env['cwd']) self.assertTrue(os.path.isfile(os.path.join(instance.env['cwd'], 'me'))) time.sleep(1.1) instance.backup() #1 incr self.assertEqual(len(instance.list_increments().increments), 1) instance._command_direct('touch you', instance.env['cwd']) self.assertTrue( os.path.isfile(os.path.join(instance.env['cwd'], 'you'))) time.sleep(1.2) instance.backup() #2 incr self.assertEqual(len(instance.list_increments().increments), 2) instance.prune(1) self.assertEqual(len(instance.list_increments().increments), 1) instance.prune('now') self.assertEqual(len(instance.list_increments().increments), 0)
def logs(self, **raw_args): args = {k: str(v) for k, v in raw_args.iteritems()} server_name = args.pop('server_name') retval = None response = {'result': None, 'cmd': 'logs', 'payload': None} try: instance = mc(server_name, self.login, self.base_directory) if 'log_offset' not in cherrypy.session or 'reset' in args: cherrypy.session['log_offset'] = os.stat( instance.env['log']).st_size retval = instance.list_last_loglines(100) elif not cherrypy.session['log_offset']: cherrypy.session['log_offset'] = os.stat( instance.env['log']).st_size retval = instance.list_last_loglines(100) elif cherrypy.session['log_offset']: with open(instance.env['log'], 'rb') as log: log.seek(cherrypy.session['log_offset'], 0) retval = log.readlines() cherrypy.session['log_offset'] = os.stat( instance.env['log']).st_size except (RuntimeError, KeyError, CalledProcessError) as ex: response['result'] = 'error' retval = ex.message except (RuntimeWarning, OSError) as ex: response['result'] = 'warning' retval = ex.message else: response['result'] = 'success' response['payload'] = to_jsonable_type(retval) return dumps(response)
def test_backup(self): instance = mc('one', **self.instance_arguments) instance.create() instance.backup() self.assertTrue( os.path.exists( os.path.join(instance.env['bwd'], 'rdiff-backup-data')))
def import_server(self, **raw_args): args = {k: str(v) for k, v in raw_args.iteritems()} server_name = args.pop('server_name') retval = None response = {'result': None, 'cmd': 'import_server', 'payload': None} from json import loads from collections import defaultdict try: instance = mc(server_name, self.login, self.base_directory) instance.import_server(**args) except (RuntimeError, KeyError, OSError) as ex: response['result'] = 'error' retval = ex.message except CalledProcessError as ex: response['result'] = 'error' retval = ex.message except RuntimeWarning as ex: response['result'] = 'warning' retval = ex.message else: response['result'] = 'success' retval = "Server '%s' successfully imported" % server_name response['payload'] = to_jsonable_type(retval) return dumps(response)
def act_update_jars(form): configfile = os.path.join(mineos.mc().mc_path, 'mineos.config') for key in form.keys(): if key not in ['server', 'command', 'action']: mineos.mc.config_alter(configfile, 'update', key, form[key], 'None') for key in form.keys(): print "%s = %s<br>" % (key, form[key])
def test_valid_server_name(self): bad_names = [ 'this!', 'another,server', '"hello"', '.minecraft', 'top^sirloin', 'me@you', 'server-with-hyphens', '`', '\t', 'minecraft 1.6', '' ] ok_names = [ 'server', 'pvp', '21324', 'server_one', 'minecraft1.6', '_a_server' ] for server_name in bad_names: with self.assertRaises(ValueError): instance = mc(server_name, **self.instance_arguments) for server_name in ok_names: instance = mc(server_name, **self.instance_arguments) self.assertIsNotNone(instance.server_name)
def create(self, **raw_args): args = {k:str(v) for k,v in raw_args.iteritems()} server_name = args.pop('server_name') group = args.pop('group', None) retval = None response = { 'result': None, 'cmd': 'create', 'payload': None } from json import loads from collections import defaultdict from grp import getgrnam from stat import S_IWGRP try: group_info = None if group: try: group_info = getgrnam(group) except KeyError: raise KeyError("There is no group '%s'" % group) else: if self.login not in group_info.gr_mem and self.login != group_info.gr_name: raise OSError("user '%s' is not part of group '%s'" % (self.login, group)) instance = mc(server_name, self.login, self.base_directory) sp_unicode = loads(args['sp']) sc_unicode = loads(args['sc']) sp = {str(k):str(v) for k,v in sp_unicode.iteritems()} sc = defaultdict(dict) for section in sc_unicode.keys(): for key in sc_unicode[section].keys(): sc[str(section)][str(key)] = str(sc_unicode[section][key]) instance.create(dict(sc),sp) if group: for d in ('servers', 'backup', 'archive'): path_ = os.path.join(self.base_directory, mc.DEFAULT_PATHS[d], server_name) os.lchown(path_, -1, group_info.gr_gid) except (RuntimeError, KeyError, OSError, ValueError) as ex: response['result'] = 'error' retval = ex.message except CalledProcessError as ex: response['result'] = 'error' retval = ex.output except RuntimeWarning as ex: response['result'] = 'warning' retval = ex.message else: response['result'] = 'success' response['payload'] = to_jsonable_type(retval) return response
def check_interval(self): from procfs_reader import path_owner for action in ('backup', 'archive'): for i in mc.list_servers_to_act(action, self.base_directory): path_ = os.path.join(self.base_directory, mc.DEFAULT_PATHS['servers'], i) getattr(mc(i, path_owner(path_), self.base_directory), action)()
def selects_mod(): selects = [] for mods in mineos.mc.list_server_jars(): if mods == mineos.mc().mineos_config['downloads']['mc_jar']: selects.append('<option value="%s" SELECTED>%s</option>' % (mods, mods)) else: selects.append('<option value="%s">%s</option>' % (mods, mods)) return ' '.join(selects)
def selects_mod(): selects = [] for mods in mineos.mc.list_server_jars(): if mods == mineos.mc(server_name).server_config['java']['server_jar']: selects.append('<option value="%s" SELECTED>%s</option>' % (mods, mods)) else: selects.append('<option value="%s">%s</option>' % (mods, mods)) return ' '.join(selects)
def selects_mod(mod): selects = [] if mineos.mc().mineos_config['update'][mod] == 'true': selects.append('<option value="true" SELECTED>true</option>') selects.append('<option value="false">false</option>') else: selects.append('<option value="true">true</option>') selects.append('<option value="false" SELECTED>false</option>') return ' '.join(selects)
def display_bam(page): print ''' <script type="text/javascript"> $('.%s').one("click", (function(event){ event.preventDefault(); $(this).addClass("plaintext"); $.post("cgi-bin/server.py", { command: "act", server: $(this).attr("id"), action: $(this).html() }, function(data){ $('#main').html(data); }); $(this).html("Executing command..."); })); $('.archive_logs').one("click", (function(event){ event.preventDefault(); $(this).addClass("plaintext"); $.post("cgi-bin/server.py", { command: "act", server: $(this).attr("id"), action: 'log_archive' }, function(data){ $('#main').html(data); }); $(this).html("Executing command..."); })); </script>''' % page print '<h2>%s</h2>' % page.title() print '<p><span class="green">%s</span> servers were located in <span class="green">%s</a>:</p>' % (len(mineos.mc.ports_reserved()), mineos.mc().mineos_config['paths']['world_path']) print '<pre><b>%s%s%s</b><br>' % ('{:<20}'.format('server'), '{:<12}'.format('freq'), '{:<12}'.format('status')) colors = { 'template': '<span class="black">%s</span>' % '{:<12}'.format('template'), 'down': '<span class="red">%s</span>' % '{:<12}'.format('down'), 'up': '<span class="green">%s</span>' % '{:<12}'.format('up'), 'unclean': '<span class="red">%s</span>' % '{:<12}'.format('unclean'), 'foreign': '<span class="purple">%s</span>' % '{:<12}'.format('foreign'), } for server, port, status in mineos.mc.ports_reserved(): print '%s%s%s' % ('{:<20}'.format(server), '{:<12}'.format(mineos.mc(server).server_config['crontabs']['freq_%s' % page]), colors.get(status)), if status in ['up', 'down', 'unclean']: print '<a href="#" class="%s" id="%s">%s</a>' % (page, server, page), else: print '%s'% page, if status == 'down' and page == 'archive': print '<a href="#" class="%s" id="%s">%s</a>' % ('archive_logs', server, 'gzip server.log'), print print '</pre>'
def act_update_sc(form): sp = os.path.join(mineos.mc().mineos_config['paths']['world_path'], form['server'], 'server.properties') sc = os.path.join(mineos.mc().mineos_config['paths']['world_path'], form['server'], 'server.config') for key in form.keys(): if key in ['port', 'max_players', 'mem']: mineos.mc.config_alter(sc, 'minecraft', key, form[key], form['server']) elif key in ['freq_archive', 'freq_backup', 'freq_map']: mineos.mc.config_alter(sc, 'crontabs', key, form[key], form['server']) elif key in ['server_jar', 'server_jar_args', 'java_tweaks']: mineos.mc.config_alter(sc, 'java', key, form[key], form['server']) elif key in ['restore', 'start']: mineos.mc.config_alter(sc, 'onreboot', key, form[key], form['server']) if key == 'port': mineos.mc.attribute_change(sp, 'server-port', form[key], form['server']) elif key == 'max_players': mineos.mc.attribute_change(sp, 'max-players', form[key], form['server']) for key in form.keys(): print "%s = %s<br>" % (key, form[key])
def display_restore(): print ''' <script type="text/javascript"> $('.restore').one("click", (function(event){ event.preventDefault(); $.post("cgi-bin/server.py", { command: "act", action: "restore", server: $(this).attr("id"), steps: $(this).html() }, function(data){ $('#main').html(data); }); })); </script>''' print '<h2>%s</h2>' % 'Incremental Backups' print '<p>The following backup states were found in <span class="green">%s</a>:</p>' % mineos.mc().mineos_config['paths']['backup_path'] print '<p><i>Click an increment to restore a server to a previous state.</i><br>Servers currently running cannot be restored until stopped.</p>' for server, port, status in mineos.mc.ports_reserved_backup(): print '<h4>%s</h4>' % server try: output = mineos.mc(server).list_backups() print '<ol class="backupli">' for index, item in enumerate(output): count = len(output) - index - 2 if not index: print '<li>%s</li>' % item, elif count < 0: pass else: if mineos.mc(server).status() != 'up': print '<li><a href="#" class="restore" id="%s">%s</a> %s</li>' % (server, str(count) + 'B', item) else: print '<li>%s %s</li>' % (str(count) + 'B', item) except: print '<li>None</li>' print '</ol>'
def test_start(self): instance = mc('one', **self.instance_arguments) instance.create() self.assertIsNone(instance.java_pid) self.assertIsNone(instance.screen_pid) self.assertEqual(instance.memory, '0') with self.assertRaises(RuntimeError): instance.start() self.assertIsNone(instance.java_pid) self.assertIsNone(instance.screen_pid)
def test_start_home_server_x2(self): global VANILLA_PROFILE ta = mc('throwaway', **self.instance_arguments) ta.define_profile(VANILLA_PROFILE) ta.update_profile(VANILLA_PROFILE['name']) srv_a = mc('one', **self.instance_arguments) srv_a.create(sp={'server-port':25566}) srv_a.profile = VANILLA_PROFILE['name'] srv_b = mc('two', **self.instance_arguments) srv_b.create(sp={'server-port':25567}) srv_b.profile = VANILLA_PROFILE['name'] srv_a.start() time.sleep(20) self.assertTrue(srv_a.up) srv_b.start() time.sleep(20) self.assertTrue(srv_b.up) srv_a._command_stuff('stop') srv_b._command_stuff('stop') time.sleep(5) try: srv_a.kill() except RuntimeError: pass #just want to suppress, not anticipate try: srv_b.kill() except RuntimeError: pass #just want to suppress, not anticipate time.sleep(1.5)
def test_create(self): instance = mc('one', **self.instance_arguments) instance.create() for d in ('cwd', 'bwd', 'awd'): self.assertTrue(os.path.exists(instance.env[d])) for f in ('sp', 'sc'): self.assertTrue(os.path.isfile(instance.env[f])) self.assertTrue(instance.server_properties[:]) self.assertTrue(instance.server_config[:]) with self.assertRaises(RuntimeError): self.assertTrue(instance.command_start) with self.assertRaises(RuntimeError): self.assertIsNone(instance.command_kill) self.assertTrue(instance.command_backup) self.assertTrue(instance.command_archive) self.assertTrue(instance.command_restore) ''' FIXME: how should prune/apply_profile/wget_profile respond? ''' instance = mc('two', **self.instance_arguments) instance.create({'java': {'java_xmx': 2048}}, {'server-port': '27000'}) self.assertEqual(instance.server_properties['server-port'], '27000') self.assertEqual(instance.server_config['java':'java_xmx'], '2048') instance = mc('three', **self.instance_arguments) instance.create(sc={'java': { 'java_bogus': 'wow!' }}, sp={'bogus-value': 'abcd'}) self.assertEqual(instance.server_properties['bogus-value'], 'abcd') self.assertEqual(instance.server_config['java':'java_bogus'], 'wow!')
def test_start_home_server_x2(self): global VANILLA_PROFILE ta = mc('throwaway', **self.instance_arguments) ta.define_profile(VANILLA_PROFILE) ta.update_profile(VANILLA_PROFILE['name']) srv_a = mc('one', **self.instance_arguments) srv_a.create(sp={'server-port': 25566}) srv_a.profile = VANILLA_PROFILE['name'] srv_b = mc('two', **self.instance_arguments) srv_b.create(sp={'server-port': 25567}) srv_b.profile = VANILLA_PROFILE['name'] srv_a.start() time.sleep(20) self.assertTrue(srv_a.up) srv_b.start() time.sleep(20) self.assertTrue(srv_b.up) srv_a._command_stuff('stop') srv_b._command_stuff('stop') time.sleep(5) try: srv_a.kill() except RuntimeError: pass #just want to suppress, not anticipate try: srv_b.kill() except RuntimeError: pass #just want to suppress, not anticipate time.sleep(1.5)
def test_profile_jar_match_md5(self): global VANILLA_PROFILE mc._make_skeleton(self.instance_arguments['base_directory']) instance = mc('one', **self.instance_arguments) instance.create() instance.define_profile(VANILLA_PROFILE) instance.update_profile(VANILLA_PROFILE['name']) instance.profile = VANILLA_PROFILE['name'] with instance.profile_config as pc: pc[VANILLA_PROFILE['name']:'run_as_md5'] = 'abcd' self.assertEqual(instance.profile_config[VANILLA_PROFILE['name']:'run_as_md5'], 'abcd')
def test_load_config(self): from conf_reader import config_file instance = mc('one', **self.instance_arguments) self.assertIsInstance(instance.server_properties, config_file) self.assertIsInstance(instance.server_properties[:], dict) self.assertIsInstance(instance.server_config, config_file) self.assertIsInstance(instance.server_config[:], dict) self.assertIsInstance(instance.profile_config, config_file) self.assertIsInstance(instance.profile_config[:], dict) self.assertFalse(os.path.isfile(instance.env['sp'])) self.assertFalse(os.path.isfile(instance.env['sc'])) self.assertFalse(os.path.isfile(instance.env['pc']))
def test_restore(self): instance = mc('one', **self.instance_arguments) instance.create() with self.assertRaises(RuntimeError): instance.restore() instance.backup() rmtree(instance.env['cwd']) self.assertFalse(os.path.exists(instance.env['cwd'])) instance.restore() self.assertTrue(os.path.exists(instance.env['cwd'])) time.sleep(1) instance.restore(force=True)
def server(self, **raw_args): args = {k:str(v) for k,v in raw_args.iteritems()} command = args.pop('cmd') server_name = args.pop('server_name') retval = None response = { 'result': None, 'cmd': command, 'payload': None } owner = mc.has_server_rights(self.login, server_name, self.base_directory) try: if server_name is None: raise KeyError('Required value missing: server_name') elif not owner: raise OSError('User %s does not have permissions on %s' % (self.login, server_name)) instance = mc(server_name, owner, self.base_directory) if command in self.METHODS: retval = getattr(instance, command)(**args) elif command in self.PROPERTIES: if args: setattr(instance, command, args.values()[0]) retval = args.values()[0] else: retval = getattr(instance, command) else: instance._command_stuff(command) retval = '"%s" successfully sent to server.' % command except (RuntimeError, KeyError, NotImplementedError) as ex: response['result'] = 'error' retval = ex.message except CalledProcessError as ex: response['result'] = 'error' retval = ex.output except RuntimeWarning as ex: response['result'] = 'warning' retval = ex.message else: response['result'] = 'success' response['payload'] = to_jsonable_type(retval) return response
def status(self): servers = [] for i in self.server_list(): try: instance = mc(i, self.login, self.base_directory) except ValueError: continue # fails valid_server_name try: java_xmx = int(instance.server_config['java':'java_xmx']) except (KeyError, ValueError): java_xmx = 0 srv = { 'server_name': i, 'jarfile': instance.jarfile, 'up': instance.up, 'ip_address': instance.ip_address, 'port': instance.port, 'memory': instance.memory, 'java_xmx': java_xmx, 'eula': instance.eula } try: ping = instance.ping except KeyError: continue except IndexError: srv.update({ 'protocol_version': '', 'server_version': '', 'motd': '', 'players_online': -1, 'max_players': instance.server_properties['max-players'::0] }) else: srv.update(dict(instance.ping._asdict())) servers.append(srv) return servers
def test_profile_jar_match_md5(self): global VANILLA_PROFILE mc._make_skeleton(self.instance_arguments['base_directory']) instance = mc('one', **self.instance_arguments) instance.create() instance.define_profile(VANILLA_PROFILE) instance.update_profile(VANILLA_PROFILE['name']) instance.profile = VANILLA_PROFILE['name'] with instance.profile_config as pc: pc[VANILLA_PROFILE['name']:'run_as_md5'] = 'abcd' self.assertEqual( instance.profile_config[VANILLA_PROFILE['name']:'run_as_md5'], 'abcd')
def test_change_config(self): instance = mc('one', **self.instance_arguments) instance.create() with instance.server_properties as sp: sp['server-ip'] = '127.0.0.1' self.assertEqual(instance.server_properties['server-ip'], '127.0.0.1') instance._load_config() self.assertEqual(instance.server_properties['server-ip'], '127.0.0.1') with instance.server_config as sc: sc['java':'java_xmx'] = '1024' self.assertEqual(instance.server_config['java':'java_xmx'], '1024') instance._load_config() self.assertEqual(instance.server_config['java':'java_xmx'], '1024')
def test_update_profile(self): global VANILLA_PROFILE mc._make_skeleton(self.instance_arguments['base_directory']) instance = mc('one', **self.instance_arguments) instance.define_profile(VANILLA_PROFILE) with self.assertRaises(RuntimeError): instance.update_profile(VANILLA_PROFILE['name'], 'asdfasdf') instance.update_profile(VANILLA_PROFILE['name']) with self.assertRaises(RuntimeWarning): instance.update_profile(VANILLA_PROFILE['name'], '39df9f29e6904ea7b351ffb4fe949881') with self.assertRaises(RuntimeWarning): instance.update_profile(VANILLA_PROFILE['name'])
def test_start_home_server(self): global VANILLA_PROFILE mc._make_skeleton(self.instance_arguments['base_directory']) instance = mc('one', **self.instance_arguments) instance.create() instance.define_profile(VANILLA_PROFILE) instance.update_profile(VANILLA_PROFILE['name']) instance.profile = VANILLA_PROFILE['name'] instance.start() time.sleep(20) self.assertTrue(instance.up) instance._command_stuff('stop') time.sleep(5) try: instance.kill() except RuntimeError: pass #just want to suppress, not anticipate else: time.sleep(1.5)
def status(self): servers = [] for i in self.server_list(): instance = mc(i, self.login, self.base_directory) try: ping = instance.ping except KeyError: continue srv = { 'server_name': i, 'profile': instance.profile, 'up': instance.up, 'ip_address': instance.ip_address, 'port': instance.port, 'memory': instance.memory, 'java_xmx': instance.server_config['java':'java_xmx'] } srv.update(dict(instance.ping._asdict())) servers.append(srv) return dumps(servers)
def increments(self, server_name): instance = mc(server_name, self.login, self.base_directory) return [dict(d._asdict()) for d in instance.list_increment_sizes()]
def host(self, **raw_args): args = {k: str(v) for k, v in raw_args.iteritems()} command = args.pop('cmd') retval = None response = {'result': None, 'cmd': command, 'payload': None} try: if command == 'define_profile': mc.has_ownership( self.login, os.path.join(self.base_directory, mc.DEFAULT_PATHS['profiles'], 'profile.config')) from json import loads from urllib import unquote definition_unicode = loads(args['profile_dict']) definition = { str(k): str(v) for k, v in definition_unicode.iteritems() } try: definition['url'] = unquote(definition['url']) except KeyError: pass if definition['name'] in mc.list_profiles( self.base_directory).keys(): raise KeyError('Profiles may not be modified once created') instance = mc('throwaway', None, self.base_directory) retval = instance.define_profile(definition) elif command == 'update_profile': mc.has_ownership( self.login, os.path.join(self.base_directory, mc.DEFAULT_PATHS['profiles'], 'profile.config')) instance = mc('throwaway', None, self.base_directory) retval = instance.update_profile(**args) elif command == 'remove_profile': for i in mc.list_servers(self.base_directory): if mc(i, None, self.base_directory).profile == args['profile']: raise KeyError( 'May not remove profiles in use by 1 or more servers' ) instance = mc('throwaway', None, self.base_directory) retval = instance.remove_profile(**args) elif command == 'stock_profile': from stock_profiles import STOCK_PROFILES profile = iter([ i for i in STOCK_PROFILES if i['name'] == args['profile'] ]).next() mc('throwaway', None, self.base_directory).define_profile(profile) retval = '%s profile created' % profile['name'] elif command == 'modify_profile': mc('throwaway', None, self.base_directory).modify_profile(args['option'], args['value'], args['section']) retval = '%s profile updated' % args['section'] elif command in self.METHODS: import inspect try: if 'base_directory' in inspect.getargspec( getattr(mc, command)).args: retval = getattr(mc, command)( base_directory=init_args['base_directory'], **args) else: retval = getattr(mc, command)(**args) except TypeError as ex: raise RuntimeError(ex.message) else: raise RuntimeWarning( 'Command not found: should this be to a server?') except (RuntimeError, KeyError, OSError, NotImplementedError) as ex: response['result'] = 'error' retval = ex.message except CalledProcessError as ex: response['result'] = 'error' retval = ex.output except RuntimeWarning as ex: response['result'] = 'warning' retval = ex.message else: response['result'] = 'success' response['payload'] = to_jsonable_type(retval) return response
def archives(self, server_name): instance = mc(server_name, self.login, self.base_directory) return [dict(d._asdict()) for d in instance.list_archives()]