def commit(self, request, body): """ Commit specified container to named image. if image repository is provided, use the provided repository as the new image's repository, otherwise get the image name by `image_id` for the repoistory. """ repository = body.pop('repository') tag = body.pop('tag') image_id = body.pop('id') project_id = body.pop('project_id') container_id = body.pop('container_id') project = self.db.get_project(project_id) if not project: LOG.error("no such project %s" % project_id) return Response(404) container_instance = self.db.get_container(container_id) if not container_instance: LOG.error("no such container %s" % container_id) return Response(404) container_uuid = container_instance.uuid image_instance = self.db.get_image(image_id) if not image_instance: LOG.error("no such image %s" % image_id) return Response(404) """If repository is None, use the image's name as repository.""" if not repository: repository = image_instance.name new_image_id = uuid.uuid4().hex self.db.add_image(dict(id=new_image_id, name=repository, tag=tag, desc=image_instance.desc, repos=image_instance.repos, branch=image_instance.branch, user_id=image_instance.user_id, status='building'), project=project) #eventlet.spawn_n(self._manager.commit, # new_image_id, # repository, # tag, # container_uuid) self._process_task(self._manager.commit, new_image_id, repository, tag, container_uuid) #NOTE(nmg):there may be a bug here. return ResponseObject({"id": new_image_id})
def refresh(self, request, id): """Refresh code in container.""" query = self.db.get_container(id) if not query: LOG.info("container %s not found" % id) return Response(404) # FIXME(nmg) try: self._process_task(self._manager.refresh, id) except: raise return Response(204)
def stop(self, request, id): """ Send stop `request` to container node for stoping container. This method contains the following two steps: - find the host where the container run on - send stop request to that host If no host found, the request will be droped. :params request: `wsgi.Request` :params id : container id """ container = self.db.get_container(id) if not container: LOG.error("nu such container %s" % id) return webob.exc.HTTPNotFound() host_id = container.host_id host = self.db.get_host(host_id) if not host: LOG.error("no such host") return webob.exc.HTTPNotFound() host, port = host.host, host.port response = self.http.post("http://%s:%s/v1/containers/%s/stop" \ % (host,port,id)) return Response(response.status_code)
def delete(self, request, id): """ Send delete `request` to container node for deleting. if failed,excepiton will be occured. This method contains the following two steps: - find the host where the container run on - send delete request to that host If no host found, the request will be droped. :param request: `wsgi.Request` :param id : container idenfier """ container = self.db.get_container(id) if not container: return webob.exc.HTTPOk() host_id = container.host_id host = self.db.get_host(host_id) if not host: LOG.error("no such host %s" % host_id) return webob.exc.HTTPNotFound() host, port = host.host, host.port # FIXME: try to catch exceptions and dealing with it. response = self.http.delete("http://%s:%s/v1/containers/%s" \ %(host,port,id)) return Response(response.status_code)
def create(self, request, body): """Create new container and start it.""" # FIXME(nmg): try to do this with a pythonic way. id = body.pop('db_id') name = body.pop('name') image_id = body.pop('image_id') query = self.db.get_image(image_id) if not query: msg = "image id is invalid" raise exception.ImageNotFound(msg) image_uuid = query.uuid repository = query.name tag = query.tag env = body.pop('env') project_id = body.pop('project_id') repos = body.pop('repos') branch = body.pop('branch') app_type = body.pop('app_type') user_id = body.pop('user_id') user_key = body.pop('user_key') fixed_ip = body.pop('fixed_ip') try: self._process_task(self._manager.create, id, name, image_id, image_uuid, repository, tag, repos, branch, app_type, env, user_key, fixed_ip, user_id) except: raise return Response(201)
def start(self, request, id): """ Start container according container id. :params request: `wsgi.Request` :params id: the container id returns: if start succeed, 204 will be returned. """ query = self.db.get_container(id) if query.status == states.RUNNING: LOG.info("already running,ignore...") return Response(204) # FIXME(nmg) try: self._process_task(self._manager.start, id) except: raise return Response(204)
def commit(self, request, body): """Commit container to image.""" # FIXME(nmg) repo = body.pop('repo') tag = body.pop('tag') try: self._process_task(self._manager.commit(repo, tag)) except: raise return Response(200)
def delete(self, request, id): """ Delete project identified by `id`. """ LOG.info("DELETE +job delete %s" % id) try: self.db.delete_project(id) except IntegrityError, err: LOG.error(err) LOG.info("DELETE -job delete = ERR") return Response(500)
def delete(self, request, id): """ Delete image by id. :param request: `wsgi.Request` object :param id : image id """ #eventlet.spawn_n(self._manager.delete,id) self._process_task(self._manager.delete, id) return Response(200)
def destroy(self, request, name): """ Destroy a temporary container by a given name. :params name: the temporary container name """ # FIXME(nmg) try: self._process_task(self._manager.destroy, name) except: raise return Response(200)
def save_to_db(self, db_id, name, env, project_id, repos, branch, image_id, user_id, host_id): """Creating db entry for creation""" project = self.db.get_project(project_id) if not project: LOG.error("no such project %s" % project_id) return Response(404) self.db.add_container(dict(id=db_id, name=name, env=env, repos=repos, branch=branch, image_id=image_id, user_id=user_id, host_id=host_id, status="building"), project=project)
def delete(self, request, id): """ Delete container by container id. :params request: `wsgi.Request` :params id : container id """ query = self.db.get_container(id) if not query: LOG.error("no such container") return webob.exc.HttpNotFound() try: self._process_task(self._manager.delete, id) except: raise return Response(200)
def refresh(self, request, id): """ Refresh code in container. `refresh request` will be send to remote container server for refreshing. if send request failed,exception will occured. Is it necessary to catch the exception? I don't know. :param request: `wsgi.Request` object :param id : container idenfier """ """ Check if this container is really exists, otherwise return 404 not found. """ container = self.db.get_container(id) if not container: LOG.error("nu such container %s" % id) return webob.exc.HTTPNotFound() """ Get host id from container info, if host id is None,return 404. """ host_id = container.host_id if not host_id: LOG.error("container %s has no host_id" % id) return webob.exc.HTTPNotFound() """ Get host instance by `host_id`, if host instance is None,return 404. """ host = self.db.get_host(host_id) if not host: LOG.error("no such host") return webob.exc.HTTPNotFound() """Get ip address and port for host instance.""" host, port = host.host, host.port """send `refresh request` to the host where container on.""" #FIXME: exception shoud be catched? response = self.http.post("http://%s:%s/v1/containers/%s/refresh" \ % (host,port,id)) return Response(response.status_code)
def create(self, request, body): """create image.""" name = body.get('name').lower() desc = body.get('desc') project_id = body.get('project_id') repos = body.get('repos') branch = body.get('branch') user_id = body.get('user_id') id = uuid.uuid4().hex project = self.db.get_project(project_id) if not project: LOG.error("no such project %s" % project_id) return Response(404) """add db entry first.""" self.db.add_image(dict(id=id, name=name, tag="latest", desc=desc, repos=repos, branch=branch, user_id=user_id, status='building'), project=project) #eventlet.spawn_n(self._manager.create, # id, # name, # desc, # repos, # branch, # user_id) self._process_task(self._manager.create, id, name, desc, repos, branch, user_id) return ResponseObject({"id": id})
def destroy(self, request, id): """destroy temporary container for image edit.""" #eventlet.spawn_n(self._manager.destroy,id) self._process_task(self._manager.destroy, id) return Response(200)
class Controller(Base): def __init__(self): super(Controller, self).__init__() self.http = client.HTTPClient() def index(self, request): """ List all images accorind to `project_id`. This method returns a dictionary list and each dict contains the following keys: - id - uuid - name - tag - desc - project_id - created - user_id - status If no images found, empty list will be returned. """ images = [] project_id = request.GET.get('project_id') if not project_id: LOG.error("project_id cannot be None") return webob.exc.HTTPNotFound() project_instance = self.db.get_project(project_id) if project_instance is None: LOG.error("no such project %s" % project_id) return webob.exc.HTTPNotFound() for image_instance in project_instance.images: image = { 'id': image_instance.id, 'uuid': image_instance.uuid, 'name': image_instance.name, 'tag': image_instance.tag, 'desc': image_instance.desc, 'project_id': image_instance.project_id, 'created': isotime(image_instance.created), 'user_id': image_instance.user_id, 'status': image_instance.status } images.append(image) return ResponseObject(images) def show(self, request, id): """ Show the image detail according to `id`. :parmas id: the image id This method returns a dictionary with the following keys: - id - uuid - name - repos - tag - desc - project_id - created - user_id - status If no image found, empty dictionary will be returned. """ image = {} query = self.db.get_image(id) if query is not None: image = { 'id': query.id, 'uuid': query.uuid, 'name': query.name, 'repos': query.repos, 'tag': query.tag, 'desc': query.desc, 'project_id': query.project_id, 'created': isotime(query.created), 'user_id': query.user_id, 'status': query.status } return ResponseObject(image) def create(self, request, body=None): """ For creating image, body should not be None and should contains the following params: - project_id the project's id which the image belong to - name the image name -desc the image description - repos the repos contains `Dockerfile` - branch the branch - user_id the user who created the image All the above params are not optional and have no default value. """ """This schema is used for data validate""" schema = { "type": "object", "properties": { "project_id": { "type": "string", "minLength": 32, "maxLength": 64, "pattern": "^[a-zA-Z0-9]*$", }, "name": { "type": "string", "minLength": 1, "maxLength": 255 }, "desc": { "type": "string", "minLength": 1, "maxLength": 255 }, "repos": { "type": "string", "minLength": 1, "maxLength": 255 }, "branch": { "type": "string", "minLength": 1, "maxLength": 255 }, "user_id": { "type": "string", "minLength": 32, "maxLength": 64, "pattern": "^[a-zA-Z0-9]*$", }, }, "required": ["project_id", "name", "desc", "repos", "branch", "user_id"] } try: self.validator(body, schema) except (SchemaError, ValidationError) as ex: LOG.error(ex) return webob.exc.HTTPBadRequest(explanation="Bad Paramaters") #if not body: # LOG.error('body cannot be empty!') # return webob.exc.HTTPBadRequest() #project_id = body.get('project_id') #if not project_id: # LOG.error('project_id cannot be None!') # return webob.exc.HTTPBadRequest() limit = QUOTAS.images or _IMAGE_LIMIT query = self.db.get_images(project_id) if len(query) >= limit: LOG.error("images limit exceed,can not created anymore...") return webob.exc.HTTPMethodNotAllowed() #name = body.get('name',utils.random_str()) #desc = body.get('desc','') #repos = body.get('repos') #if not repos: # LOG.error('repos cannot be None!') # return webob.exc.HTTPBadRequest() #branch = body.get('branch') #if not branch: # LOG.error("branch cannot be None!") # return webob.exc.HTTPBadRequest() #user_id = body.get('user_id') #if not user_id: # LOG.error('user_id cannot be None!') # return webob.exc.HTTPBadRequest() image_service_endpoint = CONF.image_service_endpoint if not image_service_endpoint: LOG.error("image service endpoint not found!") return webob.exc.HTTPNotFound() try: image = self.http.post(image_service_endpoint, \ headers={'Content-Type':'application/json'}, \ data=json.dumps(body)) except exceptions.ConnectionError as ex: LOG.error("Connect to remote server Error %s" % ex) return webob.exc.HTTPInternalServerError() except exceptions.ConnectTimeout as ex: LOG.error("Connect to remote server Timeout. %s " % ex) return webob.exc.HTTPRequestTimeout() except exceptions.MissingSchema as ex: LOG.error("The URL schema (e.g. http or https) is missing. %s" % ex) return webob.exc.HTTPBadRequest() except exceptions.InvalidSchema as ex: LOG.error("The URL schema is invalid. %s" % ex) return webob.exc.HTTPBadRequest() return ResponseObject(image.json()) def delete(self, request, id): """ Delete image from db and registry. This method contains the following three steps: 1. delete db entry 2. delete image from private image registry 3. delete local image """ image_instance = self.db.get_image(id) if not image_instance: LOG.warning("no such image %s" % id) return webob.exc.HTTPNotFound() """Delete image from database""" self.db.delete_image(id) """Delete image from image registry""" image_service_endpoint = CONF.image_service_endpoint if not image_service_endpoint: LOG.error("no image service endpoint found!") return webob.exc.HTTPNotFound() if not image_service_endpoint.startswith("http://"): image_service_endpoint += "http://" try: response = self.http.delete("%s/%s" % \ (image_service_endpoint,id)) except ConnectionError, err: LOG.error(err) return webob.exc.HTTPInternalServerError() return Response(response.status_code)