def generate_by_python_source(function_info): service_dir = configs.docker_file_root_python + "/" + function_info.service_name + "/" docker_file_dir = service_dir + function_info.function_name + "/" clear_and_make_docker_dir(service_dir, docker_file_dir) # 将模板文件拷贝到指定目录 command = "cp {0}/template/python2.7/source/Dockerfile {1}".format(configs.project_root, docker_file_dir) common_util.execute_print_cmd(command) command = "cp {0}/template/python2.7/source/requirements.txt {1}".format(configs.project_root, docker_file_dir) common_util.execute_print_cmd(command) command = "cp {0}/template/python2.7/source/server.py.tmpl {1}".format(configs.project_root, docker_file_dir) common_util.execute_print_cmd(command) # 使用函数配置信息替换文件模板中的占位符 random_id = str(random.randint(10000, 99999)) docker_file_path = docker_file_dir + "Dockerfile" for line in fileinput.input(docker_file_path, inplace=1): line = line.replace("${MODULE_NAME}", function_info.file_name).replace("${RANDOM}", random_id) print line, fileinput.close() server_file_path = docker_file_dir + "server.py.tmpl" logger.info(server_file_path) for line in fileinput.input(server_file_path, inplace=1): line = line.replace("${MODULE_NAME}", function_info.file_name).replace("${METHOD_NAME}", function_info.method_name) print line, fileinput.close() # 将函数源代码生成文件,放入构建目录 source_file = open(docker_file_dir + function_info.file_name + ".py", "w+") source_file.write(function_info.source_code) source_file.close() return docker_file_dir
def do_GET(self): self.send_response(200) self.send_header('Content-type', 'application/json') self.end_headers() uri = str(self.path) param_map = {} # 从uri中提取参数 if self.path.find("?") > 0: question_index = self.path.index("?") uri = str(self.path[:question_index]) param_pairs = self.path[question_index + 1:].split("&") for param_pair in param_pairs: key = param_pair.split("=")[0] value = param_pair.split("=")[1] param_map[key] = value # 根据uri映射到对应的方法 result = None try: if uri == "/createFunction": function_id = param_map["functionId"] result = create_function(function_id) elif uri == "/executeFunction": function_id = param_map["functionId"] result = execute_function(function_id) elif uri == "/deleteFunction": function_id = param_map["functionId"] result = delete_function(function_id) elif uri == "/getExecuteLog": function_id = param_map["functionId"] result = get_execute_log(function_id) elif uri == "/executeK8sFunction": function_id = param_map["functionId"] result = execute_k8s_function(function_id) elif uri == "/getK8sExecuteLog": function_id = param_map["functionId"] result = get_k8s_execute_log(function_id) elif uri == "/getK8sOverview": type = param_map["type"] result = get_k8s_overview(type) elif uri == "/scaleDeployment": target_num = param_map["targetNum"] deployment_name = param_map["deploymentName"] result = scale_deployment(target_num, deployment_name) elif uri.find("/proxy") == 0: result = function_proxy(uri, param_map) elif uri.find("/k8sProxy") == 0: result = k8s_function_proxy(uri, param_map) except Exception as e: msg = traceback.format_exc() logger.error("Exception:" + msg) result = e.message logger.info("request:{0},response:{1}".format(self.path, result)) self.wfile.write(result)
def generate_by_python_zip(function_info): service_dir = configs.docker_file_root_python + "/" + function_info.service_name + "/" docker_file_dir = service_dir + function_info.function_name + "/" clear_and_make_docker_dir(service_dir, docker_file_dir) # 将模板文件拷贝到指定目录 command = "cp {0}/template/python2.7/zip/Dockerfile {1}".format(configs.project_root, docker_file_dir) common_util.execute_print_cmd(command) command = "cp {0}/template/python2.7/zip/requirements.txt {1}".format(configs.project_root, docker_file_dir) common_util.execute_print_cmd(command) command = "cp {0}/template/python2.7/zip/server.py.tmpl {1}".format(configs.project_root, docker_file_dir) common_util.execute_print_cmd(command) random_id = str(random.randint(10000, 99999)) upload_file_path = function_info.upload_file_path upload_file_name = upload_file_path.rsplit("/", 1)[1] upload_file_dir = upload_file_path.rsplit("/", 1)[0] # 将上传的文件解压后,复制到dockerfile目录 command = "mkdir {0}/{1}".format(upload_file_dir, random_id) common_util.execute_print_cmd(command) command = "cp {0} {1}/{2}".format(upload_file_path, upload_file_dir, random_id) common_util.execute_print_cmd(command) command = "cd {0}/{1} && unzip {2}".format(upload_file_dir, random_id, upload_file_name) common_util.execute_print_cmd(command) command = "rm -f {0}/{1}/{2}".format(upload_file_dir, random_id, upload_file_name) common_util.execute_print_cmd(command) command = "cp -r {0}/{1} {2}".format(upload_file_dir, random_id, docker_file_dir) common_util.execute_print_cmd(command) command = "rm -rf {0}/{1}".format(upload_file_dir, random_id) common_util.execute_print_cmd(command) # 使用函数配置信息替换文件模板中的占位符 docker_file_path = docker_file_dir + "Dockerfile" for line in fileinput.input(docker_file_path, inplace=1): line = line.replace("${MODULE_NAME}", function_info.file_name).replace("${RANDOM}", random_id) print line, fileinput.close() server_file_path = docker_file_dir + "server.py.tmpl" logger.info(server_file_path) for line in fileinput.input(server_file_path, inplace=1): line = line.replace("${MODULE_NAME}", function_info.file_name).replace("${METHOD_NAME}", function_info.method_name) print line, fileinput.close() # 将函数源代码生成文件,放入构建目录 source_file = open(docker_file_dir + function_info.file_name + ".py", "w+") source_file.write(function_info.source_code) source_file.close() return docker_file_dir
def get_pod_log(function_info): k8s_service_name = get_k8s_service_name(function_info) pod_names = get_pod_names(k8s_service_name) result = "" for pod_name in pod_names: pod_name = pod_name.replace("\n", "") cmd = 'kubectl logs {0} -n {1} --tail 20'.format( pod_name, configs.k8s_namespace) logger.info(cmd) lines = os.popen(cmd, "r").readlines() result += "=" * 10 + pod_name.replace("\n", "") + "=" * 10 + "\n" for line in lines: result += line result += "\n" return result
def run_container(function_info): container_name = get_container_name(function_info) newest_image_name = common_util.get_image_name_with_version(function_info) # 查询docker容器是否存在 try: container = client.containers.get(container_name) running_image_tags = container.image.tags # 判断当前容器的镜像是否为最新版本 if newest_image_name not in running_image_tags: logger.info("container is old version, stop and run new container") client.api.remove_container(container_name, force=True) container = client.containers.run(newest_image_name, name=container_name, publish_all_ports=True, detach=True) logger.info("new container running,container_id:" + container.id) else: # 如果没有运行,则运行 if container.status == 'running': logger.info("container is already running,container_id:" + container.id) else: logger.info("starting container,container_id:" + container.id) container.start() logger.info("container started,container_id:" + container.id) except docker.errors.NotFound: logger.info("container not found,run new container") container = client.containers.run(newest_image_name, name=container_name, publish_all_ports=True, detach=True) logger.info("new container running,container_id:" + container.id) # 获取容器映射的端口号 port = get_run_port(container_name) if port != '0': return 'http://{0}:{1}'.format(configs.mini_fc_host, port) else: return '函数运行失败,请查看日志'
def remove_image(function_info): container_name = get_container_name(function_info) try: container = client.containers.get(container_name) if container: logger.info("removing container,container_name:" + container_name) client.api.remove_container(container_name, force=True) logger.info("container remove success,container_name:" + container_name) except: pass image_name = common_util.get_image_name(function_info) try: image = client.images.get(image_name) if image: logger.info("removing image,image_name:" + image_name) client.images.remove(image=image_name, force=True) logger.info("image remove success,image_name:" + image_name) except: pass try: image_name = configs.docker_registry + "/" + image_name image = client.images.get(image_name) if image: logger.info("removing image,image_name:" + image_name) client.images.remove(image=image_name, force=True) logger.info("image remove success,image_name:" + image_name) except: pass cmd = "docker images | grep -E '.*{0}\s+v.*' | awk '{1}' | xargs docker rmi -f".format( image_name, "{print $3}") common_util.execute_print_cmd(cmd) return "ok"
def build_image(function_info): # 创建Dockerfile的目录 docker_file_dir = file_tool.generate_docker_file(function_info) # 构建docker镜像 image_name = common_util.get_image_name(function_info) logger.info("building image,image_name:" + image_name) client.images.build(tag=image_name, path=docker_file_dir) logger.info("image build success,image_name:" + image_name) # 添加标签 tag = "v" + function_info.function_version logger.info("tagging image,image_name:{0},tag:{1}".format(image_name, tag)) client.api.tag(image_name, image_name, tag) client.api.tag(image_name, configs.docker_registry + "/" + image_name, tag) logger.info("image tag success,image_name:{0},tag:{1}".format( image_name, tag)) # 推送到仓库 logger.info("pushing image,image_name:{0},tag:{1}".format(image_name, tag)) client.images.push(configs.docker_registry + "/" + image_name, tag) logger.info("image push success,image_name:{0},tag:{1}".format( image_name, tag)) return "ok"
elif uri == "/getK8sOverview": type = param_map["type"] result = get_k8s_overview(type) elif uri == "/scaleDeployment": target_num = param_map["targetNum"] deployment_name = param_map["deploymentName"] result = scale_deployment(target_num, deployment_name) elif uri.find("/proxy") == 0: result = function_proxy(uri, param_map) elif uri.find("/k8sProxy") == 0: result = k8s_function_proxy(uri, param_map) except Exception as e: msg = traceback.format_exc() logger.error("Exception:" + msg) result = e.message logger.info("request:{0},response:{1}".format(self.path, result)) self.wfile.write(result) class MultiThreadedHTTPServer(ThreadingMixIn, HTTPServer): pass if __name__ == '__main__': ip = '0.0.0.0' port = int(configs.mini_fc_ops_port) server = MultiThreadedHTTPServer((ip, port), OpsApiHandler) logger.info("Starting server, use <Ctrl-C> to stop.ip:" + ip + ",port:" + str(port)) server.serve_forever()
def get_pod_names(k8s_service_name): cmd = 'kubectl get po -o=custom-columns=NAME:.metadata.name -n {0} | grep {1}-'.format( configs.k8s_namespace, k8s_service_name) logger.info(cmd) return os.popen(cmd, "r").readlines()