Completed
Push — master ( fe66bc...2a24eb )
by Manas
18:11
created

delete_file()   A

Complexity

Conditions 1

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 14
rs 9.4286
cc 1
1
# Licensed to the StackStorm, Inc ('StackStorm') under one or more
2
# contributor license agreements.  See the NOTICE file distributed with
3
# this work for additional information regarding copyright ownership.
4
# The ASF licenses this file to You under the Apache License, Version 2.0
5
# (the "License"); you may not use this file except in compliance with
6
# the License.  You may obtain a copy of the License at
7
#
8
#     http://www.apache.org/licenses/LICENSE-2.0
9
#
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS,
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
# See the License for the specific language governing permissions and
14
# limitations under the License.
15
16
import os
17
import abc
18
19
from fabric.api import (env, execute)
20
from oslo_config import cfg
21
import six
22
23
from st2actions.runners import ActionRunner
24
from st2actions.runners import ShellRunnerMixin
25
from st2common import log as logging
26
from st2common.exceptions.actionrunner import ActionRunnerPreRunError
27
from st2common.exceptions.fabricrunner import FabricExecutionFailureException
28
from st2common.constants.action import LIVEACTION_STATUS_SUCCEEDED, LIVEACTION_STATUS_FAILED
29
from st2common.constants.runners import FABRIC_RUNNER_DEFAULT_ACTION_TIMEOUT
30
31
# Replace with container call to get logger.
32
LOG = logging.getLogger(__name__)
33
34
35
# Fabric environment level settings.
36
# XXX: Note fabric env is a global singleton.
37
env.parallel = True  # By default, execute things in parallel. Uses multiprocessing under the hood.
38
env.use_ssh_config = cfg.CONF.ssh_runner.use_ssh_config
39
env.user = cfg.CONF.system_user.user
40
ssh_key_file = cfg.CONF.system_user.ssh_key_file
41
42
if ssh_key_file:
43
    ssh_key_file = os.path.expanduser(ssh_key_file)
44
45
if ssh_key_file and os.path.exists(ssh_key_file):
46
    env.key_filename = ssh_key_file
47
48
env.timeout = 10  # Timeout for connections (in seconds)
49
env.command_timeout = FABRIC_RUNNER_DEFAULT_ACTION_TIMEOUT  # timeout for commands (in seconds)
50
env.combine_stderr = False
51
env.group = 'staff'
52
env.abort_exception = FabricExecutionFailureException
53
54
# constants to lookup in runner_parameters.
55
RUNNER_HOSTS = 'hosts'
56
RUNNER_USERNAME = 'username'
57
RUNNER_PASSWORD = 'password'
58
RUNNER_PRIVATE_KEY = 'private_key'
59
RUNNER_PARALLEL = 'parallel'
60
RUNNER_SUDO = 'sudo'
61
RUNNER_ON_BEHALF_USER = 'user'
62
RUNNER_REMOTE_DIR = 'dir'
63
RUNNER_COMMAND = 'cmd'
64
RUNNER_CWD = 'cwd'
65
RUNNER_ENV = 'env'
66
RUNNER_KWARG_OP = 'kwarg_op'
67
RUNNER_TIMEOUT = 'timeout'
68
69
70
@six.add_metaclass(abc.ABCMeta)
71
class BaseFabricRunner(ActionRunner, ShellRunnerMixin):
72
    def __init__(self, runner_id):
73
        super(BaseFabricRunner, self).__init__(runner_id=runner_id)
74
        self._hosts = None
75
        self._parallel = True
76
        self._sudo = False
77
        self._on_behalf_user = None
78
        self._username = None
79
        self._password = None
80
        self._private_key = None
81
        self._kwarg_op = '--'
82
        self._cwd = None
83
        self._env = None
84
        self._timeout = None
85
86
    def pre_run(self):
87
        LOG.debug('Entering FabricRunner.pre_run() for liveaction_id="%s"',
88
                  self.liveaction_id)
89
        hosts = self.runner_parameters.get(RUNNER_HOSTS, '').split(',')
90
        self._hosts = [h.strip() for h in hosts if len(h) > 0]
91
        if len(self._hosts) < 1:
92
            raise ActionRunnerPreRunError('No hosts specified to run action for action %s.',
93
                                          self.liveaction_id)
94
        self._username = self.runner_parameters.get(RUNNER_USERNAME, cfg.CONF.system_user.user)
95
        self._username = self._username or cfg.CONF.system_user.user
96
        self._password = self.runner_parameters.get(RUNNER_PASSWORD, None)
97
        self._private_key = self.runner_parameters.get(RUNNER_PRIVATE_KEY, None)
98
        self._parallel = self.runner_parameters.get(RUNNER_PARALLEL, True)
99
        self._sudo = self.runner_parameters.get(RUNNER_SUDO, False)
100
        self._sudo = self._sudo if self._sudo else False
101
        self._on_behalf_user = self.context.get(RUNNER_ON_BEHALF_USER, env.user)
102
        self._cwd = self.runner_parameters.get(RUNNER_CWD, None)
103
        self._env = self.runner_parameters.get(RUNNER_ENV, {})
104
        self._kwarg_op = self.runner_parameters.get(RUNNER_KWARG_OP, '--')
105
        self._timeout = self.runner_parameters.get(RUNNER_TIMEOUT,
106
                                                   FABRIC_RUNNER_DEFAULT_ACTION_TIMEOUT)
107
108
        LOG.info('[FabricRunner="%s", liveaction_id="%s"] Finished pre_run.',
109
                 self.runner_id, self.liveaction_id)
110
111
    def _run(self, remote_action):
112
        LOG.info('Executing action via FabricRunner: %s for user: %s.',
113
                 self.runner_id, remote_action.get_on_behalf_user())
114
        LOG.info(('[Action info] name: %s, Id: %s, command: %s, on behalf user: %s, '
115
                  'actual user: %s, sudo: %s'),
116
                 remote_action.name, remote_action.action_exec_id, remote_action.get_command(),
117
                 remote_action.get_on_behalf_user(), remote_action.get_user(),
118
                 remote_action.is_sudo())
119
        results = execute(remote_action.get_fabric_task(), hosts=remote_action.hosts)
120
        return results
121
122
    def _get_env_vars(self):
123
        """
124
        :rtype: ``dict``
125
        """
126
        env_vars = {}
127
128
        if self._env:
129
            env_vars.update(self._env)
130
131
        # Include common st2 env vars
132
        st2_env_vars = self._get_common_action_env_variables()
133
        env_vars.update(st2_env_vars)
134
135
        return env_vars
136
137
    @staticmethod
138
    def _get_result_status(result, allow_partial_failure):
139
        success = not allow_partial_failure
140
        for r in six.itervalues(result):
141
            r_succeess = r.get('succeeded', False) if r else False
142
            if allow_partial_failure:
143
                success |= r_succeess
144
                if success:
145
                    return LIVEACTION_STATUS_SUCCEEDED
146
            else:
147
                success &= r_succeess
148
                if not success:
149
                    return LIVEACTION_STATUS_FAILED
150
        return LIVEACTION_STATUS_SUCCEEDED if success else LIVEACTION_STATUS_FAILED
151