Skip to content

Commit

Permalink
Fixes for SCVMM
Browse files Browse the repository at this point in the history
- correct scvmm references
- add unit tests for scvmm detection
- ensure all matching devices are mounted and examined for scvmm configuration
- exit once vmm startup script is found and executed
- fixes Azure#185
  • Loading branch information
hglkrijger committed Jun 9, 2016
1 parent 25a1a91 commit 8e96299
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 27 deletions.
31 changes: 20 additions & 11 deletions azurelinuxagent/common/osutil/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,25 +280,27 @@ def conf_sshd(self, disable_password):


def get_dvd_device(self, dev_dir='/dev'):
patten=r'(sr[0-9]|hd[c-z]|cdrom[0-9]|cd[0-9])'
for dvd in [re.match(patten, dev) for dev in os.listdir(dev_dir)]:
pattern=r'(sr[0-9]|hd[c-z]|cdrom[0-9]|cd[0-9])'
for dvd in [re.match(pattern, dev) for dev in os.listdir(dev_dir)]:
if dvd is not None:
return "/dev/{0}".format(dvd.group(0))
raise OSUtilError("Failed to get dvd device")

def mount_dvd(self, max_retry=6, chk_err=True):
dvd = self.get_dvd_device()
mount_point = conf.get_dvd_mount_point()
def mount_dvd(self, max_retry=6, chk_err=True, dvd_device=None, mount_point=None):
if dvd_device is None:
dvd_device = self.get_dvd_device()
if mount_point is None:
mount_point = conf.get_dvd_mount_point()
mountlist = shellutil.run_get_output("mount")[1]
existing = self.get_mount_point(mountlist, dvd)
existing = self.get_mount_point(mountlist, dvd_device)
if existing is not None: #Already mounted
logger.info("{0} is already mounted at {1}", dvd, existing)
logger.info("{0} is already mounted at {1}", dvd_device, existing)
return
if not os.path.isdir(mount_point):
os.makedirs(mount_point)

for retry in range(0, max_retry):
retcode = self.mount(dvd, mount_point, option="-o ro -t udf,iso9660",
retcode = self.mount(dvd_device, mount_point, option="-o ro -t udf,iso9660",
chk_err=chk_err)
if retcode == 0:
logger.info("Successfully mounted dvd")
Expand All @@ -310,8 +312,9 @@ def mount_dvd(self, max_retry=6, chk_err=True):
if chk_err:
raise OSUtilError("Failed to mount dvd.")

def umount_dvd(self, chk_err=True):
mount_point = conf.get_dvd_mount_point()
def umount_dvd(self, chk_err=True, mount_point=None):
if mount_point is None:
mount_point = conf.get_dvd_mount_point()
retcode = self.umount(mount_point, chk_err=chk_err)
if chk_err and retcode != 0:
raise OSUtilError("Failed to umount dvd.")
Expand All @@ -322,7 +325,13 @@ def eject_dvd(self, chk_err=True):
if chk_err and retcode != 0:
raise OSUtilError("Failed to eject dvd: ret={0}".format(retcode))

def load_atappix_mod(self):
def try_load_atapiix_mod(self):
try:
self.load_atapiix_mod()
except Exception as e:
logger.warn("Could not load ATAPI driver: {0}".format(e))

def load_atapiix_mod(self):
if self.is_atapiix_mod_loaded():
return
ret, kern_version = shellutil.run_get_output("uname -r")
Expand Down
2 changes: 1 addition & 1 deletion azurelinuxagent/daemon/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def daemon(self):

if conf.get_detect_scvmm_env():
self.scvmm_handler.run()

if conf.get_resourcedisk_format():
self.resourcedisk_handler.run()

Expand Down
30 changes: 21 additions & 9 deletions azurelinuxagent/daemon/scvmm.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
# Requires Python 2.4+ and Openssl 1.0+
#

import re
import os
import sys
import subprocess
Expand All @@ -34,21 +35,32 @@ class ScvmmHandler(object):
def __init__(self):
self.osutil = get_osutil()

def detect_scvmm_env(self):
def detect_scvmm_env(self, dev_dir='/dev'):
logger.info("Detecting Microsoft System Center VMM Environment")
self.osutil.mount_dvd(max_retry=1, chk_err=False)
found=False

# try to load the ATAPI driver, continue on failure
self.osutil.try_load_atapiix_mod()

# cycle through all available /dev/sr*|hd*|cdrom*|cd* looking for the scvmm configuration file
mount_point = conf.get_dvd_mount_point()
found = os.path.isfile(os.path.join(mount_point, VMM_CONF_FILE_NAME))
if found:
self.start_scvmm_agent()
else:
self.osutil.umount_dvd(chk_err=False)
for devices in filter(lambda x: x is not None, [re.match(r'(sr[0-9]|hd[c-z]|cdrom[0-9]?|cd[0-9]+)', dev) for dev in os.listdir(dev_dir)]):
dvd_device = os.path.join(dev_dir, devices.group(0))
self.osutil.mount_dvd(max_retry=1, chk_err=False, dvd_device=dvd_device, mount_point=mount_point)
found = os.path.isfile(os.path.join(mount_point, VMM_CONF_FILE_NAME))
if found:
self.start_scvmm_agent(mount_point=mount_point)
break
else:
self.osutil.umount_dvd(chk_err=False, mount_point=mount_point)

return found

def start_scvmm_agent(self):
def start_scvmm_agent(self, mount_point=None):
logger.info("Starting Microsoft System Center VMM Initialization "
"Process")
mount_point = conf.get_dvd_mount_point()
if mount_point is None:
mount_point = conf.get_dvd_mount_point()
startup_script = os.path.join(mount_point, VMM_STARTUP_SCRIPT_NAME)
devnull = open(os.devnull, 'w')
subprocess.Popen(["/bin/bash", startup_script, "-p " + mount_point],
Expand Down
8 changes: 2 additions & 6 deletions tests/distro/test_resourceDisk.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,7 @@
# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx

from tests.tools import *
import azurelinuxagent.distro.default.resourceDisk as resourceDisk
from azurelinuxagent.distro.loader import get_distro
from azurelinuxagent.distro.default.protocolUtil import *
import azurelinuxagent.utils.fileutil as fileutil

from azurelinuxagent.daemon.resourcedisk import get_resourcedisk_handler

class TestResourceDisk(AgentTestCase):
def test_mkfile(self):
Expand All @@ -34,7 +30,7 @@ def test_mkfile(self):
os.remove(test_file)

# execute
get_distro().resource_disk_handler.mkfile(test_file, file_size)
get_resourcedisk_handler().mkfile(test_file, file_size)

# assert
assert os.path.exists(test_file)
Expand Down
85 changes: 85 additions & 0 deletions tests/distro/test_scvmm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Copyright 2014 Microsoft Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Requires Python 2.4+ and Openssl 1.0+
#
# Implements parts of RFC 2131, 1541, 1497 and
# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx

import mock
from tests.tools import *

import azurelinuxagent.daemon.scvmm as scvmm
from azurelinuxagent.daemon.main import *
from azurelinuxagent.common.osutil.default import DefaultOSUtil

class TestSCVMM(AgentTestCase):
def test_scvmm_detection_with_file(self):
# setup
conf.get_dvd_mount_point = Mock(return_value=self.tmp_dir)
conf.get_detect_scvmm_env = Mock(return_value=True)
scvmm_file = os.path.join(self.tmp_dir, scvmm.VMM_CONF_FILE_NAME)
fileutil.write_file(scvmm_file, "")

patch = mock.patch.object(scvmm.ScvmmHandler, 'start_scvmm_agent').start()

# execute
with self.assertRaises(SystemExit):
get_daemon_handler().daemon()

# assert
patch.assert_called()

# cleanup
os.remove(scvmm_file)


def test_scvmm_detection_with_multiple_cdroms(self):
# setup
conf.get_dvd_mount_point = Mock(return_value=self.tmp_dir)
conf.get_detect_scvmm_env = Mock(return_value=True)

patch_mount = mock.patch.object(DefaultOSUtil, 'mount_dvd').start()

# execute
with patch('os.listdir', return_value=["sr0", "sr1", "sr2"]):
scvmm.ScvmmHandler().detect_scvmm_env()

# assert
assert patch_mount.call_count == 3
assert patch_mount.call_args_list[0][1]['dvd_device'] == '/dev/sr0'
assert patch_mount.call_args_list[1][1]['dvd_device'] == '/dev/sr1'
assert patch_mount.call_args_list[2][1]['dvd_device'] == '/dev/sr2'


def test_scvmm_detection_without_file(self):
# setup
conf.get_dvd_mount_point = Mock(return_value=self.tmp_dir)
conf.get_detect_scvmm_env = Mock(return_value=True)
scvmm_file = os.path.join(self.tmp_dir, scvmm.VMM_CONF_FILE_NAME)
if os.path.exists(scvmm_file):
os.remove(scvmm_file)

patch_start = mock.patch.object(scvmm.ScvmmHandler, 'start_scvmm_agent').start()

# execute
scvmm.ScvmmHandler().detect_scvmm_env()

# assert
patch_start.assert_not_called()


if __name__ == '__main__':
unittest.main()

0 comments on commit 8e96299

Please sign in to comment.