From 9c10e991b1ca6eff0dc3b508217982a02f4943b7 Mon Sep 17 00:00:00 2001 From: Dong Liu Date: Wed, 13 Jan 2016 17:19:07 +0800 Subject: [PATCH 01/14] Fix get_distro for FreeBSD. --- azurelinuxagent/metadata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurelinuxagent/metadata.py b/azurelinuxagent/metadata.py index 0593fab..b97e5db 100644 --- a/azurelinuxagent/metadata.py +++ b/azurelinuxagent/metadata.py @@ -28,7 +28,7 @@ def get_distro(): if 'FreeBSD' in platform.system(): release = re.sub('\-.*\Z', '', ustr(platform.release())) osinfo = ['freebsd', release, '', 'freebsd'] - if 'linux_distribution' in dir(platform): + elif 'linux_distribution' in dir(platform): osinfo = list(platform.linux_distribution(full_distribution_name=0)) full_name = platform.linux_distribution()[0].strip() osinfo.append(full_name) From 25f488bc641c063e71a6c056dc3ff6de5da30b24 Mon Sep 17 00:00:00 2001 From: Dong Liu Date: Fri, 15 Jan 2016 15:51:06 +0800 Subject: [PATCH 02/14] Add FreeBSD distro class. --- azurelinuxagent/distro/freebsd/__init__.py | 19 ++++++++++++++++ azurelinuxagent/distro/freebsd/distro.py | 25 ++++++++++++++++++++++ azurelinuxagent/distro/loader.py | 3 +++ 3 files changed, 47 insertions(+) create mode 100644 azurelinuxagent/distro/freebsd/__init__.py create mode 100644 azurelinuxagent/distro/freebsd/distro.py diff --git a/azurelinuxagent/distro/freebsd/__init__.py b/azurelinuxagent/distro/freebsd/__init__.py new file mode 100644 index 0000000..d9b82f5 --- /dev/null +++ b/azurelinuxagent/distro/freebsd/__init__.py @@ -0,0 +1,19 @@ +# Microsoft Azure Linux Agent +# +# Copyright 2014 Microsoft Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Requires Python 2.4+ and Openssl 1.0+ +# + diff --git a/azurelinuxagent/distro/freebsd/distro.py b/azurelinuxagent/distro/freebsd/distro.py new file mode 100644 index 0000000..b9e98b5 --- /dev/null +++ b/azurelinuxagent/distro/freebsd/distro.py @@ -0,0 +1,25 @@ +# 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 + + +class FreeBSDDistro(DefaultDistro): + def __init__(self): + super(FreeBSDDistro, self).__init__() diff --git a/azurelinuxagent/distro/loader.py b/azurelinuxagent/distro/loader.py index 74ea9e7..f6800b3 100644 --- a/azurelinuxagent/distro/loader.py +++ b/azurelinuxagent/distro/loader.py @@ -28,6 +28,7 @@ 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 +from azurelinuxagent.distro.freebsd.distro import FreeBSDDistro def get_distro(distro_name=DISTRO_NAME, distro_version=DISTRO_VERSION, distro_full_name=DISTRO_FULL_NAME): @@ -60,6 +61,8 @@ def get_distro(distro_name=DISTRO_NAME, distro_version=DISTRO_VERSION, return Redhat6xDistro() else: return RedhatDistro() + elif distro_name == "freebsd": + return FreeBSDDistro() else: logger.warn("Unable to load distro implemetation for {0}.", distro_name) logger.warn("Use default distro implemetation instead.") From b65718d59d3c067bbb82bdbfba68496085054b4a Mon Sep 17 00:00:00 2001 From: Dong Liu Date: Fri, 15 Jan 2016 17:13:15 +0800 Subject: [PATCH 03/14] Add Resource Disk handler for FreeBSD. --- azurelinuxagent/distro/freebsd/distro.py | 2 + .../distro/freebsd/resourceDisk.py | 118 ++++++++++++++++++ config/freebsd/waagent.conf | 88 +++++++++++++ setup.py | 3 + 4 files changed, 211 insertions(+) create mode 100644 azurelinuxagent/distro/freebsd/resourceDisk.py create mode 100644 config/freebsd/waagent.conf diff --git a/azurelinuxagent/distro/freebsd/distro.py b/azurelinuxagent/distro/freebsd/distro.py index b9e98b5..4a76f7d 100644 --- a/azurelinuxagent/distro/freebsd/distro.py +++ b/azurelinuxagent/distro/freebsd/distro.py @@ -18,8 +18,10 @@ # from azurelinuxagent.distro.default.distro import DefaultDistro +from azurelinuxagent.distro.freebsd.resourceDisk import FreeBSDResourceDiskHandler class FreeBSDDistro(DefaultDistro): def __init__(self): super(FreeBSDDistro, self).__init__() + self.resource_disk_handler = FreeBSDResourceDiskHandler(self) diff --git a/azurelinuxagent/distro/freebsd/resourceDisk.py b/azurelinuxagent/distro/freebsd/resourceDisk.py new file mode 100644 index 0000000..455eb39 --- /dev/null +++ b/azurelinuxagent/distro/freebsd/resourceDisk.py @@ -0,0 +1,118 @@ +# Microsoft Azure Linux Agent +# +# Copyright 2014 Microsoft Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Requires Python 2.4+ and Openssl 1.0+ +# +import azurelinuxagent.logger as logger +import azurelinuxagent.utils.fileutil as fileutil +import azurelinuxagent.utils.shellutil as shellutil +from azurelinuxagent.distro.default.resourceDisk import ResourceDiskHandler +from azurelinuxagent.exception import ResourceDiskError + + +class FreeBSDResourceDiskHandler(ResourceDiskHandler): + """ + This class handles resource disk mounting for FreeBSD. + + The resource disk locates at following slot: + scbus2 on blkvsc1 bus 0: + at scbus2 target 1 lun 0 (da1,pass2) + + There are 2 variations based on partition table type: + 1. MBR: The resource disk partition is /dev/da1s1 + 2. GPT: The resource disk partition is /dev/da1p2, /dev/da1p1 is for reserved usage. + """ + def __init__(self, distro): + super(FreeBSDResourceDiskHandler, self).__init__(distro) + + @staticmethod + def parse_gpart_list(data): + dic = {} + for line in data.split('\n'): + if line.find("Geom name: ") != -1: + geom_name = line[11:] + elif line.find("scheme: ") != -1: + dic[geom_name] = line[8:] + return dic + + def mount_resource_disk(self, mount_point, fs): + if fs != 'ufs': + raise ResourceDiskError("Unsupported filesystem type:{0}, only ufs is supported.".format(fs)) + + # 1. Detect device + err, output = shellutil.run_get_output('gpart list') + if err: + raise ResourceDiskError("Unable to detect resource disk device:{0}".format(output)) + disks = self.parse_gpart_list(output) + + err, output = shellutil.run_get_output('camcontrol periphlist 2:1:0') + if err: + raise ResourceDiskError("Unable to detect resource disk device:{0}".format(output)) + + # 'da1: generation: 4 index: 1 status: MORE\npass2: generation: 4 index: 2 status: LAST\n' + device = None + for line in output.split('\n'): + index = line.find(':') + if index > 0: + geom_name = line[:index] + if geom_name in disks: + device = geom_name + break + + if not device: + raise ResourceDiskError("Unable to detect resource disk device.") + logger.info('Resource disk device {0} found.', device) + + # 2. Detect partition + partition_table_type = disks[device] + + if partition_table_type == 'MBR': + provider_name = device + 's1' + elif partition_table_type == 'GPT': + provider_name = device + 'p2' + else: + raise ResourceDiskError("Unsupported partition table type:{0}".format(output)) + + err, output = shellutil.run_get_output('gpart show -p {0}'.format(device)) + if err or output.find(provider_name) == -1: + raise ResourceDiskError("Resource disk partition not found.") + + partition = '/dev/' + provider_name + logger.info('Resource disk partition {0} found.', partition) + + # 3. Mount partition + mount_list = shellutil.run_get_output("mount")[1] + existing = self.distro.osutil.get_mount_point(mount_list, partition) + + if existing: + logger.info("Resource disk {0} is already mounted", partition) + return existing + + fileutil.mkdir(mount_point, mode=0o755) + mount_cmd = 'mount -t {0} {1} {2}'.format(fs, partition, mount_point) + err = shellutil.run(mount_cmd, chk_err=False) + if err: + logger.info('Creating {0} filesystem on partition {1}'.format(fs, partition)) + err, output = shellutil.run_get_output('newfs -U {0}'.format(partition)) + if err: + raise ResourceDiskError("Failed to create new filesystem on partition {0}, error:{1}" + .format(partition, output)) + err, output = shellutil.run_get_output(mount_cmd, chk_err=False) + if err: + raise ResourceDiskError("Failed to mount partition {0}, error".format(partition, output)) + + logger.info("Resource disk partition {0} is mounted at {1} with fstype {2}", partition, mount_point, fs) + return mount_point diff --git a/config/freebsd/waagent.conf b/config/freebsd/waagent.conf new file mode 100644 index 0000000..dcf90e6 --- /dev/null +++ b/config/freebsd/waagent.conf @@ -0,0 +1,88 @@ +# +# Microsoft Azure Linux Agent Configuration +# + +# Specified program is invoked with the argument "Ready" when we report ready status +# to the endpoint server. +Role.StateConsumer=None + +# Specified program is invoked with XML file argument specifying role +# configuration. +Role.ConfigurationConsumer=None + +# Specified program is invoked with XML file argument specifying role topology. +Role.TopologyConsumer=None + +# Enable instance creation +Provisioning.Enabled=y + +# Password authentication for root account will be unavailable. +Provisioning.DeleteRootPassword=y + +# Generate fresh host key pair. +Provisioning.RegenerateSshHostKeyPair=y + +# Supported values are "rsa", "dsa" and "ecdsa". +Provisioning.SshHostKeyPairType=rsa + +# Monitor host name changes and publish changes via DHCP requests. +Provisioning.MonitorHostName=y + +# Decode CustomData from Base64. +Provisioning.DecodeCustomData=n + +# Execute CustomData after provisioning. +Provisioning.ExecuteCustomData=n + +# Algorithm used by crypt when generating password hash. +#Provisioning.PasswordCryptId=6 + +# Length of random salt used when generating password hash. +#Provisioning.PasswordCryptSaltLength=10 + +# Format if unformatted. If 'n', resource disk will not be mounted. +ResourceDisk.Format=y + +# File system on the resource disk +# Typically ext3 or ext4. FreeBSD images should use 'ufs' here. +ResourceDisk.Filesystem=ufs + +# Mount point for the resource disk +ResourceDisk.MountPoint=/mnt/resource + +# Create and use swapfile on resource disk. +ResourceDisk.EnableSwap=n + +# Size of the swapfile. +ResourceDisk.SwapSizeMB=0 + +# Enable verbose logging (y|n) +Logs.Verbose=n + +# Root device timeout in seconds. +OS.RootDeviceScsiTimeout=300 + +# If "None", the system default version is used. +OS.OpensslPath=None + +# If set, agent will use proxy server to access internet +#HttpProxy.Host=None +#HttpProxy.Port=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 diff --git a/setup.py b/setup.py index c799787..8c8501e 100755 --- a/setup.py +++ b/setup.py @@ -106,6 +106,9 @@ def get_data_files(name, version, fullname): else: #sles 12+ and openSUSE 13.2+ use systemd set_systemd_files(data_files, dest='/usr/lib/systemd/system') + elif name == 'freebsd': + set_bin_files(data_files) + set_conf_files(data_files, src=["config/freebsd/waagent.conf"]) else: #Use default setting set_bin_files(data_files) From 885fbaf6bf162867699ce618ade3f00190d840b9 Mon Sep 17 00:00:00 2001 From: Dong Liu Date: Tue, 19 Jan 2016 15:05:40 +0800 Subject: [PATCH 04/14] Add osutil for FreeBSD, add net support. --- azurelinuxagent/distro/freebsd/distro.py | 2 + azurelinuxagent/distro/freebsd/osutil.py | 74 ++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 azurelinuxagent/distro/freebsd/osutil.py diff --git a/azurelinuxagent/distro/freebsd/distro.py b/azurelinuxagent/distro/freebsd/distro.py index 4a76f7d..a889b53 100644 --- a/azurelinuxagent/distro/freebsd/distro.py +++ b/azurelinuxagent/distro/freebsd/distro.py @@ -19,9 +19,11 @@ from azurelinuxagent.distro.default.distro import DefaultDistro from azurelinuxagent.distro.freebsd.resourceDisk import FreeBSDResourceDiskHandler +from azurelinuxagent.distro.freebsd.osutil import FreeBSDOSUtil class FreeBSDDistro(DefaultDistro): def __init__(self): super(FreeBSDDistro, self).__init__() + self.osutil = FreeBSDOSUtil() self.resource_disk_handler = FreeBSDResourceDiskHandler(self) diff --git a/azurelinuxagent/distro/freebsd/osutil.py b/azurelinuxagent/distro/freebsd/osutil.py new file mode 100644 index 0000000..950175b --- /dev/null +++ b/azurelinuxagent/distro/freebsd/osutil.py @@ -0,0 +1,74 @@ +# Microsoft Azure Linux Agent +# +# Copyright 2014 Microsoft Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Requires Python 2.4+ and Openssl 1.0+ + +from azurelinuxagent.distro.default.osutil import DefaultOSUtil + + +class FreeBSDOSUtil(DefaultOSUtil): + def __init__(self): + super(FreeBSDOSUtil, self).__init__() + + def get_mac_addr(self): + + return 1 + + @staticmethod + def _get_net_info(): + """ + There is no SIOCGIFCONF + on freeBSD - just parse ifconfig. + Returns strings: iface, inet4_addr, and mac + or 'None,None,None' if unable to parse. + We will sleep and retry as the network must be up. + """ + code,output=RunGetOutput("ifconfig",chk_err=False) + Log(output) + retries=10 + cmd='ifconfig | grep -A2 -B2 ether | grep -B3 inet | grep -A4 UP ' + code=1 + + while code > 0 : + if code > 0 and retries == 0: + Error("GetFreeBSDEthernetInfo - Failed to detect ethernet interface") + return None, None, None + code,output=RunGetOutput(cmd,chk_err=False) + retries-=1 + if code > 0 and retries > 0 : + Log("GetFreeBSDEthernetInfo - Error: retry ethernet detection " + str(retries)) + if retries == 9 : + c,o=RunGetOutput("ifconfig | grep -A1 -B2 ether",chk_err=False) + if c == 0: + t=o.replace('\n',' ') + t=t.split() + i=t[0][:-1] + Log(RunGetOutput('id')[1]) + Run('dhclient '+i) + time.sleep(10) + + j=output.replace('\n',' ') + j=j.split() + iface=j[0][:-1] + + for i in range(len(j)): + if j[i] == 'inet' : + inet=j[i+1] + elif j[i] == 'ether' : + mac=j[i+1] + + return iface, inet, mac + From adf778581256a4268df4a15538631ba7f9bdb88d Mon Sep 17 00:00:00 2001 From: Dong Liu Date: Tue, 19 Jan 2016 15:34:34 +0800 Subject: [PATCH 05/14] Fix route for FreeBSD. --- azurelinuxagent/distro/freebsd/osutil.py | 81 ++++++++++++++---------- 1 file changed, 47 insertions(+), 34 deletions(-) diff --git a/azurelinuxagent/distro/freebsd/osutil.py b/azurelinuxagent/distro/freebsd/osutil.py index 950175b..5a69fd2 100644 --- a/azurelinuxagent/distro/freebsd/osutil.py +++ b/azurelinuxagent/distro/freebsd/osutil.py @@ -16,16 +16,41 @@ # # Requires Python 2.4+ and Openssl 1.0+ +import azurelinuxagent.utils.shellutil as shellutil +import azurelinuxagent.logger as logger from azurelinuxagent.distro.default.osutil import DefaultOSUtil +from azurelinuxagent.exception import OSUtilError class FreeBSDOSUtil(DefaultOSUtil): def __init__(self): super(FreeBSDOSUtil, self).__init__() - def get_mac_addr(self): - - return 1 + def get_if_mac(self, ifname): + data = self._get_net_info() + if data[0] == ifname: + return data[2].replace(':', '').upper() + return None + + def get_first_if(self): + return self._get_net_info()[:2] + + def route_add(self, net, mask, gateway): + cmd = 'route add {0} {1} {2}'.format(net, gateway, mask) + return shellutil.run(cmd, chk_err=False) + + def is_missing_default_route(self): + routes = shellutil.run_get_output("netstat -rn4")[1] + for route in routes.split("\n"): + if route.startswith("0.0.0.0 ") or route.startswith("default "): + return False + return True + + def set_route_for_dhcp_broadcast(self, ifname): + return shellutil.run("route add 255.255.255.255 0.0.0.0 -ifp {0}".format(ifname), chk_err=False) + + def remove_route_for_dhcp_broadcast(self, ifname): + shellutil.run("route delete 255.255.255.255", chk_err=False) @staticmethod def _get_net_info(): @@ -36,39 +61,27 @@ class FreeBSDOSUtil(DefaultOSUtil): or 'None,None,None' if unable to parse. We will sleep and retry as the network must be up. """ - code,output=RunGetOutput("ifconfig",chk_err=False) - Log(output) - retries=10 - cmd='ifconfig | grep -A2 -B2 ether | grep -B3 inet | grep -A4 UP ' - code=1 + iface = '' + inet = '' + mac = '' - while code > 0 : - if code > 0 and retries == 0: - Error("GetFreeBSDEthernetInfo - Failed to detect ethernet interface") - return None, None, None - code,output=RunGetOutput(cmd,chk_err=False) - retries-=1 - if code > 0 and retries > 0 : - Log("GetFreeBSDEthernetInfo - Error: retry ethernet detection " + str(retries)) - if retries == 9 : - c,o=RunGetOutput("ifconfig | grep -A1 -B2 ether",chk_err=False) - if c == 0: - t=o.replace('\n',' ') - t=t.split() - i=t[0][:-1] - Log(RunGetOutput('id')[1]) - Run('dhclient '+i) - time.sleep(10) + err, output = shellutil.run_get_output('ifconfig -l ether', chk_err=False) + if err: + raise OSUtilError("Can't find ether interface:{0}".format(output)) + ifaces = output.split() + if not ifaces: + raise OSUtilError("Can't find ether interface.") + iface = ifaces[0] - j=output.replace('\n',' ') - j=j.split() - iface=j[0][:-1] + err, output = shellutil.run_get_output('ifconfig ' + iface, chk_err=False) + if err: + raise OSUtilError("Can't get info for interface:{0}".format(iface)) - for i in range(len(j)): - if j[i] == 'inet' : - inet=j[i+1] - elif j[i] == 'ether' : - mac=j[i+1] + for line in output.split('\n'): + if line.find('inet ') != -1: + inet = line.split()[1] + elif line.find('ether ') != -1: + mac = line.split()[1] + logger.verb("Interface info: ({0},{1},{2})", iface, inet, mac) return iface, inet, mac - From 042be3654b128abc30b013a59a3bb8882247243a Mon Sep 17 00:00:00 2001 From: Dong Liu Date: Tue, 19 Jan 2016 17:13:07 +0800 Subject: [PATCH 06/14] Support dvd mount for FreeBSD. --- azurelinuxagent/distro/default/osutil.py | 8 ++++---- azurelinuxagent/distro/freebsd/osutil.py | 10 ++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/azurelinuxagent/distro/default/osutil.py b/azurelinuxagent/distro/default/osutil.py index 19efd73..da4d291 100644 --- a/azurelinuxagent/distro/default/osutil.py +++ b/azurelinuxagent/distro/default/osutil.py @@ -267,7 +267,7 @@ class DefaultOSUtil(object): def get_dvd_device(self, dev_dir='/dev'): - patten=r'(sr[0-9]|hd[c-z]|cdrom[0-9])' + patten=r'(sr[0-9]|hd[c-z]|cdrom[0-9]|cd[0-9])' for dvd in [re.match(patten, dev) for dev in os.listdir(dev_dir)]: if dvd is not None: return "/dev/{0}".format(dvd.group(0)) @@ -285,7 +285,7 @@ class DefaultOSUtil(object): os.makedirs(mount_point) for retry in range(0, max_retry): - retcode = self.mount(dvd, mount_point, option="-o ro -t iso9660,udf", + retcode = self.mount(dvd, mount_point, option="-o ro -t udf,iso9660", chk_err=chk_err) if retcode == 0: logger.info("Successfully mounted dvd") @@ -338,7 +338,7 @@ class DefaultOSUtil(object): return False def mount(self, dvd, mount_point, option="", chk_err=True): - cmd = "mount {0} {1} {2}".format(dvd, option, mount_point) + cmd = "mount {0} {1} {2}".format(option, dvd, mount_point) return shellutil.run_get_output(cmd, chk_err)[0] def umount(self, mount_point, chk_err=True): @@ -492,7 +492,7 @@ class DefaultOSUtil(object): def set_dhcp_hostname(self, hostname): autosend = r'^[^#]*?send\s*host-name.*?(|gethostname[(,)])' - dhclient_files = ['/etc/dhcp/dhclient.conf', '/etc/dhcp3/dhclient.conf'] + dhclient_files = ['/etc/dhcp/dhclient.conf', '/etc/dhcp3/dhclient.conf', '/etc/dhclient.conf'] for conf_file in dhclient_files: if not os.path.isfile(conf_file): continue diff --git a/azurelinuxagent/distro/freebsd/osutil.py b/azurelinuxagent/distro/freebsd/osutil.py index 5a69fd2..cd4e0c7 100644 --- a/azurelinuxagent/distro/freebsd/osutil.py +++ b/azurelinuxagent/distro/freebsd/osutil.py @@ -52,6 +52,16 @@ class FreeBSDOSUtil(DefaultOSUtil): def remove_route_for_dhcp_broadcast(self, ifname): shellutil.run("route delete 255.255.255.255", chk_err=False) + def eject_dvd(self, chk_err=True): + return + dvd = self.get_dvd_device() + retcode = shellutil.run("cdcontrol -f {0} eject".format(dvd)) + if chk_err and retcode != 0: + raise OSUtilError("Failed to eject dvd: ret={0}".format(retcode)) + + def restart_if(self, ifname): + shellutil.run("/etc/rc.d/netif restart {0}".format(ifname)) + @staticmethod def _get_net_info(): """ From f8d57f8d6b2ac61f1755c661367cb56d0a7afc55 Mon Sep 17 00:00:00 2001 From: Dong Liu Date: Wed, 20 Jan 2016 13:24:04 +0800 Subject: [PATCH 07/14] Support dhcp, user admin for FreeBSD. --- azurelinuxagent/distro/default/osutil.py | 2 +- azurelinuxagent/distro/freebsd/osutil.py | 53 +++++++++++++++++++++++- azurelinuxagent/utils/fileutil.py | 36 +--------------- config/freebsd/waagent.conf | 2 + 4 files changed, 56 insertions(+), 37 deletions(-) diff --git a/azurelinuxagent/distro/default/osutil.py b/azurelinuxagent/distro/default/osutil.py index da4d291..1c8ccff 100644 --- a/azurelinuxagent/distro/default/osutil.py +++ b/azurelinuxagent/distro/default/osutil.py @@ -501,7 +501,7 @@ class DefaultOSUtil(object): return fileutil.update_conf_file(conf_file, 'send host-name', - 'send host-name {0}'.format(hostname)) + 'send host-name "{0}";'.format(hostname)) def restart_if(self, ifname): shellutil.run("ifdown {0} && ifup {1}".format(ifname, ifname)) diff --git a/azurelinuxagent/distro/freebsd/osutil.py b/azurelinuxagent/distro/freebsd/osutil.py index cd4e0c7..1356b38 100644 --- a/azurelinuxagent/distro/freebsd/osutil.py +++ b/azurelinuxagent/distro/freebsd/osutil.py @@ -17,6 +17,9 @@ # Requires Python 2.4+ and Openssl 1.0+ import azurelinuxagent.utils.shellutil as shellutil +import azurelinuxagent.utils.textutil as textutil +import azurelinuxagent.utils.fileutil as fileutil +import azurelinuxagent.conf as conf import azurelinuxagent.logger as logger from azurelinuxagent.distro.default.osutil import DefaultOSUtil from azurelinuxagent.exception import OSUtilError @@ -26,6 +29,51 @@ class FreeBSDOSUtil(DefaultOSUtil): def __init__(self): super(FreeBSDOSUtil, self).__init__() + def useradd(self, username, expiration=None): + """ + Create user account with 'username' + """ + userentry = self.get_userentry(username) + if userentry is not None: + logger.warn("User {0} already exists, skip useradd", username) + return + + if expiration is not None: + cmd = "pw useradd {0} -e {1} -m".format(username, expiration) + else: + cmd = "pw useradd {0} -m".format(username) + retcode, out = shellutil.run_get_output(cmd) + if retcode != 0: + raise OSUtilError(("Failed to create user account:{0}, " + "retcode:{1}, " + "output:{2}").format(username, retcode, out)) + + + def chpasswd(self, username, password, crypt_id=6, salt_len=10): + if self.is_sys_user(username): + raise OSUtilError(("User {0} is a system user. " + "Will not set passwd.").format(username)) + passwd_hash = textutil.gen_password_hash(password, crypt_id, salt_len) + cmd = "echo '{0}'|pw usermod {1} -H 0 ".format(passwd_hash, username) + ret, output = shellutil.run_get_output(cmd, log_cmd=False) + if ret != 0: + raise OSUtilError(("Failed to set password for {0}: {1}" + "").format(username, output)) + + def del_root_password(self): + try: + passwd_file_path = conf.get_passwd_file_path() + passwd_content = fileutil.read_file(passwd_file_path) + passwd = passwd_content.split('\n') + new_passwd = [x for x in passwd if not x.startswith("root:")] + new_passwd.insert(0, "root:*LOCK*:0:0::0:0:::") + fileutil.write_file(passwd_file_path, "\n".join(new_passwd)) + except IOError as e: + raise OSUtilError("Failed to delete root password:{0}".format(e)) + err, output = shellutil.run('pwd_mkdb -u root ' + passwd_file_path) + if err: + raise OSUtilError("Failed to delete root password: Failed to update password database.") + def get_if_mac(self, ifname): data = self._get_net_info() if data[0] == ifname: @@ -52,8 +100,11 @@ class FreeBSDOSUtil(DefaultOSUtil): def remove_route_for_dhcp_broadcast(self, ifname): shellutil.run("route delete 255.255.255.255", chk_err=False) + def get_dhcp_pid(self): + ret = shellutil.run_get_output("pgrep dhclient") + return ret[1] if ret[0] == 0 else None + def eject_dvd(self, chk_err=True): - return dvd = self.get_dvd_device() retcode = shellutil.run("cdcontrol -f {0} eject".format(dvd)) if chk_err and retcode != 0: diff --git a/azurelinuxagent/utils/fileutil.py b/azurelinuxagent/utils/fileutil.py index 5369a7c..82fd973 100644 --- a/azurelinuxagent/utils/fileutil.py +++ b/azurelinuxagent/utils/fileutil.py @@ -66,40 +66,6 @@ def append_file(filepath, contents, asbin=False, encoding='utf-8'): """ write_file(filepath, contents, asbin=asbin, encoding=encoding, append=True) -def replace_file(filepath, contents): - """ - Write 'contents' to 'filepath' by creating a temp file, - and replacing original. - """ - handle, temp = tempfile.mkstemp(dir=os.path.dirname(filepath)) - #if type(contents) == str: - #contents=contents.encode('latin-1') - try: - os.write(handle, contents) - except IOError as err: - logger.error('Write to file {0}, Exception is {1}', filepath, err) - return 1 - finally: - os.close(handle) - - try: - os.rename(temp, filepath) - except IOError as err: - logger.info('Rename {0} to {1}, Exception is {2}', temp, filepath, err) - logger.info('Remove original file and retry') - try: - os.remove(filepath) - except IOError as err: - logger.error('Remove {0}, Exception is {1}', temp, filepath, err) - - try: - os.rename(temp, filepath) - except IOError as err: - logger.error('Rename {0} to {1}, Exception is {2}', temp, filepath, - err) - return 1 - return 0 - def base_name(path): head, tail = os.path.split(path) @@ -156,7 +122,7 @@ def update_conf_file(path, line_start, val, chk_err=False): conf = read_file(path).split('\n') conf = [x for x in conf if not x.startswith(line_start)] conf.append(val) - replace_file(path, '\n'.join(conf)) + write_file(path, '\n'.join(conf)) def search_file(target_dir_name, target_file_name): for root, dirs, files in os.walk(target_dir_name): diff --git a/config/freebsd/waagent.conf b/config/freebsd/waagent.conf index dcf90e6..b39042e 100644 --- a/config/freebsd/waagent.conf +++ b/config/freebsd/waagent.conf @@ -65,6 +65,8 @@ OS.RootDeviceScsiTimeout=300 # If "None", the system default version is used. OS.OpensslPath=None +OS.PasswordPath=/etc/master.passwd + # If set, agent will use proxy server to access internet #HttpProxy.Host=None #HttpProxy.Port=None From c277ed5e1870bbfb8ad840fc5641899bcfea23d6 Mon Sep 17 00:00:00 2001 From: Dong Liu Date: Wed, 27 Jan 2016 14:38:24 +0800 Subject: [PATCH 08/14] Fix for del_root_password on FreeBSD. --- azurelinuxagent/distro/freebsd/osutil.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/azurelinuxagent/distro/freebsd/osutil.py b/azurelinuxagent/distro/freebsd/osutil.py index 1356b38..1e73e12 100644 --- a/azurelinuxagent/distro/freebsd/osutil.py +++ b/azurelinuxagent/distro/freebsd/osutil.py @@ -61,16 +61,7 @@ class FreeBSDOSUtil(DefaultOSUtil): "").format(username, output)) def del_root_password(self): - try: - passwd_file_path = conf.get_passwd_file_path() - passwd_content = fileutil.read_file(passwd_file_path) - passwd = passwd_content.split('\n') - new_passwd = [x for x in passwd if not x.startswith("root:")] - new_passwd.insert(0, "root:*LOCK*:0:0::0:0:::") - fileutil.write_file(passwd_file_path, "\n".join(new_passwd)) - except IOError as e: - raise OSUtilError("Failed to delete root password:{0}".format(e)) - err, output = shellutil.run('pwd_mkdb -u root ' + passwd_file_path) + err = shellutil.run('pw mod user root -w no') if err: raise OSUtilError("Failed to delete root password: Failed to update password database.") From a0362915eb0116bc6b7dccd8b07e7401c0759929 Mon Sep 17 00:00:00 2001 From: Dong Liu Date: Mon, 25 Jan 2016 15:04:36 +0800 Subject: [PATCH 09/14] Fix for memory info, cpu info, setting scsi timeout and pid checking for FreeBSD. --- azurelinuxagent/distro/default/daemon.py | 2 +- azurelinuxagent/distro/default/env.py | 2 +- azurelinuxagent/distro/default/osutil.py | 4 ++- azurelinuxagent/distro/freebsd/osutil.py | 32 ++++++++++++++++++++++-- 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/azurelinuxagent/distro/default/daemon.py b/azurelinuxagent/distro/default/daemon.py index cf9eb16..aa7f4e6 100644 --- a/azurelinuxagent/distro/default/daemon.py +++ b/azurelinuxagent/distro/default/daemon.py @@ -65,7 +65,7 @@ class DaemonHandler(object): if os.path.isfile(pid_file): pid = fileutil.read_file(pid_file) - if pid is not None and os.path.isdir(os.path.join("/proc", pid)): + if self.distro.osutil.check_pid_alive(pid): logger.info("Daemon is already running: {0}", pid) sys.exit(0) diff --git a/azurelinuxagent/distro/default/env.py b/azurelinuxagent/distro/default/env.py index 094cc2a..ce6d0be 100644 --- a/azurelinuxagent/distro/default/env.py +++ b/azurelinuxagent/distro/default/env.py @@ -84,7 +84,7 @@ class EnvHandler(object): return #The dhcp process hasn't changed since last check - if os.path.isdir(os.path.join('/proc', self.dhcpid.strip())): + if self.distro.osutil.check_pid_alive(self.dhcpid.strip()): return newpid = self.distro.osutil.get_dhcp_pid() diff --git a/azurelinuxagent/distro/default/osutil.py b/azurelinuxagent/distro/default/osutil.py index 1c8ccff..31de3dc 100644 --- a/azurelinuxagent/distro/default/osutil.py +++ b/azurelinuxagent/distro/default/osutil.py @@ -606,7 +606,7 @@ class DefaultOSUtil(object): if ret[0] == 0: return int(ret[1]) else: - raise OSUtilError("Failed to get procerssor cores") + raise OSUtilError("Failed to get processor cores") def set_admin_access_to_ip(self, dest_ip): #This root allow root to access dest_ip @@ -621,3 +621,5 @@ class DefaultOSUtil(object): shellutil.run(rm_old.format(dest_ip), chk_err=False) shellutil.run(rule.format(dest_ip)) + def check_pid_alive(self, pid): + return pid is not None and os.path.isdir(os.path.join('/proc', pid)) diff --git a/azurelinuxagent/distro/freebsd/osutil.py b/azurelinuxagent/distro/freebsd/osutil.py index 1e73e12..6aa7846 100644 --- a/azurelinuxagent/distro/freebsd/osutil.py +++ b/azurelinuxagent/distro/freebsd/osutil.py @@ -28,6 +28,7 @@ from azurelinuxagent.exception import OSUtilError class FreeBSDOSUtil(DefaultOSUtil): def __init__(self): super(FreeBSDOSUtil, self).__init__() + self._scsi_disks_timeout_set = False def useradd(self, username, expiration=None): """ @@ -92,7 +93,7 @@ class FreeBSDOSUtil(DefaultOSUtil): shellutil.run("route delete 255.255.255.255", chk_err=False) def get_dhcp_pid(self): - ret = shellutil.run_get_output("pgrep dhclient") + ret = shellutil.run_get_output("pgrep -n dhclient") return ret[1] if ret[0] == 0 else None def eject_dvd(self, chk_err=True): @@ -102,7 +103,34 @@ class FreeBSDOSUtil(DefaultOSUtil): raise OSUtilError("Failed to eject dvd: ret={0}".format(retcode)) def restart_if(self, ifname): - shellutil.run("/etc/rc.d/netif restart {0}".format(ifname)) + shellutil.run("/etc/rc.d/netif restart {0}".format(ifname), chk_err=False) + + def get_total_mem(self): + cmd = "sysctl hw.physmem |awk '{print $2}'" + ret, output = shellutil.run_get_output(cmd) + if ret == 0: + return int(output)/1024/1024 + else: + raise OSUtilError("Failed to get total memory: {0}".format(output)) + + def get_processor_cores(self): + ret, output = shellutil.run_get_output("sysctl hw.ncpu |awk '{print $2}'") + if ret: + raise OSUtilError("Failed to get processor cores.") + + return int(output) + + def set_scsi_disks_timeout(self, timeout): + if self._scsi_disks_timeout_set: + return + + ret, output = shellutil.run_get_output('sysctl kern.cam.da.default_timeout={0}'.format(timeout)) + if ret: + raise OSUtilError("Failed set SCSI disks timeout: {0}".format(output)) + self._scsi_disks_timeout_set = True + + def check_pid_alive(self, pid): + return shellutil.run('ps -p {0}'.format(pid), chk_err=False) == 0 @staticmethod def _get_net_info(): From da8afab7bea8c30c5c95c372c6b1cecdabe63015 Mon Sep 17 00:00:00 2001 From: Dong Liu Date: Tue, 26 Jan 2016 17:28:46 +0800 Subject: [PATCH 10/14] Fix DHCP in issue VNET for FreeBSD. --- azurelinuxagent/distro/freebsd/osutil.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/azurelinuxagent/distro/freebsd/osutil.py b/azurelinuxagent/distro/freebsd/osutil.py index 6aa7846..3548793 100644 --- a/azurelinuxagent/distro/freebsd/osutil.py +++ b/azurelinuxagent/distro/freebsd/osutil.py @@ -80,10 +80,11 @@ class FreeBSDOSUtil(DefaultOSUtil): return shellutil.run(cmd, chk_err=False) def is_missing_default_route(self): - routes = shellutil.run_get_output("netstat -rn4")[1] - for route in routes.split("\n"): - if route.startswith("0.0.0.0 ") or route.startswith("default "): - return False + """ + For FreeBSD, the default broadcast goes to current default gw, not a all-ones broadcast address, need to + specify the route manually to get it work in a VNET environment. + SEE ALSO: man ip(4) IP_ONESBCAST, + """ return True def set_route_for_dhcp_broadcast(self, ifname): From 5b52117f19ee9d944551207630e2a1e42839a102 Mon Sep 17 00:00:00 2001 From: Dong Liu Date: Fri, 29 Jan 2016 13:36:32 +0800 Subject: [PATCH 11/14] Fix netif restart issue for FreeBSD. --- azurelinuxagent/distro/freebsd/osutil.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/azurelinuxagent/distro/freebsd/osutil.py b/azurelinuxagent/distro/freebsd/osutil.py index 3548793..46ead9c 100644 --- a/azurelinuxagent/distro/freebsd/osutil.py +++ b/azurelinuxagent/distro/freebsd/osutil.py @@ -104,7 +104,8 @@ class FreeBSDOSUtil(DefaultOSUtil): raise OSUtilError("Failed to eject dvd: ret={0}".format(retcode)) def restart_if(self, ifname): - shellutil.run("/etc/rc.d/netif restart {0}".format(ifname), chk_err=False) + # Restart dhclient only to publish hostname + shellutil.run("/etc/rc.d/dhclient restart {0}".format(ifname), chk_err=False) def get_total_mem(self): cmd = "sysctl hw.physmem |awk '{print $2}'" From f0a41081cbbaa3d8a78a8a05da15a8c5bbb94f93 Mon Sep 17 00:00:00 2001 From: Dong Liu Date: Fri, 29 Jan 2016 15:00:25 +0800 Subject: [PATCH 12/14] Fix ssh issue for FreeBSD. --- azurelinuxagent/distro/freebsd/osutil.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/azurelinuxagent/distro/freebsd/osutil.py b/azurelinuxagent/distro/freebsd/osutil.py index 46ead9c..c453fd5 100644 --- a/azurelinuxagent/distro/freebsd/osutil.py +++ b/azurelinuxagent/distro/freebsd/osutil.py @@ -18,8 +18,6 @@ import azurelinuxagent.utils.shellutil as shellutil import azurelinuxagent.utils.textutil as textutil -import azurelinuxagent.utils.fileutil as fileutil -import azurelinuxagent.conf as conf import azurelinuxagent.logger as logger from azurelinuxagent.distro.default.osutil import DefaultOSUtil from azurelinuxagent.exception import OSUtilError @@ -30,6 +28,9 @@ class FreeBSDOSUtil(DefaultOSUtil): super(FreeBSDOSUtil, self).__init__() self._scsi_disks_timeout_set = False + def restart_ssh_service(self): + return shellutil.run('service sshd restart', chk_err=False) + def useradd(self, username, expiration=None): """ Create user account with 'username' From 78d9a9d7b1740f4c68d29888c1600f303c95f68a Mon Sep 17 00:00:00 2001 From: Dong Liu Date: Fri, 29 Jan 2016 15:28:38 +0800 Subject: [PATCH 13/14] Fix sudo for FreeBSD. --- azurelinuxagent/conf.py | 3 ++ azurelinuxagent/distro/default/osutil.py | 54 ++++++++++++--------- azurelinuxagent/distro/default/provision.py | 2 +- azurelinuxagent/distro/freebsd/osutil.py | 6 +++ config/freebsd/waagent.conf | 2 + 5 files changed, 42 insertions(+), 25 deletions(-) diff --git a/azurelinuxagent/conf.py b/azurelinuxagent/conf.py index 7921e79..1ac65cb 100644 --- a/azurelinuxagent/conf.py +++ b/azurelinuxagent/conf.py @@ -104,6 +104,9 @@ def get_home_dir(conf=__conf__): def get_passwd_file_path(conf=__conf__): return conf.get("OS.PasswordPath", "/etc/shadow") +def get_sudoers_dir(conf=__conf__): + return conf.get("OS.SudoersDir", "/etc/sudoers.d") + def get_sshd_conf_file_path(conf=__conf__): return conf.get("OS.SshdConfigPath", "/etc/ssh/sshd_config") diff --git a/azurelinuxagent/distro/default/osutil.py b/azurelinuxagent/distro/default/osutil.py index 31de3dc..3fef336 100644 --- a/azurelinuxagent/distro/default/osutil.py +++ b/azurelinuxagent/distro/default/osutil.py @@ -114,21 +114,36 @@ class DefaultOSUtil(object): raise OSUtilError(("Failed to set password for {0}: {1}" "").format(username, output)) - def conf_sudoer(self, username, nopasswd): - # for older distros create sudoers.d - if not os.path.isdir('/etc/sudoers.d/'): - # create the /etc/sudoers.d/ directory - os.mkdir('/etc/sudoers.d/') - # add the include of sudoers.d to the /etc/sudoers - sudoers = '\n' + '#includedir /etc/sudoers.d/\n' - fileutil.append_file('/etc/sudoers', sudoers) - sudoer = None - if nopasswd: - sudoer = "{0} ALL = (ALL) NOPASSWD\n".format(username) + def conf_sudoer(self, username, nopasswd=False, remove=False): + sudoers_dir = conf.get_sudoers_dir() + sudoers_wagent = os.path.join(sudoers_dir, 'waagent') + + if not remove: + # for older distros create sudoers.d + if not os.path.isdir(sudoers_dir): + sudoers_file = os.path.join(sudoers_dir, '../sudoers') + # create the sudoers.d directory + os.mkdir(sudoers_dir) + # add the include of sudoers.d to the /etc/sudoers + sudoers = '\n#includedir ' + sudoers_dir + '\n' + fileutil.append_file(sudoers_file, sudoers) + sudoer = None + if nopasswd: + sudoer = "{0} ALL=(ALL) NOPASSWD: ALL\n".format(username) + else: + sudoer = "{0} ALL=(ALL) ALL\n".format(username) + fileutil.append_file(sudoers_wagent, sudoer) + fileutil.chmod(sudoers_wagent, 0o440) else: - sudoer = "{0} ALL = (ALL) ALL\n".format(username) - fileutil.append_file('/etc/sudoers.d/waagent', sudoer) - fileutil.chmod('/etc/sudoers.d/waagent', 0o440) + #Remove user from sudoers + if os.path.isfile(sudoers_wagent): + try: + content = fileutil.read_file(sudoers_wagent) + sudoers = content.split("\n") + sudoers = [x for x in sudoers if username not in x] + fileutil.write_file(sudoers_wagent, "\n".join(sudoers)) + except IOError as e: + raise OSUtilError("Failed to remove sudoer: {0}".format(e)) def del_root_password(self): try: @@ -579,16 +594,7 @@ class DefaultOSUtil(object): logger.error("{0} is a system user. Will not delete it.", username) shellutil.run("> /var/run/utmp") shellutil.run("userdel -f -r " + username) - #Remove user from suders - if os.path.isfile("/etc/suders.d/waagent"): - try: - content = fileutil.read_file("/etc/sudoers.d/waagent") - sudoers = content.split("\n") - sudoers = [x for x in sudoers if username not in x] - fileutil.write_file("/etc/sudoers.d/waagent", - "\n".join(sudoers)) - except IOError as e: - raise OSUtilError("Failed to remove sudoer: {0}".format(e)) + self.conf_sudoer(username, remove=True) def decode_customdata(self, data): return base64.b64decode(data) diff --git a/azurelinuxagent/distro/default/provision.py b/azurelinuxagent/distro/default/provision.py index 695b82a..ae2951d 100644 --- a/azurelinuxagent/distro/default/provision.py +++ b/azurelinuxagent/distro/default/provision.py @@ -122,7 +122,7 @@ class ProvisionHandler(object): crypt_id=crypt_id, salt_len=salt_len) logger.info("Configure sudoer") - self.distro.osutil.conf_sudoer(ovfenv.username, ovfenv.user_password is None) + self.distro.osutil.conf_sudoer(ovfenv.username, nopasswd=ovfenv.user_password is None) logger.info("Configure sshd") self.distro.osutil.conf_sshd(ovfenv.disable_ssh_password_auth) diff --git a/azurelinuxagent/distro/freebsd/osutil.py b/azurelinuxagent/distro/freebsd/osutil.py index c453fd5..0663f23 100644 --- a/azurelinuxagent/distro/freebsd/osutil.py +++ b/azurelinuxagent/distro/freebsd/osutil.py @@ -50,6 +50,12 @@ class FreeBSDOSUtil(DefaultOSUtil): "retcode:{1}, " "output:{2}").format(username, retcode, out)) + def del_account(self, username): + if self.is_sys_user(username): + logger.error("{0} is a system user. Will not delete it.", username) + shellutil.run('> /var/run/utx.active') + shellutil.run('rmuser -y ' + username) + self.conf_sudoer(username, remove=True) def chpasswd(self, username, password, crypt_id=6, salt_len=10): if self.is_sys_user(username): diff --git a/config/freebsd/waagent.conf b/config/freebsd/waagent.conf index b39042e..441bcc7 100644 --- a/config/freebsd/waagent.conf +++ b/config/freebsd/waagent.conf @@ -67,6 +67,8 @@ OS.OpensslPath=None OS.PasswordPath=/etc/master.passwd +OS.SudoersDir=/usr/local/etc/sudoers.d + # If set, agent will use proxy server to access internet #HttpProxy.Host=None #HttpProxy.Port=None From e522afc3070f5e268aed69d8ffae9cc1f00dbc56 Mon Sep 17 00:00:00 2001 From: Dong Liu Date: Fri, 29 Jan 2016 17:16:00 +0800 Subject: [PATCH 14/14] Add service script for FreeBSD. --- azurelinuxagent/distro/freebsd/osutil.py | 11 ++++++++--- init/freebsd/waagent | 18 ++++++++++++++++++ setup.py | 7 ++++++- 3 files changed, 32 insertions(+), 4 deletions(-) create mode 100755 init/freebsd/waagent diff --git a/azurelinuxagent/distro/freebsd/osutil.py b/azurelinuxagent/distro/freebsd/osutil.py index 0663f23..fa19a64 100644 --- a/azurelinuxagent/distro/freebsd/osutil.py +++ b/azurelinuxagent/distro/freebsd/osutil.py @@ -117,9 +117,11 @@ class FreeBSDOSUtil(DefaultOSUtil): def get_total_mem(self): cmd = "sysctl hw.physmem |awk '{print $2}'" ret, output = shellutil.run_get_output(cmd) - if ret == 0: + if ret: + raise OSUtilError("Failed to get total memory: {0}".format(output)) + try: return int(output)/1024/1024 - else: + except ValueError: raise OSUtilError("Failed to get total memory: {0}".format(output)) def get_processor_cores(self): @@ -127,7 +129,10 @@ class FreeBSDOSUtil(DefaultOSUtil): if ret: raise OSUtilError("Failed to get processor cores.") - return int(output) + try: + return int(output) + except ValueError: + raise OSUtilError("Failed to get total memory: {0}".format(output)) def set_scsi_disks_timeout(self, timeout): if self._scsi_disks_timeout_set: diff --git a/init/freebsd/waagent b/init/freebsd/waagent new file mode 100755 index 0000000..99ddef7 --- /dev/null +++ b/init/freebsd/waagent @@ -0,0 +1,18 @@ +#!/bin/sh + +# PROVIDE: waagent +# REQUIRE: sshd netif dhclient +# KEYWORD: nojail + +. /etc/rc.subr + +PATH=$PATH:/usr/local/bin +name="waagent" +rcvar="waagent_enable" +pidfile="/var/run/waagent.pid" +command="/usr/local/sbin/${name}" +command_interpreter="python" +command_args="start" + +load_rc_config $name +run_rc_command "$1" diff --git a/setup.py b/setup.py index 8c8501e..1291b66 100755 --- a/setup.py +++ b/setup.py @@ -51,6 +51,10 @@ def set_systemd_files(data_files, dest="/lib/systemd/system", src=["init/waagent.service"]): data_files.append((dest, src)) +def set_rc_files(data_files, dest="/etc/rc.d/", src=["init/freebsd/waagent"]): + data_files.append((dest, src)) + + def get_data_files(name, version, fullname): """ Determine data_files according to distro name, version and init system type @@ -107,8 +111,9 @@ def get_data_files(name, version, fullname): #sles 12+ and openSUSE 13.2+ use systemd set_systemd_files(data_files, dest='/usr/lib/systemd/system') elif name == 'freebsd': - set_bin_files(data_files) + set_bin_files(data_files, dest="/usr/local/sbin") set_conf_files(data_files, src=["config/freebsd/waagent.conf"]) + set_rc_files(data_files) else: #Use default setting set_bin_files(data_files)