示例#1
0
    def testAddInstance(self):
        LoadInfo.InitializeTable()
        LoadInfo.AddInstance('test-instance')

        self.assertEqual(['test-instance'],
                         memcache.get(LoadInfo.ALL_INSTANCES))
        self.assertEqual({}, LoadInfo.GetAll())
        self.assertIsNone(memcache.get('test-instance'))
        self.assertIsNotNone(SingleInstance.GetByName('test-instance'))
        self.assertRaises(ValueError,
                          SingleInstance.GetByName('test-instance').ip_address)
示例#2
0
 def testRegisterInstance(self):
     LoadInfo.InitializeTable()
     LoadInfo.AddInstance('test-instance')
     LoadInfo.RegisterInstanceIpAddress('test-instance', '1.2.3.4')
     self.assertEqual(['test-instance'],
                      memcache.get(LoadInfo.ALL_INSTANCES))
     self.assertEqual({'test-instance': {
         'ip_address': '1.2.3.4'
     }}, LoadInfo.GetAll())
     self.assertEqual({'ip_address': '1.2.3.4'},
                      memcache.get('test-instance'))
     self.assertEqual('1.2.3.4',
                      SingleInstance.GetByName('test-instance').ip_address)
示例#3
0
    def get(self):
        """Starts up initial Compute Engine cluster."""
        instances = LoadInfo.GetAllInstances()
        if instances:
            raise SystemError("Instances already loaded, teardown first.")

        ComputeEngineController(decorator.credentials).StartUpCluster()
 def get(self):
     """Returns an available server's IP address in JSON format."""
     ip = LoadInfo.GetIdleInstanceIpAddress()
     if not ip:
         ip = ''
     self.response.out.write(json.dumps({'ipaddress': ip}))
     IpAddressRequestLog(client_ip=self.request.remote_addr,
                         server_ip=ip).put()
示例#5
0
 def _DeleteInstance(self, instance_name):
     """Stops and deletes the instance specified by the name."""
     logging.info('Deleting instance %s', instance_name)
     LoadInfo.RemoveInstance(instance_name)
     result = self.compute_api.instances().delete(
         project=self.PROJECT_ID,
         zone=self.DEFAULT_ZONE,
         instance=instance_name).execute()
     logging.info(str(result))
示例#6
0
    def StartUpCluster(self):
        """Initializes and start up Compute Engine cluster.

    Records user ID and use it later by Taskqueue, Cron job handlers
    and other handlers which is initiated by Compute Engine (therefore
    without log in), to retrieve credential from Datastore.  It means
    those tasks work under permission of the user who started the cluster.
    """
        LoadInfo.InitializeTable()
        self.IncreaseEngine(self.INITIAL_CLUSTER_SIZE)
示例#7
0
    def post(self):
        # TODO: Secure this URL by using Cloud Endpoints.
        grid = self.request.get('grid')
        num = int(self.request.get('numPlayers'))

        logging.info('Server update received: ' + str(grid) +
                     ' with numPlayers: ' + str(num))
        loadresp = LoadInfo.UpdateServerNumPlayers(grid, num)

        self.response.out.write(json.dumps({"loadresp": loadresp}))
 def post(self):
     """Adds the new instance to managed cluster by registering IP address."""
     # TODO(user): Secure this URL by using Cloud Endpoints.
     name = self.request.get('name')
     instance = ComputeEngineController().GetInstanceInfo(name)
     if not instance:
         return
     logging.info('Instance created: %s', str(instance))
     external_ip = instance['networkInterfaces'][0]['accessConfigs'][0][
         'natIP']
     LoadInfo.RegisterInstanceIpAddress(name, external_ip)
示例#9
0
    def post(self):
        # TODO(user): Secure this URL by using Cloud Endpoints.
        grid = self.request.get('grid')
        logging.info('Received server require for grid:' + grid)

        loadresp = LoadInfo.GetServerLoadInfo(grid)
        if not loadresp:
            logging.info('No server so starting server for grid:' + str(grid))
            ComputeEngineController().AddServer(grid)
            loadresp = {LoadInfo.STATUS: LoadInfo.STATUS_LOADING}
        self.response.out.write(json.dumps(loadresp))
示例#10
0
    def testAverageLoadExcludingImmatureInstance(self):
        LoadInfo.InitializeTable()
        LoadInfo.AddInstance('test-instance1')
        LoadInfo.RegisterInstanceIpAddress('test-instance1', '1.2.3.4')
        # test-instance1 hasn't yet reported load information.
        LoadInfo.AddInstance('test-instance2')
        LoadInfo.RegisterInstanceIpAddress('test-instance2', '5.6.7.8')
        LoadInfo.UpdateLoadInfo('test-instance2', 33)

        self.assertEqual((1, 33), LoadInfo.GetAverageLoad())
示例#11
0
    def testGetIdleInstanceExcludingImmatureInstance(self):
        LoadInfo.InitializeTable()
        LoadInfo.AddInstance('test-instance1')
        LoadInfo.RegisterInstanceIpAddress('test-instance1', '1.2.3.4')
        LoadInfo.UpdateLoadInfo('test-instance1', 55)
        LoadInfo.AddInstance('test-instance2')
        LoadInfo.RegisterInstanceIpAddress('test-instance2', '5.6.7.8')
        # test-instance2 hasn't yet reported load information.

        self.assertEqual('1.2.3.4', LoadInfo.GetIdleInstanceIpAddress())
示例#12
0
    def get(self):
        user = users.get_current_user()
        # TODO: Check to make sure game account is up to date/paid for/whatever.

        # Determine what server to transfer player to
        servertoload = ""
        q = Entity.all()
        q.filter("user_id =", user.user_id())
        q.filter("__type =", "Player")
        userplayers = []
        for userplayer in q.run(limit=5):
            userplayers.append(userplayer)
        if len(userplayers) > 1:
            logging.error("UserID has more than one player")
            return
        elif len(userplayers) == 0:
            logging.info("No current players, attaching to root")
            servertoload = "0,0"
        else:
            servertoload = userplayers[0].gridkey

        logging.info("Loading server " + servertoload + " for " +
                     user.nickname())

        info = LoadInfo.GetServerLoadInfo(servertoload)
        if info:
            if info[LoadInfo.STATUS] == LoadInfo.STATUS_UP:
                ip = info[LoadInfo.IP_ADDRESS]
                port = info[LoadInfo.PORT]

                # Generate login token
                token_key = uuid.uuid4().hex
                expiration_time = datetime.datetime.now() + datetime.timedelta(
                    seconds=20)
                LoginToken(key_name=token_key,
                           expiration=expiration_time,
                           user_id=user.user_id()).put()

                # Send IP and token info
                self.response.out.write(
                    json.dumps({
                        'status': 'up',
                        'ipaddress': ip,
                        'port': port,
                        'token': token_key
                    }))
                IpAddressRequestLog(client_ip=self.request.remote_addr,
                                    server_ip=ip).put()
            else:
                self.response.out.write(json.dumps({'status': 'loading'}))
        else:
            ComputeEngineController().AddServer(servertoload)
            self.response.out.write(json.dumps({'status': 'loading'}))
    def get(self):
        """Returns stats of game instances for non logged-in users."""
        load_entries = []
        all_load_info = LoadInfo.GetAll()

        for name, info in all_load_info.items():
            load_entries.append({
                'host': name,
                'ipaddress': info.get(LoadInfo.IP_ADDRESS, ''),
                'load': info.get(LoadInfo.LOAD, 0),
            })

        self.response.out.write(json.dumps(load_entries))
示例#14
0
    def IncreaseEngine(self, increase_count):
        """Starts specified number of Compute Engine instances.

    Args:
      increase_count: Number of instances to increase.
    """
        for _ in xrange(increase_count):
            instance_name = self.WORKER_NAME_PREFIX + str(uuid.uuid4())
            # Add instance name to load information before actually creating the
            # instance to avoid, to make sure the instance is managed
            # when it registers IP address.
            LoadInfo.AddInstance(instance_name)
            self._StartInstance(instance_name)
示例#15
0
    def AddServer(self, grid):
        # If current instance has open room, use it
        idle_instance = LoadInfo.GetIdleInstance()
        if not (idle_instance == None):
            ip_address = idle_instance[LoadInfo.IP_ADDRESS]

            # Send request to server manager to create new server
            h = httplib2.Http()
            data = {
                "grid": grid
            }
            resp, content = h.request(
                "http://" + ip_address + ":" + self.INSTANCE_MANAGER_PORT +
                "/" + self.INSTANCE_MANAGER_ADDSERVER, "POST", urlencode(data))

            # Track new server
            LoadInfo.AddServer(grid, resp)

            # Re-assess load
            self.assessLoad()
        else:  # Otherwise, start new instance
            logging.error(
                'Attempting to add server %s, but no idle instances!', grid)
示例#16
0
    def testRemoveInstanceFromTwo(self):
        LoadInfo.InitializeTable()
        LoadInfo.AddInstance('test-instance1')
        LoadInfo.RegisterInstanceIpAddress('test-instance1', '1.2.3.4')
        LoadInfo.UpdateLoadInfo('test-instance1', 55)
        LoadInfo.AddInstance('test-instance2')
        LoadInfo.RegisterInstanceIpAddress('test-instance2', '5.6.7.8')
        LoadInfo.UpdateLoadInfo('test-instance2', 22)
        LoadInfo.RemoveInstance('test-instance1')

        self.assertEqual(
            {
                'test-instance2': {
                    'ip_address': '5.6.7.8',
                    'load': 22,
                    'force': False
                }
            }, LoadInfo.GetAll())
        self.assertIsNone(memcache.get('test-instance1'))
        self.assertIsNone(SingleInstance.GetByName('test-instance1'))
示例#17
0
    def post(self):
        # TODO: Secure this URL by using Cloud Endpoints.
        name = self.request.get('name')

        # TODO: Figure out credentials issues with below, likely due to ComputeEngineController credentials expiring
        #instance = ComputeEngineController().GetInstanceInfo(name)
        #if not instance:
        #  return

        load = int(self.request.get('load'))
        logging.info('Instance update received: ' + str(name) +
                     ' with load: ' + str(load))
        loadresp = LoadInfo.UpdateInstanceLoadInfo(name, load)

        self.response.out.write(json.dumps({"loadresp": loadresp}))
示例#18
0
    def testRemoveInstanceFromOne(self):
        LoadInfo.InitializeTable()
        LoadInfo.AddInstance('test-instance')
        LoadInfo.RegisterInstanceIpAddress('test-instance', '1.2.3.4')
        LoadInfo.UpdateLoadInfo('test-instance', 55)
        LoadInfo.RemoveInstance('test-instance')

        self.assertEqual({}, LoadInfo.GetAll())
        self.assertEqual([], memcache.get(LoadInfo.ALL_INSTANCES))
        self.assertIsNone(memcache.get('test-instance'))
        self.assertIsNone(SingleInstance.GetByName('test-instance'))
 def post(self):
     """Receives request from instance and updates load information."""
     # TODO(user): Secure this URL by using Cloud Endpoints.
     name = self.request.get('name')
     load = self.request.get('load')
     if not load:
         load = 0
     force = self.request.get('force')
     force_set = None
     if force:
         if int(force):
             force_set = True
         else:
             force_set = False
     LoadInfo.UpdateLoadInfo(name, int(load), force_set)
     self.response.headers['Content-Type'] = 'text/plain'
     self.response.out.write('ok')
示例#20
0
    def post(self):
        """ Adds the new server to server list by registering IP/port """
        # TODO(user): Secure this URL by using Cloud Endpoints
        name = self.request.get('instancename')
        grid = self.request.get('grid')
        port = self.request.get('port')
        instance = ComputeEngineController().GetInstanceInfo(name)
        if not instance:
            logging.error("Instance name doesn't match existing instance: %s",
                          name)
            return
        logging.info('Instance created: %s', str(instance))
        external_ip = instance['networkInterfaces'][0]['accessConfigs'][0][
            'natIP']

        LoadInfo.RegisterServerAddress(grid, external_ip, port)
        resp = {'external_ip': external_ip, 'success': 1}
        self.response.out.write(json.dumps(resp))
    def get(self):
        """Checks average load level and adjusts cluster size if necessary.

    If average load level of instances is more than upper threshold, increase
    the number of instances by 20% of original size.  If average load level is
    less than lower threshold and the current cluster size is larger than
    minimum size, decrease the number of instances by 10%.  Since shortage
    of server is more harmful than excessive instances, we increase more
    rapidly than we decrease.

    However, shutting down the instance is more complicated than adding
    instances depending on game servers.  If client is not capable to auto-
    reconnect, the game server must be drained before shutting down the
    instance.  In this exsample, decrement of the instance is not implemented.
    """
        cluster_size, average_load = LoadInfo.GetAverageLoad()
        if cluster_size:
            if average_load > self.UPPER_THRESHOLD:
                ComputeEngineController().IncreaseEngine(cluster_size / 5 + 1)
            elif (average_load < self.LOWER_THRESHOLD
                  and cluster_size > self.MIN_CLUSTER_SIZE):
                ComputeEngineController().DecreaseEngine(cluster_size / 10 + 1)
示例#22
0
    def testMemcacheClear(self):
        LoadInfo.InitializeTable()
        LoadInfo.AddInstance('test-instance')
        LoadInfo.RegisterInstanceIpAddress('test-instance', '1.2.3.4')
        LoadInfo.UpdateLoadInfo('test-instance', 55)
        # Simulate loss of all data in Memcache.
        memcache.flush_all()
        LoadInfo.UpdateLoadInfo('test-instance', 38)

        self.assertEqual(
            {
                'test-instance': {
                    'ip_address': '1.2.3.4',
                    'load': 38,
                    'force': False
                }
            }, LoadInfo.GetAll())
示例#23
0
    def post(self):
        """Adds the new instance to managed cluster by registering IP address."""
        # TODO(user): Secure this URL by using Cloud Endpoints.
        name = self.request.get('name')
        instance = ComputeEngineController().GetInstanceInfo(name)
        if not instance:
            return
        logging.info('Instance created: %s', str(instance))
        external_ip = instance['networkInterfaces'][0]['accessConfigs'][0][
            'natIP']
        LoadInfo.RegisterInstanceIpAddress(name, external_ip)
        """Returns script to set up overarching server manager."""

        template = jinja_environment.get_template('setup-and-start-game.sh')
        self.response.out.write(
            template.render({
                'apphostname':
                app_identity.get_default_version_hostname(),
                'ip_address':
                self.request.remote_addr,
                'name':
                name
            }))
    def get(self):
        """Returns stats of managed Compute Engine instances for Admin UI."""
        load_entries = []
        instance_list = ComputeEngineController(
            decorator.credentials).ListInstances()
        all_load_info = LoadInfo.GetAll()

        # First, list managed instances whose Compute Engine status is found.
        for instance in instance_list:
            instance_name = instance['name']
            if instance_name in all_load_info:
                info = all_load_info[instance_name]
                load_entries.append({
                    'host':
                    instance_name,
                    'ipaddress':
                    info.get(LoadInfo.IP_ADDRESS, ''),
                    'status':
                    instance['status'],
                    'load':
                    info.get(LoadInfo.LOAD, 0),
                    'force_set':
                    info.get(LoadInfo.FORCE, False),
                })
                del all_load_info[instance_name]

        # Then, list managed instances without Compute Engine status.
        for name, info in all_load_info.items():
            load_entries.append({
                'host': name,
                'ipaddress': info.get(LoadInfo.IP_ADDRESS, ''),
                'status': 'NOT FOUND',
                'load': info.get(LoadInfo.LOAD, 0),
                'force_set': info.get(LoadInfo.FORCE, False),
            })

        self.response.out.write(json.dumps(load_entries))
示例#25
0
    def testUpdateLoadInfo(self):
        LoadInfo.InitializeTable()
        LoadInfo.AddInstance('test-instance')
        LoadInfo.RegisterInstanceIpAddress('test-instance', '1.2.3.4')

        LoadInfo.UpdateLoadInfo('test-instance', 55)
        self.assertEqual(
            {
                'test-instance': {
                    'ip_address': '1.2.3.4',
                    'load': 55,
                    'force': False
                }
            }, LoadInfo.GetAll())

        LoadInfo.UpdateLoadInfo('test-instance', 73)
        self.assertEqual(
            {
                'test-instance': {
                    'ip_address': '1.2.3.4',
                    'load': 73,
                    'force': False
                }
            }, LoadInfo.GetAll())
示例#26
0
 def StartUpCluster(self):
     LoadInfo.InitializeTable()
     self.IncreaseEngine()
示例#27
0
 def RemoveServer(self, grid):
     # TODO: Maybe confirm with server manager that actual process is ended in case servers need to be force-quit
     LoadInfo.RemoveServer(grid)
示例#28
0
    def testUpdateLoadInfoForce(self):
        LoadInfo.InitializeTable()
        LoadInfo.AddInstance('test-instance')
        LoadInfo.RegisterInstanceIpAddress('test-instance', '1.2.3.4')

        LoadInfo.UpdateLoadInfo('test-instance', 55)
        self.assertEqual(
            {
                'test-instance': {
                    'ip_address': '1.2.3.4',
                    'load': 55,
                    'force': False
                }
            }, LoadInfo.GetAll())

        LoadInfo.UpdateLoadInfo('test-instance', 92, True)
        self.assertEqual(
            {
                'test-instance': {
                    'ip_address': '1.2.3.4',
                    'load': 92,
                    'force': True
                }
            }, LoadInfo.GetAll())

        # This update is ignored since force flag is set in data and this is not
        # force update.
        LoadInfo.UpdateLoadInfo('test-instance', 15)
        self.assertEqual(
            {
                'test-instance': {
                    'ip_address': '1.2.3.4',
                    'load': 92,
                    'force': True
                }
            }, LoadInfo.GetAll())

        # Updated because of force_set flag.
        LoadInfo.UpdateLoadInfo('test-instance', 8, True)
        self.assertEqual(
            {
                'test-instance': {
                    'ip_address': '1.2.3.4',
                    'load': 8,
                    'force': True
                }
            }, LoadInfo.GetAll())

        LoadInfo.UpdateLoadInfo('test-instance', 41, False)
        self.assertEqual(
            {
                'test-instance': {
                    'ip_address': '1.2.3.4',
                    'load': 41,
                    'force': False
                }
            }, LoadInfo.GetAll())

        LoadInfo.UpdateLoadInfo('test-instance', 28)
        self.assertEqual(
            {
                'test-instance': {
                    'ip_address': '1.2.3.4',
                    'load': 28,
                    'force': False
                }
            }, LoadInfo.GetAll())
示例#29
0
 def IncreaseEngine(self):
     instance_name = self.WORKER_NAME_PREFIX + str(uuid.uuid4())
     response = self._StartInstance(instance_name)
     LoadInfo.AddInstance(instance_name, response)
示例#30
0
 def get(self):
     """Deletes Compute Engine cluster."""
     ComputeEngineController(decorator.credentials).TearDownCluster()
     LoadInfo.RemoveAllInstancesAndServers()