summaryrefslogtreecommitdiff
path: root/azurelinuxagent/daemon
diff options
context:
space:
mode:
Diffstat (limited to 'azurelinuxagent/daemon')
-rw-r--r--azurelinuxagent/daemon/__init__.py18
-rw-r--r--azurelinuxagent/daemon/main.py130
-rw-r--r--azurelinuxagent/daemon/resourcedisk/__init__.py20
-rw-r--r--azurelinuxagent/daemon/resourcedisk/default.py219
-rw-r--r--azurelinuxagent/daemon/resourcedisk/factory.py33
-rw-r--r--azurelinuxagent/daemon/resourcedisk/freebsd.py117
-rw-r--r--azurelinuxagent/daemon/scvmm.py74
7 files changed, 611 insertions, 0 deletions
diff --git a/azurelinuxagent/daemon/__init__.py b/azurelinuxagent/daemon/__init__.py
new file mode 100644
index 0000000..979e01b
--- /dev/null
+++ b/azurelinuxagent/daemon/__init__.py
@@ -0,0 +1,18 @@
+# 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+
+#
+
+from azurelinuxagent.daemon.main import get_daemon_handler
diff --git a/azurelinuxagent/daemon/main.py b/azurelinuxagent/daemon/main.py
new file mode 100644
index 0000000..d3185a1
--- /dev/null
+++ b/azurelinuxagent/daemon/main.py
@@ -0,0 +1,130 @@
+# Microsoft Azure Linux Agent
+#
+# 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+
+#
+
+import os
+import sys
+import time
+import traceback
+
+import azurelinuxagent.common.conf as conf
+import azurelinuxagent.common.event as event
+import azurelinuxagent.common.utils.fileutil as fileutil
+import azurelinuxagent.common.logger as logger
+
+from azurelinuxagent.common.future import ustr
+from azurelinuxagent.common.event import add_event, WALAEventOperation
+from azurelinuxagent.common.exception import ProtocolError
+from azurelinuxagent.common.osutil import get_osutil
+from azurelinuxagent.common.protocol import get_protocol_util
+from azurelinuxagent.common.rdma import RDMADeviceHandler, setup_rdma_device
+from azurelinuxagent.common.utils.textutil import parse_doc, find, getattrib
+from azurelinuxagent.common.version import AGENT_LONG_NAME, AGENT_VERSION, \
+ DISTRO_NAME, DISTRO_VERSION, \
+ DISTRO_FULL_NAME, PY_VERSION_MAJOR, \
+ PY_VERSION_MINOR, PY_VERSION_MICRO
+from azurelinuxagent.daemon.resourcedisk import get_resourcedisk_handler
+from azurelinuxagent.daemon.scvmm import get_scvmm_handler
+from azurelinuxagent.pa.provision import get_provision_handler
+from azurelinuxagent.pa.rdma import get_rdma_handler
+from azurelinuxagent.ga.update import get_update_handler
+
+def get_daemon_handler():
+ return DaemonHandler()
+
+class DaemonHandler(object):
+ """
+ Main thread of daemon. It will invoke other threads to do actual work
+ """
+ def __init__(self):
+ self.running = True
+ self.osutil = get_osutil()
+
+ def run(self):
+ logger.info("{0} Version:{1}", AGENT_LONG_NAME, AGENT_VERSION)
+ logger.info("OS: {0} {1}", DISTRO_NAME, DISTRO_VERSION)
+ logger.info("Python: {0}.{1}.{2}", PY_VERSION_MAJOR, PY_VERSION_MINOR,
+ PY_VERSION_MICRO)
+
+ self.check_pid()
+
+ while self.running:
+ try:
+ self.daemon()
+ except Exception as e:
+ err_msg = traceback.format_exc()
+ add_event("WALA", is_success=False, message=ustr(err_msg),
+ op=WALAEventOperation.UnhandledError)
+ logger.info("Sleep 15 seconds and restart daemon")
+ time.sleep(15)
+
+
+ def check_pid(self):
+ """Check whether daemon is already running"""
+ pid = None
+ pid_file = conf.get_agent_pid_file_path()
+ if os.path.isfile(pid_file):
+ pid = fileutil.read_file(pid_file)
+
+ if self.osutil.check_pid_alive(pid):
+ logger.info("Daemon is already running: {0}", pid)
+ sys.exit(0)
+
+ fileutil.write_file(pid_file, ustr(os.getpid()))
+
+ def daemon(self):
+ logger.info("Run daemon")
+
+ self.protocol_util = get_protocol_util()
+ self.scvmm_handler = get_scvmm_handler()
+ self.resourcedisk_handler = get_resourcedisk_handler()
+ self.rdma_handler = get_rdma_handler()
+ self.provision_handler = get_provision_handler()
+ self.update_handler = get_update_handler()
+
+ # Create lib dir
+ if not os.path.isdir(conf.get_lib_dir()):
+ fileutil.mkdir(conf.get_lib_dir(), mode=0o700)
+ os.chdir(conf.get_lib_dir())
+
+ if conf.get_detect_scvmm_env():
+ self.scvmm_handler.run()
+
+ if conf.get_resourcedisk_format():
+ self.resourcedisk_handler.run()
+
+ # Always redetermine the protocol start (e.g., wireserver vs.
+ # on-premise) since a VHD can move between environments
+ self.protocol_util.clear_protocol()
+
+ self.provision_handler.run()
+
+ # Enable RDMA, continue in errors
+ if conf.enable_rdma():
+ self.rdma_handler.install_driver()
+
+ logger.info("RDMA capabilities are enabled in configuration")
+ try:
+ setup_rdma_device()
+ except Exception as e:
+ logger.error("Error setting up rdma device: %s" % e)
+ else:
+ logger.info("RDMA capabilities are not enabled, skipping")
+
+ while self.running:
+ self.update_handler.run_latest()
diff --git a/azurelinuxagent/daemon/resourcedisk/__init__.py b/azurelinuxagent/daemon/resourcedisk/__init__.py
new file mode 100644
index 0000000..021cecd
--- /dev/null
+++ b/azurelinuxagent/daemon/resourcedisk/__init__.py
@@ -0,0 +1,20 @@
+# Microsoft Azure Linux Agent
+#
+# 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+
+#
+
+from azurelinuxagent.daemon.resourcedisk.factory import get_resourcedisk_handler
diff --git a/azurelinuxagent/daemon/resourcedisk/default.py b/azurelinuxagent/daemon/resourcedisk/default.py
new file mode 100644
index 0000000..d2e400a
--- /dev/null
+++ b/azurelinuxagent/daemon/resourcedisk/default.py
@@ -0,0 +1,219 @@
+# 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+
+#
+
+import os
+import re
+import sys
+import threading
+import azurelinuxagent.common.logger as logger
+from azurelinuxagent.common.future import ustr
+import azurelinuxagent.common.conf as conf
+from azurelinuxagent.common.event import add_event, WALAEventOperation
+import azurelinuxagent.common.utils.fileutil as fileutil
+import azurelinuxagent.common.utils.shellutil as shellutil
+from azurelinuxagent.common.exception import ResourceDiskError
+from azurelinuxagent.common.osutil import get_osutil
+
+DATALOSS_WARNING_FILE_NAME="DATALOSS_WARNING_README.txt"
+DATA_LOSS_WARNING="""\
+WARNING: THIS IS A TEMPORARY DISK.
+
+Any data stored on this drive is SUBJECT TO LOSS and THERE IS NO WAY TO RECOVER IT.
+
+Please do not use this disk for storing any personal or application data.
+
+For additional details to please refer to the MSDN documentation at : http://msdn.microsoft.com/en-us/library/windowsazure/jj672979.aspx
+"""
+
+class ResourceDiskHandler(object):
+ def __init__(self):
+ self.osutil = get_osutil()
+
+ def start_activate_resource_disk(self):
+ disk_thread = threading.Thread(target = self.run)
+ disk_thread.start()
+
+ def run(self):
+ mount_point = None
+ if conf.get_resourcedisk_format():
+ mount_point = self.activate_resource_disk()
+ if mount_point is not None and \
+ conf.get_resourcedisk_enable_swap():
+ self.enable_swap(mount_point)
+
+ def activate_resource_disk(self):
+ logger.info("Activate resource disk")
+ try:
+ mount_point = conf.get_resourcedisk_mountpoint()
+ fs = conf.get_resourcedisk_filesystem()
+ mount_point = self.mount_resource_disk(mount_point, fs)
+ warning_file = os.path.join(mount_point, DATALOSS_WARNING_FILE_NAME)
+ try:
+ fileutil.write_file(warning_file, DATA_LOSS_WARNING)
+ except IOError as e:
+ logger.warn("Failed to write data loss warnning:{0}", e)
+ return mount_point
+ except ResourceDiskError as e:
+ logger.error("Failed to mount resource disk {0}", e)
+ add_event(name="WALA", is_success=False, message=ustr(e),
+ op=WALAEventOperation.ActivateResourceDisk)
+
+ def enable_swap(self, mount_point):
+ logger.info("Enable swap")
+ try:
+ size_mb = conf.get_resourcedisk_swap_size_mb()
+ self.create_swap_space(mount_point, size_mb)
+ except ResourceDiskError as e:
+ logger.error("Failed to enable swap {0}", e)
+
+ def mount_resource_disk(self, mount_point, fs):
+ device = self.osutil.device_for_ide_port(1)
+ if device is None:
+ raise ResourceDiskError("unable to detect disk topology")
+
+ device = "/dev/" + device
+ mountlist = shellutil.run_get_output("mount")[1]
+ existing = self.osutil.get_mount_point(mountlist, device)
+
+ if(existing):
+ logger.info("Resource disk {0}1 is already mounted", device)
+ return existing
+
+ fileutil.mkdir(mount_point, mode=0o755)
+
+ logger.info("Detect GPT...")
+ partition = device + "1"
+ ret = shellutil.run_get_output("parted {0} print".format(device))
+ if ret[0]:
+ raise ResourceDiskError("({0}) {1}".format(device, ret[1]))
+
+ if "gpt" in ret[1]:
+ logger.info("GPT detected")
+ logger.info("Get GPT partitions")
+ parts = [x for x in ret[1].split("\n") if re.match("^\s*[0-9]+", x)]
+ logger.info("Found more than {0} GPT partitions.", len(parts))
+ if len(parts) > 1:
+ logger.info("Remove old GPT partitions")
+ for i in range(1, len(parts) + 1):
+ logger.info("Remove partition: {0}", i)
+ shellutil.run("parted {0} rm {1}".format(device, i))
+
+ logger.info("Create a new GPT partition using entire disk space")
+ shellutil.run("parted {0} mkpart primary 0% 100%".format(device))
+
+ logger.info("Format partition: {0} with fstype {1}",partition,fs)
+ shellutil.run("mkfs." + fs + " " + partition + " -F")
+ else:
+ logger.info("GPT not detected")
+ logger.info("Check fstype")
+ ret = shellutil.run_get_output("sfdisk -q -c {0} 1".format(device))
+ if ret[1].rstrip() == "7" and fs != "ntfs":
+ logger.info("The partition is formatted with ntfs")
+ logger.info("Format partition: {0} with fstype {1}",partition,fs)
+ shellutil.run("sfdisk -c {0} 1 83".format(device))
+ shellutil.run("mkfs." + fs + " " + partition + " -F")
+
+ logger.info("Mount resource disk")
+ ret = shellutil.run("mount {0} {1}".format(partition, mount_point),
+ chk_err=False)
+ if ret:
+ logger.warn("Failed to mount resource disk. Retry mounting")
+ shellutil.run("mkfs." + fs + " " + partition + " -F")
+ ret = shellutil.run("mount {0} {1}".format(partition, mount_point))
+ if ret:
+ raise ResourceDiskError("({0}) {1}".format(partition, ret))
+
+ logger.info("Resource disk ({0}) is mounted at {1} with fstype {2}",
+ device, mount_point, fs)
+ return mount_point
+
+ def create_swap_space(self, mount_point, size_mb):
+ size_kb = size_mb * 1024
+ size = size_kb * 1024
+ swapfile = os.path.join(mount_point, 'swapfile')
+ swaplist = shellutil.run_get_output("swapon -s")[1]
+
+ if swapfile in swaplist and os.path.getsize(swapfile) == size:
+ logger.info("Swap already enabled")
+ return
+
+ if os.path.isfile(swapfile) and os.path.getsize(swapfile) != size:
+ logger.info("Remove old swap file")
+ shellutil.run("swapoff -a", chk_err=False)
+ os.remove(swapfile)
+
+ if not os.path.isfile(swapfile):
+ logger.info("Create swap file")
+ self.mkfile(swapfile, size_kb * 1024)
+ shellutil.run("mkswap {0}".format(swapfile))
+ if shellutil.run("swapon {0}".format(swapfile)):
+ raise ResourceDiskError("{0}".format(swapfile))
+ logger.info("Enabled {0}KB of swap at {1}".format(size_kb, swapfile))
+
+ def mkfile(self, filename, nbytes):
+ """
+ Create a non-sparse file of that size. Deletes and replaces existing file.
+
+ To allow efficient execution, fallocate will be tried first. This includes
+ ``os.posix_fallocate`` on Python 3.3+ (unix) and the ``fallocate`` command
+ in the popular ``util-linux{,-ng}`` package.
+
+ A dd fallback will be tried too. When size < 64M, perform single-pass dd.
+ Otherwise do two-pass dd.
+ """
+
+ if not isinstance(nbytes, int):
+ nbytes = int(nbytes)
+
+ if nbytes < 0:
+ raise ValueError(nbytes)
+
+ if os.path.isfile(filename):
+ os.remove(filename)
+
+ # os.posix_fallocate
+ if sys.version_info >= (3, 3):
+ # Probable errors:
+ # - OSError: Seen on Cygwin, libc notimpl?
+ # - AttributeError: What if someone runs this under...
+ with open(filename, 'w') as f:
+ try:
+ os.posix_fallocate(f.fileno(), 0, nbytes)
+ return 0
+ except:
+ # Not confident with this thing, just keep trying...
+ pass
+
+ # fallocate command
+ fn_sh = shellutil.quote((filename,))
+ ret = shellutil.run(u"fallocate -l {0} {1}".format(nbytes, fn_sh))
+ if ret != 127: # 127 = command not found
+ return ret
+
+ # dd fallback
+ dd_maxbs = 64 * 1024 ** 2
+ dd_cmd = "dd if=/dev/zero bs={0} count={1} conv=notrunc of={2}"
+
+ blocks = int(nbytes / dd_maxbs)
+ if blocks > 0:
+ ret = shellutil.run(dd_cmd.format(dd_maxbs, fn_sh, blocks)) << 8
+
+ remains = int(nbytes % dd_maxbs)
+ if remains > 0:
+ ret += shellutil.run(dd_cmd.format(remains, fn_sh, 1))
+
+ return ret
diff --git a/azurelinuxagent/daemon/resourcedisk/factory.py b/azurelinuxagent/daemon/resourcedisk/factory.py
new file mode 100644
index 0000000..76e5a23
--- /dev/null
+++ b/azurelinuxagent/daemon/resourcedisk/factory.py
@@ -0,0 +1,33 @@
+# 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+
+#
+
+import azurelinuxagent.common.logger as logger
+from azurelinuxagent.common.utils.textutil import Version
+from azurelinuxagent.common.version import DISTRO_NAME, \
+ DISTRO_VERSION, \
+ DISTRO_FULL_NAME
+from .default import ResourceDiskHandler
+from .freebsd import FreeBSDResourceDiskHandler
+
+def get_resourcedisk_handler(distro_name=DISTRO_NAME,
+ distro_version=DISTRO_VERSION,
+ distro_full_name=DISTRO_FULL_NAME):
+ if distro_name == "freebsd":
+ return FreeBSDResourceDiskHandler()
+
+ return ResourceDiskHandler()
+
diff --git a/azurelinuxagent/daemon/resourcedisk/freebsd.py b/azurelinuxagent/daemon/resourcedisk/freebsd.py
new file mode 100644
index 0000000..36a3ac9
--- /dev/null
+++ b/azurelinuxagent/daemon/resourcedisk/freebsd.py
@@ -0,0 +1,117 @@
+# Microsoft Azure Linux Agent
+#
+# 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+
+#
+import azurelinuxagent.common.logger as logger
+import azurelinuxagent.common.utils.fileutil as fileutil
+import azurelinuxagent.common.utils.shellutil as shellutil
+from azurelinuxagent.common.exception import ResourceDiskError
+from azurelinuxagent.daemon.resourcedisk.default import ResourceDiskHandler
+
+class FreeBSDResourceDiskHandler(ResourceDiskHandler):
+ """
+ This class handles resource disk mounting for FreeBSD.
+
+ The resource disk locates at following slot:
+ scbus2 on blkvsc1 bus 0:
+ <Msft Virtual Disk 1.0> at scbus2 target 1 lun 0 (da1,pass2)
+
+ There are 2 variations based on partition table type:
+ 1. MBR: The resource disk partition is /dev/da1s1
+ 2. GPT: The resource disk partition is /dev/da1p2, /dev/da1p1 is for reserved usage.
+ """
+ def __init__(self):
+ super(FreeBSDResourceDiskHandler, self).__init__()
+
+ @staticmethod
+ def parse_gpart_list(data):
+ dic = {}
+ for line in data.split('\n'):
+ if line.find("Geom name: ") != -1:
+ geom_name = line[11:]
+ elif line.find("scheme: ") != -1:
+ dic[geom_name] = line[8:]
+ return dic
+
+ def mount_resource_disk(self, mount_point, fs):
+ if fs != 'ufs':
+ raise ResourceDiskError("Unsupported filesystem type:{0}, only ufs is supported.".format(fs))
+
+ # 1. Detect device
+ err, output = shellutil.run_get_output('gpart list')
+ if err:
+ raise ResourceDiskError("Unable to detect resource disk device:{0}".format(output))
+ disks = self.parse_gpart_list(output)
+
+ err, output = shellutil.run_get_output('camcontrol periphlist 2:1:0')
+ if err:
+ raise ResourceDiskError("Unable to detect resource disk device:{0}".format(output))
+
+ # 'da1: generation: 4 index: 1 status: MORE\npass2: generation: 4 index: 2 status: LAST\n'
+ device = None
+ for line in output.split('\n'):
+ index = line.find(':')
+ if index > 0:
+ geom_name = line[:index]
+ if geom_name in disks:
+ device = geom_name
+ break
+
+ if not device:
+ raise ResourceDiskError("Unable to detect resource disk device.")
+ logger.info('Resource disk device {0} found.', device)
+
+ # 2. Detect partition
+ partition_table_type = disks[device]
+
+ if partition_table_type == 'MBR':
+ provider_name = device + 's1'
+ elif partition_table_type == 'GPT':
+ provider_name = device + 'p2'
+ else:
+ raise ResourceDiskError("Unsupported partition table type:{0}".format(output))
+
+ err, output = shellutil.run_get_output('gpart show -p {0}'.format(device))
+ if err or output.find(provider_name) == -1:
+ raise ResourceDiskError("Resource disk partition not found.")
+
+ partition = '/dev/' + provider_name
+ logger.info('Resource disk partition {0} found.', partition)
+
+ # 3. Mount partition
+ mount_list = shellutil.run_get_output("mount")[1]
+ existing = self.osutil.get_mount_point(mount_list, partition)
+
+ if existing:
+ logger.info("Resource disk {0} is already mounted", partition)
+ return existing
+
+ fileutil.mkdir(mount_point, mode=0o755)
+ mount_cmd = 'mount -t {0} {1} {2}'.format(fs, partition, mount_point)
+ err = shellutil.run(mount_cmd, chk_err=False)
+ if err:
+ logger.info('Creating {0} filesystem on partition {1}'.format(fs, partition))
+ err, output = shellutil.run_get_output('newfs -U {0}'.format(partition))
+ if err:
+ raise ResourceDiskError("Failed to create new filesystem on partition {0}, error:{1}"
+ .format(partition, output))
+ err, output = shellutil.run_get_output(mount_cmd, chk_err=False)
+ if err:
+ raise ResourceDiskError("Failed to mount partition {0}, error {1}".format(partition, output))
+
+ logger.info("Resource disk partition {0} is mounted at {1} with fstype {2}", partition, mount_point, fs)
+ return mount_point
diff --git a/azurelinuxagent/daemon/scvmm.py b/azurelinuxagent/daemon/scvmm.py
new file mode 100644
index 0000000..dc6832a
--- /dev/null
+++ b/azurelinuxagent/daemon/scvmm.py
@@ -0,0 +1,74 @@
+# Microsoft Azure Linux Agent
+#
+# 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+
+#
+
+import re
+import os
+import sys
+import subprocess
+import time
+import azurelinuxagent.common.logger as logger
+import azurelinuxagent.common.conf as conf
+from azurelinuxagent.common.osutil import get_osutil
+
+VMM_CONF_FILE_NAME = "linuxosconfiguration.xml"
+VMM_STARTUP_SCRIPT_NAME= "install"
+
+def get_scvmm_handler():
+ return ScvmmHandler()
+
+class ScvmmHandler(object):
+ def __init__(self):
+ self.osutil = get_osutil()
+
+ def detect_scvmm_env(self, dev_dir='/dev'):
+ logger.info("Detecting Microsoft System Center VMM Environment")
+ 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()
+ 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, mount_point=None):
+ logger.info("Starting Microsoft System Center VMM Initialization "
+ "Process")
+ 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],
+ stdout=devnull, stderr=devnull)
+
+ def run(self):
+ if self.detect_scvmm_env():
+ logger.info("Exiting")
+ time.sleep(300)
+ sys.exit(0)