This commit is contained in:
Yue Zhang 2015-11-23 12:34:03 +08:00
Родитель d5a2bb12be
Коммит e875ac866f
45 изменённых файлов: 1116 добавлений и 1098 удалений

Просмотреть файл

@ -29,27 +29,60 @@ from azurelinuxagent.metadata import AGENT_NAME, AGENT_LONG_VERSION, \
DISTRO_NAME, DISTRO_VERSION, \
PY_VERSION_MAJOR, PY_VERSION_MINOR, \
PY_VERSION_MICRO
from azurelinuxagent.utils.osutil import OSUTIL
from azurelinuxagent.handler import HANDLERS
from azurelinuxagent.distro.loader import get_distro
def init(verbose):
"""
Initialize agent running environment.
"""
HANDLERS.init_handler.init(verbose)
class Agent(object):
def __init__(self, verbose):
"""
Initialize agent running environment.
"""
self.distro = get_distro();
self.distro.init_handler.run(verbose)
def run():
"""
Run agent daemon
"""
HANDLERS.main_handler.run()
def daemon(self):
"""
Run agent daemon
"""
self.distro.daemon_handler.run()
def deprovision(force=False, deluser=False):
def deprovision(self, force=False, deluser=False):
"""
Run deprovision command
"""
self.distro.deprovision_handler.run(force=force, deluser=deluser)
def register_service(self):
"""
Register agent as a service
"""
print("Register {0} service".format(AGENT_NAME))
self.distro.osutil.register_agent_service()
print("Start {0} service".format(AGENT_NAME))
self.distro.osutil.start_agent_service()
def main(args):
"""
Run deprovision command
Parse command line arguments, exit with usage() on error.
Invoke different methods according to different command
"""
HANDLERS.deprovision_handler.deprovision(force=force, deluser=deluser)
command, force, verbose = parse_args(args)
if command == "version":
version()
elif command == "help":
usage()
elif command == "start":
start()
else:
agent = Agent(verbose)
if command == "deprovision+user":
agent.deprovision(force, deluser=True)
elif command == "deprovision":
agent.deprovision(force, deluser=False)
elif command == "register-service":
agent.register_service()
elif command == "daemon":
agent.daemon()
def parse_args(sys_args):
"""
@ -108,34 +141,3 @@ def start():
devnull = open(os.devnull, 'w')
subprocess.Popen([sys.argv[0], '-daemon'], stdout=devnull, stderr=devnull)
def register_service():
"""
Register agent as a service
"""
print("Register {0} service".format(AGENT_NAME))
OSUTIL.register_agent_service()
print("Start {0} service".format(AGENT_NAME))
OSUTIL.start_agent_service()
def main():
"""
Parse command line arguments, exit with usage() on error.
Invoke different methods according to different command
"""
command, force, verbose = parse_args(sys.argv[1:])
if command == "version":
version()
elif command == "help":
usage()
else:
init(verbose)
if command == "deprovision+user":
deprovision(force, deluser=True)
elif command == "deprovision":
deprovision(force, deluser=False)
elif command == "start":
start()
elif command == "register-service":
register_service()
elif command == "daemon":
run()

Просмотреть файл

@ -43,11 +43,11 @@ class ConfigurationProvider(object):
else:
self.values[parts[0]] = None
def get(self, key, default_val=None):
def get(self, key, default_val):
val = self.values.get(key)
return val if val is not None else default_val
def get_switch(self, key, default_val=False):
def get_switch(self, key, default_val):
val = self.values.get(key)
if val is not None and val.lower() == 'y':
return True
@ -55,7 +55,7 @@ class ConfigurationProvider(object):
return False
return default_val
def get_int(self, key, default_val=-1):
def get_int(self, key, default_val):
try:
return int(self.values.get(key))
except TypeError:
@ -64,9 +64,9 @@ class ConfigurationProvider(object):
return default_val
__config__ = ConfigurationProvider()
__conf__ = ConfigurationProvider()
def load_conf(conf_file_path, conf=__config__):
def load_conf_from_file(conf_file_path, conf=__conf__):
"""
Load conf file from: conf_file_path
"""
@ -80,30 +80,75 @@ def load_conf(conf_file_path, conf=__config__):
raise AgentConfigError(("Failed to load conf file:{0}, {1}"
"").format(conf_file_path, err))
def get(key, default_val=None, conf=__config__):
"""
Get option value by key, return default_val if not found
"""
if conf is not None:
return conf.get(key, default_val)
else:
return default_val
def get_lib_dir(conf=__conf__):
return conf.get("Lib.Dir", "/var/lib/waagent")
def get_switch(key, default_val=None, conf=__config__):
"""
Get bool option value by key, return default_val if not found
"""
if conf is not None:
return conf.get_switch(key, default_val)
else:
return default_val
def get_dvd_mount_point(conf=__conf__):
return conf.get("DVD.MountPoint", "/mnt/cdrom/secure")
def get_int(key, default_val=None, conf=__config__):
"""
Get int option value by key, return default_val if not found
"""
if conf is not None:
return conf.get_int(key, default_val)
else:
return default_val
def get_agent_pid_file_path(conf=__conf__):
return conf.get("Pid.File", "/mnt/cdrom/secure")
def get_ext_log_dir(conf=__conf__):
return conf.get("Extension.LogDir", "/var/log/azure")
def get_openssl_cmd(conf=__conf__):
return conf.get("OS.OpensslPath", "/usr/bin/openssl")
def get_home_dir(conf=__conf__):
return conf.get("OS.HomeDir", "/home")
def get_passwd_file_path(conf=__conf__):
return conf.get("OS.PasswordPath", "/etc/shadow")
def get_sshd_conf_file_path(conf=__conf__):
return conf.get("OS.SshdConfigPath", "/etc/ssh/sshd_config")
def get_root_device_scsi_timeout(conf=__conf__):
return conf.get_int("OS.RootDeviceScsiTimeout", None)
def get_ssh_host_keypair_type(conf=__conf__):
return conf.get("Provisioning.SshHostKeyPairType", "rsa")
def get_provision_enabled(conf=__conf__):
return conf.get_switch("Provisioning.Enabled", True)
def get_regenerate_ssh_host_key(conf=__conf__):
return conf.get_switch("Provisioning.RegenerateSshHostKeyPair", False)
def get_delete_root_password(conf=__conf__):
return conf.get_switch("Provisioning.DeleteRootPassword", False)
def get_password_cryptid(conf=__conf__):
return conf.get("Provisioning.PasswordCryptId", "6")
def get_password_crypt_salt_len(conf=__conf__):
return conf.get_int("Provisioning.PasswordCryptSaltLength", 10)
def get_monitor_hostname(conf=__conf__):
return conf.get_switch("Provisioning.MonitorHostName", False)
def get_httpproxy_host(conf=__conf__):
return conf.get("HttpProxy.Host", None)
def get_httpproxy_port(conf=__conf__):
return conf.get("HttpProxy.Port", None)
def get_detect_scvmm_env(conf=__conf__):
return conf.get_switch("DetectScvmmEnv", False)
def get_resourcedisk_format(conf=__conf__):
return conf.get_switch("ResourceDisk.Format", False)
def get_resourcedisk_enable_swap(conf=__conf__):
return conf.get_switch("ResourceDisk.EnableSwap", False)
def get_resourcedisk_mountpoint(conf=__conf__):
return conf.get("ResourceDisk.MountPoint", "/mnt/resource")
def get_resourcedisk_filesystem(conf=__conf__):
return conf.get("ResourceDisk.MountPoint", "/mnt/resource")
def get_resourcedisk_swap_size_mb(conf=__conf__):
return conf.get_int("ResourceDisk.SwapSizeMB", 0)

Просмотреть файл

@ -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+
#

Просмотреть файл

@ -1,25 +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.metadata import DISTRO_NAME, DISTRO_VERSION
import azurelinuxagent.distro.redhat.loader as redhat
def get_osutil():
return redhat.get_osutil()

Просмотреть файл

@ -21,8 +21,8 @@ import azurelinuxagent.utils.fileutil as fileutil
from azurelinuxagent.distro.default.deprovision import DeprovisionHandler, DeprovisionAction
class CoreOSDeprovisionHandler(DeprovisionHandler):
def __init__(self, handlers):
self.handlers = handlers
def __init__(self, distro):
self.distro = distro
def setup(self, deluser):
warnings, actions = super(CoreOSDeprovisionHandler, self).setup(deluser)

Просмотреть файл

@ -17,11 +17,13 @@
# Requires Python 2.4+ and Openssl 1.0+
#
from .deprovision import CoreOSDeprovisionHandler
from azurelinuxagent.distro.default.handlerFactory import DefaultHandlerFactory
from azurelinuxagent.distro.default.distro import DefaultDistro
from azurelinuxagent.distro.coreos.osutil import CoreOSUtil
from azurelinuxagent.distro.coreos.deprovision import CoreOSDeprovisionHandler
class CoreOSHandlerFactory(DefaultHandlerFactory):
class CoreOSDistro(DefaultDistro):
def __init__(self):
super(CoreOSHandlerFactory, self).__init__()
super(CoreOSDistro, self).__init__()
self.osutil = CoreOSUtil()
self.deprovision_handler = CoreOSDeprovisionHandler(self)

Просмотреть файл

@ -1,28 +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.coreos.osutil import CoreOSUtil
return CoreOSUtil()
def get_handlers():
from azurelinuxagent.distro.coreos.handlerFactory import CoreOSHandlerFactory
return CoreOSHandlerFactory()

Просмотреть файл

@ -35,9 +35,9 @@ 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'
self.conf_file_path = '/usr/share/oem/waagent.conf'
if 'PATH' in os.environ:
path = "{0}:{1}".format(os.environ['PATH'], self.python_path)
else:

Просмотреть файл

@ -17,9 +17,11 @@
# Requires Python 2.4+ and Openssl 1.0+
#
from azurelinuxagent.metadata import DISTRO_NAME, DISTRO_VERSION
import azurelinuxagent.distro.redhat.loader as redhat
from azurelinuxagent.distro.default.distro import DefaultDistro
from azurelinuxagent.distro.debian.osutil import DebianOSUtil
def get_osutil():
return redhat.get_osutil()
class DebianDistro(DefaultDistro):
def __init__(self):
super(DebianDistro, self).__init__()
self.osutil = DebianOSUtil()

Просмотреть файл

@ -20,51 +20,57 @@
import os
import time
import sys
import azurelinuxagent.conf as conf
import azurelinuxagent.logger as logger
from azurelinuxagent.future import text
import azurelinuxagent.conf as conf
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.protocol.dhcp as dhcp
from azurelinuxagent.protocol.factory import PROT_FACTORY
from azurelinuxagent.utils.osutil import OSUTIL
import azurelinuxagent.utils.fileutil as fileutil
class MainHandler(object):
def __init__(self, handlers):
self.handlers = handlers
class DaemonHandler(object):
def __init__(self, distro):
self.distro = distro
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)
#Create lib dir
if not os.path.isdir(self.distro.conf.get_lib_dir()):
fileutil.mkdir(self.distro.conf.get_lib_dir(), mode=0o700)
os.chdir(self.distro.conf.get_lib_dir())
event.enable_unhandled_err_dump(AGENT_LONG_NAME)
fileutil.write_file(OSUTIL.get_agent_pid_file_path(), text(os.getpid()))
#TODO check running daemon
fileutil.write_file(self.distro.osutil.get_agent_pid_file_path(),
text(os.getpid()))
if conf.get_switch("DetectScvmmEnv", False):
if self.handlers.scvmm_handler.detect_scvmm_env():
if conf.get_detect_scvmm_env():
if self.distro.scvmm_handler.run():
return
self.distro.provision_handler.run()
PROT_FACTORY.wait_for_network()
if conf.get_resourcedisk_format():
self.distro.resource_disk_handler.run()
self.handlers.provision_handler.process()
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()
PROT_FACTORY.detect_protocol()
if conf.get_switch("ResourceDisk.Format", False):
self.handlers.resource_disk_handler.start_activate_resource_disk()
event.EventMonitor().start()
self.handlers.env_handler.start()
while True:
#Handle extensions
self.handlers.ext_handlers_handler.process()
self.distro.ext_distro_handler.run()
time.sleep(25)

Просмотреть файл

@ -18,10 +18,8 @@
#
import azurelinuxagent.conf as conf
from azurelinuxagent.utils.osutil import OSUTIL
from azurelinuxagent.exception import ProtocolError
from azurelinuxagent.future import read_input
import azurelinuxagent.protocol as prot
import azurelinuxagent.protocol.ovfenv as ovf
import azurelinuxagent.utils.fileutil as fileutil
import azurelinuxagent.utils.shellutil as shellutil
@ -35,20 +33,20 @@ class DeprovisionAction(object):
self.func(*self.args, **self.kwargs)
class DeprovisionHandler(object):
def __init__(self, handlers):
self.handlers = handlers
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(OSUTIL.del_root_password))
actions.append(DeprovisionAction(self.distro.osutil.del_root_password))
def del_user(self, warnings, actions):
try:
ovfenv = ovf.get_ovf_env()
except prot.ProtocolError:
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
@ -56,7 +54,8 @@ class DeprovisionHandler(object):
username = ovfenv.username
warnings.append(("WARNING! {0} account and entire home directory "
"will be deleted.").format(username))
actions.append(DeprovisionAction(OSUTIL.del_account, [username]))
actions.append(DeprovisionAction(self.distro.osutil.del_account,
[username]))
def regen_ssh_host_key(self, warnings, actions):
@ -66,7 +65,7 @@ class DeprovisionHandler(object):
def stop_agent_service(self, warnings, actions):
warnings.append("WARNING! The waagent service will be stopped.")
actions.append(DeprovisionAction(OSUTIL.stop_agent_service))
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']
@ -78,26 +77,28 @@ class DeprovisionHandler(object):
actions.append(DeprovisionAction(fileutil.rm_dirs, dirs_to_del))
def del_lib_dir(self, warnings, actions):
dirs_to_del = [OSUTIL.get_lib_dir()]
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(OSUTIL.set_hostname, localhost))
actions.append(DeprovisionAction(OSUTIL.set_dhcp_hostname, localhost))
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_switch("Provisioning.RegenerateSshHostkey", False):
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_switch("Provisioning.DeleteRootPassword", False):
if conf.get_delete_root_password():
self.del_root_password(warnings, actions)
self.del_lib_dir(warnings, actions)
@ -108,7 +109,7 @@ class DeprovisionHandler(object):
return warnings, actions
def deprovision(self, force=False, deluser=False):
def run(self, force=False, deluser=False):
warnings, actions = self.setup(deluser)
for warning in warnings:
print(warning)

Просмотреть файл

@ -21,20 +21,49 @@ import array
import time
import threading
import azurelinuxagent.logger as logger
from azurelinuxagent.utils.osutil import OSUTIL
import azurelinuxagent.conf as conf
import azurelinuxagent.utils.fileutil as fileutil
import azurelinuxagent.utils.shellutil as shellutil
from azurelinuxagent.utils.textutil import *
from azurelinuxagent.protocol.common import ProtocolError
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
DHCP_FILE_NAME = "DHCP"
class DhcpResponse(object):
def __init__(self, resp):
endpoint, gateway, routes = parse_dhcp_resp(resp)
self.endpoint = endpoint
self.gateway = gateway
self.routes = routes
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.route = 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()
if self.endpoint is not None:
self.distro.osutil.set_wireserver_endpoint(self.endpoint)
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")
@ -42,56 +71,56 @@ class DhcpResponse(object):
logger.info("Routes:{0}", self.routes)
#Add default gateway
if self.gateway is not None:
OSUTIL.route_add(0 , 0, self.gateway)
self.distro.osutil.route_add(0 , 0, self.gateway)
if self.routes is not None:
for route in self.routes:
OSUTIL.route_add(route[0], route[1], route[2])
self.distro.osutil.route_add(route[0], route[1], route[2])
def _load_dhcp_resp():
dhcp_file_path = os.path.join(OSUTIL.get_lib_dir(), DHCP_FILE_NAME)
resp = fileutil.read_file(dhcp_file_path, asbin=True)
return DhcpResponse(resp)
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 _fetch_dhcp_resp():
logger.info("Send dhcp request")
mac_addr = OSUTIL.get_mac_addr()
req = build_dhcp_request(mac_addr)
resp = send_dhcp_request(req)
if resp is None:
raise ProtocolError("Failed to receive dhcp response.")
dhcp_file_path = os.path.join(OSUTIL.get_lib_dir(), DHCP_FILE_NAME)
try:
fileutil.write_file(dhcp_file_path, resp, asbin=True)
except IOError as e:
logger.warn("Failed to save dhcp response: {0}", e)
return DhcpResponse(resp)
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)
class DhcpClient(object):
def __init__(self):
self._resp = None
self._lock = threading.Lock()
# 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)
def get_dhcp_resp(self):
self._lock.acquire()
try:
if self._resp is None:
try:
self._resp = _load_dhcp_resp()
except IOError:
self._resp = _fetch_dhcp_resp()
return self._resp
finally:
self._lock.release()
# 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()
def fetch_dhcp_resp(self):
self._lock.acquire()
try:
self._resp = _fetch_dhcp_resp()
return self._resp
finally:
self._lock.release()
resp = self._send_dhcp_req(req)
if self.distro.osutil.is_dhcp_enabled():
self.distro.osutil.start_dhcp_service()
DHCPCLIENT = DhcpClient()
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)
@ -110,20 +139,20 @@ def validate_dhcp_resp(request, response):
logger.verb("Cookie not match:\nsend={0},\nreceive={1}",
hex_dump3(request, 0xEC, 4),
hex_dump3(response, 0xEC, 4))
raise ProtocolError("Cookie in dhcp respones doesn't match the request")
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 ProtocolError("TransactionID in dhcp respones "
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 ProtocolError("Mac Addr in dhcp respones "
raise DhcpError("Mac Addr in dhcp respones "
"doesn't match the request")
def parse_route(response, option, i, length, bytes_recv):
@ -203,53 +232,6 @@ def parse_dhcp_resp(response):
i += length + 2
return endpoint, gateway, routes
def allow_dhcp_broadcast(func):
"""
Temporary allow broadcase for dhcp. Remove the route when done.
"""
def wrapper(*args, **kwargs):
missing_default_route = OSUTIL.is_missing_default_route()
ifname = OSUTIL.get_if_name()
if missing_default_route:
OSUTIL.set_route_for_dhcp_broadcast(ifname)
result = func(*args, **kwargs)
if missing_default_route:
OSUTIL.remove_route_for_dhcp_broadcast(ifname)
return result
return wrapper
def disable_dhcp_service(func):
"""
In some distros, dhcp service needs to be shutdown before agent probe
endpoint through dhcp.
"""
def wrapper(*args, **kwargs):
if OSUTIL.is_dhcp_enabled():
OSUTIL.stop_dhcp_service()
result = func(*args, **kwargs)
OSUTIL.start_dhcp_service()
return result
else:
return func(*args, **kwargs)
return wrapper
@allow_dhcp_broadcast
@disable_dhcp_service
def send_dhcp_request(request):
__waiting_duration__ = [0, 10, 30, 60, 60]
for duration in __waiting_duration__:
try:
OSUTIL.allow_dhcp_broadcast()
response = socket_send(request)
validate_dhcp_resp(request, response)
return response
except ProtocolError as e:
logger.warn("Failed to send DHCP request: {0}", e)
time.sleep(duration)
return None
def socket_send(request):
sock = None
try:
@ -265,7 +247,7 @@ def socket_send(request):
response = sock.recv(1024)
return response
except IOError as e:
raise ProtocolError("{0}".format(e))
raise DhcpError("{0}".format(e))
finally:
if sock is not None:
sock.close()

Просмотреть файл

@ -16,8 +16,14 @@
#
# 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.run import MainHandler
from azurelinuxagent.distro.default.event import EventHandler
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
@ -25,10 +31,17 @@ from azurelinuxagent.distro.default.resourceDisk import ResourceDiskHandler
from azurelinuxagent.distro.default.extension import ExtHandlersHandler
from azurelinuxagent.distro.default.deprovision import DeprovisionHandler
class DefaultHandlerFactory(object):
class DefaultDistro(object):
"""
"""
def __init__(self):
self.osutil = DefaultOSUtil()
self.protocol_util = ProtocolUtil(self)
self.init_handler = InitHandler(self)
self.main_handler = MainHandler(self)
self.daemon_handler = DaemonHandler(self)
self.event_handler = EventHandler(self)
self.dhcp_handler = DhcpHandler(self)
self.scvmm_handler = ScvmmHandler(self)
self.env_handler = EnvHandler(self)
self.provision_handler = ProvisionHandler(self)

Просмотреть файл

@ -23,8 +23,6 @@ import threading
import time
import azurelinuxagent.logger as logger
import azurelinuxagent.conf as conf
import azurelinuxagent.protocol.dhcp as dhcp
from azurelinuxagent.utils.osutil import OSUTIL
class EnvHandler(object):
"""
@ -32,37 +30,25 @@ class EnvHandler(object):
If dhcp clinet process re-start has occurred, reset routes, dhcp with fabric.
Monitor scsi disk.
If new scsi disk found, set
If new scsi disk found, set timeout
"""
def __init__(self, handlers):
self.handlers = handlers
self.monitor = EnvMonitor()
def start(self):
self.monitor.start()
def stop(self):
self.monitor.stop()
class EnvMonitor(object):
def __init__(self):
def __init__(self, distro):
self.distro = distro
self.stopped = True
self.hostname = None
self.dhcpid = None
self.server_thread=None
def start(self):
self.dhcp_resp = dhcp.DHCPCLIENT.get_dhcp_resp()
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.dhcp_resp.conf_routes()
self.distro.dhcp_handler.conf_routes()
self.hostname = socket.gethostname()
self.dhcpid = OSUTIL.get_dhcp_pid()
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()
@ -73,11 +59,11 @@ class EnvMonitor(object):
If dhcp clinet process re-start has occurred, reset routes.
"""
while not self.stopped:
OSUTIL.remove_rules_files()
timeout = conf.get("OS.RootDeviceScsiTimeout", None)
self.distro.osutil.remove_rules_files()
timeout = conf.get_root_device_scsi_timeout()
if timeout is not None:
OSUTIL.set_scsi_disks_timeout(timeout)
if conf.get_switch("Provisioning.MonitorHostName", False):
self.distro.osutil.set_scsi_disks_timeout(timeout)
if conf.get_monitor_hostname():
self.handle_hostname_update()
self.handle_dhclient_restart()
time.sleep(5)
@ -87,25 +73,25 @@ class EnvMonitor(object):
if curr_hostname != self.hostname:
logger.info("EnvMonitor: Detected host name change: {0} -> {1}",
self.hostname, curr_hostname)
OSUTIL.set_hostname(curr_hostname)
OSUTIL.publish_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 = OSUTIL.get_dhcp_pid()
self.dhcpid = self.distro.dhcp_handler.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 = OSUTIL.get_dhcp_pid()
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.dhcp_resp.conf_routes()
self.distro.dhcp_handler.conf_routes()
self.dhcpid = newpid
def stop(self):

Просмотреть файл

@ -0,0 +1,133 @@
# 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
from azurelinuxagent.event import WALAEventOperation, add_event
from azurelinuxagent.exception import EventError, ProtocolError, OSUtilError
from azurelinuxagent.future import text
from azurelinuxagent.protocol.restapi import TelemetryEventParam, \
TelemetryEventList, \
TelemetryEvent, \
set_properties, get_properties
from azurelinuxagent.metadata import DISTRO_NAME, DISTRO_VERSION, \
DISTRO_CODE_NAME, AGENT_VERSION
class EventHandler(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_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()
#TODO add more system info
self.sysinfo.append(TelemetryEventParam("VMName", vminfo.vmName ))
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
json_str = evt_file.read().decode("utf-8",'ignore')
logger.verb("Processed event file: {0}", evt_file_name)
os.remove(evt_file_name)
return json_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(self.distro.osutil.get_lib_dir(), "event")
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:
data = json.loads(data_str)
except ValueError as e:
logger.verb(data_str)
logger.verb("Failed to decode json event file: {0}", e)
continue
event = TelemetryEvent()
set_properties("event", event, data)
event.parameters.extend(self.sysinfo)
event_list.events.append(event)
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)
self.collect_and_send_events()
time.sleep(60)

Просмотреть файл

@ -22,14 +22,15 @@ import time
import json
import subprocess
import shutil
import azurelinuxagent.conf as conf
import azurelinuxagent.logger as logger
from azurelinuxagent.future import text
from azurelinuxagent.utils.osutil import OSUTIL
from azurelinuxagent.protocol.factory import PROT_FACTORY
import azurelinuxagent.protocol.common as prot
from azurelinuxagent.metadata import AGENT_VERSION
from azurelinuxagent.event import add_event, WALAEventOperation
from azurelinuxagent.exception import ExtensionError
from azurelinuxagent.exception import ExtensionError, ProtocolError
from azurelinuxagent.future import text
from azurelinuxagent.metadata import AGENT_VERSION
from azurelinuxagent.protocol.restapi import ExtHandlerStatus, ExtensionStatus, \
ExtensionSubStatus, Extension, \
VMStatus
import azurelinuxagent.utils.fileutil as fileutil
import azurelinuxagent.utils.restutil as restutil
import azurelinuxagent.utils.shellutil as shellutil
@ -72,7 +73,7 @@ def parse_ext_substatus(substatus):
validate_has_key(substatus, 'status', 'substatus/status')
validate_in_range(substatus['status'], VALID_EXTENSION_STATUS,
'substatus/status')
status = prot.ExtensionSubStatus()
status = ExtensionSubStatus()
status.name = substatus.get('name')
status.status = substatus.get('status')
status.code = substatus.get('code', 0)
@ -120,7 +121,7 @@ def get_installed_version(target_name):
Return the highest version instance with the same name
"""
installed_version = None
lib_dir = OSUTIL.get_lib_dir()
lib_dir = conf.get_lib_dir()
for dir_name in os.listdir(lib_dir):
path = os.path.join(lib_dir, dir_name)
if os.path.isdir(path) and dir_name.startswith(target_name):
@ -139,19 +140,18 @@ class ExtHandlerState(object):
class ExtHandlersHandler(object):
def __init__(self, handlers):
self.handlers = handlers
def __init__(self, distro):
self.distro = distro
def process(self):
def run(self):
try:
protocol = PROT_FACTORY.get_protocol()
protocol = self.distro.protocol_util.get_protocol()
ext_handlers = protocol.get_ext_handlers()
except prot.ProtocolError as e:
except ProtocolError as e:
add_event(name="WALA", is_success=False, message = text(e))
return
vm_status = prot.VMStatus()
vm_status = VMStatus()
vm_status.vmAgent.version = AGENT_VERSION
vm_status.vmAgent.status = "Ready"
vm_status.vmAgent.message = "Guest Agent is running"
@ -164,7 +164,7 @@ class ExtHandlersHandler(object):
#TODO handle extension in parallel
try:
pkg_list = protocol.get_ext_handler_pkgs(ext_handler)
except prot.ProtocolError as e:
except ProtocolError as e:
add_event(name="WALA", is_success=False, message=text(e))
continue
@ -175,14 +175,14 @@ class ExtHandlersHandler(object):
try:
logger.verb("Report vm agent status")
protocol.report_vm_status(vm_status)
except prot.ProtocolError as e:
except ProtocolError as e:
add_event(name="WALA", is_success=False, message = text(e))
def process_extension(self, ext_handler, pkg_list):
installed_version = get_installed_version(ext_handler.name)
if installed_version is not None:
handler = ExtHandlerInstance(ext_handler, pkg_list,
installed_version, installed=True)
handler = ExtHandlerInstance(ext_handler, pkg_list, installed_version,
installed=True)
else:
handler = ExtHandlerInstance(ext_handler, pkg_list,
ext_handler.properties.version)
@ -190,16 +190,17 @@ class ExtHandlersHandler(object):
if handler.ext_status is not None:
try:
protocol = PROT_FACTORY.get_protocol()
protocol = self.distro.protocol_util.get_protocol()
protocol.report_ext_status(handler.name, handler.ext.name,
handler.ext_status)
except prot.ProtocolError as e:
except ProtocolError as e:
add_event(name="WALA", is_success=False, message=text(e))
return handler.handler_status
class ExtHandlerInstance(object):
def __init__(self, ext_handler, pkg_list, curr_version, installed=False):
def __init__(self, ext_handler, pkg_list, curr_version,
installed=False):
self.ext_handler = ext_handler
self.name = ext_handler.name
self.version = ext_handler.properties.version
@ -210,10 +211,10 @@ class ExtHandlerInstance(object):
self.curr_version = curr_version
self.installed = installed
self.handler_state = None
self.lib_dir = OSUTIL.get_lib_dir()
self.lib_dir = conf.get_lib_dir()
self.ext_status = prot.ExtensionStatus()
self.handler_status = prot.ExtHandlerStatus()
self.ext_status = ExtensionStatus()
self.handler_status = ExtHandlerStatus()
self.handler_status.name = self.name
self.handler_status.version = self.curr_version
@ -223,7 +224,7 @@ class ExtHandlerInstance(object):
self.handler_status.extensions = [self.ext.name]
else:
#When no extension settings, set sequenceNumber to 0
self.ext = prot.Extension(sequenceNumber=0)
self.ext = Extension(sequenceNumber=0)
self.ext_status.sequenceNumber = self.ext.sequenceNumber
prefix = "[{0}]".format(self.get_full_name())
@ -571,7 +572,7 @@ class ExtHandlerInstance(object):
def collect_heartbeat(self):
self.logger.info("Collect heart beat")
heartbeat_file = os.path.join(OSUTIL.get_lib_dir(),
heartbeat_file = os.path.join(conf.get_lib_dir(),
self.get_heartbeat_file())
if not os.path.isfile(heartbeat_file):
raise ExtensionError("Failed to get heart beat file")
@ -696,7 +697,7 @@ class ExtHandlerInstance(object):
return "{0}-{1}".format(self.name, self.curr_version)
def get_base_dir(self):
return os.path.join(OSUTIL.get_lib_dir(), self.get_full_name())
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")
@ -713,7 +714,7 @@ class ExtHandlerInstance(object):
"{0}.settings".format(self.ext.sequenceNumber))
def get_handler_state_dir(self):
return os.path.join(OSUTIL.get_lib_dir(), "handler_state",
return os.path.join(conf.get_lib_dir(), "handler_state",
self.get_full_name())
def get_handler_state_file(self):
@ -735,7 +736,7 @@ class ExtHandlerInstance(object):
return os.path.join(self.get_base_dir(), 'HandlerEnvironment.json')
def get_log_dir(self):
return os.path.join(OSUTIL.get_ext_log_dir(), self.name,
return os.path.join(conf.get_ext_log_dir(), self.name,
self.curr_version)
class HandlerEnvironment(object):

Просмотреть файл

@ -20,33 +20,34 @@
import os
import azurelinuxagent.conf as conf
import azurelinuxagent.logger as logger
from azurelinuxagent.utils.osutil import OSUTIL
import azurelinuxagent.utils.fileutil as fileutil
import azurelinuxagent.event as event
class InitHandler(object):
def __init__(self, handlers):
self.handlers = handlers
def __init__(self, distro):
self.distro = distro
def init(self, verbose):
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 = OSUTIL.get_conf_file_path()
conf.load_conf(conf_file_path)
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_switch("Logs.Verbose", False)
verbose = verbose or self.distro.conf.get_switch("Logs.Verbose", False)
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")
#Create lib dir
fileutil.mkdir(OSUTIL.get_lib_dir(), mode=0o700)
os.chdir(OSUTIL.get_lib_dir())
#Init event reporter
event_dir = os.path.join(self.distro.conf.get_lib_dir(), "events")
event.init_event_reporter(event_dir)
event.enable_unhandled_err_dump("WALA")

Просмотреть файл

@ -26,6 +26,8 @@ import time
import pwd
import fcntl
import azurelinuxagent.logger as logger
import azurelinuxagent.conf as conf
from azurelinuxagent.exception import OSUtilError
from azurelinuxagent.future import text
import azurelinuxagent.utils.fileutil as fileutil
import azurelinuxagent.utils.shellutil as shellutil
@ -40,44 +42,14 @@ for all distros. Each concrete distro classes could overwrite default behavior
if needed.
"""
class OSUtilError(Exception):
pass
class DefaultOSUtil(object):
def __init__(self):
self.lib_dir = "/var/lib/waagent"
self.ext_log_dir = "/var/log/azure"
self.dvd_mount_point = "/mnt/cdrom/secure"
self.ovf_env_file_path = "/mnt/cdrom/secure/ovf-env.xml"
self.agent_pid_file_path = "/var/run/waagent.pid"
self.passwd_file_path = "/etc/shadow"
self.home = '/home'
self.sshd_conf_file_path = '/etc/ssh/sshd_config'
self.openssl_cmd = '/usr/bin/openssl'
self.conf_file_path = '/etc/waagent.conf'
self.agent_conf_file_path = '/etc/waagent.conf'
self.selinux=None
def get_lib_dir(self):
return self.lib_dir
def get_ext_log_dir(self):
return self.ext_log_dir
def get_dvd_mount_point(self):
return self.dvd_mount_point
def get_conf_file_path(self):
return self.conf_file_path
def get_ovf_env_file_path_on_dvd(self):
return self.ovf_env_file_path
def get_agent_pid_file_path(self):
return self.agent_pid_file_path
def get_openssl_cmd(self):
return self.openssl_cmd
def get_agent_conf_file_path(self):
return self.agent_conf_file_path
def get_userentry(self, username):
try:
@ -146,37 +118,37 @@ class DefaultOSUtil(object):
def del_root_password(self):
try:
passwd_content = fileutil.read_file(self.passwd_file_path)
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(self.passwd_file_path, "\n".join(new_passwd))
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 get_home(self):
return self.home
def get_pubkey_from_prv(self, file_name):
cmd = "{0} rsa -in {1} -pubout 2>/dev/null".format(self.openssl_cmd,
openssl_cmd = conf.get_openssl_cmd()
cmd = "{0} rsa -in {1} -pubout 2>/dev/null".format(openssl_cmd,
file_name)
pub = shellutil.run_get_output(cmd)[1]
return pub
def get_pubkey_from_crt(self, file_name):
cmd = "{0} x509 -in {1} -pubkey -noout".format(self.openssl_cmd,
file_name)
openssl_cmd = conf.get_openssl_cmd()
cmd = "{0} x509 -in {1} -pubkey -noout".format(openssl_cmd, file_name)
pub = shellutil.run_get_output(cmd)[1]
return pub
def _norm_path(self, filepath):
home = self.get_home()
home = conf.get_home_dir()
# Expand HOME variable if present in path
path = os.path.normpath(filepath.replace("$HOME", home))
return path
def get_thumbprint_from_crt(self, file_name):
cmd="{0} x509 -in {1} -fingerprint -noout".format(self.openssl_cmd,
openssl_cmd = conf.get_openssl_cmd()
cmd="{0} x509 -in {1} -fingerprint -noout".format(openssl_cmd,
file_name)
thumbprint = shellutil.run_get_output(cmd)[1]
thumbprint = thumbprint.rstrip().split('=')[1].replace(':', '').upper()
@ -190,7 +162,7 @@ class DefaultOSUtil(object):
path = self._norm_path(path)
dir_path = os.path.dirname(path)
fileutil.mkdir(dir_path, mode=0o700, owner=username)
lib_dir = self.get_lib_dir()
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))
@ -223,7 +195,7 @@ class DefaultOSUtil(object):
raise OSUtilError("Bad public key: {0}".format(value))
fileutil.write_file(path, value)
elif thumbprint is not None:
lib_dir = self.get_lib_dir()
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))
@ -280,11 +252,8 @@ class DefaultOSUtil(object):
if self.is_selinux_system():
return shellutil.run('chcon ' + con + ' ' + path)
def get_sshd_conf_file_path(self):
return self.sshd_conf_file_path
def set_ssh_client_alive_interval(self):
conf_file_path = self.get_sshd_conf_file_path()
conf_file_path = conf.get_sshd_conf_file_path()
conf = fileutil.read_file(conf_file_path).split("\n")
textutil.set_ssh_config(conf, "ClientAliveInterval", "180")
fileutil.write_file(conf_file_path, '\n'.join(conf))
@ -292,7 +261,7 @@ class DefaultOSUtil(object):
def conf_sshd(self, disable_password):
option = "no" if disable_password else "yes"
conf_file_path = self.get_sshd_conf_file_path()
conf_file_path = conf.get_sshd_conf_file_path()
conf = fileutil.read_file(conf_file_path).split("\n")
textutil.set_ssh_config(conf, "PasswordAuthentication", option)
textutil.set_ssh_config(conf, "ChallengeResponseAuthentication", option)
@ -309,7 +278,7 @@ class DefaultOSUtil(object):
def mount_dvd(self, max_retry=6, chk_err=True):
dvd = self.get_dvd_device()
mount_point = self.get_dvd_mount_point()
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
@ -332,7 +301,7 @@ class DefaultOSUtil(object):
raise OSUtilError("Failed to mount dvd.")
def umount_dvd(self, chk_err=True):
mount_point = self.get_dvd_mount_point()
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.")
@ -390,13 +359,14 @@ class DefaultOSUtil(object):
"""
Create ssl certificate for https communication with endpoint server.
"""
openssl_cmd = conf.get_openssl_cmd()
cmd = ("{0} req -x509 -nodes -subj /CN=LinuxTransport -days 32768 "
"-newkey rsa:2048 -keyout {1} "
"-out {2}").format(self.openssl_cmd, prv_file, crt_file)
"-out {2}").format(openssl_cmd, prv_file, crt_file)
shellutil.run(cmd)
def remove_rules_files(self, rules_files=__RULES_FILES__):
lib_dir = self.get_lib_dir()
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)
@ -407,7 +377,7 @@ class DefaultOSUtil(object):
shutil.move(src, dest)
def restore_rules_files(self, rules_files=__RULES_FILES__):
lib_dir = self.get_lib_dir()
lib_dir = conf.get_lib_dir()
for dest in rules_files:
filename = fileutil.base_name(dest)
src = os.path.join(lib_dir, filename)
@ -649,4 +619,5 @@ class DefaultOSUtil(object):
return int(ret[1])
else:
raise OSUtilError("Failed to get procerssor cores")

Просмотреть файл

@ -0,0 +1,236 @@
# 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
from azurelinuxagent.future import text
import azurelinuxagent.utils.fileutil as fileutil
from azurelinuxagent.protocol.ovfenv import OvfEnv
from azurelinuxagent.protocol.wire import WireProtocol
from azurelinuxagent.protocol.metadata import MetadataProtocol
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 = 60
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 = self.distro.osutil.get_dvd_mount_point()
ovf_file_path_on_dvd = self.distro.osutil.get_ovf_env_file_path_on_dvd()
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(text(e))
try:
self.distro.osutil.umount_dvd()
self.distro.osutil.eject_dvd()
except OSUtilError as e:
logger.warn(text(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(text(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(text(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")
self.distro.dhcp_handler.run()
endpoint = self.distro.dhcp_handler.endpoint
try:
protocol = WireProtocol(self.distro.osutil, endpoint)
protocol.detect()
self._set_wireserver_endpoint(endpoint)
return protocol
except ProtocolError as e:
logger.info("WireServer is not responding. Rerun dhcp handler")
self.distro.dhcp_handler.run()
raise e
def _detect_metadata_protocol(self):
protocol = MetadataProtocol(self.distro.osutil)
protocol.detect()
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.__name__:
return self._detect_wire_protocol()
if protocol == MetadataProtocol.__name__:
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.__name__:
endpoint = self._get_wireserver_endpoint()
return WireProtocol(self.distro.osutil, endpoint)
elif protocol_name == MetadataProtocol.__name__:
return MetadataProtocol(self.distro.osutil)
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.__name__, MetadataProtocol.__name__]
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(self.distro.conf.get_lib_dir(),
TAG_FILE_NAME)
if self.protocol is None:
protocols = []
if os.path.isfile(tag_file_path):
protocols.append(MetadataProtocol.__name__)
else:
protocols.append(WireProtocol.__name__)
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

Просмотреть файл

@ -24,11 +24,8 @@ import azurelinuxagent.logger as logger
from azurelinuxagent.future import text
import azurelinuxagent.conf as conf
from azurelinuxagent.event import add_event, WALAEventOperation
from azurelinuxagent.exception import ProvisionError
from azurelinuxagent.utils.osutil import OSUTIL, OSUtilError
from azurelinuxagent.protocol.factory import PROT_FACTORY, ProvisionStatus, \
ProtocolError
import azurelinuxagent.protocol.ovfenv as ovf
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
@ -36,49 +33,30 @@ CUSTOM_DATA_FILE="CustomData"
class ProvisionHandler(object):
def __init__(self, handlers):
self.handlers = handlers
def __init__(self, distro):
self.distro = distro
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, protocol, sub_status, description):
status = ProvisionStatus(status="NotReady", subStatus=sub_status,
description=description)
try:
protocol.report_provision_status(status)
except ProtocolError as e:
self.report_event(text(e))
def report_ready(self, protocol, thumbprint=None):
status = ProvisionStatus(status="Ready")
status.properties.certificateThumbprint = thumbprint
try:
protocol.report_provision_status(status)
except ProtocolError as e:
self.report_event(text(e))
def process(self):
def run(self):
#If provision is not enabled, return
if not conf.get_switch("Provisioning.Enabled", True):
if not conf.get_provision_enabled():
logger.info("Provisioning is disabled. Skip.")
return
provisioned = os.path.join(OSUTIL.get_lib_dir(), "provisioned")
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 = ovf.copy_ovf_env()
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
protocol = PROT_FACTORY.detect_protocol_by_file()
self.report_not_ready(protocol, "Provisioning", "Starting")
self.distro.protocol_util.detect_protocol_by_file()
self.report_not_ready("Provisioning", "Starting")
try:
logger.info("Start provisioning")
@ -88,16 +66,16 @@ class ProvisionHandler(object):
logger.info("Finished provisioning")
except ProvisionError as e:
logger.error("Provision failed: {0}", e)
self.report_not_ready(protocol, "ProvisioningFailed", text(e))
self.report_not_ready("ProvisioningFailed", text(e))
self.report_event(text(e))
return
self.report_ready(protocol, thumbprint)
self.report_ready(thumbprint)
self.report_event("Provision succeed", is_success=True)
def reg_ssh_host_key(self):
keypair_type = conf.get("Provisioning.SshHostKeyPairType", "rsa")
if conf.get_switch("Provisioning.RegenerateSshHostKeyPair"):
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))
@ -117,66 +95,89 @@ class ProvisionHandler(object):
logger.info("Handle ovf-env.xml.")
try:
logger.info("Set host name.")
OSUTIL.set_hostname(ovfenv.hostname)
self.distro.osutil.set_hostname(ovfenv.hostname)
logger.info("Publish host name.")
OSUTIL.publish_hostname(ovfenv.hostname)
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()
if conf.get_switch("Provisioning.DeleteRootPassword"):
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")
OSUTIL.useradd(ovfenv.username)
self.distro.osutil.useradd(ovfenv.username)
if ovfenv.user_password is not None:
logger.info("Set user password.")
crypt_id = conf.get("Provision.PasswordCryptId", "6")
salt_len = conf.get_int("Provision.PasswordCryptSaltLength", 10)
OSUTIL.chpasswd(ovfenv.username, ovfenv.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")
OSUTIL.conf_sudoer(ovfenv.username, ovfenv.user_password is None)
self.distro.osutil.conf_sudoer(ovfenv.username, ovfenv.user_password is None)
logger.info("Configure sshd")
OSUTIL.conf_sshd(ovfenv.disable_ssh_password_auth)
self.distro.osutil.conf_sshd(ovfenv.disable_ssh_password_auth)
#Disable selinux temporary
sel = OSUTIL.is_selinux_enforcing()
sel = self.distro.osutil.is_selinux_enforcing()
if sel:
OSUTIL.set_selinux_enforce(0)
self.distro.osutil.set_selinux_enforce(0)
self.deploy_ssh_pubkeys(ovfenv)
self.deploy_ssh_keypairs(ovfenv)
if sel:
OSUTIL.set_selinux_enforce(1)
self.distro.osutil.set_selinux_enforce(1)
OSUTIL.restart_ssh_service()
self.distro.osutil.restart_ssh_service()
def save_customdata(self, ovfenv):
logger.info("Save custom data")
customdata = ovfenv.customdata
if customdata is None:
return
lib_dir = OSUTIL.get_lib_dir()
lib_dir = conf.get_lib_dir()
fileutil.write_file(os.path.join(lib_dir, CUSTOM_DATA_FILE),
OSUTIL.decode_customdata(customdata))
self.distro.osutil.decode_customdata(customdata))
def deploy_ssh_pubkeys(self, ovfenv):
for pubkey in ovfenv.ssh_pubkeys:
logger.info("Deploy ssh public key.")
OSUTIL.deploy_ssh_pubkey(ovfenv.username, pubkey)
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.")
OSUTIL.deploy_ssh_keypair(ovfenv.username, keypair)
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(text(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(text(e))

Просмотреть файл

@ -23,7 +23,6 @@ import threading
import azurelinuxagent.logger as logger
from azurelinuxagent.future import text
import azurelinuxagent.conf as conf
from azurelinuxagent.utils.osutil import OSUTIL
from azurelinuxagent.event import add_event, WALAEventOperation
import azurelinuxagent.utils.fileutil as fileutil
import azurelinuxagent.utils.shellutil as shellutil
@ -41,8 +40,8 @@ For additional details to please refer to the MSDN documentation at : http://msd
"""
class ResourceDiskHandler(object):
def __init__(self, handlers):
self.handlers = handlers
def __init__(self, distro):
self.distro = distro
def start_activate_resource_disk(self):
disk_thread = threading.Thread(target = self.run)
@ -50,17 +49,17 @@ class ResourceDiskHandler(object):
def run(self):
mount_point = None
if conf.get_switch("ResourceDisk.Format", False):
if conf.get_resourcedisk_format():
mount_point = self.activate_resource_disk()
if mount_point is not None and \
conf.get_switch("ResourceDisk.EnableSwap", False):
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", "/mnt/resource")
fs = conf.get("ResourceDisk.Filesystem", "ext3")
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:
@ -76,19 +75,19 @@ class ResourceDiskHandler(object):
def enable_swap(self, mount_point):
logger.info("Enable swap")
try:
size_mb = conf.get_int("ResourceDisk.SwapSizeMB", 0)
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 = OSUTIL.device_for_ide_port(1)
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 = OSUTIL.get_mount_point(mountlist, device)
existing = self.distro.osutil.get_mount_point(mountlist, device)
if(existing):
logger.info("Resource disk {0}1 is already mounted", device)

Просмотреть файл

@ -20,30 +20,29 @@
import os
import subprocess
import azurelinuxagent.logger as logger
from azurelinuxagent.utils.osutil import OSUTIL
VMM_CONF_FILE_NAME = "linuxosconfiguration.xml"
VMM_STARTUP_SCRIPT_NAME= "install"
class ScvmmHandler(object):
def __init__(self, handlers):
self.handlers = handlers
def __init__(self, distro):
self.distro = distro
def detect_scvmm_env(self):
logger.info("Detecting Microsoft System Center VMM Environment")
OSUTIL.mount_dvd(max_retry=1, chk_err=False)
mount_point = OSUTIL.get_dvd_mount_point()
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:
OSUTIL.umount_dvd(chk_err=False)
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 = OSUTIL.get_dvd_mount_point()
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])

Просмотреть файл

@ -16,31 +16,51 @@
#
import azurelinuxagent.logger as logger
from azurelinuxagent.metadata import DISTRO_NAME
import azurelinuxagent.distro.default.loader as default_loader
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_loader():
try:
logger.verb("Loading distro implemetation from: {0}", DISTRO_NAME)
pkg_name = "azurelinuxagent.distro.{0}.loader".format(DISTRO_NAME)
return __import__(pkg_name, fromlist="loader")
except (ImportError, ValueError):
def get_distro():
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 default_loader
DISTRO_LOADER = get_distro_loader()
def get_osutil():
try:
return DISTRO_LOADER.get_osutil()
except AttributeError:
return default_loader.get_osutil()
def get_handlers():
try:
return DISTRO_LOADER.get_handlers()
except AttributeError:
return default_loader.get_handlers()
return DefaultDistro()

Просмотреть файл

@ -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+
#

Просмотреть файл

@ -17,13 +17,16 @@
# Requires Python 2.4+ and Openssl 1.0+
#
from azurelinuxagent.distro.ubuntu.provision import UbuntuProvisionHandler
from azurelinuxagent.distro.ubuntu.deprovision import UbuntuDeprovisionHandler
from azurelinuxagent.distro.default.handlerFactory import DefaultHandlerFactory
from azurelinuxagent.distro.default.distro import DefaultDistro
from azurelinuxagent.distro.redhat.osutil import RedhatOSUtil, Redhat6xOSUtil
from azurelinuxagent.distro.coreos.deprovision import CoreOSDeprovisionHandler
class UbuntuHandlerFactory(DefaultHandlerFactory):
class Redhat6xDistro(DefaultDistro):
def __init__(self):
super(UbuntuHandlerFactory, self).__init__()
self.provision_handler = UbuntuProvisionHandler(self)
self.deprovision_handler = UbuntuDeprovisionHandler(self)
super(Redhat6xDistro, self).__init__()
self.osutil = Redhat6xOSUtil()
class RedhatDistro(DefaultDistro):
def __init__(self):
super(RedhatDistro, self).__init__()
self.osutil = RedhatOSUtil()

Просмотреть файл

@ -1,28 +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.metadata import DISTRO_NAME, DISTRO_VERSION
def get_osutil():
from azurelinuxagent.distro.redhat.osutil import Redhat6xOSUtil, RedhatOSUtil
if DISTRO_VERSION < "7":
return Redhat6xOSUtil()
else:
return RedhatOSUtil()

Просмотреть файл

@ -17,12 +17,16 @@
# Requires Python 2.4+ and Openssl 1.0+
#
def get_osutil():
from azurelinuxagent.distro.default.osutil import DefaultOSUtil
return DefaultOSUtil()
from azurelinuxagent.distro.default.distro import DefaultDistro
from azurelinuxagent.distro.suse.osutil import SUSE11OSUtil, SUSEOSUtil
def get_handlers():
from azurelinuxagent.distro.default.handlerFactory import DefaultHandlerFactory
return DefaultHandlerFactory()
class SUSE11Distro(DefaultDistro):
def __init__(self):
super(SUSE11Distro, self).__init__()
self.osutil = SUSE11Distro()
class SUSEDistro(DefaultDistro):
def __init__(self):
super(SUSEDistro, self).__init__()
self.osutil = SUSEOSUtil()

Просмотреть файл

@ -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.metadata import DISTRO_NAME, DISTRO_VERSION, DISTRO_FULL_NAME
def get_osutil():
from azurelinuxagent.distro.suse.osutil import SUSE11OSUtil, SUSEOSUtil
if DISTRO_FULL_NAME=='SUSE Linux Enterprise Server' and DISTRO_VERSION < '12' \
or DISTRO_FULL_NAME == 'openSUSE' and DISTRO_VERSION < '13.2':
return SUSE11OSUtil()
else:
return SUSEOSUtil()

Просмотреть файл

@ -0,0 +1,55 @@
# 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)

Просмотреть файл

@ -1,40 +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.metadata import DISTRO_NAME, DISTRO_VERSION, DISTRO_FULL_NAME
def get_osutil():
from azurelinuxagent.distro.ubuntu.osutil import Ubuntu1204OSUtil, \
UbuntuOSUtil, \
Ubuntu14xOSUtil, \
UbuntuSnappyOSUtil
if DISTRO_VERSION == "12.04":
return Ubuntu1204OSUtil()
elif DISTRO_VERSION == "14.04" or DISTRO_VERSION == "14.10":
return Ubuntu14xOSUtil()
elif DISTRO_FULL_NAME == "Snappy Ubuntu Core":
return UbuntuSnappyOSUtil()
else:
return UbuntuOSUtil()
def get_handlers():
from azurelinuxagent.distro.ubuntu.handlerFactory import UbuntuHandlerFactory
return UbuntuHandlerFactory()

Просмотреть файл

@ -31,9 +31,9 @@ import azurelinuxagent.utils.shellutil as shellutil
import azurelinuxagent.utils.textutil as textutil
from azurelinuxagent.distro.default.osutil import DefaultOSUtil
class Ubuntu14xOSUtil(DefaultOSUtil):
class Ubuntu14OSUtil(DefaultOSUtil):
def __init__(self):
super(Ubuntu14xOSUtil, self).__init__()
super(Ubuntu14OSUtil, self).__init__()
def start_network(self):
return shellutil.run("service networking start", chk_err=False)
@ -44,16 +44,16 @@ class Ubuntu14xOSUtil(DefaultOSUtil):
def start_agent_service(self):
return shellutil.run("service walinuxagent start", chk_err=False)
class Ubuntu1204OSUtil(Ubuntu14xOSUtil):
class Ubuntu12OSUtil(Ubuntu14OSUtil):
def __init__(self):
super(Ubuntu1204OSUtil, self).__init__()
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(Ubuntu14xOSUtil):
class UbuntuOSUtil(Ubuntu14OSUtil):
def __init__(self):
super(UbuntuOSUtil, self).__init__()
@ -63,7 +63,7 @@ class UbuntuOSUtil(Ubuntu14xOSUtil):
def unregister_agent_service(self):
return shellutil.run("systemctl mask walinuxagent", chk_err=False)
class UbuntuSnappyOSUtil(Ubuntu14xOSUtil):
class UbuntuSnappyOSUtil(Ubuntu14OSUtil):
def __init__(self):
super(UbuntuSnappyOSUtil, self).__init__()
self.conf_file_path = '/apps/walinuxagent/current/waagent.conf'

Просмотреть файл

@ -22,11 +22,9 @@ import time
import azurelinuxagent.logger as logger
from azurelinuxagent.future import text
import azurelinuxagent.conf as conf
from azurelinuxagent.protocol.factory import PROT_FACTORY
import azurelinuxagent.protocol.ovfenv as ovf
import azurelinuxagent.protocol.ovfenv as ovfenv
from azurelinuxagent.event import add_event, WALAEventOperation
from azurelinuxagent.exception import ProvisionError
from azurelinuxagent.utils.osutil import OSUTIL
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
@ -35,25 +33,25 @@ from azurelinuxagent.distro.default.provision import ProvisionHandler
On ubuntu image, provision could be disabled.
"""
class UbuntuProvisionHandler(ProvisionHandler):
def __init__(self, handlers):
self.handlers = handlers
def __init__(self, distro):
self.distro = distro
def process(self):
#If provision is enabled, run default provision handler
if conf.get_switch("Provisioning.Enabled", False):
if conf.get_provision_enabled():
super(UbuntuProvisionHandler, self).process()
return
logger.info("run Ubuntu provision handler")
provisioned = os.path.join(OSUTIL.get_lib_dir(), "provisioned")
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 = PROT_FACTORY.detect_protocol_by_file()
self.report_not_ready(protocol, "Provisioning", "Starting")
protocol = self.distro.protocol_util.detect_protocol_by_file()
self.report_not_ready("Provisioning", "Starting")
logger.info("Sleep 15 seconds to prevent throttling")
time.sleep(15) #Sleep to prevent throttling
try:
@ -64,31 +62,32 @@ class UbuntuProvisionHandler(ProvisionHandler):
except ProvisionError as e:
logger.error("Provision failed: {0}", e)
self.report_not_ready(protocol, "ProvisioningFailed", text(e))
self.report_not_ready("ProvisioningFailed", text(e))
self.report_event(text(e))
return
self.report_ready(protocol, thumbprint)
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
"""
ovf_file_path = os.path.join(OSUTIL.get_lib_dir(), ovf.OVF_FILE_NAME)
for retry in range(0, max_retry):
if os.path.isfile(ovf_file_path):
try:
self.distro.protocol_util.get_ovf_env()
return
if retry < max_retry - 1:
logger.info("Wait for cloud-init to copy ovf-env.xml")
time.sleep(5)
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("Provisioning.SshHostKeyPairType", "rsa")
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):

Просмотреть файл

@ -25,15 +25,15 @@ import datetime
import threading
import platform
import azurelinuxagent.logger as logger
from azurelinuxagent.exception import EventError, ProtocolError
from azurelinuxagent.future import text
import azurelinuxagent.protocol as prot
from azurelinuxagent.protocol.factory import PROT_FACTORY
from azurelinuxagent.protocol.restapi import TelemetryEventParam, \
TelemetryEventList, \
TelemetryEvent, \
set_properties, get_properties
from azurelinuxagent.metadata import DISTRO_NAME, DISTRO_VERSION, \
DISTRO_CODE_NAME, AGENT_VERSION
from azurelinuxagent.utils.osutil import OSUTIL
class EventError(Exception):
pass
class WALAEventOperation:
HeartBeat="HeartBeat"
@ -48,132 +48,60 @@ class WALAEventOperation:
ActivateResourceDisk="ActivateResourceDisk"
UnhandledError="UnhandledError"
class EventMonitor(object):
class EventReporter(object):
def __init__(self):
self.sysinfo = []
self.event_dir = os.path.join(OSUTIL.get_lib_dir(), "events")
self.event_dir = None
def init_sysinfo(self):
osversion = "{0}:{1}-{2}-{3}:{4}".format(platform.system(),
DISTRO_NAME,
DISTRO_VERSION,
DISTRO_CODE_NAME,
platform.release())
def save_event(self, data):
if not os.path.exists(self.event_dir):
os.mkdir(self.event_dir)
os.chmod(self.event_dir, 0o700)
if len(os.listdir(self.event_dir)) > 1000:
raise EventError("Too many files under: {0}", self.event_dir)
self.sysinfo.append(prot.TelemetryEventParam("OSVersion", osversion))
self.sysinfo.append(prot.TelemetryEventParam("GAVersion",
AGENT_VERSION))
self.sysinfo.append(prot.TelemetryEventParam("RAM",
OSUTIL.get_total_mem()))
self.sysinfo.append(prot.TelemetryEventParam("Processors",
OSUTIL.get_processor_cores()))
filename = os.path.join(self.event_dir, text(int(time.time()*1000000)))
try:
protocol = PROT_FACTORY.get_protocol()
vminfo = protocol.get_vminfo()
self.sysinfo.append(prot.TelemetryEventParam("VMName",
vminfo.vmName))
#TODO add other system info like, subscription id, etc.
except prot.ProtocolError as e:
logger.warn("Failed to get vm info: {0}", e)
def start(self):
event_thread = threading.Thread(target = self.run)
event_thread.setDaemon(True)
event_thread.start()
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
json_str = evt_file.read().decode("utf-8",'ignore')
logger.verb("Processed event file: {0}", evt_file_name)
os.remove(evt_file_name)
return json_str
with open(filename+".tmp",'wb+') as hfile:
hfile.write(data.encode("utf-8"))
os.rename(filename+".tmp", filename+".tld")
except IOError as e:
msg = "Failed to process {0}, {1}".format(evt_file_name, e)
raise EventError(msg)
raise EventError("Failed to write events to file:{0}", e)
def collect_and_send_events(self):
event_list = prot.TelemetryEventList()
event_files = os.listdir(self.event_dir)
for event_file in event_files:
if not event_file.endswith(".tld"):
continue
event_file_path = os.path.join(self.event_dir, event_file)
try:
data_str = self.collect_event(event_file_path)
except EventError as e:
logger.error("{0}", e)
continue
try:
data = json.loads(data_str)
except ValueError as e:
logger.verb(data_str)
logger.verb("Failed to decode json event file: {0}", e)
continue
def add_event(self, name, op="", is_success=True, duration=0, version="1.0",
message="", evt_type="", is_internal=False):
log = logger.info if is_success else logger.error
log("Event: name={0}, op={1}, message={2}", name, op, message)
event = TelemetryEvent(1, "69B669B9-4AF8-4C50-BDC4-6006FA76E975")
event.parameters.append(TelemetryEventParam('Name', name))
event.parameters.append(TelemetryEventParam('Version', version))
event.parameters.append(TelemetryEventParam('IsInternal', is_internal))
event.parameters.append(TelemetryEventParam('Operation', op))
event.parameters.append(TelemetryEventParam('OperationSuccess',
is_success))
event.parameters.append(TelemetryEventParam('Message', message))
event.parameters.append(TelemetryEventParam('Duration', duration))
event.parameters.append(TelemetryEventParam('ExtensionType', evt_type))
event = prot.TelemetryEvent()
prot.set_properties("event", event, data)
event.parameters.extend(self.sysinfo)
event_list.events.append(event)
if len(event_list.events) == 0:
return
data = get_properties(event)
try:
protocol = PROT_FACTORY.get_protocol()
protocol.report_event(event_list)
except prot.ProtocolError as e:
self.save_event(json.dumps(data))
except EventError as e:
logger.error("{0}", e)
def run(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)
self.collect_and_send_events()
time.sleep(60)
def save_event(data):
event_dir = os.path.join(OSUTIL.get_lib_dir(), 'events')
if not os.path.exists(event_dir):
os.mkdir(event_dir)
os.chmod(event_dir,0o700)
if len(os.listdir(event_dir)) > 1000:
raise EventError("Too many files under: {0}", event_dir)
filename = os.path.join(event_dir, text(int(time.time()*1000000)))
try:
with open(filename+".tmp",'wb+') as hfile:
hfile.write(data.encode("utf-8"))
os.rename(filename+".tmp", filename+".tld")
except IOError as e:
raise EventError("Failed to write events to file:{0}", e)
__event_reporter__ = EventReporter()
def add_event(name, op="", is_success=True, duration=0, version="1.0",
message="", evt_type="", is_internal=False):
log = logger.info if is_success else logger.error
log("Event: name={0}, op={1}, message={2}", name, op, message)
event = prot.TelemetryEvent(1, "69B669B9-4AF8-4C50-BDC4-6006FA76E975")
event.parameters.append(prot.TelemetryEventParam('Name', name))
event.parameters.append(prot.TelemetryEventParam('Version', version))
event.parameters.append(prot.TelemetryEventParam('IsInternal', is_internal))
event.parameters.append(prot.TelemetryEventParam('Operation', op))
event.parameters.append(prot.TelemetryEventParam('OperationSuccess',
is_success))
event.parameters.append(prot.TelemetryEventParam('Message', message))
event.parameters.append(prot.TelemetryEventParam('Duration', duration))
event.parameters.append(prot.TelemetryEventParam('ExtensionType', evt_type))
message="", evt_type="", is_internal=False,
reporter=__event_reporter__):
if reporter.event_dir is None:
logger.warn("Event reporter is not initialized.")
return
reporter.add_event(name, op=op, is_success=is_success, duration=duration,
version=version, message=message, evt_type=evt_type,
is_internal=is_internal)
data = prot.get_properties(event)
try:
save_event(json.dumps(data))
except EventError as e:
logger.error("{0}", e)
def init_event_reporter(event_dir, reporter=__event_reporter__):
reporter.event_dir = event_dir
def dump_unhandled_err(name):
if hasattr(sys, 'last_type') and hasattr(sys, 'last_value') and \
@ -185,8 +113,7 @@ def dump_unhandled_err(name):
last_traceback)
message= "".join(error)
add_event(name, is_success=False, message=message,
op=WALAEventOperation.UnhandledError)
op=WALAEventOperation.UnhandledError)
def enable_unhandled_err_dump(name):
atexit.register(dump_unhandled_err, name)

Просмотреть файл

@ -63,3 +63,44 @@ class ResourceDiskError(AgentError):
def __init__(self, msg):
super(ResourceDiskError, self).__init__('000005', msg)
class DhcpError(AgentError):
"""
Failed to handle dhcp response
"""
def __init__(self, msg):
super(DhcpError, self).__init__('000006', msg)
class OSUtilError(AgentError):
"""
Failed to perform operation to OS configuration
"""
def __init__(self, msg):
super(OSUtilError, self).__init__('000007', msg)
class ProtocolError(AgentError):
"""
Azure protocol error
"""
def __init__(self, msg):
super(ProtocolError, self).__init__('000008', msg)
class ProtocolNotFoundError(ProtocolError):
"""
Azure protocol endpoint not found
"""
def __init__(self, msg):
super(ProtocolNotFoundError, self).__init__(msg)
class HttpError(AgentError):
"""
Http request failure
"""
def __init__(self, msg):
super(HttpError, self).__init__('000009', msg)
class EventError(AgentError):
"""
Event reporting error
"""
def __init__(self, msg):
super(EventError, self).__init__('000010', msg)

Просмотреть файл

@ -7,15 +7,25 @@ Add alies for python2 and python3 libs and fucntions.
if sys.version_info[0]== 3:
import http.client as httpclient
from urllib.parse import urlparse
text = str
"""Rename Python3 str to ustr"""
ustr = str
bytebuffer = memoryview
read_input = input
elif sys.version_info[0] == 2:
import httplib as httpclient
from urlparse import urlparse
text = unicode
"""Rename Python2 unicode to ustr"""
ustr = unicode
bytebuffer = buffer
read_input = raw_input
else:
raise ImportError("Unknown python version:{0}".format(sys.version_info))

Просмотреть файл

@ -1,28 +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+
#
"""
Handler handles different tasks like, provisioning, deprovisioning etc.
The handlers could be extended for different distros. The default
implementation is under azurelinuxagent.distros.default
"""
import azurelinuxagent.distro.loader as loader
HANDLERS = loader.get_handlers()

Просмотреть файл

@ -16,5 +16,3 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
from azurelinuxagent.protocol.common import *

Просмотреть файл

@ -1,126 +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 traceback
import time
import threading
import azurelinuxagent.logger as logger
from azurelinuxagent.exception import *
from azurelinuxagent.future import text
import azurelinuxagent.utils.fileutil as fileutil
from azurelinuxagent.utils.osutil import OSUTIL
from azurelinuxagent.protocol.common import *
from azurelinuxagent.protocol.v1 import WireProtocol
from azurelinuxagent.protocol.v2 import MetadataProtocol
from azurelinuxagent.protocol.ovfenv import TAG_FILE_NAME
PROTOCOL_FILE_NAME = "Protocol"
MAX_RETRY = 60
def _detect_protocol(protocols=[WireProtocol, MetadataProtocol]):
protocol_file_path = os.path.join(OSUTIL.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_cls in protocols:
try:
logger.info("Detecting protocol: {0}", protocol_cls.__name__)
protocol = protocol_cls()
protocol.initialize()
logger.info("Found protocol: {0}", protocol_cls.__name__)
fileutil.write_file(protocol_file_path, protocol_cls.__name__)
return protocol
except ProtocolError as e:
logger.info("Protocol endpoint not found: {0}, {1}",
protocol_cls.__name__, e)
if retry < MAX_RETRY -1:
logger.info("Retry detect protocols: retry={0}", retry)
time.sleep(10)
raise ProtocolNotFound("No protocol found.")
def _get_protocol():
protocol_file_path = os.path.join(OSUTIL.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.__name__:
protoc0l = WireProtocol()
else:
protocol = MetadataProtocol()
protocol.reinitialize()
return protocol
class ProtocolFactory(object):
def __init__(self):
self.protocol = None
self.lock = threading.Lock()
def detect_protocol(self):
logger.info("Detect protocol endpoints")
self.lock.acquire()
try:
if self.protocol is None:
self.protocol = _detect_protocol()
return self.protocol
finally:
self.lock.release()
def detect_protocol_by_file(self):
logger.info("Detect protocol by file")
self.lock.acquire()
try:
tag_file_path = os.path.join(OSUTIL.get_lib_dir(), TAG_FILE_NAME)
if self.protocol is None:
if os.path.isfile(tag_file_path):
protocol = _detect_protocol(protocols=[MetadataProtocol])
else:
protocol = _detect_protocol(protocols=[WireProtocol])
self.protocol = protocol
return self.protocol
finally:
self.lock.release()
def get_protocol(self):
"""
Get protocol detected
"""
self.lock.acquire()
try:
if self.protocol is None:
self.protocol = _get_protocol()
return self.protocol
finally:
self.lock.release()
return self.protocol
def wait_for_network(self):
"""
Wait for network stack to be initialized
"""
ipv4 = OSUTIL.get_ip4_addr()
while ipv4 == '' or ipv4 == '0.0.0.0':
logger.info("Waiting for network.")
time.sleep(10)
OSUTIL.start_network()
ipv4 = OSUTIL.get_ip4_addr()
PROT_FACTORY = ProtocolFactory()

Просмотреть файл

@ -20,11 +20,13 @@ import json
import shutil
import os
import time
from azurelinuxagent.utils.osutil import OSUTIL
from azurelinuxagent.exception import ProtocolError, HttpError
from azurelinuxagent.future import httpclient, text
import azurelinuxagent.conf as conf
import azurelinuxagent.logger as logger
import azurelinuxagent.utils.restutil as restutil
import azurelinuxagent.utils.textutil as textutil
from azurelinuxagent.protocol.common import *
from azurelinuxagent.protocol.restapi import *
ENDPOINT='169.254.169.254'
#TODO use http for azure pack test
@ -47,7 +49,8 @@ def _add_content_type(headers):
class MetadataProtocol(Protocol):
def __init__(self, apiversion=APIVERSION, endpoint=ENDPOINT):
def __init__(self, osutil, apiversion=APIVERSION, endpoint=ENDPOINT):
self.osutil = osutil
self.apiversion = apiversion
self.endpoint = endpoint
self.identity_uri = BASE_URI.format(self.endpoint, "identity",
@ -70,7 +73,7 @@ class MetadataProtocol(Protocol):
def _get_data(self, url, headers=None):
try:
resp = restutil.http_get(url, headers=headers)
except restutil.HttpError as e:
except HttpError as e:
raise ProtocolError(text(e))
if resp.status != httpclient.OK:
@ -86,7 +89,7 @@ class MetadataProtocol(Protocol):
headers = _add_content_type(headers)
try:
resp = restutil.http_put(url, json.dumps(data), headers=headers)
except restutil.HttpError as e:
except HttpError as e:
raise ProtocolError(text(e))
if resp.status != httpclient.OK:
raise ProtocolError("{0} - PUT: {1}".format(resp.status, url))
@ -95,7 +98,7 @@ class MetadataProtocol(Protocol):
headers = _add_content_type(headers)
try:
resp = restutil.http_post(url, json.dumps(data), headers=headers)
except restutil.HttpError as e:
except HttpError as e:
raise ProtocolError(text(e))
if resp.status != httpclient.CREATED:
raise ProtocolError("{0} - POST: {1}".format(resp.status, url))
@ -107,25 +110,22 @@ class MetadataProtocol(Protocol):
content = fileutil.read_file(file_name)
return textutil.get_bytes_from_pem(content)
def initialize(self):
def detect(self):
self.get_vminfo()
trans_prv_file = os.path.join(OSUTIL.get_lib_dir(),
trans_prv_file = os.path.join(conf.get_lib_dir(),
TRANSPORT_PRV_FILE_NAME)
trans_crt_file = os.path.join(OSUTIL.get_lib_dir(),
trans_crt_file = os.path.join(conf.get_lib_dir(),
TRANSPORT_CERT_FILE_NAME)
OSUTIL.gen_transport_cert(trans_prv_file, trans_crt_file)
self.osutil.gen_transport_cert(trans_prv_file, trans_crt_file)
#"Install" the cert and private key to /var/lib/waagent
thumbprint = OSUTIL.get_thumbprint_from_crt(trans_crt_file)
prv_file = os.path.join(OSUTIL.get_lib_dir(),
thumbprint = self.osutil.get_thumbprint_from_crt(trans_crt_file)
prv_file = os.path.join(conf.get_lib_dir(),
"{0}.prv".format(thumbprint))
crt_file = os.path.join(OSUTIL.get_lib_dir(),
crt_file = os.path.join(conf.get_lib_dir(),
"{0}.crt".format(thumbprint))
shutil.copyfile(trans_prv_file, prv_file)
shutil.copyfile(trans_crt_file, crt_file)
def reinitialize(self):
pass
def get_vminfo(self):
vminfo = VMInfo()

Просмотреть файл

@ -24,67 +24,15 @@ import re
import shutil
import xml.dom.minidom as minidom
import azurelinuxagent.logger as logger
from azurelinuxagent.exception import ProtocolError
from azurelinuxagent.future import text
import azurelinuxagent.utils.fileutil as fileutil
from azurelinuxagent.utils.textutil import parse_doc, findall, find, findtext
from azurelinuxagent.utils.osutil import OSUTIL, OSUtilError
from azurelinuxagent.protocol.common import ProtocolError
OVF_FILE_NAME = "ovf-env.xml"
#Tag file to indicate usage of metadata protocol
TAG_FILE_NAME = "useMetadataEndpoint.tag"
OVF_VERSION = "1.0"
OVF_NAME_SPACE = "http://schemas.dmtf.org/ovf/environment/1"
WA_NAME_SPACE = "http://schemas.microsoft.com/windowsazure"
def get_ovf_env():
"""
Load saved ovf-env.xml
"""
ovf_file_path = os.path.join(OSUTIL.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 copy_ovf_env():
"""
Copy ovf env file from dvd to hard disk.
Remove password before save it to the disk
"""
try:
OSUTIL.mount_dvd()
ovf_file_path_on_dvd = OSUTIL.get_ovf_env_file_path_on_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(OSUTIL.get_lib_dir(), OVF_FILE_NAME)
fileutil.write_file(ovf_file_path, ovfxml)
tag_file_path_on_dvd = os.path.join(OSUTIL.get_dvd_mount_point(),
TAG_FILE_NAME)
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(OSUTIL.get_lib_dir(), TAG_FILE_NAME)
shutil.copyfile(tag_file_path_on_dvd, tag_file_path)
except IOError as e:
raise ProtocolError(text(e))
except OSUtilError as e:
raise ProtocolError(text(e))
try:
OSUTIL.umount_dvd()
OSUTIL.eject_dvd()
except OSUtilError as e:
logger.warn(text(e))
return ovfenv
def _validate_ovf(val, msg):
if val is None:
raise ProtocolError("Failed to parse OVF XML: {0}".format(msg))

Просмотреть файл

@ -22,15 +22,10 @@ import re
import json
import xml.dom.minidom
import azurelinuxagent.logger as logger
from azurelinuxagent.exception import ProtocolError
from azurelinuxagent.future import text
import azurelinuxagent.utils.fileutil as fileutil
class ProtocolError(Exception):
pass
class ProtocolNotFound(Exception):
pass
def validata_param(name, val, expected_type):
if val is None:
raise ProtocolError("{0} is None".format(name))
@ -211,10 +206,7 @@ class TelemetryEventList(DataContract):
class Protocol(DataContract):
def initialize(self):
raise NotImplementedError()
def reinitialize(self):
def detect(self):
raise NotImplementedError()
def get_vminfo(self):

Просмотреть файл

@ -23,17 +23,18 @@ import time
import traceback
import xml.sax.saxutils as saxutils
import xml.etree.ElementTree as ET
import azurelinuxagent.conf as conf
import azurelinuxagent.logger as logger
from azurelinuxagent.exception import ProtocolError, HttpError, \
ProtocolNotFoundError
from azurelinuxagent.future import text, httpclient, bytebuffer
import azurelinuxagent.utils.restutil as restutil
import azurelinuxagent.utils.textutil as textutil
from azurelinuxagent.utils.textutil import parse_doc, findall, find, findtext, \
getattrib, gettext, remove_bom
from azurelinuxagent.utils.osutil import OSUTIL
import azurelinuxagent.utils.fileutil as fileutil
import azurelinuxagent.utils.shellutil as shellutil
from azurelinuxagent.protocol.common import *
import azurelinuxagent.protocol.dhcp as dhcp
from azurelinuxagent.protocol.restapi import *
VERSION_INFO_URI = "http://{0}/?comp=versions"
GOAL_STATE_URI = "http://{0}/machine/?comp=goalstate"
@ -65,21 +66,17 @@ class WireProtocolResourceGone(ProtocolError):
class WireProtocol(Protocol):
def __init__(self):
pass
def __init__(self, osutil, endpoint):
self.osutil = osutil
self.endpoint = endpoint
self.client = WireClient(self.endpoint)
def initialize(self):
dhcp_resp = dhcp.DHCPCLIENT.fetch_dhcp_resp()
self.client = WireClient(dhcp_resp.endpoint)
def detect(self):
self.client.check_wire_protocol_version()
OSUTIL.gen_transport_cert(TRANSPORT_PRV_FILE_NAME,
self.osutil.gen_transport_cert(TRANSPORT_PRV_FILE_NAME,
TRANSPORT_CERT_FILE_NAME)
self.client.update_goal_state(forced=True)
def reinitialize(self):
dhcp_resp = dhcp.DHCPCLIENT.get_dhcp_resp()
self.client = WireClient(dhcp_resp.endpoint)
def get_vminfo(self):
hosting_env = self.client.get_hosting_env()
vminfo = VMInfo()
@ -314,7 +311,7 @@ class StatusBlob(object):
self.put_page_blob(url, data)
else:
raise ProtocolError("Unknown blob type: {0}".format(blob_type))
except restutil.HttpError as e:
except HttpError as e:
raise ProtocolError("Failed to upload status blob: {0}".format(e))
def get_blob_type(self, url):
@ -326,7 +323,7 @@ class StatusBlob(object):
"x-ms-date" : timestamp,
'x-ms-version' : self.__class__.__storage_version__
})
except restutil.HttpError as e:
except HttpError as e:
raise ProtocolError((u"Failed to get status blob type: {0}"
u"").format(e))
if resp is None or resp.status != httpclient.OK:
@ -348,7 +345,7 @@ class StatusBlob(object):
"Content-Length": text(len(data)),
"x-ms-version" : self.__class__.__storage_version__
})
except restutil.HttpError as e:
except HttpError as e:
raise ProtocolError((u"Failed to upload block blob: {0}"
u"").format(e))
if resp.status != httpclient.CREATED:
@ -373,7 +370,7 @@ class StatusBlob(object):
"x-ms-blob-content-length" : text(page_blob_size),
"x-ms-version" : self.__class__.__storage_version__
})
except restutil.HttpError as e:
except HttpError as e:
raise ProtocolError((u"Failed to clean up page blob: {0}"
u"").format(e))
if resp.status != httpclient.CREATED:
@ -406,7 +403,7 @@ class StatusBlob(object):
"x-ms-version" : self.__class__.__storage_version__,
"Content-Length": text(page_end - start)
})
except restutil.HttpError as e:
except HttpError as e:
raise ProtocolError((u"Failed to upload page blob: {0}"
u"").format(e))
if resp is None or resp.status != httpclient.CREATED:
@ -506,7 +503,7 @@ class WireClient(object):
try:
resp = self.call_wireserver(restutil.http_get, uri,
headers=headers)
except restutil.HttpError as e:
except HttpError as e:
raise ProtocolError(text(e))
if(resp.status != httpclient.OK):
@ -550,7 +547,7 @@ class WireClient(object):
resp = self.call_storage_service(restutil.http_get,
version_uri.uri, None,
chk_proxy=True)
except restutil.HttpError as e:
except HttpError as e:
raise ProtocolError(text(e))
if resp.status == httpclient.OK:
@ -615,7 +612,7 @@ class WireClient(object):
xml_text = self.fetch_config(uri, self.get_header())
goal_state = GoalState(xml_text)
incarnation_file = os.path.join(OSUTIL.get_lib_dir(),
incarnation_file = os.path.join(conf.get_lib_dir(),
INCARNATION_FILE_NAME)
if not forced:
@ -633,7 +630,7 @@ class WireClient(object):
try:
self.goal_state = goal_state
file_name = GOAL_STATE_FILE_NAME.format(goal_state.incarnation)
goal_state_file = os.path.join(OSUTIL.get_lib_dir(), file_name)
goal_state_file = os.path.join(conf.get_lib_dir(), file_name)
self.save_cache(goal_state_file, xml_text)
self.save_cache(incarnation_file, goal_state.incarnation)
self.update_hosting_env(goal_state)
@ -707,7 +704,7 @@ class WireClient(object):
else:
error = ("Agent supported wire protocol version: {0} was not "
"advised by Fabric.").format(PROTOCOL_VERSION)
raise ProtocolNotFound(error)
raise ProtocolNotFoundError(error)
def upload_status_blob(self):
ext_conf = self.get_ext_conf()
@ -725,7 +722,7 @@ class WireClient(object):
try:
resp = self.call_wireserver(restutil.http_post, role_prop_uri,
role_prop, headers = headers)
except restutil.HttpError as e:
except HttpError as e:
raise ProtocolError((u"Failed to send role properties: {0}"
u"").format(e))
if resp.status != httpclient.ACCEPTED:
@ -746,7 +743,7 @@ class WireClient(object):
try:
resp = self.call_wireserver(restutil.http_post, health_report_uri,
health_report, headers = headers)
except restutil.HttpError as e:
except HttpError as e:
raise ProtocolError((u"Failed to send provision status: {0}"
u"").format(e))
if resp.status != httpclient.OK:
@ -764,7 +761,7 @@ class WireClient(object):
try:
header = self.get_header_for_xml_content()
resp = self.call_wireserver(restutil.http_post, uri, data, header)
except restutil.HttpError as e:
except HttpError as e:
raise ProtocolError("Failed to send events:{0}".format(e))
if resp.status != httpclient.OK:
@ -933,8 +930,8 @@ class Certificates(object):
def __init__(self, client, xml_text):
logger.verb("Load Certificates.xml")
self.client = client
self.lib_dir = OSUTIL.get_lib_dir()
self.openssl_cmd = OSUTIL.get_openssl_cmd()
self.lib_dir = conf.get_lib_dir()
self.openssl_cmd = self.client.osutil.get_openssl_cmd()
self.cert_list = CertList()
self.parse(xml_text)
@ -980,15 +977,15 @@ class Certificates(object):
begin_crt = True
elif re.match(r'[-]+END.*KEY[-]+', line):
tmp_file = self.write_to_tmp_file(index, 'prv', buf)
pub = OSUTIL.get_pubkey_from_prv(tmp_file)
pub = self.client.osutil.get_pubkey_from_prv(tmp_file)
prvs[pub] = tmp_file
buf = []
index += 1
begin_prv = False
elif re.match(r'[-]+END.*CERTIFICATE[-]+', line):
tmp_file = self.write_to_tmp_file(index, 'crt', buf)
pub = OSUTIL.get_pubkey_from_crt(tmp_file)
thumbprint = OSUTIL.get_thumbprint_from_crt(tmp_file)
pub = self.client.osutil.get_pubkey_from_crt(tmp_file)
thumbprint = self.client.osutil.get_thumbprint_from_crt(tmp_file)
thumbprints[pub] = thumbprint
#Rename crt with thumbprint as the file name
crt = "{0}.crt".format(thumbprint)

Просмотреть файл

@ -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+
#
"""
Load OSUtil implementation from azurelinuxagent.distro
"""
from azurelinuxagent.distro.default.osutil import OSUtilError
import azurelinuxagent.distro.loader as loader
OSUTIL = loader.get_osutil()

Просмотреть файл

@ -21,8 +21,9 @@ import time
import platform
import os
import subprocess
import azurelinuxagent.logger as logger
import azurelinuxagent.conf as conf
import azurelinuxagent.logger as logger
from azurelinuxagent.exception import HttpError
from azurelinuxagent.future import httpclient, urlparse
"""
@ -31,9 +32,6 @@ REST api util functions
RETRY_WAITING_INTERVAL = 10
class HttpError(Exception):
pass
def _parse_url(url):
o = urlparse(url)
rel_uri = o.path
@ -51,8 +49,8 @@ def get_http_proxy():
Get http_proxy and https_proxy from environment variables.
Username and password is not supported now.
"""
host = conf.get("HttpProxy.Host", None)
port = conf.get("HttpProxy.Port", None)
host = conf.get_httpproxy_host()
port = conf.get_httpproxy_port()
return (host, port)
def _http_request(method, host, rel_uri, port=None, data=None, secure=False,

Просмотреть файл

@ -71,3 +71,18 @@ OS.OpensslPath=None
# Detect Scvmm environment, default is n
# DetectScvmmEnv=n
#
# Lib.Dir=/var/lib/waagent
#
# DVD.MountPoint=/mnt/cdrom/secure
#
# Pid.File=/var/run/waagent.pid
#
# Extension.LogDir=/var/log/azure
#
# Home.Dir=/home