diff options
| -rw-r--r-- | cloudinit/sources/DataSourceOVF.py | 48 | ||||
| -rw-r--r-- | cloudinit/sources/helpers/vmware/imc/config_nic.py | 3 | ||||
| -rw-r--r-- | cloudinit/sources/helpers/vmware/imc/guestcust_error.py | 24 | ||||
| -rw-r--r-- | cloudinit/sources/helpers/vmware/imc/guestcust_event.py | 27 | ||||
| -rw-r--r-- | cloudinit/sources/helpers/vmware/imc/guestcust_state.py | 25 | ||||
| -rw-r--r-- | cloudinit/sources/helpers/vmware/imc/guestcust_util.py | 129 | 
6 files changed, 249 insertions, 7 deletions
diff --git a/cloudinit/sources/DataSourceOVF.py b/cloudinit/sources/DataSourceOVF.py index 23996b4a..fec13b93 100644 --- a/cloudinit/sources/DataSourceOVF.py +++ b/cloudinit/sources/DataSourceOVF.py @@ -34,6 +34,17 @@ from cloudinit import util  from cloudinit.sources.helpers.vmware.imc.config import Config  from cloudinit.sources.helpers.vmware.imc.config_file import ConfigFile  from cloudinit.sources.helpers.vmware.imc.config_nic import NicConfigurator +from cloudinit.sources.helpers.vmware.imc.guestcust_event import \ +    GuestCustEventEnum +from cloudinit.sources.helpers.vmware.imc.guestcust_state import \ +    GuestCustStateEnum +from cloudinit.sources.helpers.vmware.imc.guestcust_error import \ +    GuestCustErrorEnum +from cloudinit.sources.helpers.vmware.imc.guestcust_util import ( +    set_customization_status, +    get_nics_to_enable, +    enable_nics +)  LOG = logging.getLogger(__name__) @@ -73,6 +84,9 @@ class DataSourceOVF(sources.DataSource):                      self.sys_cfg, "disable_vmware_customization", True):                  deployPkgPluginPath = search_file("/usr/lib/vmware-tools",                                                    "libdeployPkgPlugin.so") +                if not deployPkgPluginPath: +                    deployPkgPluginPath = search_file("/usr/lib/open-vm-tools", +                                                      "libdeployPkgPlugin.so")                  if deployPkgPluginPath:                      vmwareImcConfigFilePath = util.log_time(                          logfunc=LOG.debug, @@ -88,19 +102,41 @@ class DataSourceOVF(sources.DataSource):                  LOG.debug("Customization for VMware platform is disabled.")          if vmwareImcConfigFilePath: +            nics = ""              try:                  cf = ConfigFile(vmwareImcConfigFilePath)                  conf = Config(cf)                  (md, ud, cfg) = read_vmware_imc(conf) -                nicConfigurator = NicConfigurator(conf.nics) -                nicConfigurator.configure() -                vmwarePlatformFound = True -            except Exception as inst: -                LOG.debug("Error while parsing the Customization " -                          "Config File: %s", inst) +                dirpath = os.path.dirname(vmwareImcConfigFilePath) +                nics = get_nics_to_enable(dirpath) +            except Exception as e: +                LOG.debug("Error parsing the customization Config File") +                LOG.exception(e) +                set_customization_status( +                    GuestCustStateEnum.GUESTCUST_STATE_RUNNING, +                    GuestCustEventEnum.GUESTCUST_EVENT_CUSTOMIZE_FAILED) +                return False              finally:                  dirPath = os.path.dirname(vmwareImcConfigFilePath)                  shutil.rmtree(dirPath) + +            try: +                LOG.debug("Applying the Network customization") +                nicConfigurator = NicConfigurator(conf.nics) +                nicConfigurator.configure() +            except Exception as e: +                LOG.debug("Error applying the Network Configuration") +                LOG.exception(e) +                set_customization_status( +                    GuestCustStateEnum.GUESTCUST_STATE_RUNNING, +                    GuestCustEventEnum.GUESTCUST_EVENT_NETWORK_SETUP_FAILED) +                return False + +            vmwarePlatformFound = True +            enable_nics(nics) +            set_customization_status( +                 GuestCustStateEnum.GUESTCUST_STATE_DONE, +                 GuestCustErrorEnum.GUESTCUST_ERROR_SUCCESS)          elif seedfile:              # Found a seed dir              seed = os.path.join(self.paths.seed_dir, seedfile) diff --git a/cloudinit/sources/helpers/vmware/imc/config_nic.py b/cloudinit/sources/helpers/vmware/imc/config_nic.py index 8c5c08cf..77098a05 100644 --- a/cloudinit/sources/helpers/vmware/imc/config_nic.py +++ b/cloudinit/sources/helpers/vmware/imc/config_nic.py @@ -205,7 +205,8 @@ class NicConfigurator:      def clear_dhcp(self):          logger.info('Clearing DHCP leases') -        util.subp(["pkill", "dhclient"]) +        # Ignore the return code 1. +        util.subp(["pkill", "dhclient"], rcs=[0, 1])          util.subp(["rm", "-f", "/var/lib/dhcp/*"])      def if_down_up(self): diff --git a/cloudinit/sources/helpers/vmware/imc/guestcust_error.py b/cloudinit/sources/helpers/vmware/imc/guestcust_error.py new file mode 100644 index 00000000..1b04161f --- /dev/null +++ b/cloudinit/sources/helpers/vmware/imc/guestcust_error.py @@ -0,0 +1,24 @@ +# vi: ts=4 expandtab
 +#
 +#    Copyright (C) 2016 Canonical Ltd.
 +#    Copyright (C) 2016 VMware Inc.
 +#
 +#    Author: Sankar Tanguturi <stanguturi@vmware.com>
 +#
 +#    This program is free software: you can redistribute it and/or modify
 +#    it under the terms of the GNU General Public License version 3, as
 +#    published by the Free Software Foundation.
 +#
 +#    This program is distributed in the hope that it will be useful,
 +#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +#    GNU General Public License for more details.
 +#
 +#    You should have received a copy of the GNU General Public License
 +#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +
 +
 +class GuestCustErrorEnum:
 +    """Specifies different errors of Guest Customization engine"""
 +
 +    GUESTCUST_ERROR_SUCCESS = 0
 diff --git a/cloudinit/sources/helpers/vmware/imc/guestcust_event.py b/cloudinit/sources/helpers/vmware/imc/guestcust_event.py new file mode 100644 index 00000000..fc22568f --- /dev/null +++ b/cloudinit/sources/helpers/vmware/imc/guestcust_event.py @@ -0,0 +1,27 @@ +# vi: ts=4 expandtab
 +#
 +#    Copyright (C) 2016 Canonical Ltd.
 +#    Copyright (C) 2016 VMware Inc.
 +#
 +#    Author: Sankar Tanguturi <stanguturi@vmware.com>
 +#
 +#    This program is free software: you can redistribute it and/or modify
 +#    it under the terms of the GNU General Public License version 3, as
 +#    published by the Free Software Foundation.
 +#
 +#    This program is distributed in the hope that it will be useful,
 +#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +#    GNU General Public License for more details.
 +#
 +#    You should have received a copy of the GNU General Public License
 +#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +
 +
 +class GuestCustEventEnum:
 +    """Specifies different types of Guest Customization Events"""
 +
 +    GUESTCUST_EVENT_CUSTOMIZE_FAILED = 100
 +    GUESTCUST_EVENT_NETWORK_SETUP_FAILED = 101
 +    GUESTCUST_EVENT_ENABLE_NICS = 103
 +    GUESTCUST_EVENT_QUERY_NICS = 104
 diff --git a/cloudinit/sources/helpers/vmware/imc/guestcust_state.py b/cloudinit/sources/helpers/vmware/imc/guestcust_state.py new file mode 100644 index 00000000..f255be5f --- /dev/null +++ b/cloudinit/sources/helpers/vmware/imc/guestcust_state.py @@ -0,0 +1,25 @@ +# vi: ts=4 expandtab
 +#
 +#    Copyright (C) 2016 Canonical Ltd.
 +#    Copyright (C) 2016 VMware Inc.
 +#
 +#    Author: Sankar Tanguturi <stanguturi@vmware.com>
 +#
 +#    This program is free software: you can redistribute it and/or modify
 +#    it under the terms of the GNU General Public License version 3, as
 +#    published by the Free Software Foundation.
 +#
 +#    This program is distributed in the hope that it will be useful,
 +#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +#    GNU General Public License for more details.
 +#
 +#    You should have received a copy of the GNU General Public License
 +#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +
 +
 +class GuestCustStateEnum:
 +    """Specifies different states of Guest Customization engine"""
 +
 +    GUESTCUST_STATE_RUNNING = 4
 +    GUESTCUST_STATE_DONE = 5
 diff --git a/cloudinit/sources/helpers/vmware/imc/guestcust_util.py b/cloudinit/sources/helpers/vmware/imc/guestcust_util.py new file mode 100644 index 00000000..b8c58f1e --- /dev/null +++ b/cloudinit/sources/helpers/vmware/imc/guestcust_util.py @@ -0,0 +1,129 @@ +# vi: ts=4 expandtab
 +#
 +#    Copyright (C) 2016 Canonical Ltd.
 +#    Copyright (C) 2016 VMware Inc.
 +#
 +#    Author: Sankar Tanguturi <stanguturi@vmware.com>
 +#
 +#    This program is free software: you can redistribute it and/or modify
 +#    it under the terms of the GNU General Public License version 3, as
 +#    published by the Free Software Foundation.
 +#
 +#    This program is distributed in the hope that it will be useful,
 +#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +#    GNU General Public License for more details.
 +#
 +#    You should have received a copy of the GNU General Public License
 +#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +
 +import logging
 +import os
 +import time
 +
 +from cloudinit import util
 +
 +from .guestcust_state import GuestCustStateEnum
 +from .guestcust_error import GuestCustErrorEnum
 +from .guestcust_event import GuestCustEventEnum
 +
 +logger = logging.getLogger(__name__)
 +
 +
 +CLOUDINIT_LOG_FILE = "/var/log/cloud-init.log"
 +QUERY_NICS_SUPPORTED = "queryNicsSupported"
 +NICS_STATUS_CONNECTED = "connected"
 +
 +
 +# This will send a RPC command to the underlying
 +# VMware Virtualization Platform.
 +def send_rpc(rpc):
 +    if not rpc:
 +        return None
 +
 +    out = ""
 +    err = "Error sending the RPC command"
 +
 +    try:
 +        logger.debug("Sending RPC command: %s", rpc)
 +        (out, err) = util.subp(["vmware-rpctool", rpc], rcs=[0])
 +        # Remove the trailing newline in the output.
 +        if out:
 +            out = out.rstrip()
 +    except Exception as e:
 +        logger.debug("Failed to send RPC command")
 +        logger.exception(e)
 +
 +    return (out, err)
 +
 +
 +# This will send the customization status to the
 +# underlying VMware Virtualization Platform.
 +def set_customization_status(custstate, custerror, errormessage=None):
 +    message = ""
 +
 +    if errormessage:
 +        message = CLOUDINIT_LOG_FILE + "@" + errormessage
 +    else:
 +        message = CLOUDINIT_LOG_FILE
 +
 +    rpc = "deployPkg.update.state %d %d %s" % (custstate, custerror, message)
 +    (out, err) = send_rpc(rpc)
 +    return (out, err)
 +
 +
 +# This will read the file nics.txt in the specified directory
 +# and return the content
 +def get_nics_to_enable(dirpath):
 +    if not dirpath:
 +        return None
 +
 +    NICS_SIZE = 1024
 +    nicsfilepath = os.path.join(dirpath, "nics.txt")
 +    if not os.path.exists(nicsfilepath):
 +        return None
 +
 +    with open(nicsfilepath, 'r') as fp:
 +        nics = fp.read(NICS_SIZE)
 +
 +    return nics
 +
 +
 +# This will send a RPC command to the underlying VMware Virtualization platform
 +# and enable nics.
 +def enable_nics(nics):
 +    if not nics:
 +        logger.warning("No Nics found")
 +        return
 +
 +    enableNicsWaitRetries = 5
 +    enableNicsWaitCount = 5
 +    enableNicsWaitSeconds = 1
 +
 +    for attempt in range(0, enableNicsWaitRetries):
 +        logger.debug("Trying to connect interfaces, attempt %d", attempt)
 +        (out, err) = set_customization_status(
 +                         GuestCustStateEnum.GUESTCUST_STATE_RUNNING,
 +                         GuestCustEventEnum.GUESTCUST_EVENT_ENABLE_NICS,
 +                         nics)
 +        if not out:
 +            time.sleep(enableNicsWaitCount * enableNicsWaitSeconds)
 +            continue
 +
 +        if out != QUERY_NICS_SUPPORTED:
 +            logger.warning("NICS connection status query is not supported")
 +            return
 +
 +        for count in range(0, enableNicsWaitCount):
 +            (out, err) = set_customization_status(
 +                             GuestCustStateEnum.GUESTCUST_STATE_RUNNING,
 +                             GuestCustEventEnum.GUESTCUST_EVENT_QUERY_NICS,
 +                             nics)
 +            if out and out == NICS_STATUS_CONNECTED:
 +                logger.info("NICS are connected on %d second", count)
 +                return
 +
 +            time.sleep(enableNicsWaitSeconds)
 +
 +    logger.warning("Can't connect network interfaces after %d attempts",
 +                   enableNicsWaitRetries)
  | 
