From 571bdcfe4b3d37c0fc94689d511712c2a0a13b69 Mon Sep 17 00:00:00 2001 From: Ben Howard Date: Thu, 21 Mar 2013 12:57:08 -0600 Subject: Import patches-unapplied version 1.3.2-0ubuntu1 to ubuntu/raring-proposed Imported using git-ubuntu import. Changelog parent: 608a9999c43d3500a13f03621c3982db505ec781 New changelog entries: * Updated to 1.3.2 as part of Windows Azure requirement (LP: #1158465). * Upstream now supports packaging; incorporated upstream packaging into Ubuntu Packaging. --- Changelog | 12 ++ debian/changelog | 8 ++ debian/patches/000_use_packaged_upstart | 118 ---------------- debian/patches/series | 1 - rpm/README | 45 ++++++ rpm/walinuxagent.spec | 89 ++++++++++++ waagent | 236 ++++++++++++++++++++++---------- 7 files changed, 318 insertions(+), 191 deletions(-) delete mode 100644 debian/patches/000_use_packaged_upstart delete mode 100644 debian/patches/series create mode 100644 rpm/README create mode 100644 rpm/walinuxagent.spec diff --git a/Changelog b/Changelog index bfa33b3..48a315e 100644 --- a/Changelog +++ b/Changelog @@ -1,6 +1,18 @@ WALinuxAgent Changelog ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +26 Feb 2013, WALinuxAgent 1.3.2 + . Fix name error in _HttpGet/HttpPost exception handlers. + +15 Feb 2013, WALinuxAgent 1.3.1 + . Merge RPM packaging information. + . Capture all system command output if an error has occurred. Normalization + of shell commands on python subprocess module. + . Duplicate non-verbose log output to /dev/console. This to support serial + logging from boot when console=/dev/ttyS0 is set in the kernel boot options. + . Merge Ubuntu packaging. + . Fixed typo in DVD mounting procedure, thanks Ante. + 18 Jan 2013, WALinuxAgent 1.3 . Add some error checking and robustness to DVD mounting operation during provisioning diff --git a/debian/changelog b/debian/changelog index 242022a..ba17763 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +walinuxagent (1.3.2-0ubuntu1) raring; urgency=low + + * Updated to 1.3.2 as part of Windows Azure requirement (LP: #1158465). + * Upstream now supports packaging; incorporated upstream packaging into + Ubuntu Packaging. + + -- Ben Howard Thu, 21 Mar 2013 12:57:08 -0600 + walinuxagent (1.3-0ubuntu2) raring; urgency=low * Changed detection of whether or not agent is packaged to using diff --git a/debian/patches/000_use_packaged_upstart b/debian/patches/000_use_packaged_upstart deleted file mode 100644 index 463ae57..0000000 --- a/debian/patches/000_use_packaged_upstart +++ /dev/null @@ -1,118 +0,0 @@ ---- a/waagent -+++ b/waagent -@@ -52,6 +52,7 @@ ProtocolVersion = "2011-12-31" - - Config = None - LinuxDistro = "UNKNOWN" -+PackagedForDistro = "UNKNOWN" - Verbose = False - WaAgent = None - DiskActivated = False -@@ -79,11 +80,23 @@ def IsLinux(): - - def DetectLinuxDistro(): - global LinuxDistro -+ global PackagedForDistro - if os.path.isfile("/etc/redhat-release"): - LinuxDistro = "RedHat" - return True - if os.path.isfile("/etc/lsb-release") and "Ubuntu" in GetFileContents("/etc/lsb-release"): - LinuxDistro = "Ubuntu" -+ -+ # Should this run as if it is packaged Ubuntu? -+ try: -+ cmd="dpkg -S %s" % os.path.basename(__file__) -+ retcode, krn = RunSafe(cmd) -+ if not retcode: -+ PackagedForDistro = "Ubuntu" -+ -+ except IOError as e: -+ pass -+ - return True - if os.path.isfile("/etc/debian_version"): - LinuxDistro = "Debian" -@@ -99,12 +112,21 @@ def IsRedHat(): - def IsUbuntu(): - return "Ubuntu" in LinuxDistro - -+def IsPackagedUbuntu(): -+ return "Ubuntu" in PackagedForDistro -+ - def IsDebian(): - return IsUbuntu() or "Debian" in LinuxDistro - - def IsSuse(): - return "Suse" in LinuxDistro - -+def IsPackaged(): -+ if PackagedForDistro == "UNKNOWN": -+ return False -+ -+ return True -+ - def UsesRpm(): - return IsRedHat() or IsSuse() - -@@ -2252,14 +2274,14 @@ def Install(): - shutil.move(a, ".") - Warn("Moved " + a + " -> " + LibDir + "/" + GetLastPathElement(a) ) - -- if IsUbuntu(): -+ if IsUbuntu() and not IsPackagedUbuntu(): - # Support for Ubuntu's upstart configuration - filename="waagent.conf" - filepath = "/etc/init/" + filename - SetFileContents(filepath, Init_Ubuntu) - os.chmod(filepath, 0644) - -- else: -+ elif not IsPackagedUbuntu(): - # Regular init.d configurations - filename = "waagent" - filepath = "/etc/init.d/" + filename -@@ -2273,6 +2295,7 @@ def Install(): - SetFileContents(filepath, init[0]) - os.chmod(filepath, 0755) - Run(init[1]) -+ - if os.path.isfile("/etc/waagent.conf"): - try: - os.remove("/etc/waagent.conf.old") -@@ -2310,12 +2333,30 @@ def Uninstall(): - if a == 0: - Error("Unable to detect Linux Distribution.") - return 1 -- Run("service " + filename + " stop") -- cmd = ["chkconfig --del " + filename, -- "update-rc.d -f " + filename + " remove", -- "insserv -r " + filename][a - 1] -- Run(cmd) -- for f in os.listdir(LibDir) + ["/etc/init/waagent.conf","/etc/init.d/" + filename, "/etc/waagent.conf", "/etc/logrotate.d/waagent", "/etc/sudoers.d/waagent"]: -+ -+ # Managed by dpkg for Packaged Ubuntu -+ if not IsPackaged(): -+ Run("service " + filename + " stop") -+ cmd = ["chkconfig --del " + filename, -+ "update-rc.d -f " + filename + " remove", -+ "insserv -r " + filename][a - 1] -+ Run(cmd) -+ -+ remove_f = [ -+ "/etc/waagent.conf", -+ "/etc/logrotate.d/waagent", -+ "/etc/sudoers.d/waagent", -+ ] -+ -+ # For packaged Ubuntu, the script should let the packaging -+ # manage the removal of these files -+ if not IsPackagedUbuntu(): -+ remove_f.append([ -+ "/etc/init/waagent.conf", -+ "/etc/init.d/" + filename, -+ ]) -+ -+ for f in os.listdir(LibDir) + remove_f: - try: - os.remove(f) - except: diff --git a/debian/patches/series b/debian/patches/series deleted file mode 100644 index 4232496..0000000 --- a/debian/patches/series +++ /dev/null @@ -1 +0,0 @@ -000_use_packaged_upstart diff --git a/rpm/README b/rpm/README new file mode 100644 index 0000000..08d9014 --- /dev/null +++ b/rpm/README @@ -0,0 +1,45 @@ +The preferred method of installing the Windows Azure Linux Agent for +CentOS and other RPM-based distributions is to use the RPM packaging. +Platform images in the Azure Gallery will already include the agent +package. This guide is primarily for individuals who would like to +build their own custom packages. + +OpenLogic provides supported RPM packages for CentOS in their package +repositories, for example +http://olcentgbl.trafficmanager.net/openlogic/6/openlogic/x86_64/RPMS/ + +Note: Official packaging and other patches for SLES and OpenSUSE can be +found on the OpenSUSE Build Service: +https://build.opensuse.org/package/show?package=WALinuxAgent&project=Cloud%3ATools + +The instructions below will describe how you can build your own RPM +package on a CentOS host: + + 1. Install required rpmbuild package: + + yum -y install rpm-build + + 2. Set up the rpmbuild environment: + + mkdir -p ~/rpmbuild/{SPECS,SOURCES} + + 3. Download the WALinuxAgent source code as a tar.gz compressed + file from Github, or create it yourself: + + tar -czf WALinuxAgent-1.x.x.tar.gz WALinuxAgent-1.x.x + + 4. Copy the files to the rpmbuild environment: + + cp walinuxagent.spec ~/rpmbuild/SPECS + cp WALinuxAgent-1.x.x.tar.gz ~/rpmbuild/SOURCES + + 5. If necessary, edit the ~/rpmbuild/SPECS/walinuxagent.spec file + and ensure that the 'Version', 'Source0' and other information + is accurate. + + 6. The following command will build the binary and source RPMs: + + rpmbuild -ba ~/rpmbuild/SPECS/walinuxagent.spec + + +Enjoy! \ No newline at end of file diff --git a/rpm/walinuxagent.spec b/rpm/walinuxagent.spec new file mode 100644 index 0000000..fda355b --- /dev/null +++ b/rpm/walinuxagent.spec @@ -0,0 +1,89 @@ +#=============================================================================== +# Name: WAAgent.spec +#------------------------------------------------------------------------------- +# Purpose : RPM Spec file for Python script packaging +# Version : 1.2 +# Created : April 20 2012 +#=============================================================================== + +#%define my_release 1 + +Name: WALinuxAgent +Summary: The Windows Azure Linux Agent +Version: 1.3.2 +Release: 1 +License: Apache License Version 2.0 +Group: Applications/Internet +Url: http://go.microsoft.com/fwlink/?LinkId=250998 +Source0: WALinuxAgent-1.3.2.tar.gz +Requires: python python-pyasn1 openssh openssl util-linux sed grep sudo iptables +Conflicts: NetworkManager +BuildRoot: %{_tmppath}/%{name}-%{version}-build +BuildArch: noarch +Vendor: Microsoft Corporation +Packager: Microsoft Corporation + +%description +The Windows Azure Linux Agent supports the provisioning and running of Linux VMs in the Windows Azure cloud. This package should be installed on Linux disk images that are built to run in the Windows Azure environment. + +%prep +%setup +find . -type f -exec sed -i 's/\r//' {} \; + +%pre -p /bin/sh +if [ $1 = "1" ] +then +echo " Fresh installation of WALinuxAgent" +elif [ $1 = "2" ] +then +echo " Upgrading to higher version of WALinuxAgent" +fi + +%install +mkdir -p %{buildroot}/usr/sbin +install -m 0755 waagent %{buildroot}%{_sbindir}/ + +%post +chmod 755 /usr/sbin/waagent +/usr/sbin/waagent -setup + +%preun -p /bin/sh +if [ $1 = "0" ] +then +echo " Un-installation of WALinuxAgent" +%{_sbindir}/waagent -uninstall +fi + +%postun +if [ $1 = "0" ] +then +rm -f %{_sbindir}/waagent +fi + +%files +%defattr(-,root,root) +%{_sbindir}/waagent +%doc LICENSE-2.0.txt +%doc NOTICE +%doc README +%doc Changelog + +%changelog +* Fri Feb 26 2013 - walinuxagent@microsoft.com +- Updated version to 1.3.2 for release + +* Fri Feb 15 2013 - walinuxagent@microsoft.com +- Updated version to 1.3.1 for release + +* Fri Jan 18 2013 - walinuxagent@microsoft.com +- Updated version to 1.3 for release + +* Fri Dec 07 2012 - walinuxagent@microsoft.com +- Updated version to 1.2 for release + +* Fri Nov 09 2012 - walinuxagent@microsoft.com +- Added README and Changelog +- Updated version to 1.1 for release + +* Thu May 17 2012 - walinuxagent@microsoft.com +- Initial WALinuxAgent packages. diff --git a/waagent b/waagent index 680c0d8..4181eca 100644 --- a/waagent +++ b/waagent @@ -43,15 +43,15 @@ import threading import time import traceback import xml.dom.minidom -import commands - + GuestAgentName = "WALinuxAgent" GuestAgentLongName = "Windows Azure Linux Agent" -GuestAgentVersion = "WALinuxAgent-1.3" +GuestAgentVersion = "WALinuxAgent-1.3.2" ProtocolVersion = "2011-12-31" Config = None LinuxDistro = "UNKNOWN" +PackagedForDistro = "UNKNOWN" Verbose = False WaAgent = None DiskActivated = False @@ -65,6 +65,34 @@ VarLibDhcpDirectories = ["/var/lib/dhclient", "/var/lib/dhcpcd", "/var/lib/dhcp" EtcDhcpClientConfFiles = ["/etc/dhcp/dhclient.conf", "/etc/dhcp3/dhclient.conf"] LibDir = "/var/lib/waagent" +# backport subprocess.check_output if not defined ( for python version < 2.7) +if not hasattr(subprocess,'check_output'): + def check_output(*popenargs, **kwargs): + r"""Backport from subprocess module from python 2.7""" + if 'stdout' in kwargs: + raise ValueError('stdout argument not allowed, it will be overridden.') + process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs) + output, unused_err = process.communicate() + retcode = process.poll() + if retcode: + cmd = kwargs.get("args") + if cmd is None: + cmd = popenargs[0] + raise subprocess.CalledProcessError(retcode, cmd, output=output) + return output + + # Exception classes used by this module. + class CalledProcessError(Exception): + def __init__(self, returncode, cmd, output=None): + self.returncode = returncode + self.cmd = cmd + self.output = output + def __str__(self): + return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode) + + subprocess.check_output=check_output + subprocess.CalledProcessError=CalledProcessError + # This lets us index into a string or an array of integers transparently. def Ord(a): if type(a) == type("a"): @@ -79,11 +107,24 @@ def IsLinux(): def DetectLinuxDistro(): global LinuxDistro + global PackagedForDistro if os.path.isfile("/etc/redhat-release"): LinuxDistro = "RedHat" return True if os.path.isfile("/etc/lsb-release") and "Ubuntu" in GetFileContents("/etc/lsb-release"): LinuxDistro = "Ubuntu" + + # Should this run as if it is packaged Ubuntu? + try: + cmd="dpkg -S %s" % os.path.basename(__file__) + retcode, krn = RunGetOutput(cmd,chk_err=False) + if not retcode: + PackagedForDistro = "Ubuntu" + + except IOError as e: + pass + + return True if os.path.isfile("/etc/debian_version"): LinuxDistro = "Debian" @@ -99,12 +140,21 @@ def IsRedHat(): def IsUbuntu(): return "Ubuntu" in LinuxDistro +def IsPackagedUbuntu(): + return "Ubuntu" in PackagedForDistro + def IsDebian(): return IsUbuntu() or "Debian" in LinuxDistro def IsSuse(): return "Suse" in LinuxDistro +def IsPackaged(): + if PackagedForDistro == "UNKNOWN": + return False + + return True + def UsesRpm(): return IsRedHat() or IsSuse() @@ -161,23 +211,38 @@ def GetLineStartingWith(prefix, filepath): return line return None -def Run(a): - LogIfVerbose(a) - return os.system(a) +def Run(cmd,chk_err=True): + retcode,out=RunGetOutput(cmd,chk_err) + return retcode -def RunSafe(cmd): - Log(cmd) - # for python2.1 double try, in order to use a finally... +def RunGetOutput(cmd,chk_err=True): + LogIfVerbose(cmd) try: - try: - (exit_status,output) = commands.getstatusoutput(cmd) - except OSError,e : # just catch the exception and proceed - Log( ("OSError " + str(e) + " caught") ) - return exit_status,output - else: - return exit_status,output - finally: - pass + output=subprocess.check_output(cmd,stderr=subprocess.STDOUT,shell=True) + except subprocess.CalledProcessError,e : + if chk_err : + Error('CalledProcessError. Error Code: ' + str(e.returncode) ) + Error('CalledProcessError. Command string: "' + e.cmd + '"') + Error('CalledProcessError. Command result: "' + e.output[:-1] + '"') + return e.returncode,e.output + return 0,output + +def RunSendStdin(cmd,input,chk_err=True): + LogIfVerbose(cmd+input) + try: + me=subprocess.Popen([cmd], shell=True, stdin=subprocess.PIPE,stderr=subprocess.STDOUT,stdout=subprocess.PIPE) + output=me.communicate(input) + except OSError,e : + if chk_err : + Error('CalledProcessError. Error Code:' + str(me.returncode)) + Error('CalledProcessError. Command string:"' + cmd + '"' ) + Error('CalledProcessError. Command result:"' + output[:-1] + '"') + return 1,output[0] + if me.returncode is not 0 and chk_err is True: + Error('CalledProcessError. Error Code:' + str(me.returncode)) + Error('CalledProcessError. Command string:"' + cmd + '"' ) + Error('CalledProcessError. Command result:"' + (output[0])[:-1] + '"') + return me.returncode,output[0] def GetNodeTextData(a): for b in a.childNodes: @@ -239,7 +304,7 @@ def CreateAccount(user, password, expiration, thumbprint): else: Log("CreateAccount: " + user + " already exists. Will update password.") if password != None: - os.popen("chpasswd", "w").write(user + ":" + password + "\n") + RunSendStdin("chpasswd",(user + ":" + password + "\n")) try: if password == None: SetFileContents("/etc/sudoers.d/waagent", user + " ALL = (ALL) NOPASSWD: ALL\n") @@ -349,7 +414,8 @@ def Logger(): class T(object): def __init__(self): self.File = None - + self.Con = None + self = T() def LogToFile(message): @@ -362,6 +428,13 @@ def Logger(): self.File.write(message + "\n") self.File.flush() + def LogToCon(message): + ConPath = '/dev/console' + if self.Con == None: + self.Con = open(ConPath, "a") + self.Con.write(message + "\n") + self.Con.flush() + def Log(message): LogWithPrefix("", message) @@ -371,9 +444,9 @@ def Logger(): t += prefix for line in message.split('\n'): line = t + line - print(line) LogToFile(line) - + LogToCon(line) + return Log, LogWithPrefix Log, LogWithPrefix = Logger() @@ -383,7 +456,7 @@ def NoLog(message): def LogIfVerbose(message): if Verbose == True: - Log(message) + LogFileWithPrefix('',message) def LogWithPrefixIfVerbose(prefix, message): if Verbose == True: @@ -393,10 +466,10 @@ def Warn(message): LogWithPrefix("WARNING:", message) def Error(message): - LogWithPrefix("ERROR:", message) + ErrorWithPrefix("", message) def ErrorWithPrefix(prefix, message): - LogWithPrefix("ERROR:" + prefix, message) + LogWithPrefix("ERROR:", message) def Linux_ioctl_GetIpv4Address(ifname): import fcntl @@ -433,7 +506,7 @@ def GetMacAddress(): if IsWindows(): # Windows: Physical Address. . . . . . . . . : 00-15-17-79-00-7F\n a = "ipconfig /all | findstr /c:\"Physical Address\" | findstr /v \"00-00-00-00-00-00-00\"" - a = os.popen(a).read() + a = os.popen(a).read() # not re-implementing wirh RunGetOutput - not called unless we're in windows a = re.sub("\s+$", "", a) a = re.sub(".+ ", "", a) a = re.sub(":", "", a) @@ -475,7 +548,7 @@ class Util(object): url = url[url.index("/"):] for retry in range(0, maxRetry + 1): strRetry = str(retry) - log = [NoLog, Log][retry > 0] + log = [NoLog, Error][retry > 0] log("retry HttpGet(" + url + "),retry=" + strRetry) response = None strStatus = "None" @@ -487,16 +560,16 @@ class Util(object): request = httpConnection.request("GET", url, None, headers) response = httpConnection.getresponse() strStatus = str(response.status) - except: - pass + except httplib.HTTPException, e: + Error('HTTPException ' + e.message + ' args: ' + repr(e.args)) log("response HttpGet(" + url + "),retry=" + strRetry + ",status=" + strStatus) if response == None or response.status != httplib.OK: Error("HttpGet(" + url + "),retry=" + strRetry + ",status=" + strStatus) if retry == maxRetry: - Log("return HttpGet(" + url + "),retry=" + strRetry + ",status=" + strStatus) + Error("return HttpGet(" + url + "),retry=" + strRetry + ",status=" + strStatus) return None else: - Log("sleep 10 seconds HttpGet(" + url + "),retry=" + strRetry + ",status=" + strStatus) + Error("sleep 10 seconds HttpGet(" + url + "),retry=" + strRetry + ",status=" + strStatus) time.sleep(10) else: log("return HttpGet(" + url + "),retry=" + strRetry + ",status=" + strStatus) @@ -519,7 +592,7 @@ class Util(object): maxRetry = 2 for retry in range(0, maxRetry + 1): strRetry = str(retry) - log = [NoLog, Log][retry > 0] + log = [NoLog, Error][retry > 0] log("retry HttpPost(" + url + "),retry=" + strRetry) response = None strStatus = "None" @@ -530,16 +603,16 @@ class Util(object): "x-ms-version": ProtocolVersion}) response = httpConnection.getresponse() strStatus = str(response.status) - except: - pass + except httplib.HTTPException, e: + Error('HTTPException ' + e.message + ' args: ' + repr(e.args)) log("response HttpPost(" + url + "),retry=" + strRetry + ",status=" + strStatus) if response == None or (response.status != httplib.OK and response.status != httplib.ACCEPTED): Error("HttpPost(" + url + "),retry=" + strRetry + ",status=" + strStatus) if retry == maxRetry: - Log("return HttpPost(" + url + "),retry=" + strRetry + ",status=" + strStatus) + Error("return HttpPost(" + url + "),retry=" + strRetry + ",status=" + strStatus) return None else: - Log("sleep 10 seconds HttpPost(" + url + "),retry=" + strRetry + ",status=" + strStatus) + Error("sleep 10 seconds HttpPost(" + url + "),retry=" + strRetry + ",status=" + strStatus) time.sleep(10) else: log("return HttpPost(" + url + "),retry=" + strRetry + ",status=" + strStatus) @@ -626,7 +699,7 @@ class EnvMonitor(object): dhcpcmd = "pidof dhcpcd" if IsDebian(): dhcpcmd = "pidof dhclient3" - dhcppid = os.popen(dhcpcmd).read() + dhcppid = RunGetOutput(dhcpcmd,chk_err=False)[1] while not self.shutdown: for a in RulesFiles: if os.path.isfile(a): @@ -640,7 +713,7 @@ class EnvMonitor(object): Log("EnvMonitor: Detected host name change: " + self.HostName + " -> " + socket.gethostname()) self.HostName = socket.gethostname() WaAgent.UpdateAndPublishHostName(self.HostName) - dhcppid = os.popen(dhcpcmd).read() + dhcppid = RunGetOutput(dhcpcmd,chk_err=False)[1] self.published = True except: pass @@ -648,7 +721,7 @@ class EnvMonitor(object): self.published = True pid = "" if not os.path.isdir("/proc/" + dhcppid.strip()): - pid = os.popen(dhcpcmd).read() + pid = RunGetOutput(dhcpcmd,chk_err=False)[1] if pid != "" and pid != dhcppid: Log("EnvMonitor: Detected dhcp client restart. Restoring routing table.") WaAgent.RestoreRoutes() @@ -733,8 +806,8 @@ class Certificates(object): index = 1 filename = str(index) + ".crt" while os.path.isfile(filename): - thumbprint = os.popen(Openssl + " x509 -in " + filename + " -fingerprint -noout").read().rstrip().split('=')[1].replace(':', '').upper() - pubkey=os.popen(Openssl + " x509 -in " + filename + " -pubkey -noout").read() + thumbprint = (RunGetOutput(Openssl + " x509 -in " + filename + " -fingerprint -noout")[1]).rstrip().split('=')[1].replace(':', '').upper() + pubkey=RunGetOutput(Openssl + " x509 -in " + filename + " -pubkey -noout")[1] keys[pubkey] = thumbprint os.rename(filename, thumbprint + ".crt") os.chmod(thumbprint + ".crt", 0600) @@ -745,7 +818,7 @@ class Certificates(object): index = 1 filename = str(index) + ".prv" while os.path.isfile(filename): - pubkey = os.popen(Openssl + " rsa -in " + filename + " -pubout").read() + pubkey = RunGetOutput(Openssl + " rsa -in " + filename + " -pubout 2> /dev/null")[1] os.rename(filename, keys[pubkey] + ".prv") os.chmod(keys[pubkey] + ".prv", 0600) if IsRedHat(): @@ -897,7 +970,7 @@ class HostingEnvironmentConfig(object): + "Content-Type: application/x-pkcs7-mime; name=\"password.p7m\"\n" + "Content-Transfer-Encoding: base64\n\n" + textwrap.fill(e, 64)) - return os.popen(Openssl + " cms -decrypt -in password.p7m -inkey Certificates.pem -recip Certificates.pem").read() + return RunGetOutput(Openssl + " cms -decrypt -in password.p7m -inkey Certificates.pem -recip Certificates.pem")[1] def ActivateResourceDisk(self): global DiskActivated @@ -914,7 +987,7 @@ class HostingEnvironmentConfig(object): Error("ActivateResourceDisk: Unable to detect disk topology.") return device = "/dev/" + device - for entry in os.popen("mount").read().split(): + for entry in RunGetOutput("mount")[1].split(): if entry.startswith(device + "1"): Log("ActivateResourceDisk: " + device + "1 is already mounted.") DiskActivated = True @@ -926,7 +999,7 @@ class HostingEnvironmentConfig(object): fs = Config.get("ResourceDisk.Filesystem") if fs == None: fs = "ext3" - if os.popen("sfdisk -q -c " + device + " 1").read().rstrip() == "7" and fs != "ntfs": + if RunGetOutput("sfdisk -q -c " + device + " 1")[1].rstrip() == "7" and fs != "ntfs": Run("sfdisk -c " + device + " 1 83") Run("mkfs." + fs + " " + device + "1") if Run("mount " + device + "1 " + mountpoint): @@ -1282,10 +1355,10 @@ class OvfEnv(object): GetFileContents(filepath).split('\n'))) + "PasswordAuthentication no\nChallengeResponseAuthentication no\n") Log("Disabled SSH password-based authentication methods.") if self.AdminPassword != None: - os.popen("chpasswd", "w").write("root:" + self.AdminPassword + "\n") + RunSendStdin("chpasswd",("root:" + self.AdminPassword + "\n")) if self.UserName != None: error = CreateAccount(self.UserName, self.UserPassword, None, None) - sel = os.popen("getenforce").read().startswith("Enforcing") + sel = RunGetOutput("getenforce",chk_err=False)[1].startswith("Enforcing") if sel == True and IsRedHat(): Run("setenforce 0") home = GetHome() @@ -1503,7 +1576,7 @@ class Agent(Util): net = self.IntegerToIpAddressV4String(net) mask = self.IntegerToIpAddressV4String(mask) gateway = self.IntegerToIpAddressV4String(gateway) - Run("/sbin/route add -net " + net + " netmask " + mask + " gw " + gateway) + Run("/sbin/route add -net " + net + " netmask " + mask + " gw " + gateway,chk_err=False) # We supress error logging on error. def HandleDhcpResponse(self, sendData, receiveBuffer): LogIfVerbose("HandleDhcpResponse") @@ -1600,8 +1673,8 @@ class Agent(Util): ShortSleep = False # Sleep 1 second before retrying DHCP queries. ifname=None if not IsWindows(): - Run("iptables -D INPUT -p udp --dport 68 -j ACCEPT") - Run("iptables -I INPUT -p udp --dport 68 -j ACCEPT") + Run("iptables -D INPUT -p udp --dport 68 -j ACCEPT",chk_err=False) # We supress error logging on error. + Run("iptables -I INPUT -p udp --dport 68 -j ACCEPT",chk_err=False) # We supress error logging on error. sleepDurations = [0, 5, 10, 30, 60, 60, 60, 60] maxRetry = len(sleepDurations) @@ -1618,7 +1691,7 @@ class Agent(Util): sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) missingDefaultRoute = True try: - for line in os.popen("route -n").read().split('\n'): + for line in RunGetOutput("route -n")[1].split('\n'): if line.startswith("0.0.0.0 "): missingDefaultRoute = False except: @@ -1633,7 +1706,7 @@ class Agent(Util): except IOError, e: pass Log("DoDhcpWork: Missing default route - adding broadcast route for DHCP.") - Run("route add 255.255.255.255 dev " + ifname) + Run("route add 255.255.255.255 dev " + ifname,chk_err=False) # We supress error logging on error. sock.bind(("0.0.0.0", 68)) sock.sendto(sendData, ("", 67)) sock.settimeout(10) @@ -1659,7 +1732,7 @@ class Agent(Util): sock.close() if missingDefaultRoute: #We added this route - delete it - Run("route del 255.255.255.255 dev " + ifname) + Run("route del 255.255.255.255 dev " + ifname,chk_err=False) # We supress error logging on error. Log("DoDhcpWork: Removing broadcast route for DHCP.") return None @@ -1668,7 +1741,7 @@ class Agent(Util): Log("Setting host name: " + name) UpdateAndPublishHostNameCommon(name) for ethernetInterface in PossibleEthernetInterfaces: - Run("ifdown " + ethernetInterface + " && ifup " + ethernetInterface) + Run("ifdown " + ethernetInterface + " && ifup " + ethernetInterface,chk_err=False) # We supress error logging on error. self.RestoreRoutes() def RestoreRoutes(self): @@ -1769,17 +1842,17 @@ class Agent(Util): if os.path.exists("/dev/sr0"): dvd = "/dev/sr0" modloaded=False - if Run("fdisk -l " + dvd + " | grep Disk"): + if Run("fdisk -l " + dvd + " | grep Disk",chk_err=False): # Is it possible to load a module for ata_piix? - retcode,krn=RunSafe('uname -r') + retcode,krn=RunGetOutput('uname -r') if retcode: Error("Unable to provision: Failed to call uname -a") return "Unable to provision: Failed to mount DVD." - krn_pth='/lib/modules/'+krn+'/kernel/drivers/ata/ata_piix.ko' + krn_pth='/lib/modules/'+krn.strip('\n')+'/kernel/drivers/ata/ata_piix.ko' if not os.path.isfile(krn_pth): Error("Unable to provision: Failed to locate ata_piix.ko") return "Unable to provision: Failed to mount DVD." - retcode,output=RunSafe('insmod ' + krn_pth) + retcode,output=RunGetOutput('insmod ' + krn_pth) if retcode: Error("Unable to provision: Failed to insmod " + krn+pth) return "Failed to retrieve provisioning data (0x01)." @@ -1795,12 +1868,12 @@ class Agent(Util): CreateDir("/mnt/cdrom/secure", "root", 0700) #begin mount loop - ten tries - 5 sec wait between for retry in range(1,11): - retcode,output=RunSafe("mount -v " + dvd + " /mnt/cdrom/secure") - Log(output) + retcode,output=RunGetOutput("mount -v " + dvd + " /mnt/cdrom/secure") + Log(output[:-1]) if retcode: Log("mount failed on attempt #" + str(retry) ) else: - Log("mount suceed on attempt #" + str(retry) ) + Log("mount succeeded on attempt #" + str(retry) ) break Log("mount loop sleeping 5...") time.sleep(5) @@ -1823,7 +1896,7 @@ class Agent(Util): Error ("Provisioninig image FAILED " + error) return ("Provisioninig image FAILED " + error) # This is done here because regenerated SSH host key pairs may be potentially overwritten when processing the ovfxml - fingerprint = os.popen("ssh-keygen -lf /etc/ssh/ssh_host_" + type + "_key.pub").read().rstrip().split()[1].replace(':','') + fingerprint = RunGetOutput("ssh-keygen -lf /etc/ssh/ssh_host_" + type + "_key.pub")[1].rstrip().split()[1].replace(':','') self.ReportRoleProperties(fingerprint) delRootPass = Config.get("Provisioning.DeleteRootPassword") if delRootPass != None and delRootPass.lower().startswith("y"): @@ -2236,13 +2309,13 @@ def Install(): if missing == True: Warn("Please resolve missing dependencies listed for full functionality.") if UsesRpm(): - if not Run("rpm --quiet -q NetworkManager"): + if not Run("rpm --quiet -q NetworkManager",chk_err=False): # We want this to fail - supress error logging on error. Error(GuestAgentLongName + " is not compatible with NetworkManager.") return 1 if Run("rpm --quiet -q python-pyasn1"): Error(GuestAgentLongName + " requires python-pyasn1.") return 1 - if UsesDpkg() and not Run("dpkg-query -s network-manager >/dev/null 2>&1"): + if UsesDpkg() and not Run("dpkg-query -s network-manager >/dev/null 2>&1",chk_err=False): # We want this to fail - supress error logging on error. Error(GuestAgentLongName + " is not compatible with network-manager.") return 1 for a in RulesFiles: @@ -2252,14 +2325,14 @@ def Install(): shutil.move(a, ".") Warn("Moved " + a + " -> " + LibDir + "/" + GetLastPathElement(a) ) - if IsUbuntu(): + if IsUbuntu() and not IsPackagedUbuntu(): # Support for Ubuntu's upstart configuration filename="waagent.conf" filepath = "/etc/init/" + filename SetFileContents(filepath, Init_Ubuntu) os.chmod(filepath, 0644) - else: + elif not IsPackagedUbuntu(): # Regular init.d configurations filename = "waagent" filepath = "/etc/init.d/" + filename @@ -2273,6 +2346,7 @@ def Install(): SetFileContents(filepath, init[0]) os.chmod(filepath, 0755) Run(init[1]) + if os.path.isfile("/etc/waagent.conf"): try: os.remove("/etc/waagent.conf.old") @@ -2310,12 +2384,30 @@ def Uninstall(): if a == 0: Error("Unable to detect Linux Distribution.") return 1 - Run("service " + filename + " stop") - cmd = ["chkconfig --del " + filename, - "update-rc.d -f " + filename + " remove", - "insserv -r " + filename][a - 1] - Run(cmd) - for f in os.listdir(LibDir) + ["/etc/init/waagent.conf","/etc/init.d/" + filename, "/etc/waagent.conf", "/etc/logrotate.d/waagent", "/etc/sudoers.d/waagent"]: + + # Managed by dpkg for Packaged Ubuntu + if not IsPackaged(): + Run("service " + filename + " stop") + cmd = ["chkconfig --del " + filename, + "update-rc.d -f " + filename + " remove", + "insserv -r " + filename][a - 1] + Run(cmd) + + remove_f = [ + "/etc/waagent.conf", + "/etc/logrotate.d/waagent", + "/etc/sudoers.d/waagent", + ] + + # For packaged Ubuntu, the script should let the packaging + # manage the removal of these files + if not IsPackagedUbuntu(): + remove_f.append([ + "/etc/init/waagent.conf", + "/etc/init.d/" + filename, + ]) + + for f in os.listdir(LibDir) + remove_f: try: os.remove(f) except: -- cgit v1.2.3