Example #1
0
    def delete(self, instance_id: uuid.UUID):
        cherrypy.response.status = 204
        # Fix for https://github.com/cherrypy/cherrypy/issues/1657
        del cherrypy.response.headers['Content-Type']
        with cherrypy.request.db_session() as session:
            instance: Instance = session.merge(
                cherrypy.request.resource_object, load=False)

            if instance.state not in [
                    InstanceState.STOPPED, InstanceState.ACTIVE,
                    InstanceState.ERROR
            ]:
                raise cherrypy.HTTPError(
                    409,
                    "Can only delete an instance in the following states: %s" %
                    [
                        InstanceState.STOPPED.value,
                        InstanceState.ACTIVE.value, InstanceState.ERROR.value
                    ])

            instance.state = InstanceState.DELETING

            create_task(session,
                        instance,
                        delete_instance,
                        instance_id=instance.id,
                        delete_backing=True)

            session.commit()
Example #2
0
    def action_start(self, instance_id: uuid.UUID):
        cherrypy.response.status = 202
        with cherrypy.request.db_session() as session:
            instance: Instance = session.merge(
                cherrypy.request.resource_object, load=False)

            if instance.state != InstanceState.STOPPED:
                raise cherrypy.HTTPError(
                    400,
                    "Can only start an instance in the following state: %s" %
                    InstanceState.STOPPED.value)

            if instance.state != InstanceState.STOPPED:
                raise cherrypy.HTTPError(
                    409,
                    "Can only start an instance in the following state: %s" %
                    InstanceState.STOPPED.value)

            instance.state = InstanceState.STARTING

            create_task(session,
                        instance,
                        start_instance,
                        instance_id=instance.id)

            session.commit()
Example #3
0
    def delete(self, image_id):
        cherrypy.response.status = 204
        # Fix for https://github.com/cherrypy/cherrypy/issues/1657
        del cherrypy.response.headers['Content-Type']
        with cherrypy.request.db_session() as session:
            image: Image = session.merge(cherrypy.request.resource_object,
                                         load=False)

            if image.state not in [ImageState.CREATED, ImageState.ERROR]:
                raise cherrypy.HTTPError(
                    409,
                    "Can only delete an image while it is in the following states: %s"
                    % ([ImageState.CREATED.value, ImageState.ERROR.value]))

            if image.locked:
                raise cherrypy.HTTPError(
                    409, "Cannot delete an image while it is locked.")

            image.state = ImageState.DELETING
            # TODO: do we allow not deleting image backing?
            create_task(session,
                        image,
                        delete_image,
                        image_id=image.id,
                        delete_backing=True)

            session.commit()
Example #4
0
    def create(self):
        request: RequestCreateRegion = cherrypy.request.model

        with cherrypy.request.db_session() as session:
            region = session.query(Region).filter(
                Region.name == request.name).first()

            if region is not None:
                raise cherrypy.HTTPError(
                    409, 'A region with the requested name already exists.')

            region = Region()
            region.name = request.name
            region.datacenter = request.datacenter
            region.image_datastore = request.image_datastore
            region.schedulable = False

            if request.image_folder is not None:
                region.image_folder = request.image_folder

            session.add(region)
            session.flush()

            create_task(session, region, create_region, region_id=region.id)

            session.commit()
            session.refresh(region)

        return ResponseRegion.from_database(region)
Example #5
0
    def create(self):
        request: RequestCreateImage = cherrypy.request.model

        if request.visibility == ImageVisibility.PUBLIC:
            self.mount.enforce_policy("images:create:public")

        with cherrypy.request.db_session() as session:
            project = cherrypy.request.project

            region = session.query(Region).filter(
                Region.id == request.region_id).first()
            if region is None:
                raise cherrypy.HTTPError(
                    404, "A region with the requested id does not exist.")

            if region.state != RegionState.CREATED:
                raise cherrypy.HTTPError(
                    412,
                    "The requested region is not in the following state: %s" %
                    RegionState.CREATED.value)

            image = session.query(Image).filter(
                Image.project_id == project.id).filter(
                    Image.name == request.name).filter(
                        Image.region_id == region.id).first()

            if image is not None:
                raise cherrypy.HTTPError(
                    409, 'An image with the requested name already exists.')

            image = session.query(Image).filter(
                Image.project_id == project.id).filter(
                    Image.file_name == request.file_name).first()

            if image is not None:
                raise cherrypy.HTTPError(
                    409, 'An image with the requested file already exists.')

            image = Image()
            image.name = request.name
            image.file_name = request.file_name
            image.visibility = request.visibility
            image.project_id = project.id
            image.region_id = region.id

            session.add(image)
            session.flush()

            create_task(session, image, create_image, image_id=image.id)

            session.commit()
            session.refresh(image)

        return ResponseImage.from_database(image)
Example #6
0
    def action_image(self, instance_id: uuid.UUID):
        request: RequestInstanceImage = cherrypy.request.model

        if request.visibility == ImageVisibility.PUBLIC:
            self.mount.enforce_policy("instances:action:image:public")

        with cherrypy.request.db_session() as session:
            instance: Instance = session.merge(
                cherrypy.request.resource_object, load=False)

            if instance.state != InstanceState.STOPPED:
                raise cherrypy.HTTPError(
                    409,
                    "Can only image an instance in the following state: %s" %
                    InstanceState.STOPPED.value)

            region = session.query(Region).filter(
                Region.id == instance.region_id).one()

            image = session.query(Image).filter(
                Image.project_id == instance.project_id).filter(
                    Image.name == request.name).filter(
                        Image.region_id == region.id).first()

            if image is not None:
                raise cherrypy.HTTPError(
                    409, 'An image with the requested name already exists.')

            instance.state = InstanceState.IMAGING

            image = Image()
            image.name = request.name
            image.file_name = str(instance.id)
            image.visibility = request.visibility
            image.project_id = instance.project_id
            image.region_id = region.id

            session.add(image)
            session.flush()

            # Clone the vm to a template
            create_task(session,
                        image,
                        convert_vm,
                        image_id=image.id,
                        instance_id=instance.id)

            instance.current_task_id = image.current_task_id
            session.commit()

            return ResponseImage.from_database(image)
Example #7
0
    def create(self):
        request: RequestCreateNetwork = cherrypy.request.model

        with cherrypy.request.db_session() as session:
            network = session.query(Network).filter(Network.name == request.name).first()

            if network is not None:
                raise cherrypy.HTTPError(409, "A network with the requested name already exists.")

            network = session.query(Network).filter(Network.port_group == request.port_group).first()

            if network is not None:
                raise cherrypy.HTTPError(409, "A network with the requested port group already exists.")

            region = session.query(Region).filter(Region.id == request.region_id).first()
            if region is None:
                raise cherrypy.HTTPError(404, "A region with the requested id does not exist.")

            if region.state != RegionState.CREATED:
                raise cherrypy.HTTPError(412,
                                         "The requested region is not in the following state: %s" %
                                         RegionState.CREATED.value)

            # TODO: make sure cidr doesn't overlap with another network

            network = Network()
            network.name = request.name
            network.port_group = request.port_group
            network.cidr = request.cidr
            network.gateway = request.gateway
            network.dns_servers = request.dns_servers
            network.pool_start = request.pool_start
            network.pool_end = request.pool_end
            network.region_id = region.id

            session.add(network)
            session.flush()

            create_task(session, network, create_network, network_id=network.id)

            session.commit()
            session.refresh(network)

        return ResponseNetwork.from_database(network)
Example #8
0
    def create(self):
        request: RequestCreateZone = cherrypy.request.model

        with cherrypy.request.db_session() as session:
            zone = session.query(Zone).filter(
                Zone.name == request.name).first()
            if zone is not None:
                raise cherrypy.HTTPError(
                    409, 'A zone with the requested name already exists.')

            region = session.query(Region).filter(
                Region.id == request.region_id).first()
            if region is None:
                raise cherrypy.HTTPError(
                    404, "A region with the requested id does not exist.")

            if region.state != RegionState.CREATED:
                raise cherrypy.HTTPError(
                    412,
                    "The requested region is not in the following state: %s" %
                    RegionState.CREATED.value)

            zone = Zone()
            zone.name = request.name
            zone.region_id = region.id
            zone.vm_cluster = request.vm_cluster
            zone.vm_datastore = request.vm_datastore
            zone.core_provision_percent = request.core_provision_percent
            zone.ram_provision_percent = request.ram_provision_percent
            zone.schedulable = False

            if request.vm_folder is not None:
                zone.vm_folder = request.vm_folder

            session.add(zone)
            session.flush()

            create_task(session, zone, create_zone, zone_id=zone.id)

            session.commit()
            session.refresh(zone)

        return ResponseZone.from_database(zone)
Example #9
0
    def action_restart(self, instance_id: uuid.UUID):
        request: RequestInstancePowerOffRestart = cherrypy.request.model
        cherrypy.response.status = 202
        with cherrypy.request.db_session() as session:
            instance: Instance = session.merge(
                cherrypy.request.resource_object, load=False)

            if instance.state != InstanceState.ACTIVE:
                raise cherrypy.HTTPError(
                    409,
                    "Can only restart an instance in the following state: %s" %
                    InstanceState.ACTIVE.value)

            instance.state = InstanceState.RESTARTING

            create_task(session,
                        instance,
                        restart_instance,
                        instance_id=instance.id,
                        hard=request.hard,
                        timeout=request.timeout)

            session.commit()
Example #10
0
    def create(self):
        request: RequestCreateInstance = cherrypy.request.model

        with cherrypy.request.db_session() as session:
            project = cherrypy.request.project

            instance = session.query(Instance).filter(
                Instance.project_id == project.id).filter(
                    Instance.name == request.name).first()
            if instance is not None:
                raise cherrypy.HTTPError(
                    409, 'An instance already exists with the requested name.')

            region = session.query(Region).filter(
                Region.id == request.region_id).first()
            if region is None:
                raise cherrypy.HTTPError(
                    404, "A region with the requested id does not exist.")

            if region.state != RegionState.CREATED:
                raise cherrypy.HTTPError(
                    412,
                    "The requested region is not in the following state: %s" %
                    RegionState.CREATED.value)

            if region.schedulable is False:
                raise cherrypy.HTTPError(
                    412, "The requested region is not currently schedulable.")

            image = session.query(Image).filter(
                Image.id == request.image_id).filter(
                    Image.region_id == region.id).first()
            if image is None:
                raise cherrypy.HTTPError(
                    404, "An image with the requested id does not exist.")

            if image.state != ImageState.CREATED:
                raise cherrypy.HTTPError(
                    412, "The requested image is not in the '%s' state" %
                    (ImageState.CREATED.value))

            if image.project_id != project.id:
                if image.visibility == ImageVisibility.PRIVATE:
                    raise cherrypy.HTTPError(
                        400,
                        "The requested image does not belong to the scoped project."
                    )
                elif image.visibility == ImageVisibility.SHARED:
                    if project not in image.members:
                        raise cherrypy.HTTPError(
                            400,
                            "The requested image is not shared with the scoped project."
                        )
                elif image.visibility == ImageVisibility.PUBLIC:
                    # Image is public so don't error
                    pass

            if request.service_account_id is not None:
                service_account: AuthNServiceAccount = session.query(
                    AuthNServiceAccount).filter(
                        AuthNServiceAccount.id ==
                        request.service_account_id).first()
                if service_account is None:
                    raise cherrypy.HTTPError(
                        404,
                        "A service account with the requested id does not exist."
                    )
                if service_account.project_id != project.id:
                    raise cherrypy.HTTPError(
                        400,
                        "The requested service account does not belong to the scoped project."
                    )
            else:
                service_account = session.query(AuthNServiceAccount).filter(
                    AuthNServiceAccount.project_id == project.id).filter(
                        AuthNServiceAccount.name == "default").first()

            network = session.query(Network).filter(
                Network.id == request.network_id).filter(
                    Network.region_id == region.id).first()
            if network is None:
                raise cherrypy.HTTPError(
                    404, "A network with the requested id does not exist.")

            if network.state != NetworkState.CREATED:
                raise cherrypy.HTTPError(
                    412, "The requested network is not in the '%s' state" %
                    (NetworkState.CREATED.value))

            zone = None
            if request.zone_id is not None:
                zone = session.query(Zone).filter(
                    Zone.id == request.zone_id).filter(
                        Zone.region_id == region.id).first()
                if zone is None:
                    raise cherrypy.HTTPError(
                        404, "A zone with the requested id does not exist.")

                if zone.state != ZoneState.CREATED:
                    raise cherrypy.HTTPError(
                        412,
                        "The requested zone is not in the following state: %s"
                        % ZoneState.CREATED.value)

                if zone.schedulable is False:
                    raise cherrypy.HTTPError(
                        412,
                        "The requested zone is not currently schedulable.")

            network_port = NetworkPort()
            network_port.network_id = network.id
            network_port.project_id = project.id
            session.add(network_port)
            session.flush()

            instance = Instance()
            instance.name = request.name
            instance.image_id = image.id
            instance.project_id = project.id
            instance.network_port_id = network_port.id
            instance.tags = request.tags
            instance.service_account_id = service_account.id

            instance.region_id = region.id
            if zone is not None:
                instance.zone_id = zone.id

            session.add(instance)
            session.flush()

            for keypair_id in request.keypair_ids:
                keypair = session.query(Keypair).filter(
                    Keypair.id == keypair_id).filter(
                        Keypair.project_id == project.id).first()

                if keypair is None:
                    raise cherrypy.HTTPError(
                        404,
                        "Could not find a keypair within the scoped project with the id %s"
                        % keypair_id)

                instance.keypairs.append(keypair)

            print("TASK")
            create_task(session,
                        instance,
                        create_instance,
                        instance_id=instance.id)

            response = ResponseInstance.from_database(instance)
            session.commit()

            return response