Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
slapos.core
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Gabriel Monnerat
slapos.core
Commits
5f177e1f
Commit
5f177e1f
authored
Dec 13, 2016
by
Alain Takoudjou
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
partition can request to update ip route of tap interface
parent
36d19481
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
188 additions
and
9 deletions
+188
-9
slapos/format.py
slapos/format.py
+3
-1
slapos/grid/slapgrid.py
slapos/grid/slapgrid.py
+185
-8
No files found.
slapos/format.py
View file @
5f177e1f
...
...
@@ -840,8 +840,10 @@ class Tap(object):
if
self
.
ipv4_addr
:
# Check if this route exits
code
,
result
=
callAndRead
([
'ip'
,
'route'
,
'show'
,
self
.
ipv4_addr
])
if
code
==
0
and
self
.
ipv4_addr
in
result
and
self
.
name
in
result
:
if
self
.
ipv4_addr
in
result
:
# Skip already configured route
return
code
,
result
=
callAndRead
([
'ip'
,
'route'
,
'show'
])
callAndRead
([
'route'
,
'add'
,
'-host'
,
self
.
ipv4_addr
,
'dev'
,
self
.
name
])
else
:
raise
ValueError
(
"%s should not be empty. No ipv4 address assigned to %s"
%
...
...
slapos/grid/slapgrid.py
View file @
5f177e1f
...
...
@@ -42,6 +42,7 @@ import warnings
import
logging
import
json
import
shutil
import
ConfigParser
if
sys
.
version_info
<
(
2
,
6
):
warnings
.
warn
(
'Used python version (%s) is old and has problems with'
...
...
@@ -61,8 +62,10 @@ from slapos.grid.svcbackend import (launchSupervisord,
_getSupervisordSocketPath
)
from
slapos.grid.utils
import
(
md5digest
,
dropPrivileges
,
SlapPopen
,
updateFile
)
from
slapos.human
import
human2bytes
from
slapos.format
import
callAndRead
import
slapos.slap
from
netaddr
import
valid_ipv4
,
valid_ipv6
import
netifaces
# XXX: should be moved to SLAP library
...
...
@@ -79,6 +82,7 @@ PROMISE_TIMEOUT = 3
COMPUTER_PARTITION_TIMESTAMP_FILENAME
=
'.timestamp'
COMPUTER_PARTITION_LATEST_BANG_TIMESTAMP_FILENAME
=
'.slapos_latest_bang_timestamp'
COMPUTER_PARTITION_INSTALL_ERROR_FILENAME
=
'.slapgrid-%s-error.log'
COMPUTER_PARTITION_UPDATE_TAP_ROUTE
=
'.%s-request-update-route'
# XXX hardcoded watchdog_path
WATCHDOG_PATH
=
'/opt/slapos/bin/slapos-watchdog'
...
...
@@ -396,6 +400,40 @@ class Slapgrid(object):
self
.
ipv4_global_network
=
""
self
.
firewall_conf
=
firewall_conf
def
_getDefaultNetworkInterface
(
self
):
return
netifaces
.
gateways
()[
'default'
][
netifaces
.
AF_INET
]
def
_checkIpAddressOnIfaces
(
self
,
ip
):
"""
Check if ip address already exists on server
"""
for
iface
in
netifaces
.
interfaces
():
if
iface
==
'lo'
:
continue
address_list
=
netifaces
.
ifaddresses
(
iface
)
if
address_list
.
has_key
(
netifaces
.
AF_INET
):
for
address
in
address_list
[
netifaces
.
AF_INET
]:
if
address
[
'addr'
]
==
ip
:
return
iface
,
address
def
_checkAndExecuteRouteCmd
(
self
,
run_command
,
check_command
,
check_list
,
rule_exists
=
False
):
self
.
logger
.
debug
(
"Execute command: %s"
%
' '
.
join
(
check_command
))
_
,
result
=
callAndRead
(
check_command
)
rule_found
=
False
for
result_line
in
result
.
split
(
'
\
n
'
):
if
not
result_line
:
continue
rule_found
=
True
for
item
in
check_list
:
rule_found
=
rule_found
and
item
in
result_line
if
rule_found
:
break
if
not
rule_exists
and
not
rule_found
:
self
.
logger
.
debug
(
"Execute command: %s"
%
' '
.
join
(
run_command
))
return
callAndRead
(
run_command
)
elif
rule_exists
and
rule_found
:
self
.
logger
.
debug
(
"Execute command: %s"
%
' '
.
join
(
run_command
))
return
callAndRead
(
run_command
)
def
_getWatchdogLine
(
self
):
invocation_list
=
[
WATCHDOG_PATH
]
...
...
@@ -862,6 +900,141 @@ stderr_logfile_backups=1
self
.
logger
.
warn
(
"IP/Network address %s is not valid. ignored.."
%
ip
)
return
valid_list
def
_restoreSlapTapRoute
(
self
,
partition_id
,
ipv4
):
instance_path
=
os
.
path
.
join
(
self
.
instance_root
,
partition_id
)
saved_request_file
=
os
.
path
.
join
(
instance_path
,
'.slapos-request-update-route'
)
if
not
os
.
path
.
exists
(
saved_request_file
):
return
self
.
logger
.
debug
(
"Cleaning custom ip routes..."
)
config_request
=
ConfigParser
.
ConfigParser
()
try
:
config_request
.
readfp
(
open
(
saved_request_file
))
except
ConfigParser
.
MissingSectionHeaderError
:
self
.
logger
.
error
(
"%s: Invalid config file specified."
%
saved_request_file
)
raise
route_section
=
'%s-routes'
%
partition_id
if
not
route_section
in
config_request
.
sections
():
raise
Exception
(
"Section %s required to restore ip route configuration"
\
"is not found in file %s"
%
(
route_section
,
saved_request_file
))
gateway_ip
=
tap_ip
=
''
option_list
=
config_request
.
options
(
route_section
)
interface
=
config_request
.
get
(
route_section
,
'interface'
)
if
'forward-to-ip'
in
option_list
:
gateway_ip
=
config_request
.
get
(
route_section
,
'forward-to-ip'
)
if
'ip-to-interface'
in
option_list
:
tap_ip
=
config_request
.
get
(
route_section
,
'ip-to-interface'
)
if
gateway_ip
:
tap_route_cmd
=
[
'route'
,
'del'
,
ipv4
,
'gw'
,
gateway_ip
]
tap_default_cmd
=
[
'route'
,
'add'
,
'-host'
,
ipv4
,
'dev'
,
interface
]
self
.
_checkAndExecuteRouteCmd
(
tap_default_cmd
,
[
'ip'
,
'route'
,
'show'
,
ipv4
],
[
ipv4
,
interface
],
False
)
self
.
_checkAndExecuteRouteCmd
(
tap_route_cmd
,
[
'ip'
,
'route'
,
'show'
,
ipv4
],
[
ipv4
,
gateway_ip
],
True
)
elif
tap_ip
:
tap_route_cmd
=
[
'ip'
,
'route'
,
'del'
,
tap_ip
,
'dev'
,
interface
]
self
.
_checkAndExecuteRouteCmd
(
tap_route_cmd
,
[
'ip'
,
'route'
,
'show'
,
tap_ip
],
[
tap_ip
,
interface
],
True
)
os
.
remove
(
saved_request_file
)
def
_updateSlapTapRoute
(
self
,
partition_id
,
ipv4
,
iface
,
hosting_ip_list
,
check_remove
=
False
):
"""
This is used to update route to tap interface in case a instance(vm) is moved to
another computer. Then we add routes to reach the moved instance.
"""
instance_path
=
os
.
path
.
join
(
self
.
instance_root
,
partition_id
)
filename
=
COMPUTER_PARTITION_UPDATE_TAP_ROUTE
%
partition_id
request_file
=
os
.
path
.
join
(
instance_path
,
filename
)
saved_request_file
=
os
.
path
.
join
(
instance_path
,
'.slapos-request-update-route'
)
if
os
.
path
.
exists
(
request_file
)
and
not
check_remove
:
self
.
logger
.
debug
(
"File %s found. Configure custom ip routes..."
%
filename
)
else
:
return
self
.
_restoreSlapTapRoute
(
partition_id
,
ipv4
)
config_request
=
ConfigParser
.
ConfigParser
()
try
:
config_request
.
readfp
(
open
(
request_file
))
except
ConfigParser
.
MissingSectionHeaderError
:
self
.
logger
.
error
(
"%s: Invalid file specified."
%
request_file
)
raise
route_section
=
'%s-routes'
%
partition_id
if
not
route_section
in
config_request
.
sections
():
self
.
logger
.
debug
(
'Section %s is missing, skiping file %s.'
%
(
route_section
,
filename
))
return
option_list
=
config_request
.
options
(
route_section
)
interface
=
config_request
.
get
(
route_section
,
'interface'
)
if
iface
!=
interface
:
raise
ValueError
(
"Cannot update ip route on unallowed or invalid interface: %s"
%
interface
)
gateway_ip
=
tap_ip
=
''
if
'forward-to-ip'
in
option_list
:
gateway_ip
=
config_request
.
get
(
route_section
,
'forward-to-ip'
)
if
not
valid_ipv4
(
gateway_ip
):
raise
ValueError
(
"Invalid or unallowed IPv4 specified: %s"
%
gateway_ip
)
if
'ip-to-interface'
in
option_list
:
tap_ip
=
config_request
.
get
(
route_section
,
'ip-to-interface'
)
if
not
tap_ip
in
hosting_ip_list
:
raise
ValueError
(
"Invalid or unallowed IPv4 specified: %s"
%
tap_ip
)
# save requested file
shutil
.
copy
(
request_file
,
saved_request_file
)
if
gateway_ip
:
# Forward route from interface to another ip
result
=
self
.
_checkIpAddressOnIfaces
(
gateway_ip
)
if
result
is
not
None
:
self
.
logger
.
debug
(
"IP address %s found on interface %s, ip route will "
\
"not be added!"
%
(
gateway_ip
,
result
[
0
]))
return
_
,
default_iface
=
self
.
_getDefaultNetworkInterface
()
tap_route_cmd
=
[
'route'
,
'add'
,
'-host'
,
ipv4
,
'gw'
,
gateway_ip
]
tap_default_cmd
=
[
'ip'
,
'route'
,
'del'
,
ipv4
,
'dev'
,
interface
]
self
.
_checkAndExecuteRouteCmd
(
[
'route'
,
'add'
,
'-host'
,
gateway_ip
,
'dev'
,
default_iface
],
[
'ip'
,
'route'
,
'show'
,
gateway_ip
],
[
gateway_ip
,
default_iface
])
# Remove current route to slaptap
self
.
_checkAndExecuteRouteCmd
(
tap_default_cmd
,
[
'ip'
,
'route'
,
'show'
,
ipv4
],
[
ipv4
,
interface
],
True
)
# Add route to new gateway
self
.
_checkAndExecuteRouteCmd
(
tap_route_cmd
,
[
'ip'
,
'route'
,
'show'
,
ipv4
],
[
ipv4
,
gateway_ip
],
False
)
elif
tap_ip
:
# add new route to tap interface
tap_route_cmd
=
[
'route'
,
'add'
,
'-host'
,
tap_ip
,
'dev'
,
interface
]
self
.
_checkAndExecuteRouteCmd
(
tap_route_cmd
,
[
'ip'
,
'route'
,
'show'
,
tap_ip
],
[
tap_ip
,
interface
],
False
)
if
'ip-to-interface-dnat'
in
option_list
:
set_dnat
=
config_request
.
get
(
route_section
,
'ip-to-interface-dnat'
)
if
set_dnat
in
[
'True'
,
'true'
,
'yes'
,
'1'
]:
# Add firewall rule to forward to another ip
command
=
'--permanent --direct --add-rule ipv4 nat '
command
+=
'PREROUTING 800 -d %s -j DNAT --to-destination %s'
%
(
ipv4
,
tap_ip
)
return
[
command
]
def
_setupComputerPartitionFirewall
(
self
,
computer_partition
,
ip_list
,
drop_entries
=
False
):
"""
Using linux iptables, limit access to IP of this partition to all
...
...
@@ -869,10 +1042,10 @@ stderr_logfile_backups=1
"""
ipv4_list
=
[]
ipv6_list
=
[]
tap_interface
=
''
tap_route_ipv4
=
''
source_ipv4_list
=
[]
source_ipv6_list
=
[]
hosting_ipv4_list
=
[]
hosting_ipv6_list
=
[]
getFirewallRules
=
getattr
(
self
,
'_getFirewallAcceptRules'
)
if
not
drop_entries
:
...
...
@@ -886,19 +1059,16 @@ stderr_logfile_backups=1
iface
,
ip
=
(
net_ip
[
0
],
net_ip
[
1
])
if
not
iface
.
startswith
(
'route_'
):
continue
tap_interface
=
iface
.
lstrip
(
'route_'
)
tap_route_ipv4
=
ip
if
valid_ipv4
(
ip
):
ipv4_list
.
append
(
ip
)
elif
valid_ipv6
(
ip
):
ipv6_list
.
append
(
ip
)
hosting_ip_list
=
computer_partition
.
getFullHostingIpAddressList
()
for
iface
,
ip
in
hosting_ip_list
:
if
valid_ipv4
(
ip
):
if
not
ip
in
ipv4_list
:
hosting_ipv4_list
.
append
(
ip
)
elif
valid_ipv6
(
ip
):
if
not
ip
in
ipv6_list
:
hosting_ipv6_list
.
append
(
ip
)
filter_dict
=
getattr
(
computer_partition
,
'_filter_dict'
,
None
)
extra_list
=
[]
...
...
@@ -916,10 +1086,17 @@ stderr_logfile_backups=1
source_ipv4_list
=
self
.
_getValidIpv4FromList
(
extra_list
,
True
)
hosting_ipv4_list
.
extend
(
self
.
_getValidIpv4FromList
(
accept_ip_list
,
True
))
# XXX - ipv6_list and source_ipv6_list ignored for the moment
# In case route need to update route of instance
result_list
=
self
.
_updateSlapTapRoute
(
computer_partition
.
getId
(),
tap_route_ipv4
,
tap_interface
,
hosting_ipv4_list
,
drop_entries
)
for
ip
in
ipv4_list
:
cmd_list
=
getFirewallRules
(
ip
,
hosting_ipv4_list
,
source_ipv4_list
,
ip_type
=
'ipv4'
)
if
ip
==
tap_route_ipv4
and
result_list
is
not
None
:
cmd_list
.
extend
(
result_list
)
self
.
_checkAddFirewallRules
(
computer_partition
.
getId
(),
cmd_list
,
add
=
add_rules
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment