Ejemplo n.º 1
0
 def __init__(self, job, *args, **kwargs):
     self.job = job
     self.configs = kwargs.get("config")
     self.region_api = RegionAPI(conf=self.configs['region'])
     self.oss_api = OssAPI(conf=self.configs['oss']['ali_shanghai'])
     self.locker = TaskLocker(conf=self.configs['etcd'])
     self.user_cs_client = UserConsoleAPI(conf=self.configs['userconsole'])
     self.api = ACPAPI(conf=self.configs['region'])
     self.region_client = RegionBackAPI()
     self.slug_configs = self.configs["publish"]["slug"]
     self.is_region_slug = self.slug_configs.get('all_region_ftp')
     self.is_oss_ftp = self.slug_configs.get('oss_ftp')
     # 用户文件存储路径
     self.SRV_SLUG_BASE_DIR = self.slug_configs.get(
         'slug_path') + '{tenantId}/slug/{serviceId}/{deployVersion}.tgz'
     # 数据中心slug存储路径
     self.SLUG_PATH = self.slug_configs.get(
         'curr_region_dir') + '{serviceKey}/{appVersion}.tgz'
     self.CURR_REGION_PATH = self.slug_configs.get(
         'curr_region_path') + self.SLUG_PATH
     # 区域中心slug的ftp配置
     self.ALL_REGION_FTP_HOST = self.slug_configs.get('all_region_ftp_host')
     self.ALL_REGION_FTP_PORT = self.slug_configs.get('all_region_ftp_port')
     self.ALL_REGION_FTP_USERNAME = self.slug_configs.get(
         'all_region_username')
     self.ALL_REGION_FTP_PASSWORD = self.slug_configs.get(
         'all_region_password')
     self.ALL_REGION_FTP_NAMESPACE = self.slug_configs.get(
         'all_region_namespace')
     self.ALL_REGION_FTP_PATH = self.ALL_REGION_FTP_NAMESPACE + '{serviceKey}/{appVersion}.tgz'
     # oss存储路径
     CLOUD_ASSISTANT = self.configs.get('CLOUD_ASSISTANT')
     self.OSS_BUCKET = self.slug_configs.get('oss_bucket', "")
     self.OSS_OBJECT_NAME = CLOUD_ASSISTANT + '/{serviceKey}/{appVersion}.tgz'
     logger.debug("mq_work.app_slug", 'init app slug')
Ejemplo n.º 2
0
 def __init__(self, job, *args, **kwargs):
     self.job = job
     self.configs = kwargs.get("config")
     self.region_api = RegionAPI(conf=self.configs['region'])
     image_config = self.configs["publish"]["image"]
     self.region_client = RegionBackAPI()
     self.region_registry = RegistryAPI(
         host=image_config.get('curr_registry'))
     # self.region_registry.set_log_topic('mq_work.image_manual')
     self.oss_registry = RegistryAPI(host=image_config.get('all_registry'))
     self.oss_registry.set_log_topic('mq_work.image_manual')
     self.locker = TaskLocker(conf=self.configs['etcd'])
     self.api = ACPAPI(conf=self.configs['region'])
     self.namespace = image_config.get('oss_namespace')
     self.user_cs_client = UserConsoleAPI(conf=self.configs['userconsole'])
Ejemplo n.º 3
0
 def __init__(self, job, *args, **kwargs):
     self.job = job
     self.configs = kwargs.get("config")
     self.region_api = RegionAPI(conf=self.configs['region'])
     image_config = self.configs["publish"]["image"]
     self.region_client = RegionBackAPI()
     self.region_registry = RegistryAPI(
         host=image_config.get('curr_registry'))
     # self.region_registry.set_log_topic('mq_work.image_manual')
     self.oss_registry = RegistryAPI(host=image_config.get('all_registry'))
     self.oss_registry.set_log_topic('mq_work.image_manual')
     self.locker = TaskLocker(conf=self.configs['etcd'])
     self.api = ACPAPI(conf=self.configs['region'])
     self.namespace = image_config.get('oss_namespace')
     self.user_cs_client = UserConsoleAPI(conf=self.configs['userconsole'])
Ejemplo n.º 4
0
 def __init__(self, job, *args, **kwargs):
     self.job = job
     self.configs = kwargs.get("config")
     self.region_api = RegionAPI(conf=self.configs["region"])
     self.region_client = RegionBackAPI()
     self.api = ACPAPI(conf=self.configs['region'])
     image_config = self.configs["publish"]["image"]
     self.region_registry = RegistryAPI(
         host=image_config.get('curr_registry'))
     self.oss_registry = RegistryAPI(host=image_config.get('all_registry'))
     self.region_registry.set_log_topic('mq_work.app_image')
     self.oss_registry.set_log_topic('mq_work.app_image')
     self.locker = TaskLocker(conf=self.configs['etcd'])
     self.namespace = image_config.get('oss_namespace')
     self.user_cs_client = UserConsoleAPI(conf=self.configs["userconsole"])
     self.hubclient = HubUtils(image_config)
     # 是否配置oss.goodrain.me
     self.is_region_image = image_config.get('all_region_image')
     self.is_oss_image = image_config.get('oss_image')
Ejemplo n.º 5
0
    def __init__(self, task, *args, **kwargs):
        self.configs = kwargs.get("config")
        self.region_api = RegionAPI(conf=self.configs['region'])
        self.api = ACPAPI(conf=self.configs['region'])
        self.user_cs_client = UserConsoleAPI(conf=self.configs['userconsole'])
        self.repo_url = task['repo_url']
        self.region_client = RegionBackAPI()
        self.tenant_id = task['tenant_id']
        self.service_id = task['service_id']
        self.tenant_name = task['tenant_name']
        self.service_alias = task['service_alias']
        self.deploy_version = task['deploy_version']
        self.action = task['action']

        if 'event_id' in task:
            self.event_id = task["event_id"]
            self.log = EventLog().bind(event_id=self.event_id)
        else:
            self.event_id = ""
            self.log = EventLog().bind(event_id=self.event_id)

        self.operator = task['operator']
        self.build_envs = task.get('envs', {})
        self.expire = task.get('expire', 60)

        self.start_time = int(time.time())

        # self.source_dir = '/tmp/goodrain_web'
        self.source_dir = SOURCE_DIR.format(tenantId=self.tenant_id,
                                            serviceId=self.service_id)
        self.cache_dir = CACHE_DIR.format(tenantId=self.tenant_id,
                                          serviceId=self.service_id)
        self.tgz_dir = TGZ_DIR.format(tenantId=self.tenant_id,
                                      serviceId=self.service_id)
        self.build_log_dir = BUILD_LOG_DIR.format(tenantId=self.tenant_id,
                                                  serviceId=self.service_id)

        self.build_cmd = 'plugins/scripts/build.pl'
Ejemplo n.º 6
0
class ImageManual():
    def __init__(self, job, *args, **kwargs):
        self.job = job
        self.configs = kwargs.get("config")
        self.region_api = RegionAPI(conf=self.configs['region'])
        image_config = self.configs["publish"]["image"]
        self.region_client = RegionBackAPI()
        self.region_registry = RegistryAPI(
            host=image_config.get('curr_registry'))
        # self.region_registry.set_log_topic('mq_work.image_manual')
        self.oss_registry = RegistryAPI(host=image_config.get('all_registry'))
        self.oss_registry.set_log_topic('mq_work.image_manual')
        self.locker = TaskLocker(conf=self.configs['etcd'])
        self.api = ACPAPI(conf=self.configs['region'])
        self.namespace = image_config.get('oss_namespace')
        self.user_cs_client = UserConsoleAPI(conf=self.configs['userconsole'])

    def do_work(self):
        try:
            task = json.loads(self.job.body)
            self.task = task
            if "event_id" in self.task:
                self.event_id = task["event_id"]
                self.log = EventLog().bind(event_id=self.event_id,
                                           step="image_manual")
            else:
                self.event_id = ""
                self.log = EventLog().bind(event_id="", step="image_manual")
            logger.info("mq_work.image_manual",
                        "new image_manual task: {}".format(task))
            if task['action'] == 'create_new_version':
                self.log.info("开始升级应用。")
                self.create_new_version()
            elif task['action'] == 'download_and_deploy':
                self.log.info("开始下载镜像并部署应用。")
                self.download_and_deploy()
            elif task['action'] == 'delete_old_version':
                self.log.info("开始删除旧版本。")
                self.delete_old_version()
        except Exception as e:
            if self.log:
                self.log.error("从自定义镜像部署应用失败。{}".format(e.message),
                               step="callback",
                               status="failure")
            logger.exception('mq_work.image_manual', e)

    def create_new_version(self):
        logger.debug("mq_work.image_manual",
                     "now create new version and upload image")

    def delete_old_version(self):
        logger.debug("mq_work.image_manual", "now delete old version")

    def download_and_deploy(self):
        image = self.task['image']
        # namespace = self.task['namespace']
        tenant_name = self.task['tenant_name']
        service_alias = self.task['service_alias']
        event_id = self.task['event_id']
        service_alias = self.task.get("service_alias", None)
        has_download = False
        inner_image = self.oss_registry.rename_image(image)
        inner_image = "{0}_{1}".format(inner_image, service_alias)
        local_image = self.region_registry.rename_image(image)
        local_image = "{0}_{1}".format(local_image, service_alias)
        # 直接下载docker image
        try:
            self.log.info("开始下载镜像:{0}".format(image))
            pull_result = self._pull(image)
            if pull_result:
                # image_id = self.get_image_property(image, 'Id')
                self._tag(image, local_image)
                self.log.info("修改镜像名为:{0}".format(local_image))
                ok = self._push(local_image)
                if not ok:
                    self.log.error("上传镜像发生错误,重试失败,退出。",
                                   step="callback",
                                   status="failure")
                    return
                self.log.info("镜像推送到本地仓库完成。")
                # self._tag(image, inner_image)
                # self._push(inner_image)
                has_download = True
            else:
                self.log.error("下载镜像发生错误。", step="callback", status="failure")
                logger.error("mq_work.image_manual",
                             "download image failed! image:{}".format(image))

        except Exception as e:
            self.log.error("镜像操作发生错误。{0}".format(e.__str__()),
                           step="callback",
                           status="failure")
            logger.exception("mq_work.image_manual", e)
        version_status = {
            "final_status": "failure",
        }
        if has_download:
            self.log.info("应用同步完成。", step="app-image", status="success")
            version_body = {
                "type": 'image',
                "path": local_image,
                "event_id": self.event_id
            }
            version_status['final_status'] = "success"
            try:
                self.region_client.update_version_region(
                    json.dumps(version_body))
                self.region_client.update_version_event(
                    self.event_id, json.dumps(version_status))
            except Exception as e:
                pass
            try:
                self.api.update_iamge(tenant_name, service_alias, local_image)
                self.log.info("应用信息更新完成,开始启动应用。",
                              step="app-image",
                              status="success")
                self.api.start_service(tenant_name, service_alias, event_id)
            except Exception as e:
                logger.exception(e)
                self.log.error("应用自动启动失败。请手动启动",
                               step="callback",
                               status="failure")
        else:
            try:
                self.region_client.update_version_event(
                    self.event_id, json.dumps(version_status))
            except Exception as e:
                pass
            self.log.error("应用同步失败。", step="callback", status="failure")

    def queryServiceStatus(self, service_id):
        try:
            res, body = self.region_api.is_service_running(service_id)
            logger.info(
                'mq_work.image_manual',
                "service_id=" + service_id + ";body=" + json.dumps(body))
            status = body.get(service_id, "closed")
            if status == "running":
                self.log.debug("依赖的应用状态已经为运行中。", step="worker")
                return True
        except:
            pass
        self.log.debug("依赖的应用状态不是运行中,本应用稍后启动。", step="worker")
        return False

    def get_image_property(self, image, name):
        query_format = '{{.%s}}' % name
        try:
            output = shell.call("{2} inspect -f '{0}' {1}".format(
                query_format, image, DOCKER_BIN))
            if output == '<no value>':
                return None
            else:
                return output[0].rstrip('\n')
        except shell.ExecException, e:
            logger.exception("mq_work.image_manual", e)
            return None
Ejemplo n.º 7
0
class AppSlug():
    def __init__(self, job, *args, **kwargs):
        self.job = job
        self.configs = kwargs.get("config")
        self.region_api = RegionAPI(conf=self.configs['region'])
        self.oss_api = OssAPI(conf=self.configs['oss']['ali_shanghai'])
        self.locker = TaskLocker(conf=self.configs['etcd'])
        self.user_cs_client = UserConsoleAPI(conf=self.configs['userconsole'])
        self.api = ACPAPI(conf=self.configs['region'])
        self.region_client = RegionBackAPI()
        self.slug_configs = self.configs["publish"]["slug"]
        self.is_region_slug = self.slug_configs.get('all_region_ftp')
        self.is_oss_ftp = self.slug_configs.get('oss_ftp')
        # 用户文件存储路径
        self.SRV_SLUG_BASE_DIR = self.slug_configs.get(
            'slug_path') + '{tenantId}/slug/{serviceId}/{deployVersion}.tgz'
        # 数据中心slug存储路径
        self.SLUG_PATH = self.slug_configs.get(
            'curr_region_dir') + '{serviceKey}/{appVersion}.tgz'
        self.CURR_REGION_PATH = self.slug_configs.get(
            'curr_region_path') + self.SLUG_PATH
        # 区域中心slug的ftp配置
        self.ALL_REGION_FTP_HOST = self.slug_configs.get('all_region_ftp_host')
        self.ALL_REGION_FTP_PORT = self.slug_configs.get('all_region_ftp_port')
        self.ALL_REGION_FTP_USERNAME = self.slug_configs.get(
            'all_region_username')
        self.ALL_REGION_FTP_PASSWORD = self.slug_configs.get(
            'all_region_password')
        self.ALL_REGION_FTP_NAMESPACE = self.slug_configs.get(
            'all_region_namespace')
        self.ALL_REGION_FTP_PATH = self.ALL_REGION_FTP_NAMESPACE + '{serviceKey}/{appVersion}.tgz'
        # oss存储路径
        CLOUD_ASSISTANT = self.configs.get('CLOUD_ASSISTANT')
        self.OSS_BUCKET = self.slug_configs.get('oss_bucket', "")
        self.OSS_OBJECT_NAME = CLOUD_ASSISTANT + '/{serviceKey}/{appVersion}.tgz'
        logger.debug("mq_work.app_slug", 'init app slug')

    def do_work(self):
        try:
            logger.debug("mq_work.app_slug",
                         'get task....{}'.format(self.job.body))
            task = json.loads(self.job.body)
            self.task = task
            if "event_id" in self.task:
                self.event_id = task["event_id"]
                self.log = EventLog().bind(event_id=self.event_id,
                                           step="image_manual")
            else:
                self.event_id = ""
                self.log = EventLog().bind(event_id="", step="image_manual")
            if task['action'] == 'create_new_version':
                self.log.info("开始分享新版本应用。")
                self.create_new_version()
            elif task['action'] == 'download_and_deploy':
                self.log.info("开始同步应用。")
                self.download_and_deploy()
            elif task['action'] == 'delete_old_version':
                self.log.info("开始删除旧版本应用。")
                self.delete_old_version()
        except Exception as e:
            logger.exception('mq_work.app_slug', e)

    def _upload_ftp(self, service_key, app_version, md5file):
        """ 上传文件到ftp """
        utils = FTPUtils(host=self.ALL_REGION_FTP_HOST,
                         username=self.ALL_REGION_FTP_USERNAME,
                         password=self.ALL_REGION_FTP_PASSWORD,
                         namespace=self.ALL_REGION_FTP_NAMESPACE,
                         port=self.ALL_REGION_FTP_PORT)
        # 检查service_key对应的文件是否存在,不存在生成
        service_dir = self.ALL_REGION_FTP_NAMESPACE + service_key
        logger.debug("mq_work.app_slug",
                     '*******upload dir is {}'.format(service_dir))
        utils.check_dir(service_dir)
        # 上传文件
        curr_region_slug = self.CURR_REGION_PATH.format(serviceKey=service_key,
                                                        appVersion=app_version)
        logger.debug("mq_work.app_slug",
                     '*******upload file path is {}'.format(curr_region_slug))
        utils.upload(service_dir, curr_region_slug)
        # 上传md5文件
        if md5file:
            utils.upload(service_dir, md5file)
        return True

    def _create_md5(self, md5string, dest_slug_file):
        try:
            md5file = dest_slug_file + ".md5"
            f = open(md5file, "w")
            f.write(md5string)
            f.close()
            return md5file
        except Exception as e:
            logger.error("mq_work.app_slug", "sum file md5 filed!")
            logger.exception("mq_work.app_slug", e)
        return None

    def _check_md5(self, md5string, md5file):
        try:
            f = open(md5file)
            new_md5 = f.readline()
            return md5string == new_md5
        except Exception as e:
            logger.error("mq_work.app_slug", "check md5 filed!")
            logger.exception("mq_work.app_slug", e)
        return False

    def create_new_version(self):
        service_key = self.task['service_key']
        app_version = self.task['app_version']
        service_id = self.task['service_id']
        deploy_version = self.task['deploy_version']
        tenant_id = self.task['tenant_id']
        dest = self.task['dest']
        share_id = self.task.get('share_id', None)

        # 检查数据中心下路径是否存在
        source_slug_file = self.SRV_SLUG_BASE_DIR.format(
            tenantId=tenant_id,
            serviceId=service_id,
            deployVersion=deploy_version)
        self.log.debug("数据中心文件路径{0}".format(source_slug_file))
        # 当前数据中心文件名称
        dest_slug_file = self.CURR_REGION_PATH.format(serviceKey=service_key,
                                                      appVersion=app_version)
        self.log.debug('当前数据中心文件名称'.format(dest_slug_file))
        # 检查目录是否存在
        curr_region_dir = os.path.dirname(dest_slug_file)
        if not os.path.exists(curr_region_dir):
            os.makedirs(curr_region_dir)
        # 复制文件
        self.log.debug("开始复制文件 file {0} to {1}".format(source_slug_file,
                                                       dest_slug_file))
        shutil.copyfile(source_slug_file, dest_slug_file)
        # 计算md5
        md5string = get_md5(source_slug_file)
        # 生成md5file
        md5file = self._create_md5(md5string, dest_slug_file)
        if md5file is None:
            self.log.error("md5文件没有生成。")
        # 区域中心对象存储,使用ftp
        slug = self.SLUG_PATH.format(serviceKey=service_key,
                                     appVersion=app_version)
        if dest == "yb":
            data = {
                'service_key': service_key,
                'app_version': app_version,
                'slug': slug,
                'image': "",
                'dest_yb': True,
                'dest_ys': False,
            }
            if share_id is not None:
                data['share_id'] = share_id
            self.region_client.service_publish_new_region(data)
            if self.is_region_slug:
                try:
                    self.log.info("开始上传应用到本地云帮")
                    self._upload_ftp(service_key, app_version, md5file)
                    logger.debug("mq_work.app_slug",
                                 "*******ftp upload success!")
                    # self.update_publish_event(event_id=event_id, status='end', desc=u"云帮应用本地发布完毕")

                    self.user_cs_client.service_publish_success(
                        json.dumps(data))
                    try:
                        self.region_client.service_publish_success_region(data)
                    except Exception as e:
                        self.region_client.service_publish_failure_region(data)
                        logger.exception(e)
                        pass

                    self.log.info("云帮应用本地发布完毕", step="last", status="success")
                except Exception as e:
                    logger.error("mq_work.app_slug",
                                 "*******ftp upload failed")
                    logger.exception("mq_work.app_slug", e)
                    self.region_client.service_publish_failure_region(data)
                    self.log.info("云帮应用本地发布失败。{}".format(e.message),
                                  step="callback",
                                  status="failure")
            else:

                self.user_cs_client.service_publish_success(json.dumps(data))
                try:
                    self.region_client.service_publish_success_region(data)
                except Exception as e:
                    self.region_client.service_publish_failure_region(data)
                    logger.exception(e)
                    pass

                self.log.info("云帮应用本地发布完毕", step="last", status="success")
        elif dest == "ys":
            data = {
                'service_key': service_key,
                'app_version': app_version,
                'slug': slug,
                'image': "",
                'dest_ys': True,
                'dest_yb': False
            }
            if share_id is not None:
                data['share_id'] = share_id
            self.region_client.service_publish_new_region(data)
            if self.is_oss_ftp:
                try:
                    self.log.info("开始上传应用到云市")
                    self._upload_ftp(service_key, app_version, md5file)
                    logger.debug("mq_work.app_slug",
                                 "*******ftp upload success!")
                    self.log.info("云市应用发布完毕", step="last", status="success")

                    self.user_cs_client.service_publish_success(
                        json.dumps(data))
                    try:
                        self.region_client.service_publish_success_region(data)
                    except Exception as e:
                        logger.exception(e)
                        self.region_client.service_publish_failure_region(data)
                        pass

                except Exception as e:
                    logger.error("mq_work.app_slug",
                                 "*******ftp upload failed, {0}".format(e))
                    self.region_client.service_publish_failure_region(data)
                    self.log.error("云市应用发布失败.",
                                   status="failure",
                                   step="callback")
            else:
                self.user_cs_client.service_publish_success(json.dumps(data))
                try:
                    self.region_client.service_publish_success_region(data)
                except Exception as e:
                    logger.exception(e)
                    self.region_client.service_publish_failure_region(data)
                    pass

                self.log.info("云市应用发布完毕", step="last", status="success")

    def _download_ftp(self, service_key, app_version, namespace, is_md5=False):
        """ 云帮ftp下载文件 """
        utils = FTPUtils(host=self.ALL_REGION_FTP_HOST,
                         username=self.ALL_REGION_FTP_USERNAME,
                         password=self.ALL_REGION_FTP_PASSWORD,
                         namespace=self.ALL_REGION_FTP_NAMESPACE,
                         port=self.ALL_REGION_FTP_PORT)
        logger.info("mq_work.app_slug",
                    "*******[download]download file from ftp")
        # 检查service_key对应的文件是否存在,不存在生成
        remote_file = self.ALL_REGION_FTP_PATH.format(serviceKey=service_key,
                                                      appVersion=app_version)
        if is_md5:
            remote_file += ".md5"
        if not namespace:
            logger.info("mq_work.app_slug",
                        "*******[download]namespace is null")
            logger.error("mq_work.app_slug",
                         "*******[download]namespace is null")
        else:
            logger.info("mq_work.app_slug",
                        "*******[download]namespace is {}".format(namespace))
            remote_file = "../" + namespace + "/" + remote_file
        logger.info("mq_work.app_slug",
                    "*******[download]remote file is {}".format(remote_file))
        curr_region_slug = self.CURR_REGION_PATH.format(serviceKey=service_key,
                                                        appVersion=app_version)
        if is_md5:
            curr_region_slug += ".md5"
        logger.info(
            "mq_work.app_slug",
            "*******[download]curr_region_slug is {}".format(curr_region_slug))
        return utils.download(remote_file, curr_region_slug)

    def _download_ftp_market(self,
                             service_key,
                             app_version,
                             namespace,
                             is_md5=False):
        """ 云市ftp下载文件 """
        utils = FTPUtils(host=self.ALL_REGION_FTP_HOST,
                         username=self.ALL_REGION_FTP_USERNAME,
                         password=self.ALL_REGION_FTP_PASSWORD,
                         namespace=self.ALL_REGION_FTP_NAMESPACE,
                         port=self.ALL_REGION_FTP_PORT)
        logger.info("mq_work.app_slug",
                    "*******[download]download file from ftp")
        # 检查service_key对应的文件是否存在,不存在生成
        remote_file = self.ALL_REGION_FTP_PATH.format(serviceKey=service_key,
                                                      appVersion=app_version)
        if is_md5:
            remote_file += ".md5"
        if not namespace:
            logger.info("mq_work.app_slug",
                        "*******[download]namespace is null")
            logger.error("mq_work.app_slug",
                         "*******[download]namespace is null")
        else:
            logger.info("mq_work.app_slug",
                        "*******[download]namespace is {}".format(namespace))
            remote_file = "../" + namespace + "/" + remote_file
        logger.info("mq_work.app_slug",
                    "*******[download]remote file is {}".format(remote_file))
        curr_region_slug = self.CURR_REGION_PATH.format(serviceKey=service_key,
                                                        appVersion=app_version)
        if is_md5:
            curr_region_slug += ".md5"
        logger.info(
            "mq_work.app_slug",
            "*******[download]curr_region_slug is {}".format(curr_region_slug))
        return utils.download(remote_file, curr_region_slug)

    def download_and_deploy(self):
        """ 下载slug包 """
        def start_service(service_id, deploy_version, operator):
            body = {
                "deploy_version": deploy_version,
                "operator": operator,
                "event_id": self.event_id
            }
            try:
                # logger.info("mq_work.app_slug", "start service {}:{}".format(service_id, deploy_version))
                self.log.info("开始调用api启动应用。")
                self.region_api.start_service(service_id, json.dumps(body))
            except self.region_api.CallApiError, e:
                self.log.info("开始调用api启动应用失败。{}".format(e.message),
                              step="callback",
                              status="failure")
                logger.exception("mq_work.app_slug", e)

        service_key = self.task['app_key']
        namespace = self.task['namespace']
        app_version = self.task['app_version']
        tenant_name = self.task['tenant_name']
        service_alias = self.task['service_alias']
        event_id = self.task['event_id']

        # 检查数据中心的是否存在slug包
        dest_slug_file = self.CURR_REGION_PATH.format(serviceKey=service_key,
                                                      appVersion=app_version)
        logger.info("mq_work.app_slug",
                    "dest_slug_file:{}".format(dest_slug_file))
        ftp_ok = False
        try:
            # 检查当前服务器是否有slug文件
            if os.path.exists(dest_slug_file):
                self.log.debug("当前服务器存在本应用。本机同步开始")
                md5string = get_md5(dest_slug_file)
                # 检查云帮ftp是否打开, 下载md5进行校验
                md5_ok = False
                if self.is_region_slug:
                    self.log.debug("文件MD5校验开始。")
                    try:
                        md5_ok = self._download_ftp(service_key, app_version,
                                                    namespace, True)
                        self.log.info("MD5校验完成。")
                    except Exception as e:
                        logger.info(
                            "mq_work.app_slug",
                            "download md5 file from cloudassistant ftp failed!"
                        )
                        self.log.error("MD5校验失败。{}".format(e.message),
                                       step="callback",
                                       status="failure")
                        logger.exception("mq_work.app_slug", e)
                # md5未下载并且云市ftp开启
                if not md5_ok and self.is_oss_ftp:
                    self.log.info("MD5校验不通过。开始从云市同步新版本。")
                    try:
                        md5_ok = self._download_ftp_market(
                            service_key, app_version, namespace, True)
                    except Exception as e:
                        self.log.info("从云市同步新版本发生异常。{}".format(e.message),
                                      step="callback",
                                      status="failure")
                        logger.exception("mq_work.app_slug", e)
                if md5_ok:
                    md5file = dest_slug_file + ".md5"
                    same_file = self._check_md5(md5string, md5file)
                    if same_file:
                        logger.debug("mq_work.app_slug", "md5 check same.")
                        ftp_ok = True
                    else:
                        logger.debug(
                            "mq_work.app_slug",
                            "file md5 is changed, now delete old file")
                        os.remove(dest_slug_file)
                else:
                    logger.debug("mq_work.app_slug",
                                 "md5file download failed, now delete slug")
                    os.remove(dest_slug_file)

            # 检查当前服务器是否有slug文件
            if not os.path.exists(dest_slug_file):
                curr_region_dir = os.path.dirname(dest_slug_file)
                if not os.path.exists(curr_region_dir):
                    os.makedirs(curr_region_dir)
                logger.debug("mq_work.app_slug",
                             "now check ftp:".format(self.is_region_slug))
                # 云帮ftp开关是否打开
                if self.is_region_slug:
                    logger.debug('mq_work.app_slug', 'now check file on ftp!')
                    try:
                        ftp_ok = self._download_ftp(service_key, app_version,
                                                    namespace)
                    except Exception as e:
                        logger.info("mq_work.app_slug",
                                    "download object failed")
                        logger.exception("mq_work.app_slug", e)
                    logger.debug(
                        "mq_work.app_slug",
                        "*******[ftp download slug]result:==={}".format(
                            ftp_ok))

                # 判断是否需要从云市上下载,未下载并且云市ftp开启
                if not ftp_ok and self.is_oss_ftp:
                    logger.info(
                        "mq_work.app_slug",
                        "now download from hub ftp:{}".format(dest_slug_file))
                    ftp_ok = self._download_ftp_market(service_key,
                                                       app_version, namespace)
                    logger.debug(
                        "mq_work.app_slug",
                        "*******[ftp download slug]result:==={}".format(
                            ftp_ok))
            else:
                ftp_ok = True
        except Exception as e:
            logger.exception("mq_work.app_slug", e)
        version_status = {
            "final_status": "failure",
        }
        if ftp_ok:
            self.log.info("应用同步完成,开始启动应用。", step="app-image", status="success")
            version_body = {
                "type": 'slug',
                "path": dest_slug_file,
                "event_id": self.event_id
            }
            version_status = {
                "final_status": "success",
            }
            try:
                self.region_client.update_version_region(
                    json.dumps(version_body))
                self.region_client.update_version_event(
                    self.event_id, json.dumps(version_status))
            except Exception as e:
                pass
            try:
                self.api.start_service(tenant_name, service_alias, event_id)
            except Exception as e:
                logger.exception(e)
                self.log.error("应用自动启动失败。请手动启动",
                               step="callback",
                               status="failure")
        else:
            self.log.error("应用同步失败。", step="callback", status="failure")
            try:
                self.region_client.update_version_event(
                    self.event_id, json.dumps(version_status))
            except Exception as e:
                self.log.error("更新version信息失败", step="app-slug")
                pass
Ejemplo n.º 8
0
class ImageManual():
    def __init__(self, job, *args, **kwargs):
        self.job = job
        self.configs = kwargs.get("config")
        self.region_api = RegionAPI(conf=self.configs['region'])
        image_config = self.configs["publish"]["image"]
        self.region_client = RegionBackAPI()
        self.region_registry = RegistryAPI(
            host=image_config.get('curr_registry'))
        # self.region_registry.set_log_topic('mq_work.image_manual')
        self.oss_registry = RegistryAPI(host=image_config.get('all_registry'))
        self.oss_registry.set_log_topic('mq_work.image_manual')
        self.locker = TaskLocker(conf=self.configs['etcd'])
        self.api = ACPAPI(conf=self.configs['region'])
        self.namespace = image_config.get('oss_namespace')
        self.user_cs_client = UserConsoleAPI(conf=self.configs['userconsole'])

    def do_work(self):
        try:
            task = json.loads(self.job.body)
            self.task = task
            if "event_id" in self.task:
                self.event_id = task["event_id"]
                self.log = EventLog().bind(
                    event_id=self.event_id, step="image_manual")
            else:
                self.event_id = ""
                self.log = EventLog().bind(event_id="", step="image_manual")
            logger.info("mq_work.image_manual",
                        "new image_manual task: {}".format(task))
            if task['action'] == 'create_new_version':
                self.log.info("开始升级应用。")
                self.create_new_version()
            elif task['action'] == 'download_and_deploy':
                self.log.info("开始下载镜像并部署应用。")
                self.download_and_deploy()
            elif task['action'] == 'delete_old_version':
                self.log.info("开始删除旧版本。")
                self.delete_old_version()
        except Exception as e:
            if self.log:
                self.log.error(
                    "从自定义镜像部署应用失败。{}".format(e.message),
                    step="callback",
                    status="failure")
            logger.exception('mq_work.image_manual', e)

    def create_new_version(self):
        logger.debug("mq_work.image_manual",
                     "now create new version and upload image")

    def delete_old_version(self):
        logger.debug("mq_work.image_manual", "now delete old version")

    def download_and_deploy(self):
        image = self.task['image']
        # namespace = self.task['namespace']
        tenant_name = self.task['tenant_name']
        service_alias = self.task['service_alias']
        event_id = self.task['event_id']
        service_alias = self.task.get("service_alias", None)
        has_download = False
        inner_image = self.oss_registry.rename_image(image)
        inner_image = "{0}_{1}".format(inner_image, service_alias)
        local_image = self.region_registry.rename_image(image)
        local_image = "{0}_{1}".format(local_image, service_alias)
        # 直接下载docker image
        try:
            self.log.info("开始下载镜像:{0}".format(image))
            pull_result = self._pull(image)
            if pull_result:
                # image_id = self.get_image_property(image, 'Id')
                self._tag(image, local_image)
                self.log.info("修改镜像名为:{0}".format(local_image))
                ok = self._push(local_image)
                if not ok:
                    self.log.error(
                        "上传镜像发生错误,重试失败,退出。", step="callback", status="failure")
                    return
                self.log.info("镜像推送到本地仓库完成。")
                # self._tag(image, inner_image)
                # self._push(inner_image)
                has_download = True
            else:
                self.log.error("下载镜像发生错误。", step="callback", status="failure")
                logger.error("mq_work.image_manual",
                             "download image failed! image:{}".format(image))

        except Exception as e:
            self.log.error(
                "镜像操作发生错误。{0}".format(e.__str__()),
                step="callback",
                status="failure")
            logger.exception("mq_work.image_manual", e)
        version_status = {
            "final_status":"failure",
        }
        if has_download:
            self.log.info("应用同步完成。", step="app-image", status="success")
            version_body = {
                "type": 'image',
                "path": local_image,
                "event_id": self.event_id
            }
            body = {
                "deploy_version": self.task['deploy_version'],
                "event_id": self.event_id,
            }
            version_status['final_status'] = "success"
            try:
                self.region_client.update_version_region(json.dumps(version_body))
                self.region_client.update_version_event(self.event_id,json.dumps(version_status))
            except Exception as e:
                pass
            try:
                self.api.update_iamge(tenant_name, service_alias, local_image)
                version = self.task['deploy_version']
                self.log.info("应用信息更新完成,开始启动应用。", step="app-image", status="success")
                self.api.upgrade_service(self.task['tenant_name'], self.task['service_alias'], json.dumps(body))
                # self.api.start_service(tenant_name, service_alias, event_id)
            except Exception as e:
                logger.exception(e)
                self.log.error(
                    "应用自动启动失败。请手动启动", step="callback", status="failure")
        else:
            try:
                self.region_client.update_version_event(self.event_id,json.dumps(version_status))
            except Exception as e:
                pass
            self.log.error("应用同步失败。", step="callback", status="failure")

    def queryServiceStatus(self, service_id):
        try:
            res, body = self.region_api.is_service_running(service_id)
            logger.info(
                'mq_work.image_manual',
                "service_id=" + service_id + ";body=" + json.dumps(body))
            status = body.get(service_id, "closed")
            if status == "running":
                self.log.debug("依赖的应用状态已经为运行中。", step="worker")
                return True
        except:
            pass
        self.log.debug("依赖的应用状态不是运行中,本应用稍后启动。", step="worker")
        return False

    def get_image_property(self, image, name):
        query_format = '{{.%s}}' % name
        try:
            output = shell.call("{2} inspect -f '{0}' {1}".format(
                query_format, image, DOCKER_BIN))
            if output == '<no value>':
                return None
            else:
                return output[0].rstrip('\n')
        except shell.ExecException, e:
            logger.exception("mq_work.image_manual", e)
            return None