monitor.py 7.6 KB
Newer Older
B
barrierye 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
B
barrierye 已提交
14 15 16 17 18 19 20 21 22 23 24 25
"""
Usage:
    Start monitor with one line command
    Example:
        python -m paddle_serving_server.monitor
"""
import os
import time
import argparse


class Monitor(object):
B
barrierye 已提交
26 27 28 29
    '''
    Monitor base class. It is used to monitor the remote model, pull and update the local model.
    '''

B
barrierye 已提交
30 31 32 33 34 35 36 37 38 39
    def __init__(self, interval):
        self._remote_path = None
        self._remote_model_name = None
        self._remote_donefile_name = None
        self._local_path = None
        self._local_model_name = None
        self._local_donefile_name = None
        self._interval = interval
        self._remote_donefile_timestamp = None
        self._local_tmp_dir = None
B
barrierye 已提交
40

B
barrierye 已提交
41 42
    def set_remote_path(self, remote_path):
        self._remote_path = remote_path
B
barrierye 已提交
43

B
barrierye 已提交
44 45
    def set_remote_model_name(self, model_name):
        self._remote_model_name = model_name
B
barrierye 已提交
46

B
barrierye 已提交
47 48
    def set_remote_donefile_name(self, donefile_name):
        self._remote_donefile_name = donefile_name
B
barrierye 已提交
49

B
barrierye 已提交
50 51
    def set_local_path(self, local_path):
        self._local_path = local_path
B
barrierye 已提交
52

B
barrierye 已提交
53 54
    def set_local_model_name(self, model_name):
        self._local_model_name = model_name
B
barrierye 已提交
55

B
barrierye 已提交
56 57
    def set_local_donefile_name(self, donefile_name):
        self._local_donefile_name = donefile_name
B
barrierye 已提交
58

B
barrierye 已提交
59 60
    def set_local_tmp_dir(self, tmp_dir):
        self._local_tmp_dir = tmp_dir
B
barrierye 已提交
61

B
barrierye 已提交
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
    def _check_params(self):
        if self._remote_path is None:
            raise Exception('remote_path not set.')
        if self._remote_model_name is None:
            raise Exception('remote_model_name not set.')
        if self._remote_donefile_name is None:
            raise Exception('remote_donefile_name not set.')
        if self._local_model_name is None:
            raise Exception('local_model_name not set.')
        if self._local_path is None:
            raise Exception('local_path not set.')
        if self._local_donefile_name is None:
            raise Exception('local_donefile_name not set.')
        if self._local_tmp_dir is None:
            raise Exception('local_tmp_dir not set.')
B
barrierye 已提交
77

B
barrierye 已提交
78
    def run(self):
B
barrierye 已提交
79
        '''
B
barrierye 已提交
80
        Monitor the remote model by polling and update the local model.
B
barrierye 已提交
81
        '''
B
barrierye 已提交
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
        self._check_params()
        if not os.path.exists(self._local_tmp_dir):
            os.makedirs(self._local_tmp_dir)
        while True:
            [flag, timestamp] = self._exist_remote_donefile()
            if flag:
                if self._remote_donefile_timestamp is None or \
                        timestamp != self._remote_donefile_timestamp:
                    self._remote_donefile_timestamp = timestamp
                    self._pull_remote_model()
                    print('[INFO] pull remote model')
                    self._update_local_model()
                    print('[INFO] update model')
                    self._update_local_donefile()
                    print('[INFO] update local donefile')
            else:
                print('[INFO] no donefile.')
            print('[INFO] sleep {}s'.format(self._interval))
            time.sleep(self._interval)
B
barrierye 已提交
101

B
barrierye 已提交
102 103
    def _exist_remote_donefile(self):
        raise Exception('This function must be inherited.')
B
barrierye 已提交
104

B
barrierye 已提交
105 106
    def _pull_remote_model(self):
        raise Exception('This function must be inherited.')
B
barrierye 已提交
107

B
barrierye 已提交
108 109
    def _update_local_model(self):
        raise Exception('This function must be inherited.')
B
barrierye 已提交
110

B
barrierye 已提交
111 112 113 114 115 116 117 118 119 120 121 122
    def _update_local_donefile(self):
        raise Exception('This function must be inherited.')


class FTPMonitor(Monitor):
    def __init__(self, ftp_ip, ftp_port, username="", password="", interval=10):
        import ftplib
        super(FTPMonitor, self).__init__(interval)
        self._ftp_ip = ftp_ip
        self._ftp_port = ftp_port
        self._ftp = ftplib.FTP()
        self._connect(ftp_ip, ftp_port, username, password)
B
barrierye 已提交
123

B
barrierye 已提交
124 125 126
    def _connect(self, ftp_ip, ftp_port, username, password):
        self._ftp.connect(ftp_ip, ftp_port)
        self._ftp.login(username, password)
B
barrierye 已提交
127

B
barrierye 已提交
128
    def _exist_remote_donefile(self):
B
barrierye 已提交
129
        import ftplib
B
barrierye 已提交
130
        try:
B
barrierye 已提交
131 132 133 134
            donefile_path = '{}/{}'.format(self._remote_path,
                                           self._remote_donefile_name)
            timestamp = self._ftp.voidcmd('MDTM {}'.format(donefile_path))[
                4:].strip()
B
barrierye 已提交
135 136 137
            return [True, timestamp]
        except ftplib.error_perm:
            return [False, None]
B
barrierye 已提交
138

B
barrierye 已提交
139
    def _pull_remote_model(self):
B
barrierye 已提交
140 141 142
        cmd = 'wget -nH -r -P {} ftp://{}:{}/{}/{} &> /dev/null'.format(
            self._local_tmp_dir, self._ftp_ip, self._ftp_port,
            self._remote_path, self._remote_model_name)
B
barrierye 已提交
143 144
        if os.system(cmd) != 0:
            raise Exception('pull remote model failed.')
B
barrierye 已提交
145

B
barrierye 已提交
146
    def _update_local_model(self):
B
barrierye 已提交
147 148 149
        cmd = 'cp -r {}/{}/* {}/{}'.format(
            self._local_tmp_dir, self._remote_model_name, self._local_path,
            self._local_model_name)
B
barrierye 已提交
150 151
        if os.system(cmd) != 0:
            raise Exception('update local model failed.')
B
barrierye 已提交
152

B
barrierye 已提交
153 154
    def _update_local_donefile(self):
        cmd = 'touch {}/{}/{}'.format(self._local_path, self._local_model_name,
B
barrierye 已提交
155
                                      self._local_donefile_name)
B
barrierye 已提交
156 157 158
        if os.system(cmd) != 0:
            raise Exception('update local donefile failed.')

B
barrierye 已提交
159

B
barrierye 已提交
160 161 162 163 164 165 166
def parse_args():
    parser = argparse.ArgumentParser(description="Monitor")
    parser.add_argument(
        "--type", type=str, required=True, help="Type of remote server")
    parser.add_argument(
        "--remote_path", type=str, required=True, help="Remote path")
    parser.add_argument(
B
barrierye 已提交
167 168 169
        "--remote_model_name",
        type=str,
        required=True,
B
barrierye 已提交
170 171
        help="Remote model name")
    parser.add_argument(
B
barrierye 已提交
172 173 174
        "--remote_donefile_name",
        type=str,
        required=True,
B
barrierye 已提交
175 176 177 178 179 180
        help="Remote donefile name")
    parser.add_argument(
        "--local_path", type=str, required=True, help="Local path")
    parser.add_argument(
        "--local_model_name", type=str, required=True, help="Local model name")
    parser.add_argument(
B
barrierye 已提交
181 182 183
        "--local_donefile_name",
        type=str,
        required=True,
B
barrierye 已提交
184
        help="Local donfile name(fluid_time_file in model file)")
B
barrierye 已提交
185 186 187 188
    parser.add_argument(
        "--local_tmp_dir", type=str, default='tmp', help="Local tmp dir")
    parser.add_argument(
        "--interval", type=int, default=10, help="Time interval")
B
barrierye 已提交
189 190 191 192
    parser.add_argument("--ftp_ip", type=str, help="Ip the ftp")
    parser.add_argument("--ftp_port", type=int, help="Port the ftp")
    return parser.parse_args()

B
barrierye 已提交
193

B
barrierye 已提交
194 195 196 197 198 199 200 201 202 203 204 205
def start_ftp_monitor():
    args = parse_args()
    obj = FTPMonitor(args.ftp_ip, args.ftp_port, interval=args.interval)
    obj.set_remote_path(args.remote_path)
    obj.set_remote_model_name(args.remote_model_name)
    obj.set_remote_donefile_name(args.remote_donefile_name)
    obj.set_local_path(args.local_path)
    obj.set_local_model_name(args.local_model_name)
    obj.set_local_donefile_name(args.local_donefile_name)
    obj.set_local_tmp_dir(args.local_tmp_dir)
    obj.run()

B
barrierye 已提交
206

B
barrierye 已提交
207 208 209 210 211 212
if __name__ == "__main__":
    args = parse_args()
    if args.type == 'ftp':
        start_ftp_monitor()
    else:
        raise Exception('unsupport type.')