def delete_instance(instance_id): """ Stops a running Packet Tracer instance. --- tags: - instance parameters: - name: instance_id in: path description: instance identifier required: true type: integer responses: 200: description: Instance stopped schema: $ref: '#/definitions/assign_instance_post_Instance' 404: description: There is not an instance for the given instance_id. schema: $ref: '#/definitions/allocate_instance_post_Error' 503: description: The instance has not been deleted in the given time. schema: $ref: '#/definitions/allocate_instance_post_Error' """ instance = Instance.get(instance_id) if not instance or not instance.is_active(): return not_found(error="The instance does not exist.") result = tasks.remove_container.delay(instance.docker_id) result.get() instance.delete() # TODO update instance object as status has changed return jsonify(instance.serialize(request.base_url, get_host()))
def show_instance_details(instance_id): """ Shows the details of a Packet Tracer instance. --- tags: - instance parameters: - name: instance_id in: path type: integer description: instance identifier required: true responses: 200: description: Details of the instance schema: $ref: '#/definitions/assign_instance_post_Instance' 404: description: There is not an instance for the given instance_id. schema: $ref: '#/definitions/allocate_instance_post_Error' """ instance = Instance.get(instance_id) if instance is None: return not_found(error="The instance does not exist.") return jsonify(instance.serialize(request.base_url, get_host()))
def show_instance_details(instance_id): """ Shows the details of a Packet Tracer instance. --- tags: - instance parameters: - name: instance_id in: path type: integer description: instance identifier required: true responses: 200: description: Details of the instance schema: $ref: '#/definitions/assign_instance_post_Instance' 404: description: There is not an instance for the given instance_id. schema: $ref: '#/definitions/allocate_instance_post_Error' """ instance = Instance.get(instance_id) if instance is None: return not_found(error="The instance does not exist.") return jsonify(instance.serialize(request.base_url, get_host()))
def delete_instance(instance_id): """ Stops a running Packet Tracer instance. --- tags: - instance parameters: - name: instance_id in: path description: instance identifier required: true type: integer responses: 200: description: Instance stopped schema: $ref: '#/definitions/assign_instance_post_Instance' 404: description: There is not an instance for the given instance_id. schema: $ref: '#/definitions/allocate_instance_post_Error' 503: description: The instance has not been deleted in the given time. schema: $ref: '#/definitions/allocate_instance_post_Error' """ instance = Instance.get(instance_id) if not instance or not instance.is_active(): return not_found(error="The instance does not exist.") result = tasks.remove_container.delay(instance.docker_id) result.get() instance.delete() # TODO update instance object as status has changed return jsonify(instance.serialize(request.base_url, get_host()))
def wait_for_ready_container(instance_id, timeout=2): """Waits for an instance to be ready (e.g., answer). Otherwise, marks it as erroneous .""" logger.info('Waiting for container to be ready.') instance = Instance.get(instance_id) container_running = is_container_running(instance.docker_id) if container_running: is_running = ptchecker.is_running(app.config['PT_CHECKER'], 'localhost', instance.pt_port, float(timeout)) if is_running: instance.mark_ready() if not instance.is_allocated(): # TODO rename the following task as it sounds confusing. # We call it here to pause the instance, not to "deallocate it". deallocate_instance.s(instance_id).delay() else: try: raise wait_for_ready_container.retry() except MaxRetriesExceededError: instance.mark_error() else: # If the container is not even running, PT won't answer no matter # how many times we try... instance.mark_error() return instance_id
def assign_instance(): """ Creates a new Packet Tracer instance. --- tags: - instance responses: 201: description: Packet Tracer instance created schema: id: Instance properties: id: type: integer description: Identifier of the instance dockerId: type: string description: Identifier of the docker container which serves the instance url: type: string description: URL to handle the instance packetTracer: type: string description: Host and port where the Packet Tracer instance can be contacted (through IPC) vnc: type: string description: VNC URL to access the Packet Tracer instance createdAt: type: string format: date-time description: When was the instance created? deletedAt: type: string format: date-time description: When was the instance removed/stopped? status: type: string enum: [all, starting, deallocated, allocated, running, finished, error] description: Show status of the given instance 500: description: The container could not be created, there was an error. schema: $ref: '#/definitions/allocate_instance_post_Error' 503: description: At the moment the server cannot create more instances. schema: $ref: '#/definitions/allocate_instance_post_Error' """ try: result = tasks.create_instance.delay() instance_id = result.get() if instance_id: instance = Instance.get(instance_id) return jsonify( instance.serialize("%s/%d" % (request.base_url, instance.id), get_host())) return unavailable() except DockerContainerError as e: return internal_error(e.args[0])
def assign_instance(): """ Creates a new Packet Tracer instance. --- tags: - instance responses: 201: description: Packet Tracer instance created schema: id: Instance properties: id: type: integer description: Identifier of the instance dockerId: type: string description: Identifier of the docker container which serves the instance url: type: string description: URL to handle the instance packetTracer: type: string description: Host and port where the Packet Tracer instance can be contacted (through IPC) vnc: type: string description: VNC URL to access the Packet Tracer instance createdAt: type: string format: date-time description: When was the instance created? deletedAt: type: string format: date-time description: When was the instance removed/stopped? status: type: string enum: [all, starting, deallocated, allocated, running, finished, error] description: Show status of the given instance 500: description: The container could not be created, there was an error. schema: $ref: '#/definitions/allocate_instance_post_Error' 503: description: At the moment the server cannot create more instances. schema: $ref: '#/definitions/allocate_instance_post_Error' """ try: result = tasks.create_instance.delay() instance_id = result.get() if instance_id: instance = Instance.get(instance_id) return jsonify(instance.serialize("%s/%d" % (request.base_url, instance.id), get_host())) return unavailable() except DockerContainerError as e: return internal_error(e.args[0])
def deallocate_instance(instance_id): """Marks instance as deallocated and pauses the associated container.""" logger.info('Deallocating instance %s.' % instance_id) instance = Instance.get(instance_id) try: docker = get_docker_client() docker.pause(instance.docker_id) instance.deallocate() except APIError as ae: logger.error('Error deallocating instance %s.' % instance_id) logger.error('Docker API exception. %s.' % ae) # e.g., if it was already paused instance.mark_error()
def deallocate_instance(instance_id): """Marks instance as deallocated and pauses the associated container.""" logger.info('Deallocating instance %s.' % instance_id) instance = Instance.get(instance_id) try: docker = get_docker_client() docker.pause(instance.docker_id) instance.deallocate() except APIError as ae: logger.error('Error deallocating instance %s.' % instance_id) logger.error('Docker API exception. %s.' % ae) # e.g., if it was already paused instance.mark_error()
def allocate_instance(): """Unpauses available container and marks associated instance as allocated.""" logger.info('Allocating instance.') docker = get_docker_client() error_discovered = False allocation_id = None for instance in Instance.get_deallocated(): try: docker.unpause(instance.docker_id) allocation_id = instance.allocate().id break except APIError as ae: logger.error('Error allocating instance %s.' % instance.id) logger.error('Docker API exception. %s.' % ae) # e.g., if it was already unpaused or it has been stopped instance.mark_error() if not allocation_id: # If there were no instances available, consider the creation of a new one instance_id = create_instance.s()() # Execute task inline allocation_id = Instance.get(instance_id).allocate().id return allocation_id
def wait_for_ready_container(instance_id, timeout=2): """Waits for an instance to be ready (e.g., answer). Otherwise, marks it as erroneous .""" logger.info('Waiting for container to be ready.') instance = Instance.get(instance_id) container_running = is_container_running(instance.docker_id) if container_running: is_running = ptchecker.is_running(app.config['PT_CHECKER'], 'localhost', instance.pt_port, float(timeout)) if is_running: instance.mark_ready() if not instance.is_allocated(): # TODO rename the following task as it sounds confusing. # We call it here to pause the instance, not to "deallocate it". deallocate_instance.s(instance_id).delay() else: try: raise wait_for_ready_container.retry() except MaxRetriesExceededError: instance.mark_error() else: # If the container is not even running, PT won't answer no matter # how many times we try... instance.mark_error() return instance_id
def allocate_instance(): """Unpauses available container and marks associated instance as allocated.""" logger.info('Allocating instance.') docker = get_docker_client() error_discovered = False allocation_id = None for instance in Instance.get_deallocated(): try: docker.unpause(instance.docker_id) allocation_id = instance.allocate().id break except APIError as ae: logger.error('Error allocating instance %s.' % instance.id) logger.error('Docker API exception. %s.' % ae) # e.g., if it was already unpaused or it has been stopped instance.mark_error() if not allocation_id: # If there were no instances available, consider the creation of a new one instance_id = create_instance.s()() # Execute task inline allocation_id = Instance.get(instance_id).allocate().id return allocation_id