Commit 996d32fd authored by Rafael Monnerat's avatar Rafael Monnerat

Unpriviledged boot and bang

This change allow us to use slapos node boot/bang under a slaprunner (or any non-root environment).

It should be usefull to not create ad-hoc implementation for those procedures.

/cc @jerome @tomo @Nicolas

See merge request !214
parents 0ab33235 7e462a6f
......@@ -27,10 +27,10 @@
#
##############################################################################
from slapos.cli.command import must_be_root
from slapos.cli.config import ConfigCommand
from slapos.bang import do_bang
from slapos.util import string_to_boolean
from slapos.cli.command import check_root_user
class BangCommand(ConfigCommand):
......@@ -41,11 +41,17 @@ class BangCommand(ConfigCommand):
def get_parser(self, prog_name):
ap = super(BangCommand, self).get_parser(prog_name)
ap.add_argument('-m', '--message',
help='Message for bang')
ap.add_argument('-m', '--message', help='Message for bang')
return ap
@must_be_root
def take_action(self, args):
configp = self.fetch_config(args)
root_check = True
if configp.has_option('slapos', 'root_check'):
root_check = configp.getboolean('slapos', 'root_check')
if root_check:
check_root_user(self)
do_bang(configp, args.message)
......@@ -37,14 +37,17 @@ import os
import netifaces
import socket
from netaddr import valid_ipv4, valid_ipv6
from slapos.cli.command import must_be_root
from slapos.cli.command import check_root_user
from slapos.cli.entry import SlapOSApp
from slapos.cli.config import ConfigCommand
from slapos.format import isGlobalScopeAddress
from slapos.util import string_to_boolean
import argparse
def _removeTimestamp(instancehome, partition_base_name):
"""
Remove .timestamp from all partitions
Remove .timestamp from all partitions
"""
timestamp_glob_path = os.path.join(
instancehome,
......@@ -54,6 +57,7 @@ def _removeTimestamp(instancehome, partition_base_name):
print("Removing %s" % timestamp_path)
os.remove(timestamp_path)
def _runBang(app):
"""
Launch slapos node format.
......@@ -64,6 +68,7 @@ def _runBang(app):
return 0
return 1
def _runFormat(app):
"""
Launch slapos node format.
......@@ -74,14 +79,15 @@ def _runFormat(app):
return 0
return 1
def _ping(hostname):
"""
"""
Ping a hostname
"""
print("[BOOT] Invoking ipv4 ping to %s..." % hostname)
p = subprocess.Popen(
["ping", "-c", "2", hostname],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p = subprocess.Popen(["ping", "-c", "2", hostname],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if p.returncode == 0:
print("[BOOT] IPv4 network reachable...")
......@@ -89,8 +95,9 @@ def _ping(hostname):
print("[BOOT] [ERROR] IPv4 network unreachable...")
return 0
def _ping6(hostname):
"""
"""
Ping an ipv6 address
"""
print("[BOOT] Invoking ipv6 ping to %s..." % hostname)
......@@ -104,18 +111,21 @@ def _ping6(hostname):
print("[BOOT] [ERROR] IPv6 network unreachable...")
return 0
def _test_ping(hostname):
is_ready = _ping(hostname)
while is_ready == 0:
sleep(5)
is_ready = _ping(hostname)
def _test_ping6(hostname):
is_ready = _ping6(hostname)
while is_ready == 0:
sleep(5)
is_ready = _ping6(hostname)
def _ping_hostname(hostname):
is_ready = _ping6(hostname)
while is_ready == 0:
......@@ -126,6 +136,7 @@ def _ping_hostname(hostname):
# try ping on ipv6
is_ready = _ping6(hostname)
def _waitIpv6Ready(ipv6_interface):
"""
test if ipv6 is ready on ipv6_interface
......@@ -140,7 +151,7 @@ def _waitIpv6Ready(ipv6_interface):
else:
ipv6_address = ""
print("[BOOT] [ERROR] No IPv6 found on interface %r, "
"try again in 5 seconds..." % ipv6_interface)
"try again in 5 seconds..." % ipv6_interface)
sleep(5)
class BootCommand(ConfigCommand):
......@@ -156,36 +167,50 @@ class BootCommand(ConfigCommand):
help='Message for bang')
return ap
@must_be_root
def take_action(self, args):
configp = self.fetch_config(args)
instance_root = configp.get('slapos','instance_root')
partition_base_name = configp.get('slapformat', 'partition_base_name')
partition_base_name = "slappart"
if configp.has_option('slapformat', 'partition_base_name'):
partition_base_name = configp.get('slapformat', 'partition_base_name')
master_url = urlparse(configp.get('slapos','master_url'))
master_hostname = master_url.hostname
root_check = True
if configp.has_option('slapos', 'root_check'):
root_check = configp.getboolean('slapos', 'root_check')
if root_check:
check_root_user(self)
# Check that we have IPv6 ready
if configp.has_option('slapformat', 'ipv6_interface'):
ipv6_interface = configp.get('slapformat', 'ipv6_interface')
else:
elif configp.has_option('slapformat', 'interface_name'):
ipv6_interface = configp.get('slapformat', 'interface_name')
_waitIpv6Ready(ipv6_interface)
else:
# It is most likely the we are running on unpriviledged environment
# so we for slapformat handle it.
ipv6_interface = None
if ipv6_interface is not None:
_waitIpv6Ready(ipv6_interface)
# Check that node can ping master
if valid_ipv4(master_hostname):
_test_ping(master_hostname)
_test_ping(master_hostname)
elif valid_ipv6(master_hostname):
_test_ping6(master_hostname)
_test_ping6(master_hostname)
else:
# hostname
_ping_hostname(master_hostname)
# hostname
_ping_hostname(master_hostname)
app = SlapOSApp()
# Make sure slapos node format returns ok
while not _runFormat(app):
print("[BOOT] [ERROR] Fail to format, try again in 15 seconds...")
sleep(15)
# Make sure slapos node bang returns ok
while not _runBang(app):
print("[BOOT] [ERROR] Fail to bang, try again in 15 seconds...")
......
......@@ -336,7 +336,8 @@ class TestCliBoot(CliMixin):
SlapOSApp().run.assert_any_call(['node', 'bang', '-m', 'Reboot'])
# timestamp files have been removed
self.assertFalse(os.path.exists(timestamp))
self.assertFalse(os.path.exists(timestamp),
timestamp)
class TestCliNode(CliMixin):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment