Update debmirror state to support transitivity when cache used

Change-Id: Ia6e65cf4356266157e9ebd6120a9de4b7d6db217
Related-Prod: PROD-32735
(cherry-picked from commit e5b036d10ff163d7044bb7923377b4157c4e9850)
diff --git a/_states/debmirror.py b/_states/debmirror.py
index ee86580..6001df1 100644
--- a/_states/debmirror.py
+++ b/_states/debmirror.py
@@ -82,12 +82,19 @@
 def _get_target_path(name, tgt):
     if not tgt.get('target_dir', False):
         raise SaltInvocationError('Argument "target_dir" is mandatory! ')
-    return {'target_dir': tgt.get('target_dir'),
+
+    out = {'target_dir': tgt.get('target_dir'),
             'lock_file': tgt.get('lock_file',
                                  os.path.join(tgt.get('target_dir'),
                                               '.lockmirror')),
             'log_file': tgt.get('log_file', '/var/log/debmirror_'.join(name))}
 
+    if tgt.get('cache_dir', False):
+        out['cache_dir'] = tgt.get('cache_dir')
+        out['cache_ready_file'] = os.path.join(out['cache_dir'], '.ready')
+
+    return out
+
 
 def _get_env(tgt):
     env = {}
@@ -101,9 +108,23 @@
     return env
 
 
-def _check_mirror_cache(cache_dir):
-    cacheReadinessKeyFile = os.path.join(cache_dir, '.ready')
-    return os.path.isfile(cacheReadinessKeyFile)
+def _check_mirror_cache(file_name):
+    return os.path.isfile(file_name)
+
+
+def _cache_copied(file_name, target_dir, action='check'):
+    pattern = '%s - copied\n' % target_dir
+    if action == 'add':
+        with open(file_name, 'a+') as f:
+            f.write(pattern)
+        return True
+    else:
+        with open(file_name, 'r') as f:
+            cache_copied = f.readlines()
+        if pattern in cache_copied:
+            return True
+        else:
+            return False
 
 
 def _get_cmdline(name, tgt):
@@ -134,10 +155,11 @@
         for key, value in enumerate(sorted(tgt['filter'])):
             cmdline += " " + tgt['filter'][value]
     if tgt.get('target_dir', False):
-        target_dir = _get_target_path(name, tgt)['target_dir']
+        targets = _get_target_path(name, tgt)
+        target_dir = targets['target_dir']
         if tgt.get('cache_dir'):
-            cache_dir = tgt.get('cache_dir')
-            if _check_mirror_cache(cache_dir):
+            cache_dir = targets['cache_dir']
+            if _check_mirror_cache(targets['cache_ready_file']):
                 cmdline += ' ' + target_dir
             else:
                 cmdline += ' ' + cache_dir
@@ -147,10 +169,12 @@
 
 
 def _update_mirror(name, tgt):
+    targetPaths = _get_target_path(name, tgt)
     # Remove old lock file, is was.
-    lock_file = _get_target_path(name, tgt)['lock_file']
+    lock_file = targetPaths['lock_file']
     if os.path.isfile(lock_file):
-        log.debug("Removing lockfile:{} for mirror{}".format(lock_file, name))
+        log.debug("Removing lockfile: {} for mirror {}".format(
+            lock_file, name))
         __states__['file.absent'](lock_file)
     cmdline = _get_cmdline(name, tgt)
     # fetch ENV params for proxy
@@ -160,7 +184,7 @@
     if not os.path.isdir(l_dir):
         __salt__['file.makedirs'](l_dir + '/')
     fh = logging.FileHandler(
-        "{0}".format(_get_target_path(name, tgt)['log_file']))
+        "{0}".format(targetPaths['log_file']))
     fh.setLevel(logging.DEBUG)
     fh_format = logging.Formatter(
         '%(asctime)s - %(lineno)d - %(levelname)-8s - %(message)s')
@@ -169,36 +193,52 @@
     log2file.addHandler(fh)
     # check cache usage
     if tgt.get('cache_dir'):
-        cache_dir = tgt.get('cache_dir')
-        target_dir = _get_target_path(name, tgt)['target_dir']
+        cache_dir = targetPaths['cache_dir']
+        cache_ready = targetPaths['cache_ready_file']
+        target_dir = targetPaths['target_dir']
         cpline = "find . -name *.deb -exec cp -rlf --parent {} %s \\;" % (
             target_dir)
-        # if cache exists - copy and run sync over cache
-        # if cache does not exist - create cache, copy and run sync again over it
-        if _check_mirror_cache(cache_dir):
-            result = __salt__['cmd.run_all'](cpline, redirect_stderr=True,
-                                             cwd=cache_dir, env=env_vars)
-            if result['retcode'] == 0:
+
+        # if cache exists and not copied - copy and run sync over cache
+        # if cache exists and copied - do nothing
+        if _check_mirror_cache(cache_ready):
+            if not _cache_copied(cache_ready, target_dir):
+                result = __salt__['cmd.run_all'](cpline, redirect_stderr=True,
+                                                 cwd=cache_dir, env=env_vars)
                 log2file.debug(result['stdout'])
-                result = __salt__['cmd.run_all'](cmdline, redirect_stderr=True,
-                                                 env=env_vars)
+
+                if result['retcode'] != 0:
+                    return _failed(name,
+                        "debmirror failed to copy cache. Reason {0}".format(
+                            result['stderr']))
+
+                _cache_copied(cache_ready, target_dir, 'add')
+        # if cache does not exist - create cache and copy
         else:
             result = __salt__['cmd.run_all'](cmdline, redirect_stderr=True,
                                              env=env_vars)
-            if result['retcode'] == 0:
-                __states__['file.managed']('%s/.ready' % cache_dir, replace=False)
-                log2file.debug(result['stdout'])
-                result = __salt__['cmd.run_all'](cpline, redirect_stderr=True,
-                                                 cwd=cache_dir, env=env_vars)
-                if result['retcode'] == 0:
-                    log2file.debug(result['stdout'])
-                    cmdline = _get_cmdline(name, tgt)
-                    result = __salt__['cmd.run_all'](cmdline, redirect_stderr=True,
-                                             env=env_vars)
+            log2file.debug(result['stdout'])
 
-    else:
-        result = __salt__['cmd.run_all'](cmdline, redirect_stderr=True,
-                                         env=env_vars)
+            if result['retcode'] != 0:
+                return _failed(name,
+                               "debmirror failed. Reason {0}".format(
+                                result['stderr']))
+
+            __states__['file.touch'](cache_ready)
+            result = __salt__['cmd.run_all'](cpline, redirect_stderr=True,
+                                             cwd=cache_dir, env=env_vars)
+            log2file.debug(result['stdout'])
+
+            if result['retcode'] != 0:
+                    return _failed(name,
+                        "debmirror failed to copy cache. Reason {0}".format(
+                            result['stderr']))
+
+            _cache_copied(cache_ready, target_dir, 'add')
+            cmdline = _get_cmdline(name, tgt)
+
+    result = __salt__['cmd.run_all'](cmdline, redirect_stderr=True,
+                                     env=env_vars)
     log2file.debug(result['stdout'])
     # destroy file logger
     for i in list(log2file.handlers):