summaryrefslogtreecommitdiff
path: root/azurelinuxagent/distro
diff options
context:
space:
mode:
Diffstat (limited to 'azurelinuxagent/distro')
-rw-r--r--azurelinuxagent/distro/__init__.py2
-rw-r--r--azurelinuxagent/distro/coreos/__init__.py18
-rw-r--r--azurelinuxagent/distro/coreos/deprovision.py33
-rw-r--r--azurelinuxagent/distro/coreos/distro.py29
-rw-r--r--azurelinuxagent/distro/coreos/osutil.py95
-rw-r--r--azurelinuxagent/distro/debian/__init__.py19
-rw-r--r--azurelinuxagent/distro/debian/distro.py27
-rw-r--r--azurelinuxagent/distro/debian/loader.py24
-rw-r--r--azurelinuxagent/distro/debian/osutil.py47
-rw-r--r--azurelinuxagent/distro/default/__init__.py19
-rw-r--r--azurelinuxagent/distro/default/daemon.py103
-rw-r--r--azurelinuxagent/distro/default/deprovision.py125
-rw-r--r--azurelinuxagent/distro/default/dhcp.py318
-rw-r--r--azurelinuxagent/distro/default/distro.py51
-rw-r--r--azurelinuxagent/distro/default/env.py104
-rw-r--r--azurelinuxagent/distro/default/extension.py817
-rw-r--r--azurelinuxagent/distro/default/init.py53
-rw-r--r--azurelinuxagent/distro/default/monitor.py182
-rw-r--r--azurelinuxagent/distro/default/osutil.py623
-rw-r--r--azurelinuxagent/distro/default/protocolUtil.py243
-rw-r--r--azurelinuxagent/distro/default/provision.py191
-rw-r--r--azurelinuxagent/distro/default/resourceDisk.py167
-rw-r--r--azurelinuxagent/distro/default/scvmm.py48
-rw-r--r--azurelinuxagent/distro/loader.py67
-rw-r--r--azurelinuxagent/distro/redhat/__init__.py19
-rw-r--r--azurelinuxagent/distro/redhat/distro.py32
-rw-r--r--azurelinuxagent/distro/redhat/osutil.py115
-rw-r--r--azurelinuxagent/distro/suse/__init__.py2
-rw-r--r--azurelinuxagent/distro/suse/distro.py32
-rw-r--r--azurelinuxagent/distro/suse/osutil.py108
-rw-r--r--azurelinuxagent/distro/ubuntu/__init__.py19
-rw-r--r--azurelinuxagent/distro/ubuntu/deprovision.py46
-rw-r--r--azurelinuxagent/distro/ubuntu/distro.py55
-rw-r--r--azurelinuxagent/distro/ubuntu/osutil.py75
-rw-r--r--azurelinuxagent/distro/ubuntu/provision.py98
35 files changed, 0 insertions, 4006 deletions
diff --git a/azurelinuxagent/distro/__init__.py b/azurelinuxagent/distro/__init__.py
index d9b82f5..1ea2f38 100644
--- a/azurelinuxagent/distro/__init__.py
+++ b/azurelinuxagent/distro/__init__.py
@@ -1,5 +1,3 @@
-# Microsoft Azure Linux Agent
-#
# Copyright 2014 Microsoft Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/azurelinuxagent/distro/coreos/__init__.py b/azurelinuxagent/distro/coreos/__init__.py
deleted file mode 100644
index 8c1bbdb..0000000
--- a/azurelinuxagent/distro/coreos/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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+
-#
diff --git a/azurelinuxagent/distro/coreos/deprovision.py b/azurelinuxagent/distro/coreos/deprovision.py
deleted file mode 100644
index 9642579..0000000
--- a/azurelinuxagent/distro/coreos/deprovision.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# 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.utils.fileutil as fileutil
-from azurelinuxagent.distro.default.deprovision import DeprovisionHandler, DeprovisionAction
-
-class CoreOSDeprovisionHandler(DeprovisionHandler):
- def __init__(self, distro):
- self.distro = distro
-
- def setup(self, deluser):
- warnings, actions = super(CoreOSDeprovisionHandler, self).setup(deluser)
- warnings.append("WARNING! /etc/machine-id will be removed.")
- files_to_del = ['/etc/machine-id']
- actions.append(DeprovisionAction(fileutil.rm_files, files_to_del))
- return warnings, actions
-
diff --git a/azurelinuxagent/distro/coreos/distro.py b/azurelinuxagent/distro/coreos/distro.py
deleted file mode 100644
index 04c7bff..0000000
--- a/azurelinuxagent/distro/coreos/distro.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# 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.distro.default.distro import DefaultDistro
-from azurelinuxagent.distro.coreos.osutil import CoreOSUtil
-from azurelinuxagent.distro.coreos.deprovision import CoreOSDeprovisionHandler
-
-class CoreOSDistro(DefaultDistro):
- def __init__(self):
- super(CoreOSDistro, self).__init__()
- self.osutil = CoreOSUtil()
- self.deprovision_handler = CoreOSDeprovisionHandler(self)
-
diff --git a/azurelinuxagent/distro/coreos/osutil.py b/azurelinuxagent/distro/coreos/osutil.py
deleted file mode 100644
index ffc83e3..0000000
--- a/azurelinuxagent/distro/coreos/osutil.py
+++ /dev/null
@@ -1,95 +0,0 @@
-#
-# 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 pwd
-import shutil
-import socket
-import array
-import struct
-import fcntl
-import time
-import base64
-import azurelinuxagent.logger as logger
-import azurelinuxagent.utils.fileutil as fileutil
-import azurelinuxagent.utils.shellutil as shellutil
-import azurelinuxagent.utils.textutil as textutil
-from azurelinuxagent.distro.default.osutil import DefaultOSUtil
-
-class CoreOSUtil(DefaultOSUtil):
- def __init__(self):
- super(CoreOSUtil, self).__init__()
- self.agent_conf_file_path = '/usr/share/oem/waagent.conf'
- self.waagent_path='/usr/share/oem/bin/waagent'
- self.python_path='/usr/share/oem/python/bin'
- if 'PATH' in os.environ:
- path = "{0}:{1}".format(os.environ['PATH'], self.python_path)
- else:
- path = self.python_path
- os.environ['PATH'] = path
-
- if 'PYTHONPATH' in os.environ:
- py_path = os.environ['PYTHONPATH']
- py_path = "{0}:{1}".format(py_path, self.waagent_path)
- else:
- py_path = self.waagent_path
- os.environ['PYTHONPATH'] = py_path
-
- def is_sys_user(self, username):
- #User 'core' is not a sysuser
- if username == 'core':
- return False
- return super(CoreOSUtil, self).is_sys_user(username)
-
- def is_dhcp_enabled(self):
- return True
-
- def start_network(self) :
- return shellutil.run("systemctl start systemd-networkd", chk_err=False)
-
- def restart_if(self, iface):
- shellutil.run("systemctl restart systemd-networkd")
-
- def restart_ssh_service(self):
- return shellutil.run("systemctl restart sshd", chk_err=False)
-
- def stop_dhcp_service(self):
- return shellutil.run("systemctl stop systemd-networkd", chk_err=False)
-
- def start_dhcp_service(self):
- return shellutil.run("systemctl start systemd-networkd", chk_err=False)
-
- def start_agent_service(self):
- return shellutil.run("systemctl start wagent", chk_err=False)
-
- def stop_agent_service(self):
- return shellutil.run("systemctl stop wagent", chk_err=False)
-
- def get_dhcp_pid(self):
- ret= shellutil.run_get_output("pidof systemd-networkd")
- return ret[1] if ret[0] == 0 else None
-
- def set_ssh_client_alive_interval(self):
- #In CoreOS, /etc/sshd_config is mount readonly. Skip the setting
- pass
-
- def conf_sshd(self, disable_password):
- #In CoreOS, /etc/sshd_config is mount readonly. Skip the setting
- pass
-
diff --git a/azurelinuxagent/distro/debian/__init__.py b/azurelinuxagent/distro/debian/__init__.py
deleted file mode 100644
index d9b82f5..0000000
--- a/azurelinuxagent/distro/debian/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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+
-#
-
diff --git a/azurelinuxagent/distro/debian/distro.py b/azurelinuxagent/distro/debian/distro.py
deleted file mode 100644
index 01f4e3e..0000000
--- a/azurelinuxagent/distro/debian/distro.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# 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.distro.default.distro import DefaultDistro
-from azurelinuxagent.distro.debian.osutil import DebianOSUtil
-
-class DebianDistro(DefaultDistro):
- def __init__(self):
- super(DebianDistro, self).__init__()
- self.osutil = DebianOSUtil()
-
diff --git a/azurelinuxagent/distro/debian/loader.py b/azurelinuxagent/distro/debian/loader.py
deleted file mode 100644
index cc0c06f..0000000
--- a/azurelinuxagent/distro/debian/loader.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# 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+
-#
-
-
-def get_osutil():
- from azurelinuxagent.distro.debian.osutil import DebianOSUtil
- return DebianOSUtil()
-
diff --git a/azurelinuxagent/distro/debian/osutil.py b/azurelinuxagent/distro/debian/osutil.py
deleted file mode 100644
index a40c1de..0000000
--- a/azurelinuxagent/distro/debian/osutil.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#
-# 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 pwd
-import shutil
-import socket
-import array
-import struct
-import fcntl
-import time
-import base64
-import azurelinuxagent.logger as logger
-import azurelinuxagent.utils.fileutil as fileutil
-import azurelinuxagent.utils.shellutil as shellutil
-import azurelinuxagent.utils.textutil as textutil
-from azurelinuxagent.distro.default.osutil import DefaultOSUtil
-
-class DebianOSUtil(DefaultOSUtil):
- def __init__(self):
- super(DebianOSUtil, self).__init__()
-
- def restart_ssh_service(self):
- return shellutil.run("service sshd restart", chk_err=False)
-
- def stop_agent_service(self):
- return shellutil.run("service azurelinuxagent stop", chk_err=False)
-
- def start_agent_service(self):
- return shellutil.run("service azurelinuxagent start", chk_err=False)
-
diff --git a/azurelinuxagent/distro/default/__init__.py b/azurelinuxagent/distro/default/__init__.py
deleted file mode 100644
index d9b82f5..0000000
--- a/azurelinuxagent/distro/default/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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+
-#
-
diff --git a/azurelinuxagent/distro/default/daemon.py b/azurelinuxagent/distro/default/daemon.py
deleted file mode 100644
index cf9eb16..0000000
--- a/azurelinuxagent/distro/default/daemon.py
+++ /dev/null
@@ -1,103 +0,0 @@
-# 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 time
-import sys
-import traceback
-import azurelinuxagent.conf as conf
-import azurelinuxagent.logger as logger
-from azurelinuxagent.future import ustr
-from azurelinuxagent.event import add_event, WALAEventOperation
-from azurelinuxagent.exception import ProtocolError
-from azurelinuxagent.metadata import AGENT_LONG_NAME, AGENT_VERSION, \
- DISTRO_NAME, DISTRO_VERSION, \
- DISTRO_FULL_NAME, PY_VERSION_MAJOR, \
- PY_VERSION_MINOR, PY_VERSION_MICRO
-import azurelinuxagent.event as event
-import azurelinuxagent.utils.fileutil as fileutil
-
-
-class DaemonHandler(object):
- def __init__(self, distro):
- self.distro = distro
- self.running = True
-
-
- 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 pid is not None and os.path.isdir(os.path.join("/proc", 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")
- #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():
- if self.distro.scvmm_handler.run():
- return
-
- self.distro.provision_handler.run()
-
- if conf.get_resourcedisk_format():
- self.distro.resource_disk_handler.run()
-
- try:
- protocol = self.distro.protocol_util.detect_protocol()
- except ProtocolError as e:
- logger.error("Failed to detect protocol, exit", e)
- return
-
- self.distro.event_handler.run()
- self.distro.env_handler.run()
-
- while self.running:
- #Handle extensions
- self.distro.ext_handlers_handler.run()
- time.sleep(25)
-
diff --git a/azurelinuxagent/distro/default/deprovision.py b/azurelinuxagent/distro/default/deprovision.py
deleted file mode 100644
index 4db4cdc..0000000
--- a/azurelinuxagent/distro/default/deprovision.py
+++ /dev/null
@@ -1,125 +0,0 @@
-# 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.conf as conf
-from azurelinuxagent.exception import ProtocolError
-from azurelinuxagent.future import read_input
-import azurelinuxagent.utils.fileutil as fileutil
-import azurelinuxagent.utils.shellutil as shellutil
-
-class DeprovisionAction(object):
- def __init__(self, func, args=[], kwargs={}):
- self.func = func
- self.args = args
- self.kwargs = kwargs
-
- def invoke(self):
- self.func(*self.args, **self.kwargs)
-
-class DeprovisionHandler(object):
- def __init__(self, distro):
- self.distro = distro
-
- def del_root_password(self, warnings, actions):
- warnings.append("WARNING! root password will be disabled. "
- "You will not be able to login as root.")
-
- actions.append(DeprovisionAction(self.distro.osutil.del_root_password))
-
- def del_user(self, warnings, actions):
-
- try:
- ovfenv = self.distro.protocol_util.get_ovf_env()
- except ProtocolError:
- warnings.append("WARNING! ovf-env.xml is not found.")
- warnings.append("WARNING! Skip delete user.")
- return
-
- username = ovfenv.username
- warnings.append(("WARNING! {0} account and entire home directory "
- "will be deleted.").format(username))
- actions.append(DeprovisionAction(self.distro.osutil.del_account,
- [username]))
-
-
- def regen_ssh_host_key(self, warnings, actions):
- warnings.append("WARNING! All SSH host key pairs will be deleted.")
- actions.append(DeprovisionAction(shellutil.run,
- ['rm -f /etc/ssh/ssh_host_*key*']))
-
- def stop_agent_service(self, warnings, actions):
- warnings.append("WARNING! The waagent service will be stopped.")
- actions.append(DeprovisionAction(self.distro.osutil.stop_agent_service))
-
- def del_files(self, warnings, actions):
- files_to_del = ['/root/.bash_history', '/var/log/waagent.log']
- actions.append(DeprovisionAction(fileutil.rm_files, files_to_del))
-
- def del_dhcp_lease(self, warnings, actions):
- warnings.append("WARNING! Cached DHCP leases will be deleted.")
- dirs_to_del = ["/var/lib/dhclient", "/var/lib/dhcpcd", "/var/lib/dhcp"]
- actions.append(DeprovisionAction(fileutil.rm_dirs, dirs_to_del))
-
- def del_lib_dir(self, warnings, actions):
- dirs_to_del = [conf.get_lib_dir()]
- actions.append(DeprovisionAction(fileutil.rm_dirs, dirs_to_del))
-
- def reset_hostname(self, warnings, actions):
- localhost = ["localhost.localdomain"]
- actions.append(DeprovisionAction(self.distro.osutil.set_hostname,
- localhost))
- actions.append(DeprovisionAction(self.distro.osutil.set_dhcp_hostname,
- localhost))
-
- def setup(self, deluser):
- warnings = []
- actions = []
-
- self.stop_agent_service(warnings, actions)
- if conf.get_regenerate_ssh_host_key():
- self.regen_ssh_host_key(warnings, actions)
-
- self.del_dhcp_lease(warnings, actions)
- self.reset_hostname(warnings, actions)
-
- if conf.get_delete_root_password():
- self.del_root_password(warnings, actions)
-
- self.del_lib_dir(warnings, actions)
- self.del_files(warnings, actions)
-
- if deluser:
- self.del_user(warnings, actions)
-
- return warnings, actions
-
- def run(self, force=False, deluser=False):
- warnings, actions = self.setup(deluser)
- for warning in warnings:
- print(warning)
-
- if not force:
- confirm = read_input("Do you want to proceed (y/n)")
- if not confirm.lower().startswith('y'):
- return
-
- for action in actions:
- action.invoke()
-
-
diff --git a/azurelinuxagent/distro/default/dhcp.py b/azurelinuxagent/distro/default/dhcp.py
deleted file mode 100644
index fc439d2..0000000
--- a/azurelinuxagent/distro/default/dhcp.py
+++ /dev/null
@@ -1,318 +0,0 @@
-# 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 socket
-import array
-import time
-import threading
-import azurelinuxagent.logger as logger
-import azurelinuxagent.conf as conf
-import azurelinuxagent.utils.fileutil as fileutil
-import azurelinuxagent.utils.shellutil as shellutil
-from azurelinuxagent.utils.textutil import hex_dump, hex_dump2, hex_dump3, \
- compare_bytes, str_to_ord, \
- unpack_big_endian, \
- unpack_little_endian, \
- int_to_ip4_addr
-from azurelinuxagent.exception import DhcpError
-
-
-class DhcpHandler(object):
- """
- Azure use DHCP option 245 to pass endpoint ip to VMs.
- """
- def __init__(self, distro):
- self.distro = distro
- self.endpoint = None
- self.gateway = None
- self.routes = None
-
- def run(self):
- """
- Send dhcp request
- Configure default gateway and routes
- Save wire server endpoint if found
- """
- self.send_dhcp_req()
- self.conf_routes()
-
- def wait_for_network(self):
- """
- Wait for network stack to be initialized.
- """
- ipv4 = self.distro.osutil.get_ip4_addr()
- while ipv4 == '' or ipv4 == '0.0.0.0':
- logger.info("Waiting for network.")
- time.sleep(10)
- logger.info("Try to start network interface.")
- self.distro.osutil.start_network()
- ipv4 = self.distro.osutil.get_ip4_addr()
-
- def conf_routes(self):
- logger.info("Configure routes")
- logger.info("Gateway:{0}", self.gateway)
- logger.info("Routes:{0}", self.routes)
- #Add default gateway
- if self.gateway is not None:
- self.distro.osutil.route_add(0 , 0, self.gateway)
- if self.routes is not None:
- for route in self.routes:
- self.distro.osutil.route_add(route[0], route[1], route[2])
-
- def _send_dhcp_req(self, request):
- __waiting_duration__ = [0, 10, 30, 60, 60]
- for duration in __waiting_duration__:
- try:
- self.distro.osutil.allow_dhcp_broadcast()
- response = socket_send(request)
- validate_dhcp_resp(request, response)
- return response
- except DhcpError as e:
- logger.warn("Failed to send DHCP request: {0}", e)
- time.sleep(duration)
- return None
-
- def send_dhcp_req(self):
- """
- Build dhcp request with mac addr
- Configure route to allow dhcp traffic
- Stop dhcp service if necessary
- """
- logger.info("Send dhcp request")
- mac_addr = self.distro.osutil.get_mac_addr()
- req = build_dhcp_request(mac_addr)
-
- # Temporary allow broadcast for dhcp. Remove the route when done.
- missing_default_route = self.distro.osutil.is_missing_default_route()
- ifname = self.distro.osutil.get_if_name()
- if missing_default_route:
- self.distro.osutil.set_route_for_dhcp_broadcast(ifname)
-
- # In some distros, dhcp service needs to be shutdown before agent probe
- # endpoint through dhcp.
- if self.distro.osutil.is_dhcp_enabled():
- self.distro.osutil.stop_dhcp_service()
-
- resp = self._send_dhcp_req(req)
-
- if self.distro.osutil.is_dhcp_enabled():
- self.distro.osutil.start_dhcp_service()
-
- if missing_default_route:
- self.distro.osutil.remove_route_for_dhcp_broadcast(ifname)
-
- if resp is None:
- raise DhcpError("Failed to receive dhcp response.")
- self.endpoint, self.gateway, self.routes = parse_dhcp_resp(resp)
-
-def validate_dhcp_resp(request, response):
- bytes_recv = len(response)
- if bytes_recv < 0xF6:
- logger.error("HandleDhcpResponse: Too few bytes received:{0}",
- bytes_recv)
- return False
-
- logger.verb("BytesReceived:{0}", hex(bytes_recv))
- logger.verb("DHCP response:{0}", hex_dump(response, bytes_recv))
-
- # check transactionId, cookie, MAC address cookie should never mismatch
- # transactionId and MAC address may mismatch if we see a response
- # meant from another machine
- if not compare_bytes(request, response, 0xEC, 4):
- logger.verb("Cookie not match:\nsend={0},\nreceive={1}",
- hex_dump3(request, 0xEC, 4),
- hex_dump3(response, 0xEC, 4))
- raise DhcpError("Cookie in dhcp respones doesn't match the request")
-
- if not compare_bytes(request, response, 4, 4):
- logger.verb("TransactionID not match:\nsend={0},\nreceive={1}",
- hex_dump3(request, 4, 4),
- hex_dump3(response, 4, 4))
- raise DhcpError("TransactionID in dhcp respones "
- "doesn't match the request")
-
- if not compare_bytes(request, response, 0x1C, 6):
- logger.verb("Mac Address not match:\nsend={0},\nreceive={1}",
- hex_dump3(request, 0x1C, 6),
- hex_dump3(response, 0x1C, 6))
- raise DhcpError("Mac Addr in dhcp respones "
- "doesn't match the request")
-
-def parse_route(response, option, i, length, bytes_recv):
- # http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
- logger.verb("Routes at offset: {0} with length:{1}", hex(i), hex(length))
- routes = []
- if length < 5:
- logger.error("Data too small for option:{0}", option)
- j = i + 2
- while j < (i + length + 2):
- mask_len_bits = str_to_ord(response[j])
- mask_len_bytes = (((mask_len_bits + 7) & ~7) >> 3)
- mask = 0xFFFFFFFF & (0xFFFFFFFF << (32 - mask_len_bits))
- j += 1
- net = unpack_big_endian(response, j, mask_len_bytes)
- net <<= (32 - mask_len_bytes * 8)
- net &= mask
- j += mask_len_bytes
- gateway = unpack_big_endian(response, j, 4)
- j += 4
- routes.append((net, mask, gateway))
- if j != (i + length + 2):
- logger.error("Unable to parse routes")
- return routes
-
-def parse_ip_addr(response, option, i, length, bytes_recv):
- if i + 5 < bytes_recv:
- if length != 4:
- logger.error("Endpoint or Default Gateway not 4 bytes")
- return None
- addr = unpack_big_endian(response, i + 2, 4)
- ip_addr = int_to_ip4_addr(addr)
- return ip_addr
- else:
- logger.error("Data too small for option:{0}", option)
- return None
-
-def parse_dhcp_resp(response):
- """
- Parse DHCP response:
- Returns endpoint server or None on error.
- """
- logger.verb("parse Dhcp Response")
- bytes_recv = len(response)
- endpoint = None
- gateway = None
- routes = None
-
- # Walk all the returned options, parsing out what we need, ignoring the
- # others. We need the custom option 245 to find the the endpoint we talk to,
- # as well as, to handle some Linux DHCP client incompatibilities,
- # options 3 for default gateway and 249 for routes. And 255 is end.
-
- i = 0xF0 # offset to first option
- while i < bytes_recv:
- option = str_to_ord(response[i])
- length = 0
- if (i + 1) < bytes_recv:
- length = str_to_ord(response[i + 1])
- logger.verb("DHCP option {0} at offset:{1} with length:{2}",
- hex(option), hex(i), hex(length))
- if option == 255:
- logger.verb("DHCP packet ended at offset:{0}", hex(i))
- break
- elif option == 249:
- routes = parse_route(response, option, i, length, bytes_recv)
- elif option == 3:
- gateway = parse_ip_addr(response, option, i, length, bytes_recv)
- logger.verb("Default gateway:{0}, at {1}", gateway, hex(i))
- elif option == 245:
- endpoint = parse_ip_addr(response, option, i, length, bytes_recv)
- logger.verb("Azure wire protocol endpoint:{0}, at {1}", gateway,
- hex(i))
- else:
- logger.verb("Skipping DHCP option:{0} at {1} with length {2}",
- hex(option), hex(i), hex(length))
- i += length + 2
- return endpoint, gateway, routes
-
-def socket_send(request):
- sock = None
- try:
- sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
- socket.IPPROTO_UDP)
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- sock.bind(("0.0.0.0", 68))
- sock.sendto(request, ("<broadcast>", 67))
- sock.settimeout(10)
- logger.verb("Send DHCP request: Setting socket.timeout=10, "
- "entering recv")
- response = sock.recv(1024)
- return response
- except IOError as e:
- raise DhcpError("{0}".format(e))
- finally:
- if sock is not None:
- sock.close()
-
-def build_dhcp_request(mac_addr):
- """
- Build DHCP request string.
- """
- #
- # typedef struct _DHCP {
- # UINT8 Opcode; /* op: BOOTREQUEST or BOOTREPLY */
- # UINT8 HardwareAddressType; /* htype: ethernet */
- # UINT8 HardwareAddressLength; /* hlen: 6 (48 bit mac address) */
- # UINT8 Hops; /* hops: 0 */
- # UINT8 TransactionID[4]; /* xid: random */
- # UINT8 Seconds[2]; /* secs: 0 */
- # UINT8 Flags[2]; /* flags: 0 or 0x8000 for broadcast */
- # UINT8 ClientIpAddress[4]; /* ciaddr: 0 */
- # UINT8 YourIpAddress[4]; /* yiaddr: 0 */
- # UINT8 ServerIpAddress[4]; /* siaddr: 0 */
- # UINT8 RelayAgentIpAddress[4]; /* giaddr: 0 */
- # UINT8 ClientHardwareAddress[16]; /* chaddr: 6 byte eth MAC address */
- # UINT8 ServerName[64]; /* sname: 0 */
- # UINT8 BootFileName[128]; /* file: 0 */
- # UINT8 MagicCookie[4]; /* 99 130 83 99 */
- # /* 0x63 0x82 0x53 0x63 */
- # /* options -- hard code ours */
- #
- # UINT8 MessageTypeCode; /* 53 */
- # UINT8 MessageTypeLength; /* 1 */
- # UINT8 MessageType; /* 1 for DISCOVER */
- # UINT8 End; /* 255 */
- # } DHCP;
- #
-
- # tuple of 244 zeros
- # (struct.pack_into would be good here, but requires Python 2.5)
- request = [0] * 244
-
- trans_id = gen_trans_id()
-
- # Opcode = 1
- # HardwareAddressType = 1 (ethernet/MAC)
- # HardwareAddressLength = 6 (ethernet/MAC/48 bits)
- for a in range(0, 3):
- request[a] = [1, 1, 6][a]
-
- # fill in transaction id (random number to ensure response matches request)
- for a in range(0, 4):
- request[4 + a] = str_to_ord(trans_id[a])
-
- logger.verb("BuildDhcpRequest: transactionId:%s,%04X" % (
- hex_dump2(trans_id),
- unpack_big_endian(request, 4, 4)))
-
- # fill in ClientHardwareAddress
- for a in range(0, 6):
- request[0x1C + a] = str_to_ord(mac_addr[a])
-
- # DHCP Magic Cookie: 99, 130, 83, 99
- # MessageTypeCode = 53 DHCP Message Type
- # MessageTypeLength = 1
- # MessageType = DHCPDISCOVER
- # End = 255 DHCP_END
- for a in range(0, 8):
- request[0xEC + a] = [99, 130, 83, 99, 53, 1, 1, 255][a]
- return array.array("B", request)
-
-def gen_trans_id():
- return os.urandom(4)
diff --git a/azurelinuxagent/distro/default/distro.py b/azurelinuxagent/distro/default/distro.py
deleted file mode 100644
index ca0d77e..0000000
--- a/azurelinuxagent/distro/default/distro.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# 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.conf import ConfigurationProvider
-from azurelinuxagent.distro.default.osutil import DefaultOSUtil
-from azurelinuxagent.distro.default.daemon import DaemonHandler
-from azurelinuxagent.distro.default.init import InitHandler
-from azurelinuxagent.distro.default.monitor import MonitorHandler
-from azurelinuxagent.distro.default.dhcp import DhcpHandler
-from azurelinuxagent.distro.default.protocolUtil import ProtocolUtil
-from azurelinuxagent.distro.default.scvmm import ScvmmHandler
-from azurelinuxagent.distro.default.env import EnvHandler
-from azurelinuxagent.distro.default.provision import ProvisionHandler
-from azurelinuxagent.distro.default.resourceDisk import ResourceDiskHandler
-from azurelinuxagent.distro.default.extension import ExtHandlersHandler
-from azurelinuxagent.distro.default.deprovision import DeprovisionHandler
-
-class DefaultDistro(object):
- """
- """
- def __init__(self):
- self.osutil = DefaultOSUtil()
- self.protocol_util = ProtocolUtil(self)
-
- self.init_handler = InitHandler(self)
- self.daemon_handler = DaemonHandler(self)
- self.event_handler = MonitorHandler(self)
- self.dhcp_handler = DhcpHandler(self)
- self.scvmm_handler = ScvmmHandler(self)
- self.env_handler = EnvHandler(self)
- self.provision_handler = ProvisionHandler(self)
- self.resource_disk_handler = ResourceDiskHandler(self)
- self.ext_handlers_handler = ExtHandlersHandler(self)
- self.deprovision_handler = DeprovisionHandler(self)
-
diff --git a/azurelinuxagent/distro/default/env.py b/azurelinuxagent/distro/default/env.py
deleted file mode 100644
index 7878cff..0000000
--- a/azurelinuxagent/distro/default/env.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# 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 socket
-import threading
-import time
-import azurelinuxagent.logger as logger
-import azurelinuxagent.conf as conf
-
-class EnvHandler(object):
- """
- Monitor changes to dhcp and hostname.
- If dhcp clinet process re-start has occurred, reset routes, dhcp with fabric.
-
- Monitor scsi disk.
- If new scsi disk found, set timeout
- """
- def __init__(self, distro):
- self.distro = distro
- self.stopped = True
- self.hostname = None
- self.dhcpid = None
- self.server_thread=None
-
- def run(self):
- if not self.stopped:
- logger.info("Stop existing env monitor service.")
- self.stop()
-
- self.stopped = False
- logger.info("Start env monitor service.")
- self.distro.dhcp_handler.conf_routes()
- self.hostname = socket.gethostname()
- self.dhcpid = self.distro.osutil.get_dhcp_pid()
- self.server_thread = threading.Thread(target = self.monitor)
- self.server_thread.setDaemon(True)
- self.server_thread.start()
-
- def monitor(self):
- """
- Monitor dhcp client pid and hostname.
- If dhcp clinet process re-start has occurred, reset routes.
- """
- while not self.stopped:
- self.distro.osutil.remove_rules_files()
- timeout = conf.get_root_device_scsi_timeout()
- if timeout is not None:
- self.distro.osutil.set_scsi_disks_timeout(timeout)
- if conf.get_monitor_hostname():
- self.handle_hostname_update()
- self.handle_dhclient_restart()
- time.sleep(5)
-
- def handle_hostname_update(self):
- curr_hostname = socket.gethostname()
- if curr_hostname != self.hostname:
- logger.info("EnvMonitor: Detected host name change: {0} -> {1}",
- self.hostname, curr_hostname)
- self.distro.osutil.set_hostname(curr_hostname)
- self.distro.osutil.publish_hostname(curr_hostname)
- self.hostname = curr_hostname
-
- def handle_dhclient_restart(self):
- if self.dhcpid is None:
- logger.warn("Dhcp client is not running. ")
- self.dhcpid = self.distro.osutil.get_dhcp_pid()
- return
-
- #The dhcp process hasn't changed since last check
- if os.path.isdir(os.path.join('/proc', self.dhcpid.strip())):
- return
-
- newpid = self.distro.osutil.get_dhcp_pid()
- if newpid is not None and newpid != self.dhcpid:
- logger.info("EnvMonitor: Detected dhcp client restart. "
- "Restoring routing table.")
- self.distro.dhcp_handler.conf_routes()
- self.dhcpid = newpid
-
- def stop(self):
- """
- Stop server comminucation and join the thread to main thread.
- """
- self.stopped = True
- if self.server_thread is not None:
- self.server_thread.join()
-
diff --git a/azurelinuxagent/distro/default/extension.py b/azurelinuxagent/distro/default/extension.py
deleted file mode 100644
index 82cdfed..0000000
--- a/azurelinuxagent/distro/default/extension.py
+++ /dev/null
@@ -1,817 +0,0 @@
-# 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 zipfile
-import time
-import json
-import subprocess
-import shutil
-import azurelinuxagent.conf as conf
-import azurelinuxagent.logger as logger
-from azurelinuxagent.event import add_event, WALAEventOperation
-from azurelinuxagent.exception import ExtensionError, ProtocolError, HttpError
-from azurelinuxagent.future import ustr
-from azurelinuxagent.metadata import AGENT_VERSION
-from azurelinuxagent.protocol.restapi import ExtHandlerStatus, ExtensionStatus, \
- ExtensionSubStatus, Extension, \
- VMStatus, ExtHandler, \
- get_properties, set_properties
-import azurelinuxagent.utils.fileutil as fileutil
-import azurelinuxagent.utils.restutil as restutil
-import azurelinuxagent.utils.shellutil as shellutil
-from azurelinuxagent.utils.textutil import Version
-
-#HandlerEnvironment.json schema version
-HANDLER_ENVIRONMENT_VERSION = 1.0
-
-VALID_EXTENSION_STATUS = ['transitioning', 'error', 'success', 'warning']
-
-VALID_HANDLER_STATUS = ['Ready', 'NotReady', "Installing", "Unresponsive"]
-
-def validate_has_key(obj, key, fullname):
- if key not in obj:
- raise ExtensionError("Missing: {0}".format(fullname))
-
-def validate_in_range(val, valid_range, name):
- if val not in valid_range:
- raise ExtensionError("Invalid {0}: {1}".format(name, val))
-
-def parse_formatted_message(formatted_message):
- if formatted_message is None:
- return None
- validate_has_key(formatted_message, 'lang', 'formattedMessage/lang')
- validate_has_key(formatted_message, 'message', 'formattedMessage/message')
- return formatted_message.get('message')
-
-def parse_ext_substatus(substatus):
- #Check extension sub status format
- validate_has_key(substatus, 'status', 'substatus/status')
- validate_in_range(substatus['status'], VALID_EXTENSION_STATUS,
- 'substatus/status')
- status = ExtensionSubStatus()
- status.name = substatus.get('name')
- status.status = substatus.get('status')
- status.code = substatus.get('code', 0)
- formatted_message = substatus.get('formattedMessage')
- status.message = parse_formatted_message(formatted_message)
- return status
-
-def parse_ext_status(ext_status, data):
- if data is None or len(data) is None:
- return
- #Currently, only the first status will be reported
- data = data[0]
- #Check extension status format
- validate_has_key(data, 'status', 'status')
- status_data = data['status']
- validate_has_key(status_data, 'status', 'status/status')
-
- validate_in_range(status_data['status'], VALID_EXTENSION_STATUS,
- 'status/status')
-
- applied_time = status_data.get('configurationAppliedTime')
- ext_status.configurationAppliedTime = applied_time
- ext_status.operation = status_data.get('operation')
- ext_status.status = status_data.get('status')
- ext_status.code = status_data.get('code', 0)
- formatted_message = status_data.get('formattedMessage')
- ext_status.message = parse_formatted_message(formatted_message)
- substatus_list = status_data.get('substatus')
- if substatus_list is None:
- return
- for substatus in substatus_list:
- ext_status.substatusList.append(parse_ext_substatus(substatus))
-
-class ExtHandlerState(object):
- NotInstalled = "NotInstalled"
- Installed = "Installed"
- Enabled = "Enabled"
-
-class ExtHandlersHandler(object):
- def __init__(self, distro):
- self.distro = distro
- self.ext_handlers = None
- self.last_etag = None
- self.log_report = False
-
- def run(self):
- ext_handlers, etag = None, None
- try:
- self.protocol = self.distro.protocol_util.get_protocol()
- ext_handlers, etag = self.protocol.get_ext_handlers()
- except ProtocolError as e:
- add_event(name="WALA", is_success=False, message=ustr(e))
- return
-
- if self.last_etag is not None and self.last_etag == etag:
- logger.verb("No change to ext handler config:{0}, skip", etag)
- self.log_report = False
- else:
- logger.info("Handle new ext handler config")
- self.log_report = True #Log status report success on new config
- self.handle_ext_handlers(ext_handlers)
- self.last_etag = etag
-
- self.report_ext_handlers_status(ext_handlers)
-
- def handle_ext_handlers(self, ext_handlers):
- if ext_handlers.extHandlers is None or \
- len(ext_handlers.extHandlers) == 0:
- logger.info("No ext handler config found")
- return
-
- for ext_handler in ext_handlers.extHandlers:
- #TODO handle install in sequence, enable in parallel
- self.handle_ext_handler(ext_handler)
-
- def handle_ext_handler(self, ext_handler):
- ext_handler_i = ExtHandlerInstance(ext_handler, self.protocol)
- try:
- state = ext_handler.properties.state
- ext_handler_i.logger.info("Expected handler state: {0}", state)
- if state == "enabled":
- self.handle_enable(ext_handler_i)
- elif state == u"disabled":
- self.handle_disable(ext_handler_i)
- elif state == u"uninstall":
- self.handle_uninstall(ext_handler_i)
- else:
- message = u"Unknown ext handler state:{0}".format(state)
- raise ExtensionError(message)
- except ExtensionError as e:
- ext_handler_i.set_handler_status(message=ustr(e), code=-1)
- ext_handler_i.report_event(message=ustr(e), is_success=False)
-
- def handle_enable(self, ext_handler_i):
-
- ext_handler_i.decide_version()
-
- old_ext_handler_i = ext_handler_i.get_installed_ext_handler()
- if old_ext_handler_i is not None and \
- old_ext_handler_i.version_gt(ext_handler_i):
- raise ExtensionError(u"Downgrade not allowed")
-
- handler_state = ext_handler_i.get_handler_state()
- ext_handler_i.logger.info("Current handler state is: {0}", handler_state)
- if handler_state == ExtHandlerState.NotInstalled:
- ext_handler_i.set_handler_state(ExtHandlerState.NotInstalled)
-
- ext_handler_i.download()
-
- ext_handler_i.update_settings()
-
- if old_ext_handler_i is None:
- ext_handler_i.install()
- elif ext_handler_i.version_gt(old_ext_handler_i):
- old_ext_handler_i.disable()
- ext_handler_i.copy_status_files(old_ext_handler_i)
- ext_handler_i.update()
- old_ext_handler_i.uninstall()
- old_ext_handler_i.rm_ext_handler_dir()
- ext_handler_i.update_with_install()
- else:
- ext_handler_i.update_settings()
-
- ext_handler_i.enable()
-
- def handle_disable(self, ext_handler_i):
- handler_state = ext_handler_i.get_handler_state()
- ext_handler_i.logger.info("Current handler state is: {0}", handler_state)
- if handler_state == ExtHandlerState.Enabled:
- ext_handler_i.disable()
-
- def handle_uninstall(self, ext_handler_i):
- handler_state = ext_handler_i.get_handler_state()
- ext_handler_i.logger.info("Current handler state is: {0}", handler_state)
- if handler_state != ExtHandlerState.NotInstalled:
- if handler_state == ExtHandlerState.Enabled:
- ext_handler_i.disable()
- ext_handler_i.uninstall()
- ext_handler_i.rm_ext_handler_dir()
-
- def report_ext_handlers_status(self, ext_handlers):
- """Go thru handler_state dir, collect and report status"""
- vm_status = VMStatus()
- vm_status.vmAgent.version = AGENT_VERSION
- vm_status.vmAgent.status = "Ready"
- vm_status.vmAgent.message = "Guest Agent is running"
-
- if ext_handlers is not None:
- for ext_handler in ext_handlers.extHandlers:
- try:
- self.report_ext_handler_status(vm_status, ext_handler)
- except ExtensionError as e:
- add_event(name="WALA", is_success=False, message=ustr(e))
-
- logger.verb("Report vm agent status")
-
- try:
- self.protocol.report_vm_status(vm_status)
- except ProtocolError as e:
- message = "Failed to report vm agent status: {0}".format(e)
- add_event(name="WALA", is_success=False, message=message)
-
- if self.log_report:
- logger.info("Successfully reported vm agent status")
-
-
- def report_ext_handler_status(self, vm_status, ext_handler):
- ext_handler_i = ExtHandlerInstance(ext_handler, self.protocol)
-
- handler_status = ext_handler_i.get_handler_status()
- if handler_status is None:
- return
-
- handler_state = ext_handler_i.get_handler_state()
- if handler_state != ExtHandlerState.NotInstalled:
- try:
- active_exts = ext_handler_i.report_ext_status()
- handler_status.extensions.extend(active_exts)
- except ExtensionError as e:
- ext_handler_i.set_handler_status(message=ustr(e), code=-1)
-
- try:
- heartbeat = ext_handler_i.collect_heartbeat()
- if heartbeat is not None:
- handler_status.status = heartbeat.get('status')
- except ExtensionError as e:
- ext_handler_i.set_handler_status(message=ustr(e), code=-1)
-
- vm_status.vmAgent.extensionHandlers.append(handler_status)
-
-class ExtHandlerInstance(object):
- def __init__(self, ext_handler, protocol):
- self.ext_handler = ext_handler
- self.protocol = protocol
- self.operation = None
- self.pkg = None
-
- prefix = "[{0}]".format(self.get_full_name())
- self.logger = logger.Logger(logger.DEFAULT_LOGGER, prefix)
-
- try:
- fileutil.mkdir(self.get_log_dir(), mode=0o744)
- except IOError as e:
- self.logger.error(u"Failed to create extension log dir: {0}", e)
-
- log_file = os.path.join(self.get_log_dir(), "CommandExecution.log")
- self.logger.add_appender(logger.AppenderType.FILE,
- logger.LogLevel.INFO, log_file)
-
- def decide_version(self):
- """
- If auto-upgrade, get the largest public extension version under
- the requested major version family of currently installed plugin version
-
- Else, get the highest hot-fix for requested version,
- """
- self.logger.info("Decide which version to use")
- try:
- pkg_list = self.protocol.get_ext_handler_pkgs(self.ext_handler)
- except ProtocolError as e:
- raise ExtensionError("Failed to get ext handler pkgs", e)
-
- version = self.ext_handler.properties.version
- update_policy = self.ext_handler.properties.upgradePolicy
-
- version_frag = version.split('.')
- if len(version_frag) < 2:
- raise ExtensionError("Wrong version format: {0}".format(version))
-
- version_prefix = None
- if update_policy is not None and update_policy == 'auto':
- version_prefix = "{0}.".format(version_frag[0])
- else:
- version_prefix = "{0}.{1}.".format(version_frag[0], version_frag[1])
-
- packages = [x for x in pkg_list.versions \
- if x.version.startswith(version_prefix) or \
- x.version == version]
-
- packages = sorted(packages, key=lambda x: Version(x.version),
- reverse=True)
-
- if len(packages) <= 0:
- raise ExtensionError("Failed to find and valid extension package")
- self.pkg = packages[0]
- self.ext_handler.properties.version = packages[0].version
- self.logger.info("Use version: {0}", self.pkg.version)
-
- def version_gt(self, other):
- self_version = self.ext_handler.properties.version
- other_version = other.ext_handler.properties.version
- return Version(self_version) > Version(other_version)
-
- def get_installed_ext_handler(self):
- lastest_version = None
- ext_handler_name = self.ext_handler.name
-
- for dir_name in os.listdir(conf.get_lib_dir()):
- path = os.path.join(conf.get_lib_dir(), dir_name)
- if os.path.isdir(path) and dir_name.startswith(ext_handler_name):
- seperator = dir_name.rfind('-')
- if seperator < 0:
- continue
- installed_name = dir_name[0: seperator]
- installed_version = dir_name[seperator + 1:]
- if installed_name != ext_handler_name:
- continue
- if lastest_version is None or \
- Version(lastest_version) < Version(installed_version):
- lastest_version = installed_version
-
- if lastest_version is None:
- return None
-
- data = get_properties(self.ext_handler)
- old_ext_handler = ExtHandler()
- set_properties("ExtHandler", old_ext_handler, data)
- old_ext_handler.properties.version = lastest_version
- return ExtHandlerInstance(old_ext_handler, self.protocol)
-
- def copy_status_files(self, old_ext_handler_i):
- self.logger.info("Copy status files from old plugin to new")
- old_ext_dir = old_ext_handler_i.get_base_dir()
- new_ext_dir = self.get_base_dir()
-
- old_ext_mrseq_file = os.path.join(old_ext_dir, "mrseq")
- if os.path.isfile(old_ext_mrseq_file):
- shutil.copy2(old_ext_mrseq_file, new_ext_dir)
-
- old_ext_status_dir = old_ext_handler_i.get_status_dir()
- new_ext_status_dir = self.get_status_dir()
-
- if os.path.isdir(old_ext_status_dir):
- for status_file in os.listdir(old_ext_status_dir):
- status_file = os.path.join(old_ext_status_dir, status_file)
- if os.path.isfile(status_file):
- shutil.copy2(status_file, new_ext_status_dir)
-
- def set_operation(self, op):
- self.operation = op
-
- def report_event(self, message="", is_success=True):
- version = self.ext_handler.properties.version
- add_event(name=self.ext_handler.name, version=version, message=message,
- op=self.operation, is_success=is_success)
-
- def download(self):
- self.logger.info("Download extension package")
- self.set_operation(WALAEventOperation.Download)
- if self.pkg is None:
- raise ExtensionError("No package uri found")
-
- package = None
- for uri in self.pkg.uris:
- try:
- package = self.protocol.download_ext_handler_pkg(uri.uri)
- except ProtocolError as e:
- logger.warn("Failed download extension: {0}", e)
-
- if package is None:
- raise ExtensionError("Failed to download extension")
-
- self.logger.info("Unpack extension package")
- pkg_file = os.path.join(conf.get_lib_dir(),
- os.path.basename(uri.uri) + ".zip")
- try:
- fileutil.write_file(pkg_file, bytearray(package), asbin=True)
- zipfile.ZipFile(pkg_file).extractall(self.get_base_dir())
- except IOError as e:
- raise ExtensionError(u"Failed to write and unzip plugin", e)
-
- chmod = "find {0} -type f | xargs chmod u+x".format(self.get_base_dir())
- shellutil.run(chmod)
- self.report_event(message="Download succeeded")
-
- self.logger.info("Initialize extension directory")
- #Save HandlerManifest.json
- man_file = fileutil.search_file(self.get_base_dir(),
- 'HandlerManifest.json')
-
- if man_file is None:
- raise ExtensionError("HandlerManifest.json not found")
-
- try:
- man = fileutil.read_file(man_file, remove_bom=True)
- fileutil.write_file(self.get_manifest_file(), man)
- except IOError as e:
- raise ExtensionError(u"Failed to save HandlerManifest.json", e)
-
- #Create status and config dir
- try:
- status_dir = self.get_status_dir()
- fileutil.mkdir(status_dir, mode=0o700)
- conf_dir = self.get_conf_dir()
- fileutil.mkdir(conf_dir, mode=0o700)
- except IOError as e:
- raise ExtensionError(u"Failed to create status or config dir", e)
-
- #Save HandlerEnvironment.json
- self.create_handler_env()
-
- def enable(self):
- self.logger.info("Enable extension.")
- self.set_operation(WALAEventOperation.Enable)
-
- man = self.load_manifest()
- self.launch_command(man.get_enable_command())
- self.set_handler_state(ExtHandlerState.Enabled)
- self.set_handler_status(status="Ready", message="Plugin enabled")
-
- def disable(self):
- self.logger.info("Disable extension.")
- self.set_operation(WALAEventOperation.Disable)
-
- man = self.load_manifest()
- self.launch_command(man.get_disable_command(), timeout=900)
- self.set_handler_state(ExtHandlerState.Installed)
- self.set_handler_status(status="NotReady", message="Plugin disabled")
-
- def install(self):
- self.logger.info("Install extension.")
- self.set_operation(WALAEventOperation.Install)
-
- man = self.load_manifest()
- self.launch_command(man.get_install_command(), timeout=900)
- self.set_handler_state(ExtHandlerState.Installed)
-
- def uninstall(self):
- self.logger.info("Uninstall extension.")
- self.set_operation(WALAEventOperation.UnInstall)
-
- try:
- man = self.load_manifest()
- self.launch_command(man.get_uninstall_command())
- except ExtensionError as e:
- self.report_event(message=ustr(e), is_success=False)
-
- def rm_ext_handler_dir(self):
- try:
- handler_state_dir = self.get_handler_state_dir()
- if os.path.isdir(handler_state_dir):
- self.logger.info("Remove ext handler dir: {0}", handler_state_dir)
- shutil.rmtree(handler_state_dir)
- base_dir = self.get_base_dir()
- if os.path.isdir(base_dir):
- self.logger.info("Remove ext handler dir: {0}", base_dir)
- shutil.rmtree(base_dir)
- except IOError as e:
- message = "Failed to rm ext handler dir: {0}".format(e)
- self.report_event(message=message, is_success=False)
-
- def update(self):
- self.logger.info("Update extension.")
- self.set_operation(WALAEventOperation.Update)
-
- man = self.load_manifest()
- self.launch_command(man.get_update_command(), timeout=900)
-
- def update_with_install(self):
- man = self.load_manifest()
- if man.is_update_with_install():
- self.install()
- else:
- self.logger.info("UpdateWithInstall not set. "
- "Skip install during upgrade.")
- self.set_handler_state(ExtHandlerState.Installed)
-
- def get_largest_seq_no(self):
- seq_no = -1
- conf_dir = self.get_conf_dir()
- for item in os.listdir(conf_dir):
- item_path = os.path.join(conf_dir, item)
- if os.path.isfile(item_path):
- try:
- seperator = item.rfind(".")
- if seperator > 0 and item[seperator + 1:] == 'settings':
- curr_seq_no = int(item.split('.')[0])
- if curr_seq_no > seq_no:
- seq_no = curr_seq_no
- except Exception as e:
- self.logger.verb("Failed to parse file name: {0}", item)
- continue
- return seq_no
-
- def collect_ext_status(self, ext):
- self.logger.verb("Collect extension status")
-
- seq_no = self.get_largest_seq_no()
- if seq_no == -1:
- return None
-
- status_dir = self.get_status_dir()
- ext_status_file = "{0}.status".format(seq_no)
- ext_status_file = os.path.join(status_dir, ext_status_file)
-
- ext_status = ExtensionStatus(seq_no=seq_no)
- try:
- data_str = fileutil.read_file(ext_status_file)
- data = json.loads(data_str)
- parse_ext_status(ext_status, data)
- except IOError as e:
- ext_status.message = u"Failed to get status file {0}".format(e)
- ext_status.code = -1
- ext_status.status = "error"
- except ValueError as e:
- ext_status.message = u"Malformed status file {0}".format(e)
- ext_status.code = -1
- ext_status.status = "error"
-
- return ext_status
-
- def report_ext_status(self):
- active_exts = []
- for ext in self.ext_handler.properties.extensions:
- ext_status = self.collect_ext_status(ext)
- if ext_status is None:
- continue
- try:
- self.protocol.report_ext_status(self.ext_handler.name, ext.name,
- ext_status)
- active_exts.append(ext.name)
- except ProtocolError as e:
- self.logger.error(u"Failed to report extension status: {0}", e)
- return active_exts
-
- def collect_heartbeat(self):
- man = self.load_manifest()
- if not man.is_report_heartbeat():
- return
- heartbeat_file = os.path.join(conf.get_lib_dir(),
- self.get_heartbeat_file())
-
- self.logger.info("Collect heart beat")
- if not os.path.isfile(heartbeat_file):
- raise ExtensionError("Failed to get heart beat file")
- if not self.is_responsive(heartbeat_file):
- return {
- "status": "Unresponsive",
- "code": -1,
- "message": "Extension heartbeat is not responsive"
- }
- try:
- heartbeat_json = fileutil.read_file(heartbeat_file)
- heartbeat = json.loads(heartbeat_json)[0]['heartbeat']
- except IOError as e:
- raise ExtensionError("Failed to get heartbeat file:{0}".format(e))
- except ValueError as e:
- raise ExtensionError("Malformed heartbeat file: {0}".format(e))
- return heartbeat
-
- def is_responsive(self, heartbeat_file):
- last_update=int(time.time() - os.stat(heartbeat_file).st_mtime)
- return last_update > 600 # not updated for more than 10 min
-
- def launch_command(self, cmd, timeout=300):
- self.logger.info("Launch command:{0}", cmd)
- base_dir = self.get_base_dir()
- try:
- devnull = open(os.devnull, 'w')
- child = subprocess.Popen(base_dir + "/" + cmd, shell=True,
- cwd=base_dir, stdout=devnull)
- except Exception as e:
- #TODO do not catch all exception
- raise ExtensionError("Failed to launch: {0}, {1}".format(cmd, e))
-
- retry = timeout / 5
- while retry > 0 and child.poll == None:
- time.sleep(5)
- retry -= 1
- if retry == 0:
- os.kill(child.pid, 9)
- raise ExtensionError("Timeout({0}): {1}".format(timeout, cmd))
-
- ret = child.wait()
- if ret == None or ret != 0:
- raise ExtensionError("Non-zero exit code: {0}, {1}".format(ret, cmd))
-
- self.report_event(message="Launch command succeeded: {0}".format(cmd))
-
- def load_manifest(self):
- man_file = self.get_manifest_file()
- try:
- data = json.loads(fileutil.read_file(man_file))
- except IOError as e:
- raise ExtensionError('Failed to load manifest file.')
- except ValueError as e:
- raise ExtensionError('Malformed manifest file.')
-
- return HandlerManifest(data[0])
-
- def update_settings_file(self, settings_file, settings):
- settings_file = os.path.join(self.get_conf_dir(), settings_file)
- try:
- fileutil.write_file(settings_file, settings)
- except IOError as e:
- raise ExtensionError(u"Failed to update settings file", e)
-
- def update_settings(self):
- if self.ext_handler.properties.extensions is None or \
- len(self.ext_handler.properties.extensions) == 0:
- #This is the behavior of waagent 2.0.x
- #The new agent has to be consistent with the old one.
- self.logger.info("Extension has no settings, write empty 0.settings")
- self.update_settings_file("0.settings", "")
- return
-
- for ext in self.ext_handler.properties.extensions:
- settings = {
- 'publicSettings': ext.publicSettings,
- 'protectedSettings': ext.protectedSettings,
- 'protectedSettingsCertThumbprint': ext.certificateThumbprint
- }
- ext_settings = {
- "runtimeSettings":[{
- "handlerSettings": settings
- }]
- }
- settings_file = "{0}.settings".format(ext.sequenceNumber)
- self.logger.info("Update settings file: {0}", settings_file)
- self.update_settings_file(settings_file, json.dumps(ext_settings))
-
- def create_handler_env(self):
- env = [{
- "name": self.ext_handler.name,
- "version" : HANDLER_ENVIRONMENT_VERSION,
- "handlerEnvironment" : {
- "logFolder" : self.get_log_dir(),
- "configFolder" : self.get_conf_dir(),
- "statusFolder" : self.get_status_dir(),
- "heartbeatFile" : self.get_heartbeat_file()
- }
- }]
- try:
- fileutil.write_file(self.get_env_file(), json.dumps(env))
- except IOError as e:
- raise ExtensionError(u"Failed to save handler environment", e)
-
- def get_handler_state_dir(self):
- return os.path.join(conf.get_lib_dir(), "handler_state",
- self.get_full_name())
-
- def set_handler_state(self, handler_state):
- state_dir = self.get_handler_state_dir()
- if not os.path.exists(state_dir):
- try:
- fileutil.mkdir(state_dir, 0o700)
- except IOError as e:
- self.logger.error("Failed to create state dir: {0}", e)
-
- try:
- state_file = os.path.join(state_dir, "state")
- fileutil.write_file(state_file, handler_state)
- except IOError as e:
- self.logger.error("Failed to set state: {0}", e)
-
- def get_handler_state(self):
- state_dir = self.get_handler_state_dir()
- state_file = os.path.join(state_dir, "state")
- if not os.path.isfile(state_file):
- return ExtHandlerState.NotInstalled
-
- try:
- return fileutil.read_file(state_file)
- except IOError as e:
- self.logger.error("Failed to get state: {0}", e)
- return ExtHandlerState.NotInstalled
-
- def set_handler_status(self, status="NotReady", message="",
- code=0):
- state_dir = self.get_handler_state_dir()
- if not os.path.exists(state_dir):
- try:
- fileutil.mkdir(state_dir, 0o700)
- except IOError as e:
- self.logger.error("Failed to create state dir: {0}", e)
-
- handler_status = ExtHandlerStatus()
- handler_status.name = self.ext_handler.name
- handler_status.version = self.ext_handler.properties.version
- handler_status.message = message
- handler_status.code = code
- handler_status.status = status
- status_file = os.path.join(state_dir, "status")
-
- try:
- fileutil.write_file(status_file,
- json.dumps(get_properties(handler_status)))
- except (IOError, ValueError, ProtocolError) as e:
- self.logger.error("Failed to save handler status: {0}", e)
-
- def get_handler_status(self):
- state_dir = self.get_handler_state_dir()
- status_file = os.path.join(state_dir, "status")
- if not os.path.isfile(status_file):
- return None
-
- try:
- data = json.loads(fileutil.read_file(status_file))
- handler_status = ExtHandlerStatus()
- set_properties("ExtHandlerStatus", handler_status, data)
- return handler_status
- except (IOError, ValueError) as e:
- self.logger.error("Failed to get handler status: {0}", e)
-
- def get_full_name(self):
- return "{0}-{1}".format(self.ext_handler.name,
- self.ext_handler.properties.version)
-
- def get_base_dir(self):
- return os.path.join(conf.get_lib_dir(), self.get_full_name())
-
- def get_status_dir(self):
- return os.path.join(self.get_base_dir(), "status")
-
- def get_conf_dir(self):
- return os.path.join(self.get_base_dir(), 'config')
-
- def get_heartbeat_file(self):
- return os.path.join(self.get_base_dir(), 'heartbeat.log')
-
- def get_manifest_file(self):
- return os.path.join(self.get_base_dir(), 'HandlerManifest.json')
-
- def get_env_file(self):
- return os.path.join(self.get_base_dir(), 'HandlerEnvironment.json')
-
- def get_log_dir(self):
- return os.path.join(conf.get_ext_log_dir(), self.ext_handler.name,
- self.ext_handler.properties.version)
-
-class HandlerEnvironment(object):
- def __init__(self, data):
- self.data = data
-
- def get_version(self):
- return self.data["version"]
-
- def get_log_dir(self):
- return self.data["handlerEnvironment"]["logFolder"]
-
- def get_conf_dir(self):
- return self.data["handlerEnvironment"]["configFolder"]
-
- def get_status_dir(self):
- return self.data["handlerEnvironment"]["statusFolder"]
-
- def get_heartbeat_file(self):
- return self.data["handlerEnvironment"]["heartbeatFile"]
-
-class HandlerManifest(object):
- def __init__(self, data):
- if data is None or data['handlerManifest'] is None:
- raise ExtensionError('Malformed manifest file.')
- self.data = data
-
- def get_name(self):
- return self.data["name"]
-
- def get_version(self):
- return self.data["version"]
-
- def get_install_command(self):
- return self.data['handlerManifest']["installCommand"]
-
- def get_uninstall_command(self):
- return self.data['handlerManifest']["uninstallCommand"]
-
- def get_update_command(self):
- return self.data['handlerManifest']["updateCommand"]
-
- def get_enable_command(self):
- return self.data['handlerManifest']["enableCommand"]
-
- def get_disable_command(self):
- return self.data['handlerManifest']["disableCommand"]
-
- def is_reboot_after_install(self):
- """
- Deprecated
- """
- return False
-
- def is_report_heartbeat(self):
- return self.data['handlerManifest'].get('reportHeartbeat', False)
-
- def is_update_with_install(self):
- update_mode = self.data['handlerManifest'].get('updateMode')
- if update_mode is None:
- return True
- return update_mode.low() == "updatewithinstall"
diff --git a/azurelinuxagent/distro/default/init.py b/azurelinuxagent/distro/default/init.py
deleted file mode 100644
index c703e87..0000000
--- a/azurelinuxagent/distro/default/init.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# 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 azurelinuxagent.conf as conf
-import azurelinuxagent.logger as logger
-import azurelinuxagent.event as event
-
-
-class InitHandler(object):
- def __init__(self, distro):
- self.distro = distro
-
- def run(self, verbose):
- #Init stdout log
- level = logger.LogLevel.VERBOSE if verbose else logger.LogLevel.INFO
- logger.add_logger_appender(logger.AppenderType.STDOUT, level)
-
- #Init config
- conf_file_path = self.distro.osutil.get_agent_conf_file_path()
- conf.load_conf_from_file(conf_file_path)
-
- #Init log
- verbose = verbose or conf.get_logs_verbose()
- level = logger.LogLevel.VERBOSE if verbose else logger.LogLevel.INFO
- logger.add_logger_appender(logger.AppenderType.FILE, level,
- path="/var/log/waagent.log")
- logger.add_logger_appender(logger.AppenderType.CONSOLE, level,
- path="/dev/console")
-
- #Init event reporter
- event_dir = os.path.join(conf.get_lib_dir(), "events")
- event.init_event_logger(event_dir)
- event.enable_unhandled_err_dump("WALA")
-
-
-
diff --git a/azurelinuxagent/distro/default/monitor.py b/azurelinuxagent/distro/default/monitor.py
deleted file mode 100644
index 3b26c9a..0000000
--- a/azurelinuxagent/distro/default/monitor.py
+++ /dev/null
@@ -1,182 +0,0 @@
-# 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 traceback
-import atexit
-import json
-import time
-import datetime
-import threading
-import platform
-import azurelinuxagent.logger as logger
-import azurelinuxagent.conf as conf
-from azurelinuxagent.event import WALAEventOperation, add_event
-from azurelinuxagent.exception import EventError, ProtocolError, OSUtilError
-from azurelinuxagent.future import ustr
-from azurelinuxagent.utils.textutil import parse_doc, findall, find, getattrib
-from azurelinuxagent.protocol.restapi import TelemetryEventParam, \
- TelemetryEventList, \
- TelemetryEvent, \
- set_properties, get_properties
-from azurelinuxagent.metadata import DISTRO_NAME, DISTRO_VERSION, \
- DISTRO_CODE_NAME, AGENT_LONG_VERSION
-
-
-def parse_event(data_str):
- try:
- return parse_json_event(data_str)
- except ValueError:
- return parse_xml_event(data_str)
-
-def parse_xml_param(param_node):
- name = getattrib(param_node, "Name")
- value_str = getattrib(param_node, "Value")
- attr_type = getattrib(param_node, "T")
- value = value_str
- if attr_type == 'mt:uint64':
- value = int(value_str)
- elif attr_type == 'mt:bool':
- value = bool(value_str)
- elif attr_type == 'mt:float64':
- value = float(value_str)
- return TelemetryEventParam(name, value)
-
-def parse_xml_event(data_str):
- try:
- xml_doc = parse_doc(data_str)
- event_id = getattrib(find(xml_doc, "Event"), 'id')
- provider_id = getattrib(find(xml_doc, "Provider"), 'id')
- event = TelemetryEvent(event_id, provider_id)
- param_nodes = findall(xml_doc, 'Param')
- for param_node in param_nodes:
- event.parameters.append(parse_xml_param(param_node))
- return event
- except Exception as e:
- raise ValueError(ustr(e))
-
-def parse_json_event(data_str):
- data = json.loads(data_str)
- event = TelemetryEvent()
- set_properties("TelemetryEvent", event, data)
- return event
-
-
-class MonitorHandler(object):
- def __init__(self, distro):
- self.distro = distro
- self.sysinfo = []
-
- def run(self):
- event_thread = threading.Thread(target = self.daemon)
- event_thread.setDaemon(True)
- event_thread.start()
-
- def init_sysinfo(self):
- osversion = "{0}:{1}-{2}-{3}:{4}".format(platform.system(),
- DISTRO_NAME,
- DISTRO_VERSION,
- DISTRO_CODE_NAME,
- platform.release())
-
-
- self.sysinfo.append(TelemetryEventParam("OSVersion", osversion))
- self.sysinfo.append(TelemetryEventParam("GAVersion", AGENT_LONG_VERSION))
-
- try:
- ram = self.distro.osutil.get_total_mem()
- processors = self.distro.osutil.get_processor_cores()
- self.sysinfo.append(TelemetryEventParam("RAM", ram))
- self.sysinfo.append(TelemetryEventParam("Processors", processors))
- except OSUtilError as e:
- logger.warn("Failed to get system info: {0}", e)
-
- try:
- protocol = self.distro.protocol_util.get_protocol()
- vminfo = protocol.get_vminfo()
- self.sysinfo.append(TelemetryEventParam("VMName",
- vminfo.vmName))
- self.sysinfo.append(TelemetryEventParam("TenantName",
- vminfo.tenantName))
- self.sysinfo.append(TelemetryEventParam("RoleName",
- vminfo.roleName))
- self.sysinfo.append(TelemetryEventParam("RoleInstanceName",
- vminfo.roleInstanceName))
- self.sysinfo.append(TelemetryEventParam("ContainerId",
- vminfo.containerId))
- except ProtocolError as e:
- logger.warn("Failed to get system info: {0}", e)
-
- def collect_event(self, evt_file_name):
- try:
- logger.verb("Found event file: {0}", evt_file_name)
- with open(evt_file_name, "rb") as evt_file:
- #if fail to open or delete the file, throw exception
- data_str = evt_file.read().decode("utf-8",'ignore')
- logger.verb("Processed event file: {0}", evt_file_name)
- os.remove(evt_file_name)
- return data_str
- except IOError as e:
- msg = "Failed to process {0}, {1}".format(evt_file_name, e)
- raise EventError(msg)
-
- def collect_and_send_events(self):
- event_list = TelemetryEventList()
- event_dir = os.path.join(conf.get_lib_dir(), "events")
- event_files = os.listdir(event_dir)
- for event_file in event_files:
- if not event_file.endswith(".tld"):
- continue
- event_file_path = os.path.join(event_dir, event_file)
- try:
- data_str = self.collect_event(event_file_path)
- except EventError as e:
- logger.error("{0}", e)
- continue
-
- try:
- event = parse_event(data_str)
- event.parameters.extend(self.sysinfo)
- event_list.events.append(event)
- except (ValueError, ProtocolError) as e:
- logger.warn("Failed to decode event file: {0}", e)
- continue
-
- if len(event_list.events) == 0:
- return
-
- try:
- protocol = self.distro.protocol_util.get_protocol()
- protocol.report_event(event_list)
- except ProtocolError as e:
- logger.error("{0}", e)
-
- def daemon(self):
- self.init_sysinfo()
- last_heartbeat = datetime.datetime.min
- period = datetime.timedelta(hours = 12)
- while(True):
- if (datetime.datetime.now()-last_heartbeat) > period:
- last_heartbeat = datetime.datetime.now()
- add_event(op=WALAEventOperation.HeartBeat, name="WALA",
- is_success=True)
- try:
- self.collect_and_send_events()
- except Exception as e:
- logger.warn("Failed to send events: {0}", e)
- time.sleep(60)
diff --git a/azurelinuxagent/distro/default/osutil.py b/azurelinuxagent/distro/default/osutil.py
deleted file mode 100644
index 18ab2ba..0000000
--- a/azurelinuxagent/distro/default/osutil.py
+++ /dev/null
@@ -1,623 +0,0 @@
-#
-# 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 shutil
-import socket
-import array
-import struct
-import time
-import pwd
-import fcntl
-import base64
-import azurelinuxagent.logger as logger
-import azurelinuxagent.conf as conf
-from azurelinuxagent.exception import OSUtilError
-from azurelinuxagent.future import ustr
-import azurelinuxagent.utils.fileutil as fileutil
-import azurelinuxagent.utils.shellutil as shellutil
-import azurelinuxagent.utils.textutil as textutil
-from azurelinuxagent.utils.cryptutil import CryptUtil
-
-__RULES_FILES__ = [ "/lib/udev/rules.d/75-persistent-net-generator.rules",
- "/etc/udev/rules.d/70-persistent-net.rules" ]
-
-"""
-Define distro specific behavior. OSUtil class defines default behavior
-for all distros. Each concrete distro classes could overwrite default behavior
-if needed.
-"""
-
-class DefaultOSUtil(object):
-
- def __init__(self):
- self.agent_conf_file_path = '/etc/waagent.conf'
- self.selinux=None
-
- def get_agent_conf_file_path(self):
- return self.agent_conf_file_path
-
- def get_userentry(self, username):
- try:
- return pwd.getpwnam(username)
- except KeyError:
- return None
-
- def is_sys_user(self, username):
- """
- Check whether use is a system user.
- If reset sys user is allowed in conf, return False
- Otherwise, check whether UID is less than UID_MIN
- """
- if conf.get_allow_reset_sys_user():
- return False
-
- userentry = self.get_userentry(username)
- uidmin = None
- try:
- uidmin_def = fileutil.get_line_startingwith("UID_MIN",
- "/etc/login.defs")
- if uidmin_def is not None:
- uidmin = int(uidmin_def.split()[1])
- except IOError as e:
- pass
- if uidmin == None:
- uidmin = 100
- if userentry != None and userentry[2] < uidmin:
- return True
- else:
- return False
-
- def useradd(self, username, expiration=None):
- """
- Create user account with 'username'
- """
- userentry = self.get_userentry(username)
- if userentry is not None:
- logger.info("User {0} already exists, skip useradd", username)
- return
-
- if expiration is not None:
- cmd = "useradd -m {0} -e {1}".format(username, expiration)
- else:
- cmd = "useradd -m {0}".format(username)
- retcode, out = shellutil.run_get_output(cmd)
- if retcode != 0:
- raise OSUtilError(("Failed to create user account:{0}, "
- "retcode:{1}, "
- "output:{2}").format(username, retcode, out))
-
- def chpasswd(self, username, password, crypt_id=6, salt_len=10):
- if self.is_sys_user(username):
- raise OSUtilError(("User {0} is a system user. "
- "Will not set passwd.").format(username))
- passwd_hash = textutil.gen_password_hash(password, crypt_id, salt_len)
- cmd = "usermod -p '{0}' {1}".format(passwd_hash, username)
- ret, output = shellutil.run_get_output(cmd, log_cmd=False)
- if ret != 0:
- raise OSUtilError(("Failed to set password for {0}: {1}"
- "").format(username, output))
-
- def conf_sudoer(self, username, nopasswd):
- # for older distros create sudoers.d
- if not os.path.isdir('/etc/sudoers.d/'):
- # create the /etc/sudoers.d/ directory
- os.mkdir('/etc/sudoers.d/')
- # add the include of sudoers.d to the /etc/sudoers
- sudoers = '\n' + '#includedir /etc/sudoers.d/\n'
- fileutil.append_file('/etc/sudoers', sudoers)
- sudoer = None
- if nopasswd:
- sudoer = "{0} ALL = (ALL) NOPASSWD\n".format(username)
- else:
- sudoer = "{0} ALL = (ALL) ALL\n".format(username)
- fileutil.append_file('/etc/sudoers.d/waagent', sudoer)
- fileutil.chmod('/etc/sudoers.d/waagent', 0o440)
-
- def del_root_password(self):
- try:
- passwd_file_path = conf.get_passwd_file_path()
- passwd_content = fileutil.read_file(passwd_file_path)
- passwd = passwd_content.split('\n')
- new_passwd = [x for x in passwd if not x.startswith("root:")]
- new_passwd.insert(0, "root:*LOCK*:14600::::::")
- fileutil.write_file(passwd_file_path, "\n".join(new_passwd))
- except IOError as e:
- raise OSUtilError("Failed to delete root password:{0}".format(e))
-
- def _norm_path(self, filepath):
- home = conf.get_home_dir()
- # Expand HOME variable if present in path
- path = os.path.normpath(filepath.replace("$HOME", home))
- return path
-
- def deploy_ssh_keypair(self, username, keypair):
- """
- Deploy id_rsa and id_rsa.pub
- """
- path, thumbprint = keypair
- path = self._norm_path(path)
- dir_path = os.path.dirname(path)
- fileutil.mkdir(dir_path, mode=0o700, owner=username)
- lib_dir = conf.get_lib_dir()
- prv_path = os.path.join(lib_dir, thumbprint + '.prv')
- if not os.path.isfile(prv_path):
- raise OSUtilError("Can't find {0}.prv".format(thumbprint))
- shutil.copyfile(prv_path, path)
- pub_path = path + '.pub'
- crytputil = CryptUtil(conf.get_openssl_cmd())
- pub = crytputil.get_pubkey_from_prv(prv_path)
- fileutil.write_file(pub_path, pub)
- self.set_selinux_context(pub_path, 'unconfined_u:object_r:ssh_home_t:s0')
- self.set_selinux_context(path, 'unconfined_u:object_r:ssh_home_t:s0')
- os.chmod(path, 0o644)
- os.chmod(pub_path, 0o600)
-
- def openssl_to_openssh(self, input_file, output_file):
- cryptutil = CryptUtil(conf.get_openssl_cmd())
- cryptutil.crt_to_ssh(input_file, output_file)
-
- def deploy_ssh_pubkey(self, username, pubkey):
- """
- Deploy authorized_key
- """
- path, thumbprint, value = pubkey
- if path is None:
- raise OSUtilError("Publich key path is None")
-
- crytputil = CryptUtil(conf.get_openssl_cmd())
-
- path = self._norm_path(path)
- dir_path = os.path.dirname(path)
- fileutil.mkdir(dir_path, mode=0o700, owner=username)
- if value is not None:
- if not value.startswith("ssh-"):
- raise OSUtilError("Bad public key: {0}".format(value))
- fileutil.write_file(path, value)
- elif thumbprint is not None:
- lib_dir = conf.get_lib_dir()
- crt_path = os.path.join(lib_dir, thumbprint + '.crt')
- if not os.path.isfile(crt_path):
- raise OSUtilError("Can't find {0}.crt".format(thumbprint))
- pub_path = os.path.join(lib_dir, thumbprint + '.pub')
- pub = crytputil.get_pubkey_from_crt(crt_path)
- fileutil.write_file(pub_path, pub)
- self.set_selinux_context(pub_path,
- 'unconfined_u:object_r:ssh_home_t:s0')
- self.openssl_to_openssh(pub_path, path)
- fileutil.chmod(pub_path, 0o600)
- else:
- raise OSUtilError("SSH public key Fingerprint and Value are None")
-
- self.set_selinux_context(path, 'unconfined_u:object_r:ssh_home_t:s0')
- fileutil.chowner(path, username)
- fileutil.chmod(path, 0o644)
-
- def is_selinux_system(self):
- """
- Checks and sets self.selinux = True if SELinux is available on system.
- """
- if self.selinux == None:
- if shellutil.run("which getenforce", chk_err=False) == 0:
- self.selinux = True
- else:
- self.selinux = False
- return self.selinux
-
- def is_selinux_enforcing(self):
- """
- Calls shell command 'getenforce' and returns True if 'Enforcing'.
- """
- if self.is_selinux_system():
- output = shellutil.run_get_output("getenforce")[1]
- return output.startswith("Enforcing")
- else:
- return False
-
- def set_selinux_enforce(self, state):
- """
- Calls shell command 'setenforce' with 'state'
- and returns resulting exit code.
- """
- if self.is_selinux_system():
- if state: s = '1'
- else: s='0'
- return shellutil.run("setenforce "+s)
-
- def set_selinux_context(self, path, con):
- """
- Calls shell 'chcon' with 'path' and 'con' context.
- Returns exit result.
- """
- if self.is_selinux_system():
- return shellutil.run('chcon ' + con + ' ' + path)
-
- def set_ssh_client_alive_interval(self):
- conf_file_path = conf.get_sshd_conf_file_path()
- conf_file = fileutil.read_file(conf_file_path).split("\n")
- textutil.set_ssh_config(conf_file, "ClientAliveInterval", "180")
- fileutil.write_file(conf_file_path, '\n'.join(conf_file))
- logger.info("Configured SSH client probing to keep connections alive.")
-
- def conf_sshd(self, disable_password):
- option = "no" if disable_password else "yes"
- conf_file_path = conf.get_sshd_conf_file_path()
- conf_file = fileutil.read_file(conf_file_path).split("\n")
- textutil.set_ssh_config(conf_file, "PasswordAuthentication", option)
- textutil.set_ssh_config(conf_file, "ChallengeResponseAuthentication",
- option)
- fileutil.write_file(conf_file_path, "\n".join(conf_file))
- logger.info("Disabled SSH password-based authentication methods.")
-
-
- def get_dvd_device(self, dev_dir='/dev'):
- patten=r'(sr[0-9]|hd[c-z]|cdrom[0-9])'
- for dvd in [re.match(patten, 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()
- mountlist = shellutil.run_get_output("mount")[1]
- existing = self.get_mount_point(mountlist, dvd)
- if existing is not None: #Already mounted
- logger.info("{0} is already mounted at {1}", dvd, 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 iso9660,udf",
- chk_err=chk_err)
- if retcode == 0:
- logger.info("Successfully mounted dvd")
- return
- if retry < max_retry - 1:
- logger.warn("Mount dvd failed: retry={0}, ret={1}", retry,
- retcode)
- time.sleep(5)
- if chk_err:
- raise OSUtilError("Failed to mount dvd.")
-
- def umount_dvd(self, chk_err=True):
- 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.")
-
- def eject_dvd(self, chk_err=True):
- dvd = self.get_dvd_device()
- retcode = shellutil.run("eject {0}".format(dvd))
- if chk_err and retcode != 0:
- raise OSUtilError("Failed to eject dvd: ret={0}".format(retcode))
-
- def load_atappix_mod(self):
- if self.is_atapiix_mod_loaded():
- return
- ret, kern_version = shellutil.run_get_output("uname -r")
- if ret != 0:
- raise Exception("Failed to call uname -r")
- mod_path = os.path.join('/lib/modules',
- kern_version.strip('\n'),
- 'kernel/drivers/ata/ata_piix.ko')
- if not os.path.isfile(mod_path):
- raise Exception("Can't find module file:{0}".format(mod_path))
-
- ret, output = shellutil.run_get_output("insmod " + mod_path)
- if ret != 0:
- raise Exception("Error calling insmod for ATAPI CD-ROM driver")
- if not self.is_atapiix_mod_loaded(max_retry=3):
- raise Exception("Failed to load ATAPI CD-ROM driver")
-
- def is_atapiix_mod_loaded(self, max_retry=1):
- for retry in range(0, max_retry):
- ret = shellutil.run("lsmod | grep ata_piix", chk_err=False)
- if ret == 0:
- logger.info("Module driver for ATAPI CD-ROM is already present.")
- return True
- if retry < max_retry - 1:
- time.sleep(1)
- return False
-
- def mount(self, dvd, mount_point, option="", chk_err=True):
- cmd = "mount {0} {1} {2}".format(dvd, option, mount_point)
- return shellutil.run_get_output(cmd, chk_err)[0]
-
- def umount(self, mount_point, chk_err=True):
- return shellutil.run("umount {0}".format(mount_point), chk_err=chk_err)
-
- def allow_dhcp_broadcast(self):
- #Open DHCP port if iptables is enabled.
- # We supress error logging on error.
- shellutil.run("iptables -D INPUT -p udp --dport 68 -j ACCEPT",
- chk_err=False)
- shellutil.run("iptables -I INPUT -p udp --dport 68 -j ACCEPT",
- chk_err=False)
-
-
- def remove_rules_files(self, rules_files=__RULES_FILES__):
- lib_dir = conf.get_lib_dir()
- for src in rules_files:
- file_name = fileutil.base_name(src)
- dest = os.path.join(lib_dir, file_name)
- if os.path.isfile(dest):
- os.remove(dest)
- if os.path.isfile(src):
- logger.warn("Move rules file {0} to {1}", file_name, dest)
- shutil.move(src, dest)
-
- def restore_rules_files(self, rules_files=__RULES_FILES__):
- lib_dir = conf.get_lib_dir()
- for dest in rules_files:
- filename = fileutil.base_name(dest)
- src = os.path.join(lib_dir, filename)
- if os.path.isfile(dest):
- continue
- if os.path.isfile(src):
- logger.warn("Move rules file {0} to {1}", filename, dest)
- shutil.move(src, dest)
-
- def get_mac_addr(self):
- """
- Convienience function, returns mac addr bound to
- first non-loobback interface.
- """
- ifname=''
- while len(ifname) < 2 :
- ifname=self.get_first_if()[0]
- addr = self.get_if_mac(ifname)
- return textutil.hexstr_to_bytearray(addr)
-
- def get_if_mac(self, ifname):
- """
- Return the mac-address bound to the socket.
- """
- sock = socket.socket(socket.AF_INET,
- socket.SOCK_DGRAM,
- socket.IPPROTO_UDP)
- param = struct.pack('256s', (ifname[:15]+('\0'*241)).encode('latin-1'))
- info = fcntl.ioctl(sock.fileno(), 0x8927, param)
- return ''.join(['%02X' % textutil.str_to_ord(char) for char in info[18:24]])
-
- def get_first_if(self):
- """
- Return the interface name, and ip addr of the
- first active non-loopback interface.
- """
- iface=''
- expected=16 # how many devices should I expect...
- struct_size=40 # for 64bit the size is 40 bytes
- sock = socket.socket(socket.AF_INET,
- socket.SOCK_DGRAM,
- socket.IPPROTO_UDP)
- buff=array.array('B', b'\0' * (expected * struct_size))
- param = struct.pack('iL',
- expected*struct_size,
- buff.buffer_info()[0])
- ret = fcntl.ioctl(sock.fileno(), 0x8912, param)
- retsize=(struct.unpack('iL', ret)[0])
- if retsize == (expected * struct_size):
- logger.warn(('SIOCGIFCONF returned more than {0} up '
- 'network interfaces.'), expected)
- sock = buff.tostring()
- for i in range(0, struct_size * expected, struct_size):
- iface=sock[i:i+16].split(b'\0', 1)[0]
- if iface == b'lo':
- continue
- else:
- break
- return iface.decode('latin-1'), socket.inet_ntoa(sock[i+20:i+24])
-
- def is_missing_default_route(self):
- routes = shellutil.run_get_output("route -n")[1]
- for route in routes.split("\n"):
- if route.startswith("0.0.0.0 ") or route.startswith("default "):
- return False
- return True
-
- def get_if_name(self):
- return self.get_first_if()[0]
-
- def get_ip4_addr(self):
- return self.get_first_if()[1]
-
- def set_route_for_dhcp_broadcast(self, ifname):
- return shellutil.run("route add 255.255.255.255 dev {0}".format(ifname),
- chk_err=False)
-
- def remove_route_for_dhcp_broadcast(self, ifname):
- shellutil.run("route del 255.255.255.255 dev {0}".format(ifname),
- chk_err=False)
-
- def is_dhcp_enabled(self):
- return False
-
- def stop_dhcp_service(self):
- pass
-
- def start_dhcp_service(self):
- pass
-
- def start_network(self):
- pass
-
- def start_agent_service(self):
- pass
-
- def stop_agent_service(self):
- pass
-
- def register_agent_service(self):
- pass
-
- def unregister_agent_service(self):
- pass
-
- def restart_ssh_service(self):
- pass
-
- def route_add(self, net, mask, gateway):
- """
- Add specified route using /sbin/route add -net.
- """
- cmd = ("/sbin/route add -net "
- "{0} netmask {1} gw {2}").format(net, mask, gateway)
- return shellutil.run(cmd, chk_err=False)
-
- def get_dhcp_pid(self):
- ret= shellutil.run_get_output("pidof dhclient")
- return ret[1] if ret[0] == 0 else None
-
- def set_hostname(self, hostname):
- fileutil.write_file('/etc/hostname', hostname)
- shellutil.run("hostname {0}".format(hostname), chk_err=False)
-
- def set_dhcp_hostname(self, hostname):
- autosend = r'^[^#]*?send\s*host-name.*?(<hostname>|gethostname[(,)])'
- dhclient_files = ['/etc/dhcp/dhclient.conf', '/etc/dhcp3/dhclient.conf']
- for conf_file in dhclient_files:
- if not os.path.isfile(conf_file):
- continue
- if fileutil.findstr_in_file(conf_file, autosend):
- #Return if auto send host-name is configured
- return
- fileutil.update_conf_file(conf_file,
- 'send host-name',
- 'send host-name {0}'.format(hostname))
-
- def restart_if(self, ifname):
- shellutil.run("ifdown {0} && ifup {1}".format(ifname, ifname))
-
- def publish_hostname(self, hostname):
- self.set_dhcp_hostname(hostname)
- ifname = self.get_if_name()
- self.restart_if(ifname)
-
- def set_scsi_disks_timeout(self, timeout):
- for dev in os.listdir("/sys/block"):
- if dev.startswith('sd'):
- self.set_block_device_timeout(dev, timeout)
-
- def set_block_device_timeout(self, dev, timeout):
- if dev is not None and timeout is not None:
- file_path = "/sys/block/{0}/device/timeout".format(dev)
- content = fileutil.read_file(file_path)
- original = content.splitlines()[0].rstrip()
- if original != timeout:
- fileutil.write_file(file_path, timeout)
- logger.info("Set block dev timeout: {0} with timeout: {1}",
- dev, timeout)
-
- def get_mount_point(self, mountlist, device):
- """
- Example of mountlist:
- /dev/sda1 on / type ext4 (rw)
- proc on /proc type proc (rw)
- sysfs on /sys type sysfs (rw)
- devpts on /dev/pts type devpts (rw,gid=5,mode=620)
- tmpfs on /dev/shm type tmpfs
- (rw,rootcontext="system_u:object_r:tmpfs_t:s0")
- none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
- /dev/sdb1 on /mnt/resource type ext4 (rw)
- """
- if (mountlist and device):
- for entry in mountlist.split('\n'):
- if(re.search(device, entry)):
- tokens = entry.split()
- #Return the 3rd column of this line
- return tokens[2] if len(tokens) > 2 else None
- return None
-
- def device_for_ide_port(self, port_id):
- """
- Return device name attached to ide port 'n'.
- """
- if port_id > 3:
- return None
- g0 = "00000000"
- if port_id > 1:
- g0 = "00000001"
- port_id = port_id - 2
- device = None
- path = "/sys/bus/vmbus/devices/"
- for vmbus in os.listdir(path):
- deviceid = fileutil.read_file(os.path.join(path, vmbus, "device_id"))
- guid = deviceid.lstrip('{').split('-')
- if guid[0] == g0 and guid[1] == "000" + ustr(port_id):
- for root, dirs, files in os.walk(path + vmbus):
- if root.endswith("/block"):
- device = dirs[0]
- break
- else : #older distros
- for d in dirs:
- if ':' in d and "block" == d.split(':')[0]:
- device = d.split(':')[1]
- break
- break
- return device
-
- def del_account(self, username):
- if self.is_sys_user(username):
- logger.error("{0} is a system user. Will not delete it.", username)
- shellutil.run("> /var/run/utmp")
- shellutil.run("userdel -f -r " + username)
- #Remove user from suders
- if os.path.isfile("/etc/suders.d/waagent"):
- try:
- content = fileutil.read_file("/etc/sudoers.d/waagent")
- sudoers = content.split("\n")
- sudoers = [x for x in sudoers if username not in x]
- fileutil.write_file("/etc/sudoers.d/waagent",
- "\n".join(sudoers))
- except IOError as e:
- raise OSUtilError("Failed to remove sudoer: {0}".format(e))
-
- def decode_customdata(self, data):
- return base64.b64decode(data)
-
- def get_total_mem(self):
- cmd = "grep MemTotal /proc/meminfo |awk '{print $2}'"
- ret = shellutil.run_get_output(cmd)
- if ret[0] == 0:
- return int(ret[1])/1024
- else:
- raise OSUtilError("Failed to get total memory: {0}".format(ret[1]))
-
- def get_processor_cores(self):
- ret = shellutil.run_get_output("grep 'processor.*:' /proc/cpuinfo |wc -l")
- if ret[0] == 0:
- return int(ret[1])
- else:
- raise OSUtilError("Failed to get procerssor cores")
-
- def set_admin_access_to_ip(self, dest_ip):
- #This allows root to access dest_ip
- rm_old= "iptables -D OUTPUT -d {0} -j ACCEPT -m owner --uid-owner 0"
- rule = "iptables -A OUTPUT -d {0} -j ACCEPT -m owner --uid-owner 0"
- shellutil.run(rm_old.format(dest_ip), chk_err=False)
- shellutil.run(rule.format(dest_ip))
-
- #This blocks all other users to access dest_ip
- rm_old = "iptables -D OUTPUT -d {0} -j DROP"
- rule = "iptables -A OUTPUT -d {0} -j DROP"
- shellutil.run(rm_old.format(dest_ip), chk_err=False)
- shellutil.run(rule.format(dest_ip))
-
diff --git a/azurelinuxagent/distro/default/protocolUtil.py b/azurelinuxagent/distro/default/protocolUtil.py
deleted file mode 100644
index 34466cf..0000000
--- a/azurelinuxagent/distro/default/protocolUtil.py
+++ /dev/null
@@ -1,243 +0,0 @@
-# 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 re
-import shutil
-import time
-import threading
-import azurelinuxagent.conf as conf
-import azurelinuxagent.logger as logger
-from azurelinuxagent.exception import ProtocolError, OSUtilError, \
- ProtocolNotFoundError, DhcpError
-from azurelinuxagent.future import ustr
-import azurelinuxagent.utils.fileutil as fileutil
-from azurelinuxagent.protocol.ovfenv import OvfEnv
-from azurelinuxagent.protocol.wire import WireProtocol
-from azurelinuxagent.protocol.metadata import MetadataProtocol, METADATA_ENDPOINT
-import azurelinuxagent.utils.shellutil as shellutil
-
-OVF_FILE_NAME = "ovf-env.xml"
-
-#Tag file to indicate usage of metadata protocol
-TAG_FILE_NAME = "useMetadataEndpoint.tag"
-
-PROTOCOL_FILE_NAME = "Protocol"
-
-#MAX retry times for protocol probing
-MAX_RETRY = 360
-
-PROBE_INTERVAL = 10
-
-ENDPOINT_FILE_NAME = "WireServerEndpoint"
-
-class ProtocolUtil(object):
- """
- ProtocolUtil handles initialization for protocol instance. 2 protocol types
- are invoked, wire protocol and metadata protocols.
- """
- def __init__(self, distro):
- self.distro = distro
- self.protocol = None
- self.lock = threading.Lock()
-
- def copy_ovf_env(self):
- """
- Copy ovf env file from dvd to hard disk.
- Remove password before save it to the disk
- """
- dvd_mount_point = conf.get_dvd_mount_point()
- ovf_file_path_on_dvd = os.path.join(dvd_mount_point, OVF_FILE_NAME)
- tag_file_path_on_dvd = os.path.join(dvd_mount_point, TAG_FILE_NAME)
- try:
- self.distro.osutil.mount_dvd()
- ovfxml = fileutil.read_file(ovf_file_path_on_dvd, remove_bom=True)
- ovfenv = OvfEnv(ovfxml)
- ovfxml = re.sub("<UserPassword>.*?<", "<UserPassword>*<", ovfxml)
- ovf_file_path = os.path.join(conf.get_lib_dir(), OVF_FILE_NAME)
- fileutil.write_file(ovf_file_path, ovfxml)
-
- if os.path.isfile(tag_file_path_on_dvd):
- logger.info("Found {0} in provisioning ISO", TAG_FILE_NAME)
- tag_file_path = os.path.join(conf.get_lib_dir(), TAG_FILE_NAME)
- shutil.copyfile(tag_file_path_on_dvd, tag_file_path)
-
- except (OSUtilError, IOError) as e:
- raise ProtocolError(ustr(e))
-
- try:
- self.distro.osutil.umount_dvd()
- self.distro.osutil.eject_dvd()
- except OSUtilError as e:
- logger.warn(ustr(e))
-
- return ovfenv
-
- def get_ovf_env(self):
- """
- Load saved ovf-env.xml
- """
- ovf_file_path = os.path.join(conf.get_lib_dir(), OVF_FILE_NAME)
- if os.path.isfile(ovf_file_path):
- xml_text = fileutil.read_file(ovf_file_path)
- return OvfEnv(xml_text)
- else:
- raise ProtocolError("ovf-env.xml is missing.")
-
- def _get_wireserver_endpoint(self):
- try:
- file_path = os.path.join(conf.get_lib_dir(), ENDPOINT_FILE_NAME)
- return fileutil.read_file(file_path)
- except IOError as e:
- raise OSUtilError(ustr(e))
-
- def _set_wireserver_endpoint(self, endpoint):
- try:
- file_path = os.path.join(conf.get_lib_dir(), ENDPOINT_FILE_NAME)
- fileutil.write_file(file_path, endpoint)
- except IOError as e:
- raise OSUtilError(ustr(e))
-
- def _detect_wire_protocol(self):
- endpoint = self.distro.dhcp_handler.endpoint
- if endpoint is None:
- logger.info("WireServer endpoint is not found. Rerun dhcp handler")
- try:
- self.distro.dhcp_handler.run()
- except DhcpError as e:
- raise ProtocolError(ustr(e))
- endpoint = self.distro.dhcp_handler.endpoint
-
- try:
- protocol = WireProtocol(endpoint)
- protocol.detect()
- self._set_wireserver_endpoint(endpoint)
- return protocol
- except ProtocolError as e:
- logger.info("WireServer is not responding. Reset endpoint")
- self.distro.dhcp_handler.endpoint = None
- raise e
-
- def _detect_metadata_protocol(self):
- protocol = MetadataProtocol()
- protocol.detect()
-
- #Only allow root access METADATA_ENDPOINT
- self.distro.osutil.set_admin_access_to_ip(METADATA_ENDPOINT)
-
- return protocol
-
- def _detect_protocol(self, protocols):
- """
- Probe protocol endpoints in turn.
- """
- protocol_file_path = os.path.join(conf.get_lib_dir(), PROTOCOL_FILE_NAME)
- if os.path.isfile(protocol_file_path):
- os.remove(protocol_file_path)
- for retry in range(0, MAX_RETRY):
- for protocol in protocols:
- try:
- if protocol == "WireProtocol":
- return self._detect_wire_protocol()
-
- if protocol == "MetadataProtocol":
- return self._detect_metadata_protocol()
-
- except ProtocolError as e:
- logger.info("Protocol endpoint not found: {0}, {1}",
- protocol, e)
-
- if retry < MAX_RETRY -1:
- logger.info("Retry detect protocols: retry={0}", retry)
- time.sleep(PROBE_INTERVAL)
- raise ProtocolNotFoundError("No protocol found.")
-
- def _get_protocol(self):
- """
- Get protocol instance based on previous detecting result.
- """
- protocol_file_path = os.path.join(conf.get_lib_dir(),
- PROTOCOL_FILE_NAME)
- if not os.path.isfile(protocol_file_path):
- raise ProtocolError("No protocl found")
-
- protocol_name = fileutil.read_file(protocol_file_path)
- if protocol_name == "WireProtocol":
- endpoint = self._get_wireserver_endpoint()
- return WireProtocol(endpoint)
- elif protocol_name == "MetadataProtocol":
- return MetadataProtocol()
- else:
- raise ProtocolNotFoundError(("Unknown protocol: {0}"
- "").format(protocol_name))
-
- def detect_protocol(self):
- """
- Detect protocol by endpoints
-
- :returns: protocol instance
- """
- logger.info("Detect protocol endpoints")
- protocols = ["WireProtocol", "MetadataProtocol"]
- self.lock.acquire()
- try:
- if self.protocol is None:
- self.protocol = self._detect_protocol(protocols)
- return self.protocol
- finally:
- self.lock.release()
-
- def detect_protocol_by_file(self):
- """
- Detect protocol by tag file.
-
- If a file "useMetadataEndpoint.tag" is found on provision iso,
- metedata protocol will be used. No need to probe for wire protocol
-
- :returns: protocol instance
- """
- logger.info("Detect protocol by file")
- self.lock.acquire()
- try:
- tag_file_path = os.path.join(conf.get_lib_dir(), TAG_FILE_NAME)
- if self.protocol is None:
- protocols = []
- if os.path.isfile(tag_file_path):
- protocols.append("MetadataProtocol")
- else:
- protocols.append("WireProtocol")
- self.protocol = self._detect_protocol(protocols)
- finally:
- self.lock.release()
- return self.protocol
-
- def get_protocol(self):
- """
- Get protocol instance based on previous detecting result.
-
- :returns protocol instance
- """
- self.lock.acquire()
- try:
- if self.protocol is None:
- self.protocol = self._get_protocol()
- return self.protocol
- finally:
- self.lock.release()
- return self.protocol
-
diff --git a/azurelinuxagent/distro/default/provision.py b/azurelinuxagent/distro/default/provision.py
deleted file mode 100644
index 695b82a..0000000
--- a/azurelinuxagent/distro/default/provision.py
+++ /dev/null
@@ -1,191 +0,0 @@
-# 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+
-#
-
-"""
-Provision handler
-"""
-
-import os
-import azurelinuxagent.logger as logger
-from azurelinuxagent.future import ustr
-import azurelinuxagent.conf as conf
-from azurelinuxagent.event import add_event, WALAEventOperation
-from azurelinuxagent.exception import ProvisionError, ProtocolError, OSUtilError
-from azurelinuxagent.protocol.restapi import ProvisionStatus
-import azurelinuxagent.utils.shellutil as shellutil
-import azurelinuxagent.utils.fileutil as fileutil
-
-CUSTOM_DATA_FILE="CustomData"
-
-class ProvisionHandler(object):
-
- def __init__(self, distro):
- self.distro = distro
-
- def run(self):
- #If provision is not enabled, return
- if not conf.get_provision_enabled():
- logger.info("Provisioning is disabled. Skip.")
- return
-
- provisioned = os.path.join(conf.get_lib_dir(), "provisioned")
- if os.path.isfile(provisioned):
- return
-
- logger.info("Run provision handler.")
- logger.info("Copy ovf-env.xml.")
- try:
- ovfenv = self.distro.protocol_util.copy_ovf_env()
- except ProtocolError as e:
- self.report_event("Failed to copy ovf-env.xml: {0}".format(e))
- return
-
- self.distro.protocol_util.detect_protocol_by_file()
-
- self.report_not_ready("Provisioning", "Starting")
-
- try:
- logger.info("Start provisioning")
- self.provision(ovfenv)
- fileutil.write_file(provisioned, "")
- thumbprint = self.reg_ssh_host_key()
- logger.info("Finished provisioning")
- except ProvisionError as e:
- logger.error("Provision failed: {0}", e)
- self.report_not_ready("ProvisioningFailed", ustr(e))
- self.report_event(ustr(e))
- return
-
- self.report_ready(thumbprint)
- self.report_event("Provision succeed", is_success=True)
-
- def reg_ssh_host_key(self):
- keypair_type = conf.get_ssh_host_keypair_type()
- if conf.get_regenerate_ssh_host_key():
- shellutil.run("rm -f /etc/ssh/ssh_host_*key*")
- shellutil.run(("ssh-keygen -N '' -t {0} -f /etc/ssh/ssh_host_{1}_key"
- "").format(keypair_type, keypair_type))
- thumbprint = self.get_ssh_host_key_thumbprint(keypair_type)
- return thumbprint
-
- def get_ssh_host_key_thumbprint(self, keypair_type):
- cmd = "ssh-keygen -lf /etc/ssh/ssh_host_{0}_key.pub".format(keypair_type)
- ret = shellutil.run_get_output(cmd)
- if ret[0] == 0:
- return ret[1].rstrip().split()[1].replace(':', '')
- else:
- raise ProvisionError(("Failed to generate ssh host key: "
- "ret={0}, out= {1}").format(ret[0], ret[1]))
-
- def provision(self, ovfenv):
- logger.info("Handle ovf-env.xml.")
- try:
- logger.info("Set host name.")
- self.distro.osutil.set_hostname(ovfenv.hostname)
-
- logger.info("Publish host name.")
- self.distro.osutil.publish_hostname(ovfenv.hostname)
-
- self.config_user_account(ovfenv)
-
- self.save_customdata(ovfenv)
-
- if conf.get_delete_root_password():
- self.distro.osutil.del_root_password()
-
- except OSUtilError as e:
- raise ProvisionError("Failed to handle ovf-env.xml: {0}".format(e))
-
- def config_user_account(self, ovfenv):
- logger.info("Create user account if not exists")
- self.distro.osutil.useradd(ovfenv.username)
-
- if ovfenv.user_password is not None:
- logger.info("Set user password.")
- crypt_id = conf.get_password_cryptid()
- salt_len = conf.get_password_crypt_salt_len()
- self.distro.osutil.chpasswd(ovfenv.username, ovfenv.user_password,
- crypt_id=crypt_id, salt_len=salt_len)
-
- logger.info("Configure sudoer")
- self.distro.osutil.conf_sudoer(ovfenv.username, ovfenv.user_password is None)
-
- logger.info("Configure sshd")
- self.distro.osutil.conf_sshd(ovfenv.disable_ssh_password_auth)
-
- #Disable selinux temporary
- sel = self.distro.osutil.is_selinux_enforcing()
- if sel:
- self.distro.osutil.set_selinux_enforce(0)
-
- self.deploy_ssh_pubkeys(ovfenv)
- self.deploy_ssh_keypairs(ovfenv)
-
- if sel:
- self.distro.osutil.set_selinux_enforce(1)
-
- self.distro.osutil.restart_ssh_service()
-
- def save_customdata(self, ovfenv):
- customdata = ovfenv.customdata
- if customdata is None:
- return
-
- logger.info("Save custom data")
- lib_dir = conf.get_lib_dir()
- if conf.get_decode_customdata():
- customdata= self.distro.osutil.decode_customdata(customdata)
- customdata_file = os.path.join(lib_dir, CUSTOM_DATA_FILE)
- fileutil.write_file(customdata_file, customdata)
-
- if conf.get_execute_customdata():
- logger.info("Execute custom data")
- os.chmod(customdata_file, 0o700)
- shellutil.run(customdata_file)
-
- def deploy_ssh_pubkeys(self, ovfenv):
- for pubkey in ovfenv.ssh_pubkeys:
- logger.info("Deploy ssh public key.")
- self.distro.osutil.deploy_ssh_pubkey(ovfenv.username, pubkey)
-
- def deploy_ssh_keypairs(self, ovfenv):
- for keypair in ovfenv.ssh_keypairs:
- logger.info("Deploy ssh key pairs.")
- self.distro.osutil.deploy_ssh_keypair(ovfenv.username, keypair)
-
- def report_event(self, message, is_success=False):
- add_event(name="WALA", message=message, is_success=is_success,
- op=WALAEventOperation.Provision)
-
- def report_not_ready(self, sub_status, description):
- status = ProvisionStatus(status="NotReady", subStatus=sub_status,
- description=description)
- try:
- protocol = self.distro.protocol_util.get_protocol()
- protocol.report_provision_status(status)
- except ProtocolError as e:
- self.report_event(ustr(e))
-
- def report_ready(self, thumbprint=None):
- status = ProvisionStatus(status="Ready")
- status.properties.certificateThumbprint = thumbprint
- try:
- protocol = self.distro.protocol_util.get_protocol()
- protocol.report_provision_status(status)
- except ProtocolError as e:
- self.report_event(ustr(e))
-
diff --git a/azurelinuxagent/distro/default/resourceDisk.py b/azurelinuxagent/distro/default/resourceDisk.py
deleted file mode 100644
index a6c5232..0000000
--- a/azurelinuxagent/distro/default/resourceDisk.py
+++ /dev/null
@@ -1,167 +0,0 @@
-# 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 re
-import threading
-import azurelinuxagent.logger as logger
-from azurelinuxagent.future import ustr
-import azurelinuxagent.conf as conf
-from azurelinuxagent.event import add_event, WALAEventOperation
-import azurelinuxagent.utils.fileutil as fileutil
-import azurelinuxagent.utils.shellutil as shellutil
-from azurelinuxagent.exception import ResourceDiskError
-
-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, distro):
- self.distro = distro
-
- 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.distro.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.distro.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")
- shellutil.run(("dd if=/dev/zero of={0} bs=1024 "
- "count={1}").format(swapfile, size_kb))
- 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))
-
diff --git a/azurelinuxagent/distro/default/scvmm.py b/azurelinuxagent/distro/default/scvmm.py
deleted file mode 100644
index 4d083b4..0000000
--- a/azurelinuxagent/distro/default/scvmm.py
+++ /dev/null
@@ -1,48 +0,0 @@
-# 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 subprocess
-import azurelinuxagent.logger as logger
-
-VMM_CONF_FILE_NAME = "linuxosconfiguration.xml"
-VMM_STARTUP_SCRIPT_NAME= "install"
-
-class ScvmmHandler(object):
- def __init__(self, distro):
- self.distro = distro
-
- def detect_scvmm_env(self):
- logger.info("Detecting Microsoft System Center VMM Environment")
- self.distro.osutil.mount_dvd(max_retry=1, chk_err=False)
- mount_point = self.distro.osutil.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.distro.osutil.umount_dvd(chk_err=False)
- return found
-
- def start_scvmm_agent(self):
- logger.info("Starting Microsoft System Center VMM Initialization "
- "Process")
- mount_point = self.distro.osutil.get_dvd_mount_point()
- startup_script = os.path.join(mount_point, VMM_STARTUP_SCRIPT_NAME)
- subprocess.Popen(["/bin/bash", startup_script, "-p " + mount_point])
-
diff --git a/azurelinuxagent/distro/loader.py b/azurelinuxagent/distro/loader.py
deleted file mode 100644
index 74ea9e7..0000000
--- a/azurelinuxagent/distro/loader.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# 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.logger as logger
-from azurelinuxagent.utils.textutil import Version
-from azurelinuxagent.metadata import DISTRO_NAME, DISTRO_VERSION, \
- DISTRO_FULL_NAME
-from azurelinuxagent.distro.default.distro import DefaultDistro
-from azurelinuxagent.distro.ubuntu.distro import UbuntuDistro, \
- Ubuntu14Distro, \
- Ubuntu12Distro, \
- UbuntuSnappyDistro
-from azurelinuxagent.distro.redhat.distro import RedhatDistro, Redhat6xDistro
-from azurelinuxagent.distro.coreos.distro import CoreOSDistro
-from azurelinuxagent.distro.suse.distro import SUSE11Distro, SUSEDistro
-from azurelinuxagent.distro.debian.distro import DebianDistro
-
-def get_distro(distro_name=DISTRO_NAME, distro_version=DISTRO_VERSION,
- distro_full_name=DISTRO_FULL_NAME):
- if distro_name == "ubuntu":
- if Version(distro_version) == Version("12.04") or \
- Version(distro_version) == Version("12.10"):
- return Ubuntu12Distro()
- elif Version(distro_version) == Version("14.04") or \
- Version(distro_version) == Version("14.10"):
- return Ubuntu14Distro()
- elif distro_full_name == "Snappy Ubuntu Core":
- return UbuntuSnappyDistro()
- else:
- return UbuntuDistro()
- if distro_name == "coreos":
- return CoreOSDistro()
- if distro_name == "suse":
- if distro_full_name=='SUSE Linux Enterprise Server' and \
- Version(distro_version) < Version('12') or \
- distro_full_name == 'openSUSE' and \
- Version(distro_version) < Version('13.2'):
- return SUSE11Distro()
- else:
- return SUSEDistro()
- elif distro_name == "debian":
- return DebianDistro()
- elif distro_name == "redhat" or distro_name == "centos" or \
- distro_name == "oracle":
- if Version(distro_version) < Version("7"):
- return Redhat6xDistro()
- else:
- return RedhatDistro()
- else:
- logger.warn("Unable to load distro implemetation for {0}.", distro_name)
- logger.warn("Use default distro implemetation instead.")
- return DefaultDistro()
-
diff --git a/azurelinuxagent/distro/redhat/__init__.py b/azurelinuxagent/distro/redhat/__init__.py
deleted file mode 100644
index d9b82f5..0000000
--- a/azurelinuxagent/distro/redhat/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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+
-#
-
diff --git a/azurelinuxagent/distro/redhat/distro.py b/azurelinuxagent/distro/redhat/distro.py
deleted file mode 100644
index 2f128d7..0000000
--- a/azurelinuxagent/distro/redhat/distro.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# 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.distro.default.distro import DefaultDistro
-from azurelinuxagent.distro.redhat.osutil import RedhatOSUtil, Redhat6xOSUtil
-from azurelinuxagent.distro.coreos.deprovision import CoreOSDeprovisionHandler
-
-class Redhat6xDistro(DefaultDistro):
- def __init__(self):
- super(Redhat6xDistro, self).__init__()
- self.osutil = Redhat6xOSUtil()
-
-class RedhatDistro(DefaultDistro):
- def __init__(self):
- super(RedhatDistro, self).__init__()
- self.osutil = RedhatOSUtil()
diff --git a/azurelinuxagent/distro/redhat/osutil.py b/azurelinuxagent/distro/redhat/osutil.py
deleted file mode 100644
index 7f769a5..0000000
--- a/azurelinuxagent/distro/redhat/osutil.py
+++ /dev/null
@@ -1,115 +0,0 @@
-#
-# 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 pwd
-import shutil
-import socket
-import array
-import struct
-import fcntl
-import time
-import base64
-import azurelinuxagent.conf as conf
-import azurelinuxagent.logger as logger
-from azurelinuxagent.future import ustr, bytebuffer
-from azurelinuxagent.exception import OSUtilError, CryptError
-import azurelinuxagent.utils.fileutil as fileutil
-import azurelinuxagent.utils.shellutil as shellutil
-import azurelinuxagent.utils.textutil as textutil
-from azurelinuxagent.utils.cryptutil import CryptUtil
-from azurelinuxagent.distro.default.osutil import DefaultOSUtil
-
-class Redhat6xOSUtil(DefaultOSUtil):
- def __init__(self):
- super(Redhat6xOSUtil, self).__init__()
-
- def start_network(self):
- return shellutil.run("/sbin/service networking start", chk_err=False)
-
- def restart_ssh_service(self):
- return shellutil.run("/sbin/service sshd condrestart", chk_err=False)
-
- def stop_agent_service(self):
- return shellutil.run("/sbin/service waagent stop", chk_err=False)
-
- def start_agent_service(self):
- return shellutil.run("/sbin/service waagent start", chk_err=False)
-
- def register_agent_service(self):
- return shellutil.run("chkconfig --add waagent", chk_err=False)
-
- def unregister_agent_service(self):
- return shellutil.run("chkconfig --del waagent", chk_err=False)
-
- def openssl_to_openssh(self, input_file, output_file):
- pubkey = fileutil.read_file(input_file)
- try:
- cryptutil = CryptUtil(conf.get_openssl_cmd())
- ssh_rsa_pubkey = cryptutil.asn1_to_ssh(pubkey)
- except CryptError as e:
- raise OSUtilError(ustr(e))
- fileutil.write_file(output_file, ssh_rsa_pubkey)
-
- #Override
- def get_dhcp_pid(self):
- ret= shellutil.run_get_output("pidof dhclient")
- return ret[1] if ret[0] == 0 else None
-
- def set_hostname(self, hostname):
- """
- Set /etc/sysconfig/network
- """
- fileutil.update_conf_file('/etc/sysconfig/network',
- 'HOSTNAME',
- 'HOSTNAME={0}'.format(hostname))
- shellutil.run("hostname {0}".format(hostname), chk_err=False)
-
- def set_dhcp_hostname(self, hostname):
- ifname = self.get_if_name()
- filepath = "/etc/sysconfig/network-scripts/ifcfg-{0}".format(ifname)
- fileutil.update_conf_file(filepath, 'DHCP_HOSTNAME',
- 'DHCP_HOSTNAME={0}'.format(hostname))
-
-class RedhatOSUtil(Redhat6xOSUtil):
- def __init__(self):
- super(RedhatOSUtil, self).__init__()
-
- def set_hostname(self, hostname):
- """
- Set /etc/hostname
- Unlike redhat 6.x, redhat 7.x will set hostname to /etc/hostname
- """
- DefaultOSUtil.set_hostname(self, hostname)
-
- def publish_hostname(self, hostname):
- """
- Restart NetworkManager first before publishing hostname
- """
- shellutil.run("service NetworkManager restart")
- super(RedhatOSUtil, self).publish_hostname(hostname)
-
- def register_agent_service(self):
- return shellutil.run("systemctl enable waagent", chk_err=False)
-
- def unregister_agent_service(self):
- return shellutil.run("systemctl disable waagent", chk_err=False)
-
- def openssl_to_openssh(self, input_file, output_file):
- DefaultOSUtil.openssl_to_openssh(self, input_file, output_file)
diff --git a/azurelinuxagent/distro/suse/__init__.py b/azurelinuxagent/distro/suse/__init__.py
index d9b82f5..1ea2f38 100644
--- a/azurelinuxagent/distro/suse/__init__.py
+++ b/azurelinuxagent/distro/suse/__init__.py
@@ -1,5 +1,3 @@
-# Microsoft Azure Linux Agent
-#
# Copyright 2014 Microsoft Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/azurelinuxagent/distro/suse/distro.py b/azurelinuxagent/distro/suse/distro.py
deleted file mode 100644
index 5b39369..0000000
--- a/azurelinuxagent/distro/suse/distro.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# 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.distro.default.distro import DefaultDistro
-from azurelinuxagent.distro.suse.osutil import SUSE11OSUtil, SUSEOSUtil
-
-class SUSE11Distro(DefaultDistro):
- def __init__(self):
- super(SUSE11Distro, self).__init__()
- self.osutil = SUSE11OSUtil()
-
-class SUSEDistro(DefaultDistro):
- def __init__(self):
- super(SUSEDistro, self).__init__()
- self.osutil = SUSEOSUtil()
-
diff --git a/azurelinuxagent/distro/suse/osutil.py b/azurelinuxagent/distro/suse/osutil.py
deleted file mode 100644
index 8d6f5bf..0000000
--- a/azurelinuxagent/distro/suse/osutil.py
+++ /dev/null
@@ -1,108 +0,0 @@
-#
-# 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 pwd
-import shutil
-import socket
-import array
-import struct
-import fcntl
-import time
-import azurelinuxagent.logger as logger
-import azurelinuxagent.utils.fileutil as fileutil
-import azurelinuxagent.utils.shellutil as shellutil
-import azurelinuxagent.utils.textutil as textutil
-from azurelinuxagent.metadata import DISTRO_NAME, DISTRO_VERSION, DISTRO_FULL_NAME
-from azurelinuxagent.distro.default.osutil import DefaultOSUtil
-
-class SUSE11OSUtil(DefaultOSUtil):
- def __init__(self):
- super(SUSE11OSUtil, self).__init__()
- self.dhclient_name='dhcpcd'
-
- def set_hostname(self, hostname):
- fileutil.write_file('/etc/HOSTNAME', hostname)
- shellutil.run("hostname {0}".format(hostname), chk_err=False)
-
- def get_dhcp_pid(self):
- ret= shellutil.run_get_output("pidof {0}".format(self.dhclient_name))
- return ret[1] if ret[0] == 0 else None
-
- def is_dhcp_enabled(self):
- return True
-
- def stop_dhcp_service(self):
- cmd = "/sbin/service {0} stop".format(self.dhclient_name)
- return shellutil.run(cmd, chk_err=False)
-
- def start_dhcp_service(self):
- cmd = "/sbin/service {0} start".format(self.dhclient_name)
- return shellutil.run(cmd, chk_err=False)
-
- def start_network(self) :
- return shellutil.run("/sbin/service start network", chk_err=False)
-
- def restart_ssh_service(self):
- return shellutil.run("/sbin/service sshd restart", chk_err=False)
-
- def stop_agent_service(self):
- return shellutil.run("/sbin/service waagent stop", chk_err=False)
-
- def start_agent_service(self):
- return shellutil.run("/sbin/service waagent start", chk_err=False)
-
- def register_agent_service(self):
- return shellutil.run("/sbin/insserv waagent", chk_err=False)
-
- def unregister_agent_service(self):
- return shellutil.run("/sbin/insserv -r waagent", chk_err=False)
-
-class SUSEOSUtil(SUSE11OSUtil):
- def __init__(self):
- super(SUSEOSUtil, self).__init__()
- self.dhclient_name = 'wickedd-dhcp4'
-
- def stop_dhcp_service(self):
- cmd = "systemctl stop {0}".format(self.dhclient_name)
- return shellutil.run(cmd, chk_err=False)
-
- def start_dhcp_service(self):
- cmd = "systemctl start {0}".format(self.dhclient_name)
- return shellutil.run(cmd, chk_err=False)
-
- def start_network(self) :
- return shellutil.run("systemctl start network", chk_err=False)
-
- def restart_ssh_service(self):
- return shellutil.run("systemctl restart sshd", chk_err=False)
-
- def stop_agent_service(self):
- return shellutil.run("systemctl stop waagent", chk_err=False)
-
- def start_agent_service(self):
- return shellutil.run("systemctl start waagent", chk_err=False)
-
- def register_agent_service(self):
- return shellutil.run("systemctl enable waagent", chk_err=False)
-
- def unregister_agent_service(self):
- return shellutil.run("systemctl disable waagent", chk_err=False)
-
-
diff --git a/azurelinuxagent/distro/ubuntu/__init__.py b/azurelinuxagent/distro/ubuntu/__init__.py
deleted file mode 100644
index d9b82f5..0000000
--- a/azurelinuxagent/distro/ubuntu/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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+
-#
-
diff --git a/azurelinuxagent/distro/ubuntu/deprovision.py b/azurelinuxagent/distro/ubuntu/deprovision.py
deleted file mode 100644
index da6e834..0000000
--- a/azurelinuxagent/distro/ubuntu/deprovision.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# 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 azurelinuxagent.logger as logger
-import azurelinuxagent.utils.fileutil as fileutil
-from azurelinuxagent.distro.default.deprovision import DeprovisionHandler, DeprovisionAction
-
-def del_resolv():
- if os.path.realpath('/etc/resolv.conf') != '/run/resolvconf/resolv.conf':
- logger.info("resolvconf is not configured. Removing /etc/resolv.conf")
- fileutil.rm_files('/etc/resolv.conf')
- else:
- logger.info("resolvconf is enabled; leaving /etc/resolv.conf intact")
- fileutil.rm_files('/etc/resolvconf/resolv.conf.d/tail',
- '/etc/resolvconf/resolv.conf.d/originial')
-
-
-class UbuntuDeprovisionHandler(DeprovisionHandler):
- def __init__(self, distro):
- super(UbuntuDeprovisionHandler, self).__init__(distro)
-
- def setup(self, deluser):
- warnings, actions = super(UbuntuDeprovisionHandler, self).setup(deluser)
- warnings.append("WARNING! Nameserver configuration in "
- "/etc/resolvconf/resolv.conf.d/{tail,originial} "
- "will be deleted.")
- actions.append(DeprovisionAction(del_resolv))
- return warnings, actions
-
diff --git a/azurelinuxagent/distro/ubuntu/distro.py b/azurelinuxagent/distro/ubuntu/distro.py
deleted file mode 100644
index f380f6c..0000000
--- a/azurelinuxagent/distro/ubuntu/distro.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# 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.distro.default.distro import DefaultDistro
-from azurelinuxagent.distro.ubuntu.osutil import Ubuntu14OSUtil, \
- Ubuntu12OSUtil, \
- UbuntuOSUtil, \
- UbuntuSnappyOSUtil
-
-from azurelinuxagent.distro.ubuntu.provision import UbuntuProvisionHandler
-from azurelinuxagent.distro.ubuntu.deprovision import UbuntuDeprovisionHandler
-
-class UbuntuDistro(DefaultDistro):
- def __init__(self):
- super(UbuntuDistro, self).__init__()
- self.osutil = UbuntuOSUtil()
- self.provision_handler = UbuntuProvisionHandler(self)
- self.deprovision_handler = UbuntuDeprovisionHandler(self)
-
-class Ubuntu12Distro(DefaultDistro):
- def __init__(self):
- super(Ubuntu12Distro, self).__init__()
- self.osutil = Ubuntu12OSUtil()
- self.provision_handler = UbuntuProvisionHandler(self)
- self.deprovision_handler = UbuntuDeprovisionHandler(self)
-
-class Ubuntu14Distro(DefaultDistro):
- def __init__(self):
- super(Ubuntu14Distro, self).__init__()
- self.osutil = Ubuntu14OSUtil()
- self.provision_handler = UbuntuProvisionHandler(self)
- self.deprovision_handler = UbuntuDeprovisionHandler(self)
-
-class UbuntuSnappyDistro(DefaultDistro):
- def __init__(self):
- super(UbuntuSnappyDistro, self).__init__()
- self.osutil = UbuntuSnappyOSUtil()
- self.provision_handler = UbuntuProvisionHandler(self)
- self.deprovision_handler = UbuntuDeprovisionHandler(self)
diff --git a/azurelinuxagent/distro/ubuntu/osutil.py b/azurelinuxagent/distro/ubuntu/osutil.py
deleted file mode 100644
index cc4b8ef..0000000
--- a/azurelinuxagent/distro/ubuntu/osutil.py
+++ /dev/null
@@ -1,75 +0,0 @@
-#
-# 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 pwd
-import shutil
-import socket
-import array
-import struct
-import fcntl
-import time
-import azurelinuxagent.logger as logger
-import azurelinuxagent.utils.fileutil as fileutil
-import azurelinuxagent.utils.shellutil as shellutil
-import azurelinuxagent.utils.textutil as textutil
-from azurelinuxagent.distro.default.osutil import DefaultOSUtil
-
-class Ubuntu14OSUtil(DefaultOSUtil):
- def __init__(self):
- super(Ubuntu14OSUtil, self).__init__()
-
- def start_network(self):
- return shellutil.run("service networking start", chk_err=False)
-
- def stop_agent_service(self):
- return shellutil.run("service walinuxagent stop", chk_err=False)
-
- def start_agent_service(self):
- return shellutil.run("service walinuxagent start", chk_err=False)
-
-class Ubuntu12OSUtil(Ubuntu14OSUtil):
- def __init__(self):
- super(Ubuntu12OSUtil, self).__init__()
-
- #Override
- def get_dhcp_pid(self):
- ret= shellutil.run_get_output("pidof dhclient3")
- return ret[1] if ret[0] == 0 else None
-
-class UbuntuOSUtil(Ubuntu14OSUtil):
- def __init__(self):
- super(UbuntuOSUtil, self).__init__()
-
- def register_agent_service(self):
- return shellutil.run("systemctl unmask walinuxagent", chk_err=False)
-
- def unregister_agent_service(self):
- return shellutil.run("systemctl mask walinuxagent", chk_err=False)
-
-class UbuntuSnappyOSUtil(Ubuntu14OSUtil):
- def __init__(self):
- super(UbuntuSnappyOSUtil, self).__init__()
- self.conf_file_path = '/apps/walinuxagent/current/waagent.conf'
-
- def remove_rules_files(self, rules_files=""):
- pass
-
- def restore_rules_files(self, rules_files=""):
- pass
diff --git a/azurelinuxagent/distro/ubuntu/provision.py b/azurelinuxagent/distro/ubuntu/provision.py
deleted file mode 100644
index 330e057..0000000
--- a/azurelinuxagent/distro/ubuntu/provision.py
+++ /dev/null
@@ -1,98 +0,0 @@
-# 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 time
-import azurelinuxagent.logger as logger
-from azurelinuxagent.future import ustr
-import azurelinuxagent.conf as conf
-import azurelinuxagent.protocol.ovfenv as ovfenv
-from azurelinuxagent.event import add_event, WALAEventOperation
-from azurelinuxagent.exception import ProvisionError, ProtocolError
-import azurelinuxagent.utils.shellutil as shellutil
-import azurelinuxagent.utils.fileutil as fileutil
-from azurelinuxagent.distro.default.provision import ProvisionHandler
-
-"""
-On ubuntu image, provision could be disabled.
-"""
-class UbuntuProvisionHandler(ProvisionHandler):
- def __init__(self, distro):
- self.distro = distro
-
- def run(self):
- #If provision is enabled, run default provision handler
- if conf.get_provision_enabled():
- super(UbuntuProvisionHandler, self).run()
- return
-
- logger.info("run Ubuntu provision handler")
- provisioned = os.path.join(conf.get_lib_dir(), "provisioned")
- if os.path.isfile(provisioned):
- return
-
- logger.info("Waiting cloud-init to copy ovf-env.xml.")
- self.wait_for_ovfenv()
-
- protocol = self.distro.protocol_util.detect_protocol()
- self.report_not_ready("Provisioning", "Starting")
- logger.info("Sleep 15 seconds to prevent throttling")
- time.sleep(15) #Sleep to prevent throttling
- try:
- logger.info("Wait for ssh host key to be generated.")
- thumbprint = self.wait_for_ssh_host_key()
- fileutil.write_file(provisioned, "")
- logger.info("Finished provisioning")
-
- except ProvisionError as e:
- logger.error("Provision failed: {0}", e)
- self.report_not_ready("ProvisioningFailed", ustr(e))
- self.report_event(ustr(e))
- return
-
- self.report_ready(thumbprint)
- self.report_event("Provision succeed", is_success=True)
-
- def wait_for_ovfenv(self, max_retry=60):
- """
- Wait for cloud-init to copy ovf-env.xml file from provision ISO
- """
- for retry in range(0, max_retry):
- try:
- self.distro.protocol_util.get_ovf_env()
- return
- except ProtocolError:
- if retry < max_retry - 1:
- logger.info("Wait for cloud-init to copy ovf-env.xml")
- time.sleep(5)
- raise ProvisionError("ovf-env.xml is not copied")
-
- def wait_for_ssh_host_key(self, max_retry=60):
- """
- Wait for cloud-init to generate ssh host key
- """
- kepair_type = conf.get_ssh_host_keypair_type()
- path = '/etc/ssh/ssh_host_{0}_key'.format(kepair_type)
- for retry in range(0, max_retry):
- if os.path.isfile(path):
- return self.get_ssh_host_key_thumbprint(kepair_type)
- if retry < max_retry - 1:
- logger.info("Wait for ssh host key be generated: {0}", path)
- time.sleep(5)
- raise ProvisionError("Ssh hsot key is not generated.")