Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
L
lustmolch
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
External wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
stustanet
lustmolch
Commits
230d1007
Commit
230d1007
authored
5 years ago
by
Michael Loipführer
Browse files
Options
Downloads
Patches
Plain Diff
smaller changes
parent
b8725536
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
lustmolch.py
+71
-37
71 additions, 37 deletions
lustmolch.py
with
71 additions
and
37 deletions
lustmolch.py
+
71
−
37
View file @
230d1007
...
@@ -14,14 +14,15 @@ cfg_template = namedtuple('cfg_template', ['source', 'path', 'filename'])
...
@@ -14,14 +14,15 @@ cfg_template = namedtuple('cfg_template', ['source', 'path', 'filename'])
template_files_host
=
[
template_files_host
=
[
cfg_template
(
'
nginx
'
,
Path
(
'
/etc/nginx/sites-available
'
),
'
{name}
'
),
cfg_template
(
'
nginx
'
,
Path
(
'
/etc/nginx/sites-available
'
),
'
{name}
'
),
cfg_template
(
'
80-container-ve.network
'
,
Path
(
'
/etc/systemd/network
'
),
cfg_template
(
'
80-container-ve.network
'
,
Path
(
'
/etc/systemd/network
'
),
'
80-container-ve-{name}.network
'
)
'
80-container-ve-{name}.network
'
)
]
]
nspawn_config
=
cfg_template
(
'
nspawn
'
,
Path
(
'
/etc/systemd/nspawn
'
),
'
{name}.nspawn
'
)
template_files_container
=
[
template_files_container
=
[
cfg_template
(
'
sshd_config
'
,
Path
(
'
/etc/ssh
'
),
'
sshd_config
'
),
cfg_template
(
'
sshd_config
'
,
Path
(
'
/etc/ssh
'
),
'
sshd_config
'
),
cfg_template
(
'
80-container-host0.network
'
,
Path
(
'
/etc/systemd/network
'
),
cfg_template
(
'
80-container-host0.network
'
,
Path
(
'
/etc/systemd/network
'
),
'
80-container-host0.network
'
)
'
80-container-host0.network
'
)
]
]
nspawn_config
=
cfg_template
(
'
nspawn
'
,
Path
(
'
/etc/systemd/nspawn
'
),
'
{name}.nspawn
'
)
DEFAULT_TEMPLATE_DIR
=
'
/srv/lustmolch-tools/templates
'
DEFAULT_TEMPLATE_DIR
=
'
/srv/lustmolch-tools/templates
'
DEFAULT_CONF_FILE
=
'
/etc/ssn/lustmolch-containers.json
'
DEFAULT_CONF_FILE
=
'
/etc/ssn/lustmolch-containers.json
'
...
@@ -41,6 +42,20 @@ IP_START_HOST = (192, 168, 0, 1)
...
@@ -41,6 +42,20 @@ IP_START_HOST = (192, 168, 0, 1)
IP_SUBNET_LENGTH
=
30
IP_SUBNET_LENGTH
=
30
def
gen_default_conf
():
return
{}
def
get_config
(
file_path
):
if
not
Path
(
file_path
).
exists
():
cfg
=
gen_default_conf
()
else
:
with
open
(
file_path
,
'
r
'
)
as
f
:
cfg
=
json
.
load
(
f
)
return
cfg
def
next_ssh_port
(
config_file
,
name
):
def
next_ssh_port
(
config_file
,
name
):
"""
"""
Return the next available port for the containers ssh server to run on.
Return the next available port for the containers ssh server to run on.
...
@@ -52,25 +67,22 @@ def next_ssh_port(config_file, name):
...
@@ -52,25 +67,22 @@ def next_ssh_port(config_file, name):
Returns: SSH port
Returns: SSH port
"""
"""
if
not
Path
(
config_file
).
exists
():
cfg
=
get_config
(
config_file
)
cfg
=
{}
else
:
with
open
(
config_file
,
'
r
'
)
as
f
:
cfg
=
json
.
load
(
f
)
if
name
in
cfg
:
if
name
in
cfg
:
return
cfg
.
get
(
name
).
get
(
'
ssh_port
'
)
return
cfg
[
name
].
get
(
'
ssh_port
'
)
port
=
SSH_START_PORT
port
=
SSH_START_PORT
for
name
,
container
in
cfg
.
items
():
for
container_
name
,
container
in
cfg
.
items
():
if
container
.
get
(
'
ssh_port
'
)
>=
port
:
if
container
[
'
ssh_port
'
]
>=
port
:
port
=
container
.
get
(
'
ssh_port
'
)
+
SSH_PORT_INCREMENT
port
=
container
[
'
ssh_port
'
]
+
SSH_PORT_INCREMENT
return
port
return
port
def
next_ip_address
(
config_file
,
name
):
def
next_ip_address
(
config_file
,
name
):
"""
"""
Return the next available (local) IP address to be assigned to the
Return the next available (local) IP address to be assigned to the
container and the host interfaces.
container and the host interfaces.
Args:
Args:
config_file: Path to container configuration file (containers.json)
config_file: Path to container configuration file (containers.json)
...
@@ -85,11 +97,12 @@ def next_ip_address(config_file, name):
...
@@ -85,11 +97,12 @@ def next_ip_address(config_file, name):
cfg
=
json
.
load
(
f
)
cfg
=
json
.
load
(
f
)
if
name
in
cfg
:
if
name
in
cfg
:
return
(
cfg
[
name
].
get
(
'
ip_address_host
'
).
split
(
'
/
'
)[
0
],
c
=
cfg
[
name
]
cfg
[
name
].
get
(
'
ip_address_container
'
).
split
(
'
/
'
)[
0
])
return
(
c
.
get
(
'
ip_address_host
'
).
split
(
'
/
'
)[
0
],
c
.
get
(
'
ip_address_container
'
).
split
(
'
/
'
)[
0
])
ip_host
=
list
(
IP_START_HOST
)
ip_host
=
list
(
IP_START_HOST
)
for
name
,
container
in
cfg
.
items
():
for
container_
name
,
container
in
cfg
.
items
():
if
'
ip_address_host
'
not
in
container
or
'
ip_address_container
'
not
in
container
:
if
'
ip_address_host
'
not
in
container
or
'
ip_address_container
'
not
in
container
:
continue
continue
ip_h
=
container
.
get
(
'
ip_address_host
'
).
split
(
'
/
'
)[
0
].
split
(
'
.
'
)
ip_h
=
container
.
get
(
'
ip_address_host
'
).
split
(
'
/
'
)[
0
].
split
(
'
.
'
)
...
@@ -102,21 +115,26 @@ def next_ip_address(config_file, name):
...
@@ -102,21 +115,26 @@ def next_ip_address(config_file, name):
ip_host
[
3
]
=
1
ip_host
[
3
]
=
1
else
:
else
:
ip_host
[
3
]
=
int
(
ip_h
[
3
])
+
4
ip_host
[
3
]
=
int
(
ip_h
[
3
])
+
4
ip_container
=
list
(
ip_host
)
ip_container
=
list
(
ip_host
)
ip_container
[
3
]
+=
1
ip_container
[
3
]
+=
1
return
(
'
.
'
.
join
(
str
(
x
)
for
x
in
ip_host
),
'
.
'
.
join
(
str
(
x
)
for
x
in
ip_container
))
return
(
'
.
'
.
join
(
str
(
x
)
for
x
in
ip_host
),
'
.
'
.
join
(
str
(
x
)
for
x
in
ip_container
))
def
update_config
(
config_file
,
name
,
container
):
def
update_config
(
config_file
,
container
):
if
not
Path
(
config_file
).
exists
():
if
not
Path
(
config_file
).
exists
():
with
open
(
config_file
,
'
w+
'
)
as
f
:
with
open
(
config_file
,
'
w+
'
)
as
f
:
cfg
=
{
name
:
container
}
cfg
=
gen_default_conf
()
cfg
[
container
[
'
name
'
]]
=
container
json
.
dump
(
cfg
,
f
,
indent
=
4
)
json
.
dump
(
cfg
,
f
,
indent
=
4
)
else
:
else
:
with
open
(
config_file
,
'
r
'
)
as
f
:
with
open
(
config_file
,
'
r
'
)
as
f
:
cfg
=
json
.
load
(
f
)
cfg
=
json
.
load
(
f
)
cfg
[
name
]
=
container
cfg
[
container
[
'
name
'
]]
=
container
with
open
(
config_file
,
'
w
'
)
as
f
:
with
open
(
config_file
,
'
w
'
)
as
f
:
json
.
dump
(
cfg
,
f
,
indent
=
4
)
json
.
dump
(
cfg
,
f
,
indent
=
4
)
...
@@ -128,7 +146,10 @@ def cli():
...
@@ -128,7 +146,10 @@ def cli():
@cli.command
()
@cli.command
()
@click.option
(
'
--dry-run
'
,
is_flag
=
True
,
default
=
False
)
@click.option
(
'
--dry-run
'
,
is_flag
=
True
,
default
=
False
)
@click.option
(
'
--config-file
'
,
default
=
DEFAULT_CONF_FILE
,
help
=
'
Container configuration file
'
)
@click.option
(
'
--config-file
'
,
default
=
DEFAULT_CONF_FILE
,
help
=
'
Container configuration file
'
)
@click.argument
(
'
name
'
)
@click.argument
(
'
name
'
)
def
create_container
(
dry_run
,
config_file
,
name
):
def
create_container
(
dry_run
,
config_file
,
name
):
if
dry_run
:
if
dry_run
:
...
@@ -166,7 +187,8 @@ def create_container(dry_run, config_file, name):
...
@@ -166,7 +187,8 @@ def create_container(dry_run, config_file, name):
machine_path
=
Path
(
'
/var/lib/machines
'
,
name
)
machine_path
=
Path
(
'
/var/lib/machines
'
,
name
)
click
.
echo
(
'
Running debootstrap
'
)
click
.
echo
(
'
Running debootstrap
'
)
if
not
dry_run
:
if
not
dry_run
:
run
([
'
debootstrap
'
,
FLAVOUR
,
machine_path
,
DEBIAN_MIRROR
],
capture_output
=
True
,
check
=
True
)
run
([
'
debootstrap
'
,
FLAVOUR
,
machine_path
,
DEBIAN_MIRROR
],
capture_output
=
True
,
check
=
True
)
click
.
echo
(
'
Bootstrapping container
'
)
click
.
echo
(
'
Bootstrapping container
'
)
if
not
dry_run
:
if
not
dry_run
:
...
@@ -174,14 +196,18 @@ def create_container(dry_run, config_file, name):
...
@@ -174,14 +196,18 @@ def create_container(dry_run, config_file, name):
script_location
=
'
/opt/bootstrap.sh
'
script_location
=
'
/opt/bootstrap.sh
'
script_location_host
=
str
(
machine_path
)
+
script_location
script_location_host
=
str
(
machine_path
)
+
script_location
shutil
.
copy
(
str
(
Path
(
DEFAULT_TEMPLATE_DIR
,
'
container/bootstrap.sh
'
)),
script_location_host
)
shutil
.
copy
(
str
(
Path
(
DEFAULT_TEMPLATE_DIR
,
'
container/bootstrap.sh
'
)),
script_location_host
)
Path
(
script_location_host
).
chmod
(
0o755
)
Path
(
script_location_host
).
chmod
(
0o755
)
run
([
'
systemd-nspawn
'
,
'
-D
'
,
str
(
machine_path
),
script_location
],
check
=
True
)
run
([
'
systemd-nspawn
'
,
'
-D
'
,
str
(
machine_path
),
script_location
],
check
=
True
)
click
.
echo
(
f
'
Installing systemd-nspawn config for container
{
name
}
'
)
click
.
echo
(
f
'
Installing systemd-nspawn config for container
{
name
}
'
)
if
not
dry_run
:
if
not
dry_run
:
template
=
env
.
get_template
(
'
host/
'
+
nspawn_config
.
source
)
template
=
env
.
get_template
(
'
host/
'
+
nspawn_config
.
source
)
file_name
=
nspawn_config
.
path
/
(
nspawn_config
.
filename
.
format
(
**
context
))
file_name
=
nspawn_config
.
path
/
\
(
nspawn_config
.
filename
.
format
(
**
context
))
with
open
(
file_name
,
'
w+
'
)
as
cfg_file
:
with
open
(
file_name
,
'
w+
'
)
as
cfg_file
:
cfg_file
.
write
(
template
.
render
(
context
))
cfg_file
.
write
(
template
.
render
(
context
))
...
@@ -199,12 +225,13 @@ def create_container(dry_run, config_file, name):
...
@@ -199,12 +225,13 @@ def create_container(dry_run, config_file, name):
if
not
dry_run
:
if
not
dry_run
:
for
ip_range
in
SSN_IP_RANGES
:
for
ip_range
in
SSN_IP_RANGES
:
run
([
'
iptables
'
,
'
-A
'
,
'
INPUT
'
,
'
-p
'
,
'
tcp
'
,
'
-m
'
,
'
tcp
'
,
run
([
'
iptables
'
,
'
-A
'
,
'
INPUT
'
,
'
-p
'
,
'
tcp
'
,
'
-m
'
,
'
tcp
'
,
'
--dport
'
,
str
(
ssh_port
),
'
-s
'
,
ip_range
,
'
-j
'
,
'
ACCEPT
'
])
'
--dport
'
,
str
(
ssh_port
),
'
-s
'
,
ip_range
,
'
-j
'
,
'
ACCEPT
'
])
run
([
'
iptables
'
,
'
-t
'
,
'
nat
'
,
'
-A
'
,
'
PREROUTING
'
,
'
-p
'
,
'
tcp
'
,
run
([
'
iptables
'
,
'
-t
'
,
'
nat
'
,
'
-A
'
,
'
PREROUTING
'
,
'
-p
'
,
'
tcp
'
,
'
-m
'
,
'
tcp
'
,
'
--dport
'
,
str
(
ssh_port
),
'
-s
'
,
ip_range
,
'
-j
'
,
'
DNAT
'
,
'
-m
'
,
'
tcp
'
,
'
--dport
'
,
str
(
'
--to-destination
'
,
f
'
{
ip_address_container
}
:22
'
])
ssh_port
),
'
-s
'
,
ip_range
,
'
-j
'
,
'
DNAT
'
,
'
--to-destination
'
,
f
'
{
ip_address_container
}
:22
'
])
run
([
'
iptables
'
,
'
-t
'
,
'
nat
'
,
'
-A
'
,
'
POSTROUTING
'
,
'
-o
'
,
f
'
ve-
{
name
}
'
,
run
([
'
iptables
'
,
'
-t
'
,
'
nat
'
,
'
-A
'
,
'
POSTROUTING
'
,
'
-o
'
,
f
'
ve-
{
name
}
'
,
'
-j
'
,
'
SNAT
'
,
'
--to-source
'
,
IP_LUSTMOLCH
])
'
-j
'
,
'
SNAT
'
,
'
--to-source
'
,
IP_LUSTMOLCH
])
click
.
echo
(
'
Starting container
'
)
click
.
echo
(
'
Starting container
'
)
if
not
dry_run
:
if
not
dry_run
:
...
@@ -212,14 +239,17 @@ def create_container(dry_run, config_file, name):
...
@@ -212,14 +239,17 @@ def create_container(dry_run, config_file, name):
click
.
echo
(
'
Updating container configuration file
'
)
click
.
echo
(
'
Updating container configuration file
'
)
if
not
dry_run
:
if
not
dry_run
:
update_config
(
config_file
,
name
,
container
=
context
)
update_config
(
config_file
,
container
=
context
)
click
.
echo
(
f
'
All done, ssh server running on port
{
ssh_port
}
\n
'
click
.
echo
(
f
'
All done, ssh server running on port
{
ssh_port
}
\n
'
'
To finish please run
"
iptables-save
"
.
'
)
'
To finish please run
"
iptables-save
"
.
'
)
@cli.command
()
@cli.command
()
@click.option
(
'
--config-file
'
,
default
=
DEFAULT_CONF_FILE
,
help
=
'
Container configuration file
'
)
@click.option
(
'
--config-file
'
,
default
=
DEFAULT_CONF_FILE
,
help
=
'
Container configuration file
'
)
@click.option
(
'
--key-string
'
,
is_flag
=
True
,
default
=
False
)
@click.option
(
'
--key-string
'
,
is_flag
=
True
,
default
=
False
)
@click.argument
(
'
name
'
)
@click.argument
(
'
name
'
)
@click.argument
(
'
key
'
)
@click.argument
(
'
key
'
)
...
@@ -241,7 +271,10 @@ def install_ssh_key(config_file, key_string, name, key):
...
@@ -241,7 +271,10 @@ def install_ssh_key(config_file, key_string, name, key):
@cli.command
()
@cli.command
()
@click.option
(
'
--dry-run
'
,
is_flag
=
True
,
default
=
False
)
@click.option
(
'
--dry-run
'
,
is_flag
=
True
,
default
=
False
)
@click.option
(
'
--config-file
'
,
default
=
DEFAULT_CONF_FILE
,
help
=
'
Container configuration file
'
)
@click.option
(
'
--config-file
'
,
default
=
DEFAULT_CONF_FILE
,
help
=
'
Container configuration file
'
)
@click.argument
(
'
name
'
)
@click.argument
(
'
name
'
)
def
remove_container
(
dry_run
,
config_file
,
name
):
def
remove_container
(
dry_run
,
config_file
,
name
):
machine_path
=
Path
(
'
/var/lib/machines
'
,
name
)
machine_path
=
Path
(
'
/var/lib/machines
'
,
name
)
...
@@ -266,7 +299,7 @@ def remove_container(dry_run, config_file, name):
...
@@ -266,7 +299,7 @@ def remove_container(dry_run, config_file, name):
file_name
.
unlink
()
file_name
.
unlink
()
except
OSError
as
e
:
except
OSError
as
e
:
click
.
echo
(
f
'
{
e
}
ignored when removing file
{
file_name
}
'
)
click
.
echo
(
f
'
{
e
}
ignored when removing file
{
file_name
}
'
)
click
.
echo
(
'
Removing nspawn config
'
)
click
.
echo
(
'
Removing nspawn config
'
)
try
:
try
:
(
nspawn_config
.
path
/
nspawn_config
.
filename
.
format
(
name
=
name
)).
unlink
()
(
nspawn_config
.
path
/
nspawn_config
.
filename
.
format
(
name
=
name
)).
unlink
()
...
@@ -292,7 +325,8 @@ def remove_container(dry_run, config_file, name):
...
@@ -292,7 +325,8 @@ def remove_container(dry_run, config_file, name):
except
OSError
as
e
:
except
OSError
as
e
:
click
.
echo
(
f
'
{
e
}
ignored when updating config file
'
)
click
.
echo
(
f
'
{
e
}
ignored when updating config file
'
)
click
.
echo
(
'
All done, although you might need to manually remove some iptable rules.
'
)
click
.
echo
(
'
All done, although you might need to manually remove some iptable rules.
'
)
if
__name__
==
'
__main__
'
:
if
__name__
==
'
__main__
'
:
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment