Test Failed
Push — master ( 0acd10...77d0f6 )
by Heiko 'riot'
01:37
created

isomer.tool.system.configure()   A

Complexity

Conditions 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 7
nop 1
dl 0
loc 10
rs 10
c 0
b 0
f 0
1
#!/usr/bin/env python
2
# -*- coding: UTF-8 -*-
3
4
# Isomer - The distributed application framework
5
# ==============================================
6
# Copyright (C) 2011-2020 Heiko 'riot' Weinen <[email protected]> and others.
7
#
8
# This program is free software: you can redistribute it and/or modify
9
# it under the terms of the GNU Affero General Public License as published by
10
# the Free Software Foundation, either version 3 of the License, or
11
# (at your option) any later version.
12
#
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
# GNU Affero General Public License for more details.
17
#
18
# You should have received a copy of the GNU Affero General Public License
19
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
21
"""
22
23
Module: system
24
==============
25
26
Contains system setup tasks.
27
28
    system all
29
    system dependencies
30
    system user
31
    system paths
32
33
"""
34
35
import os
36
import time
37
import click
38
import shutil
39
40
from click_didyoumean import DYMGroup
41
42
from isomer.logger import error
43
from isomer.misc.path import locations, get_path, get_log_path, get_etc_path
44
from isomer.tool import platforms, install_isomer, log, run_process, ask, finish
45
from isomer.tool.etc import create_configuration
46
from isomer.error import abort, EXIT_NOT_OVERWRITING_CONFIGURATION
47
48
49
@click.group(
50
    cls=DYMGroup,
51
    short_help="System and platform management tasks"
52
)
53
@click.pass_context
54
@click.option(
55
    "--platform",
56
    "-p",
57
    default=None,
58
    help="Platform name, one of %s" % list(platforms.keys()),
59
)
60
@click.option("--omit-platform", is_flag=True, default=False)
61
@click.option("--use-sudo", "-u", is_flag=True, default=False)
62
@click.option(
63
    "--log-actions",
64
    "-l",
65
    help="Show what would be installed",
66
    is_flag=True,
67
    default=False,
68
)
69
def system(ctx, platform, omit_platform, use_sudo, log_actions):
70
    """[GROUP] Various aspects of Isomer system handling"""
71
72
    if ctx.invoked_subcommand == 'configure':
73
        return
74
75
    ctx.obj["platform"] = platform
76
    ctx.obj["omit_platform"] = omit_platform
77
78
    ctx.obj["use_sudo"] = use_sudo
79
    ctx.obj["log_actions"] = log_actions
80
81
82
@system.command(name="all", short_help="Perform all system setup tasks")
83
@click.pass_context
84
def system_all(ctx):
85
    """Performs all system setup tasks"""
86
87
    use_sudo = ctx.obj["use_sudo"]
88
89
    generate_configuration(ctx)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable generate_configuration does not seem to be defined.
Loading history...
90
    install_isomer(
91
        ctx.obj["platform"], use_sudo, show=ctx.obj["log_actions"],
92
        omit_platform=ctx.obj['omit_platform'], omit_common=True
93
    )
94
    _add_system_user(use_sudo)
95
    _create_system_folders(use_sudo)
96
97
    finish(ctx)
98
99
100
@system.command(short_help="Generate a skeleton configuration for Isomer (needs sudo)")
101
@click.pass_context
102
def configure(ctx):
103
    """Generate a skeleton configuration for Isomer (needs sudo)"""
104
105
    if os.path.exists(get_etc_path()):
106
        abort(EXIT_NOT_OVERWRITING_CONFIGURATION)
107
    ctx = create_configuration(ctx)
108
109
    finish(ctx)
110
111
112
@system.command(short_help="Install system dependencies")
113
@click.pass_context
114
def dependencies(ctx):
115
    """Install Isomer platform dependencies"""
116
117
    log("Installing platform dependencies")
118
119
    install_isomer(
120
        ctx.obj["platform"],
121
        ctx.obj["use_sudo"],
122
        show=ctx.obj["log_actions"],
123
        omit_platform=ctx.obj['platform'],
124
        omit_common=True,
125
    )
126
127
    finish(ctx)
128
129
130
@system.command(name="user", short_help="create system user")
131
@click.pass_context
132
def system_user(ctx):
133
    """instance Isomer system user (isomer.isomer)"""
134
135
    _add_system_user(ctx.obj["use_sudo"])
136
    finish(ctx)
137
138
139
def _add_system_user(use_sudo=False):
140
    """instance Isomer system user (isomer.isomer)"""
141
142
    command = [
143
        "/usr/sbin/adduser",
144
        "--system",
145
        "--quiet",
146
        "--home",
147
        "/var/run/isomer",
148
        "--group",
149
        "--disabled-password",
150
        "--disabled-login",
151
        "isomer",
152
    ]
153
154
    success, output = run_process("/", command, sudo=use_sudo)
155
    if success is False:
156
        log("Error adding system user:", lvl=error)
157
        log(output, lvl=error)
158
159
    command = ["/usr/sbin/adduser", "isomer", "dialout"]
160
161
    success, output = run_process("/", command, sudo=use_sudo)
162
    if success is False:
163
        log("Error adding system user to dialout group:", lvl=error)
164
        log(output, lvl=error)
165
166
    time.sleep(2)
167
168
169
@system.command(name="paths", short_help="create system paths")
170
@click.pass_context
171
def system_paths(ctx):
172
    """instance Isomer system paths (/var/[local,lib,cache]/isomer)"""
173
174
    _create_system_folders(ctx.obj["use_sudo"])
175
    finish(ctx)
176
177
178
def _create_system_folders(use_sudo=False):
179
    target_paths = [
180
        "/var/www/challenges",  # For LetsEncrypt acme certificate challenges
181
        "/var/backups/isomer",
182
        "/var/log/isomer",
183
        "/var/run/isomer",
184
    ]
185
    for item in locations:
186
        target_paths.append(get_path(item, ""))
187
188
    target_paths.append(get_log_path())
189
190
    for item in target_paths:
191
        run_process("/", ["sudo", "mkdir", "-p", item], sudo=use_sudo)
192
        run_process("/", ["sudo", "chown", "isomer", item], sudo=use_sudo)
193
194
    # TODO: The group/ownership should be assigned per instance.user/group
195
    run_process("/", ["sudo", "chgrp", "isomer", "/var/log/isomer"], sudo=use_sudo)
196
    run_process("/", ["sudo", "chmod", "g+w", "/var/log/isomer"], sudo=use_sudo)
197
198
199
@system.command(short_help="Remove all instance data")
200
def uninstall():
201
    """Uninstall data and resource locations"""
202
203
    response = ask(
204
        "This will delete all data of your Isomer installations! Type"
205
        "YES to continue:",
206
        default="N",
207
        show_hint=False,
208
    )
209
    if response == "YES":
210
        shutil.rmtree("/var/lib/isomer")
211
        shutil.rmtree("/var/cache/isomer")
212