Ejemplo n.º 1
0
 def get_instance(self):
     """ This returns a boto Instance resource; if boto can't find the instance or if no entry for instance in database,
         it raises Server.DoesNotExist error and removes database entry if appropriate """
     self.log.debug("function get_instance for user %s" % self.user.name)
     server = Server.get_server(self.user.name)
     resource = yield retry(boto3.resource,
                            "ec2",
                            region_name=SERVER_PARAMS["REGION"])
     try:
         ret = yield retry(resource.Instance, server.server_id)
         self.log.debug("return for get_instance for user %s: %s" %
                        (self.user.name, ret))
         # boto3.Instance is lazily loaded. Force with .load()
         yield retry(ret.load)
         if ret.meta.data is None:
             Server.remove_server(server.server_id)
             raise Server.DoesNotExist()
         return ret
     except ClientError as e:
         self.log.error("get_instance client error: %s" % e)
         if "InvalidInstanceID.NotFound" not in str(e):
             self.log.error("Couldn't find instance for user '%s'" %
                            self.user.name)
             Server.remove_server(server.server_id)
             raise Server.DoesNotExist()
         raise e
Ejemplo n.º 2
0
 async def get_volume(self):
     """ This returns a boto volume resource for the case no volumewas found. 
     If boto can't find the volume or if no entry for instance in database,
         it raises VolumeNotFound error and removes database entry if appropriate """
     self.log.debug("function get_resource for user %s" % self.user.name)
     server = Server.get_server(self.user.name)
     resource = await retry(boto3.resource,
                            "ec2",
                            region_name=SERVER_PARAMS["REGION"])
     try:
         ret = await retry(resource.Volume, server.ebs_volume_id)
         self.log.debug("return for get_volume for user %s: %s" %
                        (self.user.name, ret))
         # boto3.Volume is lazily loaded. Force with .load()
         await retry(ret.load)
         if ret.meta.data is None:
             Server.remove_server(server.server_id)
             self.log.info("\nVolume DNE for user %s\n" % self.user.name)
             raise VolumeNotFound
         return ret
     except ClientError as e:
         self.log.error("get_instance client error: %s" % e)
         if "InvalidInstanceID.NotFound" not in str(e):
             self.log.error("Couldn't find volume for user '%s'" %
                            self.user.name)
             Server.remove_server(server.server_id)
             raise VolumeNotFound
         raise e
Ejemplo n.º 3
0
    async def create_new_instance(self):
        """ Creates and boots a new server to host the worker instance."""
        self.log.debug("function create_new_instance %s" % self.user.name)
        ec2 = boto3.client("ec2", region_name=SERVER_PARAMS["REGION"])
        resource = boto3.resource("ec2", region_name=SERVER_PARAMS["REGION"])
        BDM = []
        boot_drive = {
            'DeviceName': '/dev/sda1',  # this is to be the boot drive
            'Ebs': {
                'VolumeSize':
                SERVER_PARAMS["WORKER_EBS_SIZE"],  # size in gigabytes
                'DeleteOnTermination': True,
                'VolumeType': 'gp2',  # This means General Purpose SSD
                # 'Iops': 1000 }  # i/o speed for storage, default is 100, more is faster
            }
        }
        BDM = [boot_drive]
        # get user volume
        volume_id = await self.select_volume()
        # create new instance
        reservation = await retry(
            ec2.run_instances,
            ImageId=SERVER_PARAMS["WORKER_AMI"],
            MinCount=1,
            MaxCount=1,
            KeyName=SERVER_PARAMS["KEY_NAME"],
            InstanceType=self.user_options['INSTANCE_TYPE'],
            SubnetId=SERVER_PARAMS["SUBNET_ID"],
            SecurityGroupIds=SERVER_PARAMS["WORKER_SECURITY_GROUPS"],
            BlockDeviceMappings=BDM,
        )
        self.log.debug(reservation)
        try:
            instance_id = reservation["Instances"][0]["InstanceId"]
        except TypeError as e:
            raise Exception(
                'AWS sends weirdly formatted JSON. Please try again...')

        instance = await retry(resource.Instance, instance_id)
        #if an old volume is restored from a terminated instance, the user has to be updated, e.g. delted and newly saved
        # TODO: Support multiple volumes
        if self.user.volume:
            server = Server.get_server(self.user.name)
            Server.remove_server(server.server_id)
        Server.new_server(instance_id, self.user.name, volume_id)
        await retry(instance.wait_until_exists)
        # add server tags; tags cannot be added until server exists
        await retry(instance.create_tags, Tags=WORKER_TAGS)
        await retry(instance.create_tags,
                    Tags=[{
                        "Key": "User",
                        "Value": self.user.name
                    }])
        await retry(instance.create_tags,
                    Tags=[{
                        "Key":
                        "Name",
                        "Value":
                        SERVER_PARAMS["WORKER_SERVER_NAME"] + '_' +
                        self.user.name
                    }])

        # start server
        # blocking calls should be wrapped in a Future
        await retry(instance.wait_until_running)
        # Attach persistent EBS
        await retry(instance.attach_volume,
                    Device='/dev/sdf',
                    VolumeId=volume_id,
                    InstanceId=instance_id)
        return instance