Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Gabriel Monnerat
slapos.core
Commits
5f177e1f
Commit
5f177e1f
authored
8 years ago
by
Alain Takoudjou
Browse files
Options
Download
Email Patches
Plain Diff
partition can request to update ip route of tap interface
parent
36d19481
Changes
2
Hide 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"
%
...
...
This diff is collapsed.
Click to expand it.
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
)
...
...
This diff is collapsed.
Click to expand it.
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