def GET(request): """Get this Rack's Machines.""" # Make sure required parameters are there try: request.check_required_parameters(path={'tileId': 'int'}) except exceptions.ParameterError as e: return Response(400, e.message) # Instantiate a Rack from the database rack = Rack.from_tile_id(request.params_path['tileId']) # Make sure this Rack exists if not rack.exists(): return Response(404, '{} not found.'.format(rack)) # Make sure this user is authorized to view this Rack's Machines if not rack.google_id_has_at_least(request.google_id, 'VIEW'): return Response(403, 'Forbidden from viewing {}.'.format(rack)) # Get and return the Machines machines = Machine.query('rack_id', rack.id) for machine in machines: machine.read() return Response(200, 'Successfully retrieved Machines for {}.'.format(rack), [x.to_JSON() for x in machines])
def PUT(request): """Update the Rack on this Tile.""" # Make sure required parameters are there try: request.check_required_parameters(path={'tileId': 'int'}, body={ 'rack': { 'name': 'string', 'capacity': 'int', 'powerCapacityW': 'int' } }) except exceptions.ParameterError as e: return Response(400, e.message) # Instantiate a Tile from the database tile = Tile.from_primary_key((request.params_path['tileId'], )) # Make sure this Tile exists if not tile.exists(): return Response(404, '{} not found.'.format(tile)) # Make sure this user is authorized to edit this Tile if not tile.google_id_has_at_least(request.google_id, 'EDIT'): return Response(403, 'Forbidden from editing {}'.format(tile)) # Instantiate a Rack from the database rack = Rack.from_primary_key((tile.object_id, )) # Make sure this Rack exists if not rack.exists(): return Response(404, '{} not found'.format(rack)) # Update this Rack rack.name = request.params_body['rack']['name'] rack.capacity = request.params_body['rack']['capacity'] rack.update() # Return this Rack rack.read() return Response(200, 'Successfully updated {}.'.format(rack), rack.to_JSON())
def POST(request): """Add a Rack to this Tile if it is empty.""" # Make sure required parameters are there try: request.check_required_parameters(path={'tileId': 'int'}, body={ 'rack': { 'name': 'string', 'capacity': 'int', 'powerCapacityW': 'int' } }) except exceptions.ParameterError as e: return Response(400, e.message) # Instantiate a Tile from the database tile = Tile.from_primary_key((request.params_path['tileId'], )) # Make sure this Tile exists if not tile.exists(): return Response(404, '{} not found.'.format(tile)) # Make sure this user is authorized to edit this Tile if not tile.google_id_has_at_least(request.google_id, 'EDIT'): return Response(403, 'Forbidden from editing {}'.format(tile)) # Make sure this Tile isn't occupied if tile.object_id is not None: return Response(409, '{} occupied.'.format(tile)) # Instantiate a Rack and insert it into the database rack = Rack.from_JSON(request.params_body['rack']) rack.insert() # Try to add this Rack to this Tile tile.object_id = rack.id tile.object_type = 'RACK' tile.update() # Return this Rack rack.read() return Response(200, 'Successfully added {}.'.format(rack), rack.to_JSON())
def google_id_has_at_least(self, google_id, authorization_level): """Return True if the user has at least the given auth level over this Machine.""" # Get the Rack try: rack = Rack.from_primary_key((self.rack_id, )) except exceptions.RowNotFoundError: return False # Check the Rack's Authorization return rack.google_id_has_at_least(google_id, authorization_level)
def DELETE(request): """Delete this Tile's Rack.""" # Make sure required parameters are there try: request.check_required_parameters(path={'tileId': 'int'}, ) except exceptions.ParameterError as e: return Response(400, e.message) # Instantiate a Tile from the database tile = Tile.from_primary_key((request.params_path['tileId'], )) # Make sure this Tile exists if not tile.exists(): return Response(404, '{} not found.'.format(tile)) # Make sure this user is authorized to edit this Tile if not tile.google_id_has_at_least(request.google_id, 'EDIT'): return Response(403, 'Forbidden from editing {}'.format(tile)) # Instantiate a Rack from the database rack = Rack.from_primary_key((tile.object_id, )) # Make sure this Rack exists if not rack.exists(): return Response(404, '{} not found'.format(rack)) # Remove this Rack from this Tile tile.object_id = None tile.object_type = None tile.update() # Delete this Rack rack.delete() # Return this Rack return Response(200, 'Successfully deleted {}.'.format(rack), rack.to_JSON())
def from_tile_id_and_rack_position(cls, tile_id, position): """Get a Rack from the ID of the tile its Rack is on, and its position in the Rack.""" try: rack = Rack.from_tile_id(tile_id) except: return cls(id=-1) try: statement = 'SELECT id FROM machines WHERE rack_id = %s AND position = %s' machine_id = database.fetchone(statement, (rack.id, position))[0] except: return cls(id=-1) return cls.from_primary_key((machine_id, ))
def POST(request): """Create a new Path that branches off of this Path at the specified tick.""" # Make sure required parameters are there try: request.check_required_parameters( path={'pathId': 'int'}, body={'section': { 'startTick': 'int' }}) except exceptions.ParameterError as e: return Response(400, e.message) # Instantiate the current Path from the database current_path = Path.from_primary_key((request.params_path['pathId'], )) # Make sure the current Path exists if not current_path.exists(): return Response(404, '{} not found.'.format(current_path)) # Make sure this user is authorized to branch off the current Path if not current_path.google_id_has_at_least(request.google_id, 'EDIT'): return Response( 403, 'Forbidden from branching off {}.'.format(current_path)) # Create the new Path new_path = Path(simulation_id=current_path.simulation_id, datetime_created=database.datetime_to_string( datetime.now())) new_path.insert() # Get the current Path's sections and add them to the new Path if they're before the branch current_sections = Section.query('path_id', current_path.id) last_section = None for current_section in current_sections: if current_section.start_tick < request.params_body['section'][ 'startTick'] or current_section.start_tick == 0: new_section = Section(path_id=new_path.id, datacenter_id=current_section.datacenter_id, start_tick=current_section.start_tick) new_section.insert() last_section = current_section # Make a deep copy of the last section's datacenter, its rooms, their tiles, etc. path_parameters = {'simulationId': new_path.simulation_id} # Copy the Datacenter old_datacenter = Datacenter.from_primary_key( (last_section.datacenter_id, )) message = old_datacenter.generate_api_call(path_parameters, request.token) response = Request(message).process() path_parameters['datacenterId'] = response.content['id'] # Create the new last Section, with the IDs of the new Path and new Datacenter if last_section.start_tick != 0: new_section = Section( path_id=new_path.id, datacenter_id=path_parameters['datacenterId'], start_tick=request.params_body['section']['startTick']) new_section.insert() else: last_section.datacenter_id = path_parameters['datacenterId'] last_section.update() # Copy the rest of the Datacenter, starting with the Rooms... old_rooms = Room.query('datacenter_id', old_datacenter.id) for old_room in old_rooms: old_room.datacenter_id = path_parameters['datacenterId'] if old_room.topology_id is None: old_room.topology_id = old_room.id message = old_room.generate_api_call(path_parameters, request.token) response = Request(message).process() path_parameters['roomId'] = response.content['id'] # ... then the Tiles, ... old_tiles = Tile.query('room_id', old_room.id) for old_tile in old_tiles: old_tile.room_id = path_parameters['roomId'] if old_tile.topology_id is None: old_tile.topology_id = old_tile.id message = old_tile.generate_api_call(path_parameters, request.token) response = Request(message).process() path_parameters['tileId'] = response.content['id'] old_objects = Object.query('id', old_tile.object_id) # ... then the Tile's Rack, ... if len(old_objects) == 1 and old_objects[0].type == 'RACK': old_rack = Rack.query('id', old_objects[0].id)[0] if old_rack.topology_id is None: old_rack.topology_id = old_rack.id message = old_rack.generate_api_call(path_parameters, request.token) response = Request(message).process() path_parameters['rackId'] = response.content['id'] # ... then the Rack's Machines ... old_machines = Machine.query('rack_id', old_rack.id) for old_machine in old_machines: old_machine.read() old_machine.rack_id = path_parameters['rackId'] if old_machine.topology_id is None: old_machine.topology_id = old_machine.id message = old_machine.generate_api_call( path_parameters, request.token) response = Request(message).process() path_parameters['machineId'] = response.content['id'] # Return the new Path return Response(200, 'Successfully created {}.'.format(new_path), new_path.to_JSON())
def PUT(request): """Update the Machine at this location in this Rack.""" try: request.check_required_parameters( path={ 'tileId': 'int', 'position': 'int' }, body={ 'machine': { 'rackId': 'int', 'position': 'int', 'tags': 'list-string', 'cpuIds': 'list-int', 'gpuIds': 'list-int', 'memoryIds': 'list-int', 'storageIds': 'list-int' } } ) except exceptions.ParameterError as e: return Response(400, e.message) # Instantiate a Machine from the database machine = Machine.from_tile_id_and_rack_position(request.params_path['tileId'], request.params_path['position']) # Make sure this Machine exists if not machine.exists(): return Response(404, '{} not found.'.format(machine)) # Make sure this Machine's rack ID is right rack = Rack.from_tile_id(request.params_path['tileId']) if not rack.exists() or rack.id != request.params_body['machine']['rackId']: return Response(400, 'Mismatch in Rack IDs.') # Make sure this user is authorized to edit this Machine if not machine.google_id_has_at_least(request.google_id, 'EDIT'): return Response(403, 'Forbidden from retrieving {}.'.format(machine)) # Update this Machine machine.position = request.params_body['machine']['position'] machine.tags = request.params_body['machine']['tags'] machine.cpu_ids = request.params_body['machine']['cpuIds'] machine.gpu_ids = request.params_body['machine']['gpuIds'] machine.memory_ids = request.params_body['machine']['memoryIds'] machine.storage_ids = request.params_body['machine']['storageIds'] try: machine.update() except exceptions.ForeignKeyError: return Response(409, 'Rack position occupied.') except Exception as e: print e return Response(400, 'Invalid Machine.') # Return this Machine machine.read() return Response( 200, 'Successfully updated {}.'.format(machine), machine.to_JSON() )
def POST(request): """Add a Machine to this rack.""" # Make sure required parameters are there try: request.check_required_parameters(path={'tileId': 'int'}, body={ 'machine': { 'rackId': 'int', 'position': 'int', 'tags': 'list-string', 'cpuIds': 'list-int', 'gpuIds': 'list-int', 'memoryIds': 'list-int', 'storageIds': 'list-int' } }) except exceptions.ParameterError as e: return Response(400, e.message) # Instantiate a Rack from the database rack = Rack.from_tile_id(request.params_path['tileId']) # Make sure this Rack exists if not rack.exists(): return Response(404, '{} not found.'.format(rack)) # Make sure this Rack's ID matches the given rack ID if rack.id != request.params_body['machine']['rackId']: return Response(400, 'Rack ID in `machine` and path do not match.') # Make sure this user is authorized to edit this Rack's Machines if not rack.google_id_has_at_least(request.google_id, 'VIEW'): return Response(403, 'Forbidden from viewing {}.'.format(rack)) # Instantiate a Machine machine = Machine.from_JSON(request.params_body['machine']) # Try to insert this Machine try: machine.insert() except exceptions.ForeignKeyError: return Response(409, 'Rack position occupied.') except: return Response(400, 'Invalid Machine.') # Return this Machine machine.read() return Response(200, 'Successfully added {}.'.format(machine), machine.to_JSON())