Esempio n. 1
0
class PythonTaskStatus(PickleMixin, TaskStatus):

    proto = mesos_pb2.TaskStatus(
        labels=mesos_pb2.Labels(
            labels=[mesos_pb2.Label(key='python')]))

    def __init__(self, data=None, **kwargs):
        super(PythonTaskStatus, self).__init__(**kwargs)
        self.data = data
Esempio n. 2
0
def test_python_task_status_decode():
    data = {'arbitrary': 'data', 'lst': [1, 2, 3]}
    dumped = cloudpickle.dumps(data)

    proto = mesos_pb2.TaskStatus(
        data=dumped,
        labels=mesos_pb2.Labels(labels=[mesos_pb2.Label(key='python')]))
    status = decode(proto)

    assert isinstance(status, PythonTaskStatus)
    assert status['data'] == dumped
    assert status.data == data

    proto = mesos_pb2.TaskStatus(labels=mesos_pb2.Labels(
        labels=[mesos_pb2.Label(key='python')]))
    status = decode(proto)
    status.data = data

    assert isinstance(status, PythonTaskStatus)
    assert status.data == data
    assert status['data'] == dumped
Esempio n. 3
0
def test_python_task_decode():
    fn, args, kwargs = sum, [range(5)], {}
    data = (fn, args, kwargs)
    dumped = cloudpickle.dumps(data)

    proto = mesos_pb2.TaskInfo(
        data=dumped,
        labels=mesos_pb2.Labels(labels=[mesos_pb2.Label(key='python')]))
    task = decode(proto)

    assert isinstance(task, PythonTask)
    assert task['data'] == dumped
    assert task.data == data

    proto = mesos_pb2.TaskInfo(labels=mesos_pb2.Labels(
        labels=[mesos_pb2.Label(key='python')]))
    task = decode(proto)
    task.data = data

    assert isinstance(task, PythonTask)
    assert task.data == data
    assert task['data'] == dumped
Esempio n. 4
0
class PythonTaskStatus(PickleMixin, TaskStatus):

    proto = mesos_pb2.TaskStatus(labels=mesos_pb2.Labels(
        labels=[mesos_pb2.Label(key='python')]))

    def __init__(self, data=None, **kwargs):
        super(PythonTaskStatus, self).__init__(**kwargs)
        self.data = data

    @property
    def exception(self):
        try:
            return remote_exception(*self.data)
        except:
            return None
Esempio n. 5
0
class PythonTask(PickleMixin, TaskInfo):

    proto = mesos_pb2.TaskInfo(
        labels=mesos_pb2.Labels(
            labels=[mesos_pb2.Label(key='python')]))

    def __init__(self, fn=None, args=[], kwargs={},
                 docker='lensa/satyr:latest', command='python -m satyr.executor',
                 resources=[Cpus(0.1), Mem(128)], **kwds):
        super(PythonTask, self).__init__(**kwds)
        self.executor = ExecutorInfo(
            executor_id=ExecutorID(value=self.id.value),
            command=CommandInfo(value=command, shell=True),
            container=ContainerInfo(type='DOCKER', docker=DockerInfo(
                image=docker, force_pull_image=False, network='HOST')))
        self.resources = resources
        self.data = (fn, args, kwargs)

    def __call__(self):
        fn, args, kwargs = self.data
        return fn(*args, **kwargs)

    def status(self, state, **kwargs):
        return PythonTaskStatus(task_id=self.task_id, state=state, **kwargs)

    def update(self, status):
        self.on_update(status)

        if status.has_succeeded():
            self.on_success(status)
        elif status.has_failed():
            self.on_fail(status)

    def on_update(self, status):
        pass

    def on_success(self, status):
        logging.info('Task {} has been succeded'.format(self.id.value))

    def on_fail(self, status):
        logging.info('Task {} has been failed due to {}'.format(self.id.value,
                                                                status.message))
Esempio n. 6
0
class PythonTask(PickleMixin, TaskInfo):

    proto = mesos_pb2.TaskInfo(
        labels=mesos_pb2.Labels(
            labels=[mesos_pb2.Label(key='python')]))

    def __init__(self, fn=None, args=[], kwargs={},
                 resources=[Cpus(0.1), Mem(128), Disk(0)],
                 command='python -m mentor.executor', envs={}, uris=[],
                 docker='daskos/mentor:latest', force_pull=False, retries=3,
                 **kwds):
        super(PythonTask, self).__init__(**kwds)
        self.status = PythonTaskStatus(task_id=self.id, state='TASK_STAGING')
        self.executor = ExecutorInfo(
            container=ContainerInfo(type='DOCKER',
                                    docker=DockerInfo(network='HOST')),
            command=CommandInfo(shell=True))
        self.data = (fn, args, kwargs)
        self.envs = envs
        self.uris = uris
        self.docker = docker
        self.force_pull = force_pull
        self.command = command
        self.resources = resources
        self.retries = retries
        self.attempt = 1

    @property
    def uris(self):
        return [uri.value for uri in self.executor.command.uris]

    @uris.setter
    def uris(self, value):
        self.executor.command.uris = [{'value': v} for v in value]

    @property
    def envs(self):
        envs = self.executor.command.environment.variables
        return {env.name: env.value for env in envs}

    @envs.setter
    def envs(self, value):
        envs = [{'name': k, 'value': v} for k, v in value.items()]
        self.executor.command.environment = Environment(variables=envs)

    @property
    def command(self):
        return self.executor.command.value

    @command.setter
    def command(self, value):
        self.executor.command.value = value

    @property
    def docker(self):
        return self.executor.container.docker.image

    @docker.setter
    def docker(self, value):
        self.executor.container.docker.image = value

    @property
    def force_pull(self):
        return self.executor.container.docker.force_pull_image

    @force_pull.setter
    def force_pull(self, value):
        self.executor.container.docker.force_pull_image = value

    def __call__(self):
        fn, args, kwargs = self.data
        return fn(*args, **kwargs)

    def retry(self, status):
        if self.attempt < self.retries:
            logging.info('Task {} attempt #{} rescheduled due to failure with state '
                         '{} and message {}'.format(self.id, self.attempt,
                                                    status.state, status.message))
            self.attempt += 1
            status.state = 'TASK_STAGING'
        else:
            logging.error('Aborting due to task {} failed for {} attempts in state '
                          '{} with message {}'.format(self.id, self.retries,
                                                      status.state, status.message))
            raise RuntimeError('Task {} failed with state {} and message {}'.format(
                self.id, status.state, status.message))

    def update(self, status):
        assert isinstance(status, TaskStatus)
        self.on_update(status)
        if status.has_succeeded():
            self.on_success(status)
        elif status.has_failed():
            self.on_fail(status)

    def on_update(self, status):
        self.status = status  # update task's status
        logging.info('Task {} has been updated with state {}'.format(
            self.id.value, status.state))

    def on_success(self, status):
        logging.info('Task {} has been succeded'.format(self.id.value))

    def on_fail(self, status):
        logging.error('Task {} has been failed with state {} due to {}'.format(
            self.id.value, status.state, status.message))

        try:
            raise status.exception  # won't retry due to code error in PythonTaskStatus
        except KeyError as e:
            # not a code error, e.g. problem during deployment
            self.retry(status)
        else:
            logging.error('Aborting due to task {} failed with state {} and message '
                          '{}'.format(self.id, status.state, status.message))
Esempio n. 7
0
    def new_docker_task(self, offer, instance_object):

        instance = instance_object.instance_info
        image_meta = instance_object.image_meta
        network_info = instance_object.network_info
        volume_info_list = instance_object.volume_info_list

        task = self.makeTaskPrototype(offer, instance_object)
        # We want of container of type Docker
        container = mesos_pb2.ContainerInfo()
        container.type = 1  # mesos_pb2.ContainerInfo.Type.DOCKER

        # Let's create a volume
        # container.volumes, in mesos.proto, is a repeated element
        # For repeated elements, we use the method "add()" that returns an object that can be updated
        if volume_info_list:
            for volume_info in volume_info_list:
                if volume_info.type == "rbd":
                    volume = container.volumes.add()
                    #TODO(gokrokve) fix volume mountpoints. Here we hardcode
                    # a volume path to /mnt/volume
                    # originally it was /mnt/<volume name>
                    volume.container_path = "/mnt/volume"  #+ volume_info.target['name'] # Path in container
                    volume.host_path = volume_info.target[
                        'name']  # Path on host
                    volume.mode = 1  # mesos_pb2.Volume.Mode.RW
            # volume.mode = 2 # mesos_pb2.Volume.Mode.RO

        # Define the command line to execute in the Docker container
        # Command value is empry to run container's default
        # Shell is disabled as well
        #executorInfo = mesos_pb2.ExecutorInfo()
        #executorInfo.executor_id.value = task.task_id.value
        command = mesos_pb2.CommandInfo()
        command.shell = False

        task.command.MergeFrom(command)
        task.name = "nova-mesos-01"

        # Let's use Docker containers
        docker = mesos_pb2.ContainerInfo.DockerInfo()
        docker.image = instance_object.image_name
        docker.force_pull_image = False
        #TODO(gokrokve) Fix networking type to support new network model in docker
        docker.network = 2  # mesos_pb2.ContainerInfo.DockerInfo.Network.BRIDGE
        docker.volume_driver = "rbd"
        # Set docker info in container.docker

        container.docker.MergeFrom(docker)
        network = container.network_infos.add()
        #TODO(gokrokve) collect ip addresses from network_info[][subnets]

        network.ip_address = instance_object.ip
        network.protocol = 1
        labels = mesos_pb2.Labels()
        label = labels.labels.add()
        label.key = "network_id"
        #TODO(gokrokve) add proper network id
        label.value = instance_object.network_id
        #label.value = "none"
        network.labels.MergeFrom(labels)
        # Set docker container in task.container
        task.container.MergeFrom(container)
        #task.executor.container.MergeFrom(container)
        # Return the object
        return task