def __init__(self): super(ContainerManager, self).__init__() self.driver = driver.API() self.mercurial = MercurialControl() self.network = network_manager.NetworkManager() self.version = '1.0.0'
class ContainerManager(base.Base, manager.Manager): def __init__(self): super(ContainerManager, self).__init__() self.driver = driver.API() self.mercurial = MercurialControl() self.network = network_manager.NetworkManager() self.version = '1.0.0' def service_init(self): """There will be three things doing here: 1. Register host in db. 2. Start containers on this node if necessary. 3. Create rpc producers and consumers. You must do these things before service start. """ return NotImplementedError() def create(self, id, name, image_id, image_uuid, repository, tag, repos, branch, app_type, app_env, ssh_key, fixed_ip, user_id): """Create new container and start it. There are three steps to do this: 1. Pull image from docker registry. 2. Create container use the specified image. 3. Start container. """ LOG.info("CREATE +job create %s" % id) """Pull Specified Imag From Docker Registry.""" LOG.info("pull image %s from registry..." % image_id) status = self.driver.pull_image(repository, tag) if status == 404: LOG.error("pull failed,no registry found!") self.db.update_container(id, status="error") return webob.exc.HTTPNotFound() if status == 500: LOG.error("pull failed,internal server error!") self.db.update_container(id, status="error") return webob.exc.HTTPInternalServerError() """Check if the image was pulled successful.""" resp = self.driver.inspect_image(image_uuid) if resp.status_code == 404: msg = "pull image failed!" LOG.error(msg) return webob.exc.HTTPNotFound(explanation=msg) LOG.info("pull image succeed!") """ Generate arguments for container creation. """ port = resp.json()['Config']['ExposedPorts'] kwargs = { 'Hostname': '', 'User': '', 'Memory': '', 'MemorySwap': '', 'AttachStdin': False, 'AttachStdout': False, 'AttachStderr': False, 'PortSpecs': [], 'Tty': True, 'OpenStdin': True, 'StdinOnce': False, 'Env': ["REPO_PATH=%s" % repos, "BRANCH=%s" % branch, "APP_TYPE=%s" % app_type, "APP_ENV=%s" % app_env, "SSH_KEY=%s" % ssh_key], 'Cmd': ["/opt/start.sh"], 'Dns': None, 'Image': image_uuid, 'Volumes': {}, 'VolumesFrom': '', 'ExposedPorts': port, "RestartPolicy": {"Name": "always"} } """Invork docker remote api to create container.""" resp = self.driver.create(name, kwargs) if resp.status_code == 201: """Update container status to ``created``""" uuid = resp.json()['Id'] self.db.update_container(id, uuid=uuid, status="created") """ Clone or Pull code before container start. This method contains the following two steps: 1. Create code and logs directory for each container. 2. Clone or Pull the specified code and update to the specified branch. """ self.db.update_container(id, uuid=uuid, status="init") short_uuid = uuid[:12] root_path = utils.create_root_path(user_id, short_uuid) log_path = utils.create_log_path(root_path) repo_name = os.path.basename(repos) if utils.repo_exist(root_path, repo_name): try: self.mercurial.pull(root_path, repos) except: raise else: try: self.mercurial.clone(root_path, repos) except: raise try: self.mercurial.update(root_path, repos, branch) except: raise www_path = ["/home/www", "/home/jm/www"] log_pathes = ["/home/jm/logs", "/home/logs"] kwargs = { 'Binds': ['%s:%s' % (root_path, www_path[0]), '%s:%s' % (root_path, www_path[1]), '%s:%s' % (log_path, log_pathes[0]), '%s:%s' % (log_path, log_pathes[1]), ], 'Dns': [CONF.dns], } """ Start container and update db status. """ status = self.driver.start(uuid, kwargs) if status == 204: """If start container succeed, inject fixed ip addr to container""" network = self.network.get_fixed_ip() """ Add db entry immediately to prevent this fixed ip be used again. """ self.db.add_network(dict(container_id=id, fixed_ip=network)) """Set fixed ip to container""" try: nwutils.set_fixed_ip(uuid, network) except: LOG.error("Set fixed ip %s to container %s failed" % (network, uuid)) """Cleanup db entry for ip reuse""" self.db.delete_network(id) raise """Update container's network""" self.db.update_container(id, fixed_ip=network) """Update container's status""" self.db.update_container(id, status="running") if status == 500: LOG.error("start container %s error" % uuid) self.db.update_container(id, status="error") if resp.status_code == 500: self.db.update_container(id, status='error') raise web.exc.HTTPInternalServerError() if resp.status_code == 404: LOG.error("no such image %s" % image_uuid) return if resp.status_code == 409: self.db.update_container(id, status='error') LOG.error("CONFLICT!!!") return LOG.info("CREATE -job create %s = OK" % id) def delete(self, id): """ Delete container according container id :params id: container id """ LOG.info("DELETE +job delete %s" % id) query = self.db.get_container(id) if query.status == 'running': self.db.update_container(id, status="stoping") status = self.driver.stop(query.uuid) if status in (204, 304, 404): self.db.update_container(id, status="deleting") status = self.driver.delete(query.uuid) if status in (204, 404): self.db.delete_container(id) if status == 500: LOG.error("I donot known what to do") return elif query.status == 'error': self.db.update_container(id, status="deleting") status = self.driver.delete(query.uuid) if status in (204, 404): self.db.delete_container(id) elif query.status == "stoped": status = self.driver.delete(query.uuid) if status in (204, 404): self.db.delete_container(id) else: self.db.update_container(id, status="deleting") self.db.delete_container(id) #try: # nwutils.delete_virtual_iface(query.uuid[:8]) #except: # LOG.warning("delete virtual interface error") # raise """Clean db entry for ip reuse.""" self.db.delete_network(id) LOG.info("DELETE -job delete %s" % id) def start(self, id): """ Start container by container `id` :params id: container id """ LOG.info("START +job start %s" % id) self.db.update_container(id, status="starting") query = self.db.get_container(id) uuid = query.uuid network = query.fixed_ip kwargs = {"Cmd": ["/usr/bin/supervisord"]} status = self.driver.start(uuid, kwargs) if status == 204: """If container start succeed, inject fixed_ip to container.""" try: nwutils.inject_fixed_ip(uuid, network) except: raise """Update container status to running.""" self.db.update_container(id, status="running") LOG.info("START -job start %s" % id) def stop(self, id): """ Stop container by container `id`. :params id: container id """ LOG.info("STOP +job stop %s" % id) query = self.db.get_container(id) if query.status == "stoped": return self.db.update_container(id, status="stoping") status = self.driver.stop(query.uuid) if status == 204: self.db.update_container(id, status="stoped") LOG.info("STOP -job stop %s" % id) def destroy(self, name): """ Destroy a temporary container by a given name. :params name: container name """ self.driver.stop(name) self.driver.delete(name) def refresh(self, id): """ Refresh code in container. :params id: container id """ LOG.info("REFRESH +job refresh %s" % id) query = self.db.get_container(id) """ If container not found, the `request` will be canceled. """ if not query: LOG.info("Container %s not found" % id) LOG.info("REFRESH -job refresh %s = CANCELED" % id) return #if query: uuid = query.uuid user_id = query.user_id repos = query.repos branch = query.branch try: self.driver.refresh(uuid=uuid, user_id=user_id, repos=repos, branch=branch, mercurial=self.mercurial) self.db.update_container(id, status="running") except: LOG.info("REFRESH -job refresh %s = ERR" % id) self.db.update_container(id, status="refresh-failed") raise LOG.info("REFRESH -job refresh %s = OK" % id) @periodic_task def check_instance_state(self): """ Check the container instance's state every one minute. If is down, update the container's stat to 'STOPED' in database entry. You can modified the check interval by using: @periodic_task(periodic_interval = N) Which will check the status every N seconds. """ LOG.info("Check instance state") @periodic_task def check_host_state(self): """ Touch the temstamp every one minite in the database entry. If over one minite the host didn't updated, the host will be thought to down. """ LOG.info("Check host state...Done") def check(self, **args): """Just for rpc check""" print args
class ContainerManager(base.Base, manager.Manager): def __init__(self): super(ContainerManager, self).__init__() self.driver = driver.API() self.mercurial = MercurialControl() self.network = network_manager.NetworkManager() self.version = '1.0.0' def service_init(self): """There will be three things doing here: 1. Register host in db. 2. Start containers on this node if necessary. 3. Create rpc producers and consumers. You must do these things before service start. """ return NotImplementedError() def create(self, id, name, image_id, image_uuid, repository, tag, repos, branch, app_type, app_env, ssh_key, fixed_ip, user_id): """Create new container and start it. There are three steps to do this: 1. Pull image from docker registry. 2. Create container use the specified image. 3. Start container. """ LOG.info("CREATE +job create %s" % id) """Pull Specified Imag From Docker Registry.""" LOG.info("pull image %s from registry..." % image_id) status = self.driver.pull_image(repository, tag) if status == 404: LOG.error("pull failed,no registry found!") self.db.update_container(id, status="error") return webob.exc.HTTPNotFound() if status == 500: LOG.error("pull failed,internal server error!") self.db.update_container(id, status="error") return webob.exc.HTTPInternalServerError() """Check if the image was pulled successful.""" resp = self.driver.inspect_image(image_uuid) if resp.status_code == 404: msg = "pull image failed!" LOG.error(msg) return webob.exc.HTTPNotFound(explanation=msg) LOG.info("pull image succeed!") """ Generate arguments for container creation. """ port = resp.json()['Config']['ExposedPorts'] kwargs = { 'Hostname': '', 'User': '', 'Memory': '', 'MemorySwap': '', 'AttachStdin': False, 'AttachStdout': False, 'AttachStderr': False, 'PortSpecs': [], 'Tty': True, 'OpenStdin': True, 'StdinOnce': False, 'Env': [ "REPO_PATH=%s" % repos, "BRANCH=%s" % branch, "APP_TYPE=%s" % app_type, "APP_ENV=%s" % app_env, "SSH_KEY=%s" % ssh_key ], 'Cmd': ["/opt/start.sh"], 'Dns': None, 'Image': image_uuid, 'Volumes': {}, 'VolumesFrom': '', 'ExposedPorts': port, "RestartPolicy": { "Name": "always" } } """Invork docker remote api to create container.""" resp = self.driver.create(name, kwargs) if resp.status_code == 201: """Update container status to ``created``""" uuid = resp.json()['Id'] self.db.update_container(id, uuid=uuid, status="created") """ Clone or Pull code before container start. This method contains the following two steps: 1. Create code and logs directory for each container. 2. Clone or Pull the specified code and update to the specified branch. """ self.db.update_container(id, uuid=uuid, status="init") short_uuid = uuid[:12] root_path = utils.create_root_path(user_id, short_uuid) log_path = utils.create_log_path(root_path) repo_name = os.path.basename(repos) if utils.repo_exist(root_path, repo_name): try: self.mercurial.pull(root_path, repos) except: raise else: try: self.mercurial.clone(root_path, repos) except: raise try: self.mercurial.update(root_path, repos, branch) except: raise www_path = ["/home/www", "/home/jm/www"] log_pathes = ["/home/jm/logs", "/home/logs"] kwargs = { 'Binds': [ '%s:%s' % (root_path, www_path[0]), '%s:%s' % (root_path, www_path[1]), '%s:%s' % (log_path, log_pathes[0]), '%s:%s' % (log_path, log_pathes[1]), ], 'Dns': [CONF.dns], } """ Start container and update db status. """ status = self.driver.start(uuid, kwargs) if status == 204: """If start container succeed, inject fixed ip addr to container""" network = self.network.get_fixed_ip() """ Add db entry immediately to prevent this fixed ip be used again. """ self.db.add_network(dict(container_id=id, fixed_ip=network)) """Set fixed ip to container""" try: nwutils.set_fixed_ip(uuid, network) except: LOG.error("Set fixed ip %s to container %s failed" % (network, uuid)) """Cleanup db entry for ip reuse""" self.db.delete_network(id) raise """Update container's network""" self.db.update_container(id, fixed_ip=network) """Update container's status""" self.db.update_container(id, status="running") if status == 500: LOG.error("start container %s error" % uuid) self.db.update_container(id, status="error") if resp.status_code == 500: self.db.update_container(id, status='error') raise web.exc.HTTPInternalServerError() if resp.status_code == 404: LOG.error("no such image %s" % image_uuid) return if resp.status_code == 409: self.db.update_container(id, status='error') LOG.error("CONFLICT!!!") return LOG.info("CREATE -job create %s = OK" % id) def delete(self, id): """ Delete container according container id :params id: container id """ LOG.info("DELETE +job delete %s" % id) query = self.db.get_container(id) if query.status == 'running': self.db.update_container(id, status="stoping") status = self.driver.stop(query.uuid) if status in (204, 304, 404): self.db.update_container(id, status="deleting") status = self.driver.delete(query.uuid) if status in (204, 404): self.db.delete_container(id) if status == 500: LOG.error("I donot known what to do") return elif query.status == 'error': self.db.update_container(id, status="deleting") status = self.driver.delete(query.uuid) if status in (204, 404): self.db.delete_container(id) elif query.status == "stoped": status = self.driver.delete(query.uuid) if status in (204, 404): self.db.delete_container(id) else: self.db.update_container(id, status="deleting") self.db.delete_container(id) #try: # nwutils.delete_virtual_iface(query.uuid[:8]) #except: # LOG.warning("delete virtual interface error") # raise """Clean db entry for ip reuse.""" self.db.delete_network(id) LOG.info("DELETE -job delete %s" % id) def start(self, id): """ Start container by container `id` :params id: container id """ LOG.info("START +job start %s" % id) self.db.update_container(id, status="starting") query = self.db.get_container(id) uuid = query.uuid network = query.fixed_ip kwargs = {"Cmd": ["/usr/bin/supervisord"]} status = self.driver.start(uuid, kwargs) if status == 204: """If container start succeed, inject fixed_ip to container.""" try: nwutils.inject_fixed_ip(uuid, network) except: raise """Update container status to running.""" self.db.update_container(id, status="running") LOG.info("START -job start %s" % id) def stop(self, id): """ Stop container by container `id`. :params id: container id """ LOG.info("STOP +job stop %s" % id) query = self.db.get_container(id) if query.status == "stoped": return self.db.update_container(id, status="stoping") status = self.driver.stop(query.uuid) if status == 204: self.db.update_container(id, status="stoped") LOG.info("STOP -job stop %s" % id) def destroy(self, name): """ Destroy a temporary container by a given name. :params name: container name """ self.driver.stop(name) self.driver.delete(name) def refresh(self, id): """ Refresh code in container. :params id: container id """ LOG.info("REFRESH +job refresh %s" % id) query = self.db.get_container(id) """ If container not found, the `request` will be canceled. """ if not query: LOG.info("Container %s not found" % id) LOG.info("REFRESH -job refresh %s = CANCELED" % id) return #if query: uuid = query.uuid user_id = query.user_id repos = query.repos branch = query.branch try: self.driver.refresh(uuid=uuid, user_id=user_id, repos=repos, branch=branch, mercurial=self.mercurial) self.db.update_container(id, status="running") except: LOG.info("REFRESH -job refresh %s = ERR" % id) self.db.update_container(id, status="refresh-failed") raise LOG.info("REFRESH -job refresh %s = OK" % id) @periodic_task def check_instance_state(self): """ Check the container instance's state every one minute. If is down, update the container's stat to 'STOPED' in database entry. You can modified the check interval by using: @periodic_task(periodic_interval = N) Which will check the status every N seconds. """ LOG.info("Check instance state") @periodic_task def check_host_state(self): """ Touch the temstamp every one minite in the database entry. If over one minite the host didn't updated, the host will be thought to down. """ LOG.info("Check host state...Done") def check(self, **args): """Just for rpc check""" print args
def __init__(self): super(Manager, self).__init__() self.driver = driver.API() self.mercurial = MercurialControl()
class Manager(base.Base): def __init__(self): super(Manager, self).__init__() self.driver = driver.API() self.mercurial = MercurialControl() def service_init(self): """Create rpc producer and customers here.""" return NotImplementedError() #def prepare_start(self, # user, # key, # repos, # branch): # """pull or clone code from repos repos and update to branch branch.""" # user_home=utils.make_user_home(user,key) # repo_name=os.path.basename(repos) # if utils.repo_exist(user_home,repo_name): # self.mercurial.pull(user,repos) # else: # self.mercurial.clone(user,repos) # self.mercurial.update(user,repos,branch) def create(self, id, name, desc, repos, branch, user_id): """create new image.""" LOG.info("BUILD +job build %s" % name) repo_name = os.path.basename(repos) #user_home = os.path.join("/home",user_id) user_home = os.path.join(os.path.expandvars('$HOME'), user_id) if not os.path.exists(user_home): os.mkdir(user_home) if utils.repo_exist(user_id, repo_name): try: self.mercurial.pull(user_home, repos) except: LOG.error("pull %s failed!" % repos) self.db.update_image(id, status="error") raise else: try: self.mercurial.clone(user_home, repos) except: LOG.error("clone %s failed!" % repos) self.db.update_image(id, status="error") raise self.mercurial.update(user_home, repos, branch) tar_path = utils.make_zip_tar(os.path.join(user_home, repo_name)) with open(tar_path, 'rb') as data: status = self.driver.build(name, data) if status == 404: LOG.error("request URL not Found!") LOG.info("BUILD -job build %s = ERR" % name) return if status == 200: LOG.info("BUILD -job build %s = OK" % name) """update db entry if successful build.""" status, json = self.driver.inspect(name) uuid = json.get('Id') self.db.update_image(id, uuid=uuid) """ tag image into repositories if successful build.""" LOG.info("TAG +job tag %s" % id) tag_status, tag = self.driver.tag(name) LOG.info("TAG -job tag %s" % id) if tag_status == 201: """push image into repositories if successful tag.""" LOG.info("PUSH +job push %s" % tag) push_status = self.driver.push(tag) if push_status == 200: LOG.info("PUSH -job push %s = OK" % tag) """update db entry if successful push.""" self.db.update_image(id, status="ok") else: self.db.update_image(id, status="error") LOG.info("PUSH -job push %s = ERR" % tag) if status == 500: self.db.update_image(id, status="error") LOG.error("image {} create failed!".format(name)) LOG.info("BUILD -job build %s = ERR" % name) def delete(self, id): LOG.info("DELETE +job delete %s" % id) image_instance = self.db.get_image(id) if image_instance: repository = image_instance.name tag = image_instance.tag self.db.update_image(id, status="deleting") status = self.driver.delete(repository, tag) if status in (200, 404): self.db.delete_image(id) if status in (409, 500): self.db.update_image(id, status=status) LOG.info("DELETE -job delete %s" % id) def edit(self, kwargs, host, name, port): """edit image online.""" resp = self.driver.create(name, kwargs) if resp.status_code == 201: container_uuid = resp.json()['Id'] resp = self.driver.start(host, port, container_uuid) if resp.status_code != 204: LOG.debug("start for-image-edit container failed") else: LOG.debug("create for-image-edit container failed") def destroy(self, name): """ destroy a temporary container by a given name. """ self.driver.destroy(name) def commit(self, image_id, repository, tag, container_id): """commit image for online edit.""" LOG.info("COMMIT +job commit %s" % container_id) resp = self.driver.commit(container_id, repository, tag) if resp.status_code == 201: """update image uuid.""" image_uuid = resp.json()['Id'] self.db.update_image(id=image_id, uuid=image_uuid) """commit ok,tag the image to repository.""" LOG.info("TAG +job tag image %s to repository" % image_id) status, new_repository = self.driver.tag(repository, tag) if status == 201: LOG.info("TAG -job tag image %s = OK" % image_id) LOG.info("PUSH +job push %s" % tag) push_status = self.driver.push(new_repository, tag) if push_status == 200: LOG.info("PUSH -job push %s = OK" % tag) self.db.update_image(id=image_id, status="ok") LOG.info("COMMIT -job commit %s = OK" % container_id) else: LOG.info("PUSH -job push %s = ERR" % tag) self.db.update_image(id=image_id, status="error") #self.driver.destroy(container_name) if resp.status_code == 404: image_uuid = resp.json()['Id'] self.db.update_image(id=image_id, uuid=image_uuid, status="error") LOG.info("COMMIT -job commit %s = ERR" % container_id)