Changed get_serial to be fully parameterized and return the serial
initialized. Added a mapping of attributes between cloud-init and smartos.
This commit is contained in:
@@ -27,25 +27,37 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
import os
|
|
||||||
import os.path
|
|
||||||
import serial
|
|
||||||
from cloudinit import log as logging
|
from cloudinit import log as logging
|
||||||
from cloudinit import sources
|
from cloudinit import sources
|
||||||
from cloudinit import util
|
from cloudinit import util
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
import serial
|
||||||
|
|
||||||
|
|
||||||
DEF_TTY_LOC = '/dev/ttyS1'
|
DEF_TTY_LOC = '/dev/ttyS1'
|
||||||
TTY_LOC = None
|
DEF_TTY_TIMEOUT = 60
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
SMARTOS_ATTRIB_MAP = {
|
||||||
|
#Cloud-init Key : (SmartOS Key, Strip line endings)
|
||||||
|
'local-hostname': ('hostname', True),
|
||||||
|
'public-keys': ('root_authorized_keys', True),
|
||||||
|
'user-script': ('user-script', False),
|
||||||
|
'user-data': ('user-data', False),
|
||||||
|
'iptables_disable': ('iptables_disable', True),
|
||||||
|
'motd_sys_info': ('motd_sys_info', True),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class DataSourceSmartOS(sources.DataSource):
|
class DataSourceSmartOS(sources.DataSource):
|
||||||
def __init__(self, sys_cfg, distro, paths):
|
def __init__(self, sys_cfg, distro, paths):
|
||||||
sources.DataSource.__init__(self, sys_cfg, distro, paths)
|
sources.DataSource.__init__(self, sys_cfg, distro, paths)
|
||||||
self.seed_dir = os.path.join(paths.seed_dir, 'sdc')
|
self.seed_dir = os.path.join(paths.seed_dir, 'sdc')
|
||||||
self.seed = None
|
|
||||||
self.is_smartdc = None
|
self.is_smartdc = None
|
||||||
|
self.seed = self.sys_cfg.get("serial_device", DEF_TTY_LOC)
|
||||||
|
self.seed_timeout = self.sys_cfg.get("serial_timeout",
|
||||||
|
DEF_TTY_TIMEOUT)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
root = sources.DataSource.__str__(self)
|
root = sources.DataSource.__str__(self)
|
||||||
@@ -55,30 +67,25 @@ class DataSourceSmartOS(sources.DataSource):
|
|||||||
md = {}
|
md = {}
|
||||||
ud = ""
|
ud = ""
|
||||||
|
|
||||||
TTY_LOC = self.sys_cfg.get("serial_device", DEF_TTY_LOC)
|
if not os.path.exists(self.seed):
|
||||||
if not os.path.exists(TTY_LOC):
|
|
||||||
LOG.debug("Host does not appear to be on SmartOS")
|
LOG.debug("Host does not appear to be on SmartOS")
|
||||||
return False
|
return False
|
||||||
self.seed = TTY_LOC
|
self.seed = self.seed
|
||||||
|
|
||||||
system_uuid, system_type = dmi_data()
|
system_uuid, system_type = dmi_data()
|
||||||
if 'smartdc' not in system_type.lower():
|
if 'smartdc' not in system_type.lower():
|
||||||
LOG.debug("Host is not on SmartOS")
|
LOG.debug("Host is not on SmartOS")
|
||||||
return False
|
return False
|
||||||
self.is_smartdc = True
|
self.is_smartdc = True
|
||||||
|
|
||||||
hostname = query_data("hostname", strip=True)
|
|
||||||
if not hostname:
|
|
||||||
hostname = system_uuid
|
|
||||||
|
|
||||||
md['local-hostname'] = hostname
|
|
||||||
md['instance-id'] = system_uuid
|
md['instance-id'] = system_uuid
|
||||||
md['public-keys'] = query_data("root_authorized_keys", strip=True)
|
|
||||||
md['user-script'] = query_data("user-script")
|
for ci_noun, attribute in SMARTOS_ATTRIB_MAP.iteritems():
|
||||||
md['user-data'] = query_data("user-script")
|
smartos_noun, strip = attribute
|
||||||
md['iptables_disable'] = query_data("disable_iptables_flag",
|
md[ci_noun] = query_data(smartos_noun, self.seed,
|
||||||
strip=True)
|
self.seed_timeout, strip=strip)
|
||||||
md['motd_sys_info'] = query_data("enable_motd_sys_info", strip=True)
|
|
||||||
|
if not md['local-hostname']:
|
||||||
|
md['local-hostname'] = system_uuid
|
||||||
|
|
||||||
if md['user-data']:
|
if md['user-data']:
|
||||||
ud = md['user-data']
|
ud = md['user-data']
|
||||||
@@ -93,7 +100,7 @@ class DataSourceSmartOS(sources.DataSource):
|
|||||||
return self.metadata['instance-id']
|
return self.metadata['instance-id']
|
||||||
|
|
||||||
|
|
||||||
def get_serial():
|
def get_serial(seed_device, seed_timeout):
|
||||||
"""This is replaced in unit testing, allowing us to replace
|
"""This is replaced in unit testing, allowing us to replace
|
||||||
serial.Serial with a mocked class
|
serial.Serial with a mocked class
|
||||||
|
|
||||||
@@ -102,18 +109,17 @@ def get_serial():
|
|||||||
each line individually up until the single ".", the transfer is
|
each line individually up until the single ".", the transfer is
|
||||||
usually very fast (i.e. microseconds) to get the response.
|
usually very fast (i.e. microseconds) to get the response.
|
||||||
"""
|
"""
|
||||||
if not TTY_LOC:
|
if not seed_device:
|
||||||
raise AttributeError("TTY_LOC value is not set")
|
raise AttributeError("seed_device value is not set")
|
||||||
|
|
||||||
_ret = serial.Serial(TTY_LOC, timeout=60)
|
ser = serial.Serial(seed_device, timeout=seed_timeout)
|
||||||
if not _ret.isOpen():
|
if not ser.isOpen():
|
||||||
raise SystemError("Unable to open %s" % TTY_LOC)
|
raise SystemError("Unable to open %s" % seed_device)
|
||||||
|
|
||||||
return _ret
|
return ser
|
||||||
|
|
||||||
|
|
||||||
|
def query_data(noun, seed_device, seed_timeout, strip=False):
|
||||||
def query_data(noun, strip=False):
|
|
||||||
"""Makes a request to via the serial console via "GET <NOUN>"
|
"""Makes a request to via the serial console via "GET <NOUN>"
|
||||||
|
|
||||||
In the response, the first line is the status, while subsequent lines
|
In the response, the first line is the status, while subsequent lines
|
||||||
@@ -124,7 +130,7 @@ def query_data(noun, strip=False):
|
|||||||
if not noun:
|
if not noun:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
ser = get_serial()
|
ser = get_serial(seed_device, seed_timeout)
|
||||||
ser.write("GET %s\n" % noun.rstrip())
|
ser.write("GET %s\n" % noun.rstrip())
|
||||||
status = str(ser.readline()).rstrip()
|
status = str(ser.readline()).rstrip()
|
||||||
response = []
|
response = []
|
||||||
|
|||||||
@@ -1744,13 +1744,14 @@ def get_mount_info(path, log=LOG):
|
|||||||
lines = load_file(mountinfo_path).splitlines()
|
lines = load_file(mountinfo_path).splitlines()
|
||||||
return parse_mount_info(path, lines, log)
|
return parse_mount_info(path, lines, log)
|
||||||
|
|
||||||
|
|
||||||
def which(program):
|
def which(program):
|
||||||
# Return path of program for execution if found in path
|
# Return path of program for execution if found in path
|
||||||
def is_exe(fpath):
|
def is_exe(fpath):
|
||||||
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
|
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
|
||||||
|
|
||||||
fpath, fname = os.path.split(program)
|
_fpath, _ = os.path.split(program)
|
||||||
if fpath:
|
if _fpath:
|
||||||
if is_exe(program):
|
if is_exe(program):
|
||||||
return program
|
return program
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ import uuid
|
|||||||
mock_returns = {
|
mock_returns = {
|
||||||
'hostname': 'test-host',
|
'hostname': 'test-host',
|
||||||
'root_authorized_keys': 'ssh-rsa AAAAB3Nz...aC1yc2E= keyname',
|
'root_authorized_keys': 'ssh-rsa AAAAB3Nz...aC1yc2E= keyname',
|
||||||
'disable_iptables_flag': False,
|
'disable_iptables_flag': None,
|
||||||
'enable_motd_sys_info': False,
|
'enable_motd_sys_info': None,
|
||||||
'system_uuid': str(uuid.uuid4()),
|
'system_uuid': str(uuid.uuid4()),
|
||||||
'smartdc': 'smartdc',
|
'smartdc': 'smartdc',
|
||||||
'userdata': """
|
'userdata': """
|
||||||
@@ -118,7 +118,7 @@ class TestSmartOSDataSource(MockerTestCase):
|
|||||||
|
|
||||||
def _get_ds(self):
|
def _get_ds(self):
|
||||||
|
|
||||||
def _get_serial():
|
def _get_serial(*_):
|
||||||
return MockSerial()
|
return MockSerial()
|
||||||
|
|
||||||
def _dmi_data():
|
def _dmi_data():
|
||||||
@@ -169,14 +169,14 @@ class TestSmartOSDataSource(MockerTestCase):
|
|||||||
dsrc = self._get_ds()
|
dsrc = self._get_ds()
|
||||||
ret = dsrc.get_data()
|
ret = dsrc.get_data()
|
||||||
self.assertTrue(ret)
|
self.assertTrue(ret)
|
||||||
self.assertEquals(str(mock_returns['disable_iptables_flag']),
|
self.assertEquals(mock_returns['disable_iptables_flag'],
|
||||||
dsrc.metadata['iptables_disable'])
|
dsrc.metadata['iptables_disable'])
|
||||||
|
|
||||||
def test_motd_sys_info(self):
|
def test_motd_sys_info(self):
|
||||||
dsrc = self._get_ds()
|
dsrc = self._get_ds()
|
||||||
ret = dsrc.get_data()
|
ret = dsrc.get_data()
|
||||||
self.assertTrue(ret)
|
self.assertTrue(ret)
|
||||||
self.assertEquals(str(mock_returns['enable_motd_sys_info']),
|
self.assertEquals(mock_returns['enable_motd_sys_info'],
|
||||||
dsrc.metadata['motd_sys_info'])
|
dsrc.metadata['motd_sys_info'])
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user