Statistics
| Branch: | Tag: | Revision:

root / snf-deploy / snfdeploy / utils.py @ d4f28d8f

History | View | Annotate | Download (7.8 kB)

1 3c3bccab Dimitris Aragiorgis
# Copyright (C) 2010, 2011, 2012, 2013 GRNET S.A. All rights reserved.
2 3c3bccab Dimitris Aragiorgis
#
3 3c3bccab Dimitris Aragiorgis
# Redistribution and use in source and binary forms, with or
4 3c3bccab Dimitris Aragiorgis
# without modification, are permitted provided that the following
5 3c3bccab Dimitris Aragiorgis
# conditions are met:
6 3c3bccab Dimitris Aragiorgis
#
7 3c3bccab Dimitris Aragiorgis
#   1. Redistributions of source code must retain the above
8 3c3bccab Dimitris Aragiorgis
#      copyright notice, this list of conditions and the following
9 3c3bccab Dimitris Aragiorgis
#      disclaimer.
10 3c3bccab Dimitris Aragiorgis
#
11 3c3bccab Dimitris Aragiorgis
#   2. Redistributions in binary form must reproduce the above
12 3c3bccab Dimitris Aragiorgis
#      copyright notice, this list of conditions and the following
13 3c3bccab Dimitris Aragiorgis
#      disclaimer in the documentation and/or other materials
14 3c3bccab Dimitris Aragiorgis
#      provided with the distribution.
15 3c3bccab Dimitris Aragiorgis
#
16 3c3bccab Dimitris Aragiorgis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 3c3bccab Dimitris Aragiorgis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 3c3bccab Dimitris Aragiorgis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 3c3bccab Dimitris Aragiorgis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A. OR
20 3c3bccab Dimitris Aragiorgis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 3c3bccab Dimitris Aragiorgis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 3c3bccab Dimitris Aragiorgis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 3c3bccab Dimitris Aragiorgis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 3c3bccab Dimitris Aragiorgis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 3c3bccab Dimitris Aragiorgis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 3c3bccab Dimitris Aragiorgis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 3c3bccab Dimitris Aragiorgis
# POSSIBILITY OF SUCH DAMAGE.
28 3c3bccab Dimitris Aragiorgis
#
29 3c3bccab Dimitris Aragiorgis
# The views and conclusions contained in the software and
30 3c3bccab Dimitris Aragiorgis
# documentation are those of the authors and should not be
31 3c3bccab Dimitris Aragiorgis
# interpreted as representing official policies, either expressed
32 3c3bccab Dimitris Aragiorgis
# or implied, of GRNET S.A.
33 3c3bccab Dimitris Aragiorgis
34 68d6d24b Dimitris Aragiorgis
from __future__ import with_statement
35 68d6d24b Dimitris Aragiorgis
from fabric.api import hide, env, settings, local, roles
36 68d6d24b Dimitris Aragiorgis
from fabric.operations import run, put, get
37 68d6d24b Dimitris Aragiorgis
import fabric
38 68d6d24b Dimitris Aragiorgis
import re
39 68d6d24b Dimitris Aragiorgis
import os
40 68d6d24b Dimitris Aragiorgis
import shutil
41 68d6d24b Dimitris Aragiorgis
import tempfile
42 68d6d24b Dimitris Aragiorgis
import ast
43 68d6d24b Dimitris Aragiorgis
from snfdeploy.lib import debug, Conf, Env, disable_color
44 68d6d24b Dimitris Aragiorgis
from snfdeploy import massedit
45 3c3bccab Dimitris Aragiorgis
from snfdeploy.components import *
46 3c3bccab Dimitris Aragiorgis
from snfdeploy.roles import ROLES, CONFLICTS
47 68d6d24b Dimitris Aragiorgis
48 68d6d24b Dimitris Aragiorgis
49 68d6d24b Dimitris Aragiorgis
def abort(action):
50 68d6d24b Dimitris Aragiorgis
    def inner(*args, **kwargs):
51 68d6d24b Dimitris Aragiorgis
        try:
52 68d6d24b Dimitris Aragiorgis
            return action(*args, **kwargs)
53 68d6d24b Dimitris Aragiorgis
        except BaseException as e:
54 68d6d24b Dimitris Aragiorgis
            abort = kwargs.get("abort", True)
55 3c3bccab Dimitris Aragiorgis
            force = env.force
56 3c3bccab Dimitris Aragiorgis
            if not abort or force:
57 d4f28d8f Dimitris Aragiorgis
                debug(env.host,
58 d4f28d8f Dimitris Aragiorgis
                      "WARNING: command failed. Continuing anyway...")
59 68d6d24b Dimitris Aragiorgis
            else:
60 d4f28d8f Dimitris Aragiorgis
                fabric.utils.abort(e)
61 68d6d24b Dimitris Aragiorgis
    return inner
62 68d6d24b Dimitris Aragiorgis
63 68d6d24b Dimitris Aragiorgis
64 68d6d24b Dimitris Aragiorgis
@abort
65 68d6d24b Dimitris Aragiorgis
def try_get(remote_path, local_path=None, **kwargs):
66 3c3bccab Dimitris Aragiorgis
    if env.dry_run:
67 3c3bccab Dimitris Aragiorgis
        debug(env.host, " * Fetching file localy... ", remote_path)
68 3c3bccab Dimitris Aragiorgis
        return
69 68d6d24b Dimitris Aragiorgis
    get(remote_path, local_path=local_path, **kwargs)
70 68d6d24b Dimitris Aragiorgis
71 68d6d24b Dimitris Aragiorgis
72 68d6d24b Dimitris Aragiorgis
@abort
73 3c3bccab Dimitris Aragiorgis
def try_put(local_path=None, remote_path=None, mode=0644, **kwargs):
74 3c3bccab Dimitris Aragiorgis
    if env.dry_run:
75 3c3bccab Dimitris Aragiorgis
        debug(env.host, " * Upload file... ", remote_path)
76 3c3bccab Dimitris Aragiorgis
        return
77 3c3bccab Dimitris Aragiorgis
    put(local_path=local_path, remote_path=remote_path, mode=mode)
78 68d6d24b Dimitris Aragiorgis
79 68d6d24b Dimitris Aragiorgis
80 68d6d24b Dimitris Aragiorgis
@abort
81 68d6d24b Dimitris Aragiorgis
def try_run(cmd, **kwargs):
82 3c3bccab Dimitris Aragiorgis
    if env.dry_run:
83 3c3bccab Dimitris Aragiorgis
        debug(env.host, cmd)
84 3c3bccab Dimitris Aragiorgis
        return ""
85 3c3bccab Dimitris Aragiorgis
    elif env.local:
86 3c3bccab Dimitris Aragiorgis
        return local(cmd, capture=True, shell="/bin/bash")
87 68d6d24b Dimitris Aragiorgis
    else:
88 68d6d24b Dimitris Aragiorgis
        return run(cmd)
89 68d6d24b Dimitris Aragiorgis
90 68d6d24b Dimitris Aragiorgis
91 68d6d24b Dimitris Aragiorgis
def install_package(package):
92 3c3bccab Dimitris Aragiorgis
    debug(env.host, " * Installing package... ", package)
93 68d6d24b Dimitris Aragiorgis
    apt_get = "export DEBIAN_FRONTEND=noninteractive ;" + \
94 68d6d24b Dimitris Aragiorgis
              "apt-get install -y --force-yes "
95 68d6d24b Dimitris Aragiorgis
96 68d6d24b Dimitris Aragiorgis
    host_info = env.env.ips_info[env.host]
97 68d6d24b Dimitris Aragiorgis
    env.env.update_packages(host_info.os)
98 68d6d24b Dimitris Aragiorgis
    if ast.literal_eval(env.env.use_local_packages):
99 68d6d24b Dimitris Aragiorgis
        with settings(warn_only=True):
100 68d6d24b Dimitris Aragiorgis
            deb = local("ls %s/%s*%s_*.deb"
101 68d6d24b Dimitris Aragiorgis
                        % (env.env.packages, package, host_info.os),
102 68d6d24b Dimitris Aragiorgis
                        capture=True)
103 68d6d24b Dimitris Aragiorgis
            if deb:
104 68d6d24b Dimitris Aragiorgis
                debug(env.host,
105 68d6d24b Dimitris Aragiorgis
                      " * Package %s found in %s..."
106 68d6d24b Dimitris Aragiorgis
                      % (package, env.env.packages))
107 68d6d24b Dimitris Aragiorgis
                try_put(deb, "/tmp/")
108 68d6d24b Dimitris Aragiorgis
                try_run("dpkg -i /tmp/%s || "
109 68d6d24b Dimitris Aragiorgis
                        % os.path.basename(deb) + apt_get + "-f")
110 68d6d24b Dimitris Aragiorgis
                try_run("rm /tmp/%s" % os.path.basename(deb))
111 68d6d24b Dimitris Aragiorgis
                return
112 68d6d24b Dimitris Aragiorgis
113 68d6d24b Dimitris Aragiorgis
    info = getattr(env.env, package)
114 68d6d24b Dimitris Aragiorgis
    if info in \
115 68d6d24b Dimitris Aragiorgis
            ["squeeze-backports", "squeeze", "stable",
116 68d6d24b Dimitris Aragiorgis
             "testing", "unstable", "wheezy"]:
117 68d6d24b Dimitris Aragiorgis
        apt_get += " -t %s %s " % (info, package)
118 68d6d24b Dimitris Aragiorgis
    elif info:
119 68d6d24b Dimitris Aragiorgis
        apt_get += " %s=%s " % (package, info)
120 68d6d24b Dimitris Aragiorgis
    else:
121 68d6d24b Dimitris Aragiorgis
        apt_get += package
122 68d6d24b Dimitris Aragiorgis
123 68d6d24b Dimitris Aragiorgis
    try_run(apt_get)
124 68d6d24b Dimitris Aragiorgis
125 68d6d24b Dimitris Aragiorgis
    return
126 68d6d24b Dimitris Aragiorgis
127 68d6d24b Dimitris Aragiorgis
128 68d6d24b Dimitris Aragiorgis
def customize_settings_from_tmpl(tmpl, replace):
129 68d6d24b Dimitris Aragiorgis
    debug(env.host, " * Customizing template %s..." % tmpl)
130 68d6d24b Dimitris Aragiorgis
    local = env.env.templates + tmpl
131 68d6d24b Dimitris Aragiorgis
    _, custom = tempfile.mkstemp()
132 68d6d24b Dimitris Aragiorgis
    shutil.copyfile(local, custom)
133 68d6d24b Dimitris Aragiorgis
    for k, v in replace.iteritems():
134 68d6d24b Dimitris Aragiorgis
        regex = "re.sub('%{0}%', '{1}', line)".format(k.upper(), v)
135 68d6d24b Dimitris Aragiorgis
        massedit.edit_files([custom], [regex], dry_run=False)
136 68d6d24b Dimitris Aragiorgis
137 68d6d24b Dimitris Aragiorgis
    return custom
138 68d6d24b Dimitris Aragiorgis
139 68d6d24b Dimitris Aragiorgis
140 3c3bccab Dimitris Aragiorgis
def get_node_info(ident):
141 3c3bccab Dimitris Aragiorgis
    if ident in env.env.ips_info:
142 3c3bccab Dimitris Aragiorgis
        return env.env.ips_info[ident]
143 3c3bccab Dimitris Aragiorgis
    elif ident in env.env.hosts_info:
144 3c3bccab Dimitris Aragiorgis
        return env.env.hosts_info[ident]
145 3c3bccab Dimitris Aragiorgis
    elif ident in env.env.nodes_info:
146 3c3bccab Dimitris Aragiorgis
        return env.env.nodes_info[ident]
147 3c3bccab Dimitris Aragiorgis
148 3c3bccab Dimitris Aragiorgis
149 3c3bccab Dimitris Aragiorgis
def GetFromComponent(component, remote, local):
150 3c3bccab Dimitris Aragiorgis
    c = GetSynnefoComponent(component)
151 3c3bccab Dimitris Aragiorgis
    c.debug(" * Downloading: ", remote)
152 3c3bccab Dimitris Aragiorgis
    with settings(host_string=c.node_info.ip):
153 3c3bccab Dimitris Aragiorgis
        try_get(remote, local)
154 3c3bccab Dimitris Aragiorgis
155 3c3bccab Dimitris Aragiorgis
156 3c3bccab Dimitris Aragiorgis
def PutToComponent(component, local, remote):
157 3c3bccab Dimitris Aragiorgis
    c = GetSynnefoComponent(component)
158 3c3bccab Dimitris Aragiorgis
    c.debug(" * Uploading: ", remote)
159 3c3bccab Dimitris Aragiorgis
    with settings(host_string=c.node_info.ip):
160 3c3bccab Dimitris Aragiorgis
        try_put(local, remote)
161 3c3bccab Dimitris Aragiorgis
162 3c3bccab Dimitris Aragiorgis
163 3c3bccab Dimitris Aragiorgis
def RunComponentMethod(component, method, *args, **kwargs):
164 3c3bccab Dimitris Aragiorgis
    c = GetSynnefoComponent(component)
165 3c3bccab Dimitris Aragiorgis
    c.debug(" * Running method: ", method)
166 3c3bccab Dimitris Aragiorgis
    with settings(host_string=c.node_info.ip):
167 3c3bccab Dimitris Aragiorgis
        fn = getattr(c, method)
168 3c3bccab Dimitris Aragiorgis
        ret = ""
169 3c3bccab Dimitris Aragiorgis
        for cmd in fn(*args, **kwargs):
170 3c3bccab Dimitris Aragiorgis
            ret += try_run(cmd)
171 3c3bccab Dimitris Aragiorgis
        return ret
172 3c3bccab Dimitris Aragiorgis
173 3c3bccab Dimitris Aragiorgis
174 3c3bccab Dimitris Aragiorgis
def GetSynnefoComponent(component):
175 3c3bccab Dimitris Aragiorgis
    node_info = get_node_info(env.host)
176 3c3bccab Dimitris Aragiorgis
    env.password = node_info.passwd
177 3c3bccab Dimitris Aragiorgis
    return component(node_info, env)
178 3c3bccab Dimitris Aragiorgis
179 3c3bccab Dimitris Aragiorgis
180 3c3bccab Dimitris Aragiorgis
def conflicting_exists(component):
181 3c3bccab Dimitris Aragiorgis
    conflict = CONFLICTS.get(component, [])
182 3c3bccab Dimitris Aragiorgis
    for c in conflict:
183 3c3bccab Dimitris Aragiorgis
        cs = env.env.status.check_status(env.host, c)
184 3c3bccab Dimitris Aragiorgis
        if cs:
185 3c3bccab Dimitris Aragiorgis
            debug(env.host, "Conflicting component already exists", c.__name__)
186 3c3bccab Dimitris Aragiorgis
            return True
187 3c3bccab Dimitris Aragiorgis
188 3c3bccab Dimitris Aragiorgis
    return False
189 3c3bccab Dimitris Aragiorgis
190 3c3bccab Dimitris Aragiorgis
191 3c3bccab Dimitris Aragiorgis
def SetupSynnefoRole(role):
192 3c3bccab Dimitris Aragiorgis
    debug("Setting up base configuration for: ", role)
193 3c3bccab Dimitris Aragiorgis
    try:
194 3c3bccab Dimitris Aragiorgis
        components = ROLES.get(role)
195 3c3bccab Dimitris Aragiorgis
    except KeyError:
196 3c3bccab Dimitris Aragiorgis
        debug(env.host, "Please give a valid role")
197 3c3bccab Dimitris Aragiorgis
        return
198 3c3bccab Dimitris Aragiorgis
    for c in components:
199 3c3bccab Dimitris Aragiorgis
        if conflicting_exists(c):
200 3c3bccab Dimitris Aragiorgis
            continue
201 3c3bccab Dimitris Aragiorgis
        status = env.env.status.check_status(env.host, c)
202 3c3bccab Dimitris Aragiorgis
        if status:
203 3c3bccab Dimitris Aragiorgis
            debug(env.host, "Base configuration already exists", c.__name__)
204 3c3bccab Dimitris Aragiorgis
        else:
205 3c3bccab Dimitris Aragiorgis
            AddSynnefoComponent(c)
206 3c3bccab Dimitris Aragiorgis
            env.env.status.update_status(env.host, c, "ok")
207 3c3bccab Dimitris Aragiorgis
            env.env.status.write_status()
208 3c3bccab Dimitris Aragiorgis
209 3c3bccab Dimitris Aragiorgis
210 3c3bccab Dimitris Aragiorgis
class AddSynnefoComponent(object):
211 3c3bccab Dimitris Aragiorgis
212 3c3bccab Dimitris Aragiorgis
    def _run(self, commands):
213 3c3bccab Dimitris Aragiorgis
        for c in commands:
214 3c3bccab Dimitris Aragiorgis
            try_run(c)
215 3c3bccab Dimitris Aragiorgis
216 3c3bccab Dimitris Aragiorgis
    def _install(self, packages):
217 3c3bccab Dimitris Aragiorgis
        for p in packages:
218 3c3bccab Dimitris Aragiorgis
            install_package(p)
219 3c3bccab Dimitris Aragiorgis
220 3c3bccab Dimitris Aragiorgis
    def _configure(self, templates):
221 3c3bccab Dimitris Aragiorgis
        for tmpl, replace, opts in templates:
222 3c3bccab Dimitris Aragiorgis
            mode = opts.get("mode", 0644)
223 3c3bccab Dimitris Aragiorgis
            remote = opts.get("remote", tmpl)
224 3c3bccab Dimitris Aragiorgis
            custom = customize_settings_from_tmpl(tmpl, replace)
225 3c3bccab Dimitris Aragiorgis
            try_put(custom, remote, mode)
226 3c3bccab Dimitris Aragiorgis
            os.remove(custom)
227 3c3bccab Dimitris Aragiorgis
228 3c3bccab Dimitris Aragiorgis
    def __init__(self, component):
229 3c3bccab Dimitris Aragiorgis
        self.c = GetSynnefoComponent(component)
230 3c3bccab Dimitris Aragiorgis
        self.c.debug("Adding component..")
231 3c3bccab Dimitris Aragiorgis
232 3c3bccab Dimitris Aragiorgis
        self.c.debug(" * Checking prerequisites..")
233 3c3bccab Dimitris Aragiorgis
        self._run(self.c.check())
234 3c3bccab Dimitris Aragiorgis
235 3c3bccab Dimitris Aragiorgis
        self.c.debug(" * Installing packages..")
236 3c3bccab Dimitris Aragiorgis
        self._install(self.c.install())
237 3c3bccab Dimitris Aragiorgis
238 3c3bccab Dimitris Aragiorgis
        self.c.debug(" * Preparing configuration..")
239 3c3bccab Dimitris Aragiorgis
        self._run(self.c.prepare())
240 3c3bccab Dimitris Aragiorgis
241 3c3bccab Dimitris Aragiorgis
        self.c.debug(" * Setting up configuration files..")
242 3c3bccab Dimitris Aragiorgis
        self._configure(self.c.configure())
243 3c3bccab Dimitris Aragiorgis
244 3c3bccab Dimitris Aragiorgis
        self.c.debug(" * Restarting services..")
245 3c3bccab Dimitris Aragiorgis
        self._run(self.c.restart())
246 3c3bccab Dimitris Aragiorgis
247 3c3bccab Dimitris Aragiorgis
        self.c.debug(" * Initializing setup..")
248 3c3bccab Dimitris Aragiorgis
        self._run(self.c.initialize())
249 3c3bccab Dimitris Aragiorgis
250 3c3bccab Dimitris Aragiorgis
        self.c.debug(" * Testing setup..")
251 3c3bccab Dimitris Aragiorgis
        self._run(self.c.test())