Steve Ruan has proposed merging ~ruansx/cloud-init:add-zstack-datasource into cloud-init:master.
Commit message: add cloud-init to detech ZStack cloud platfrom. Requested reviews: cloud-init Commiters (cloud-init-dev) For more details, see: https://code.launchpad.net/~ruansx/cloud-init/+git/cloud-init/+merge/372445 -- Your team cloud-init Commiters is requested to review the proposed merge of ~ruansx/cloud-init:add-zstack-datasource into cloud-init:master.
diff --git a/cloudinit/apport.py b/cloudinit/apport.py index 003ff1f..fde1f75 100644 --- a/cloudinit/apport.py +++ b/cloudinit/apport.py @@ -37,6 +37,7 @@ KNOWN_CLOUD_NAMES = [ 'Scaleway', 'SmartOS', 'VMware', + 'ZStack', 'Other'] # Potentially clear text collected logs diff --git a/cloudinit/settings.py b/cloudinit/settings.py index 2060d81..7e1fa06 100644 --- a/cloudinit/settings.py +++ b/cloudinit/settings.py @@ -40,6 +40,7 @@ CFG_BUILTIN = { 'IBMCloud', 'Oracle', 'Exoscale', + 'ZStack', # At the end to act as a 'catch' when none of the above work... 'None', ], diff --git a/cloudinit/sources/DataSourceEc2.py b/cloudinit/sources/DataSourceEc2.py index 5c017bf..c75bfc8 100644 --- a/cloudinit/sources/DataSourceEc2.py +++ b/cloudinit/sources/DataSourceEc2.py @@ -33,6 +33,7 @@ class CloudNames(object): ALIYUN = "aliyun" AWS = "aws" BRIGHTBOX = "brightbox" + ZStack = "zstack" # UNKNOWN indicates no positive id. If strict_id is 'warn' or 'false', # then an attempt at the Ec2 Metadata service will be made. UNKNOWN = "unknown" diff --git a/cloudinit/sources/DataSourceZStack.py b/cloudinit/sources/DataSourceZStack.py new file mode 100644 index 0000000..1c22706 --- /dev/null +++ b/cloudinit/sources/DataSourceZStack.py @@ -0,0 +1,58 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +from cloudinit import sources +from cloudinit.sources import DataSourceEc2 as EC2 +from cloudinit import util + +CHASSIS_ASSET_TAG = "ZStack Vm" + + +class DataSourceZStack(EC2.DataSourceEc2): + + dsname = 'ZStack' + + def get_hostname(self, fqdn=False, resolve_ip=False, metadata_only=False): + return self.metadata.get('hostname', 'localhost.localdomain') + + def get_public_ssh_keys(self): + return parse_public_keys(self.metadata.get('public-keys', {})) + + def _get_cloud_name(self): + if _is_zstack(): + return EC2.CloudNames.ZStack + else: + return EC2.CloudNames.NO_EC2_METADATA + + +def _is_zstack(): + asset_tag = util.read_dmi_data('chassis-asset-tag') + return asset_tag == CHASSIS_ASSET_TAG + + +def parse_public_keys(public_keys): + keys = [] + for _key_id, key_body in public_keys.items(): + if isinstance(key_body, str): + keys.append(key_body.strip()) + elif isinstance(key_body, list): + keys.extend(key_body) + elif isinstance(key_body, dict): + key = key_body.get('openssh-key', []) + if isinstance(key, str): + keys.append(key.strip()) + elif isinstance(key, list): + keys.extend(key) + return keys + + +# Used to match classes to dependencies +datasources = [ + (DataSourceZStack, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)), +] + + +# Return a list of data sources that match this set of dependencies +def get_datasource_list(depends): + return sources.list_from_depends(depends, datasources) + +# vi: ts=4 expandtab diff --git a/doc/rtd/topics/datasources.rst b/doc/rtd/topics/datasources.rst index 2148cd5..6e71cce 100644 --- a/doc/rtd/topics/datasources.rst +++ b/doc/rtd/topics/datasources.rst @@ -165,5 +165,6 @@ Follow for more information. datasources/smartos.rst datasources/fallback.rst datasources/gce.rst + datasources/zstack.rst .. vi: textwidth=78 diff --git a/doc/rtd/topics/datasources/zstack.rst b/doc/rtd/topics/datasources/zstack.rst new file mode 100644 index 0000000..996e13a --- /dev/null +++ b/doc/rtd/topics/datasources/zstack.rst @@ -0,0 +1,15 @@ +.. _datasource_zstack: + +ZStack +====== +The ``ZStack`` datasource get data from ZStack platform cloud-init service. +More information is here `ZStack <www.zstack.io>`_. + +Discovery +--------- +To determine whether a platform is ZStack, cloud-init checks the following environment + attributes as a potential OpenStack platform: + + * **DMI chassis_asset_tag** is *"ZStack Vm"* + +.. vi: textwidth=78 diff --git a/tests/unittests/test_datasource/test_common.py b/tests/unittests/test_datasource/test_common.py index 61a7a76..8d78d5a 100644 --- a/tests/unittests/test_datasource/test_common.py +++ b/tests/unittests/test_datasource/test_common.py @@ -25,6 +25,7 @@ from cloudinit.sources import ( DataSourceOVF as OVF, DataSourceScaleway as Scaleway, DataSourceSmartOS as SmartOS, + DataSourceZStack as ZStack, ) from cloudinit.sources import DataSourceNone as DSNone @@ -60,6 +61,7 @@ DEFAULT_NETWORK = [ NoCloud.DataSourceNoCloudNet, OpenStack.DataSourceOpenStack, OVF.DataSourceOVFNet, + ZStack.DataSourceZStack ] diff --git a/tests/unittests/test_ds_identify.py b/tests/unittests/test_ds_identify.py index 587e699..b46f986 100644 --- a/tests/unittests/test_ds_identify.py +++ b/tests/unittests/test_ds_identify.py @@ -13,6 +13,7 @@ from cloudinit.tests.helpers import ( from cloudinit.sources import DataSourceIBMCloud as ds_ibm from cloudinit.sources import DataSourceSmartOS as ds_smartos from cloudinit.sources import DataSourceOracle as ds_oracle +from cloudinit.sources import DataSourceZStack as ds_zstack UNAME_MYSYS = ("Linux bart 4.4.0-62-generic #83-Ubuntu " "SMP Wed Jan 18 14:10:15 UTC 2017 x86_64 GNU/Linux") @@ -655,6 +656,18 @@ class TestOracle(DsIdentifyBase): self._check_via_dict(mycfg, rc=RC_NOT_FOUND) +class TestZStack(DsIdentifyBase): + def test_found_by_chassis(self): + """Simple positive test of ZStack by chassis id.""" + self._test_ds_found('ZStack') + + def test_not_found(self): + """Simple negative test of ZStack.""" + mycfg = copy.deepcopy(VALID_CFG['ZStack']) + mycfg['files'][P_CHASSIS_ASSET_TAG] = "Not ZStack" + self._check_via_dict(mycfg, rc=RC_NOT_FOUND) + + def blkid_out(disks=None): """Convert a list of disk dictionaries into blkid content.""" if disks is None: @@ -959,6 +972,12 @@ VALID_CFG = { {'name': 'blkid', 'ret': 2, 'out': ''}, ], 'files': {ds_smartos.METADATA_SOCKFILE: 'would be a socket\n'}, + }, + 'ZStack': { + 'ds': 'ZStack', + 'files': { + P_CHASSIS_ASSET_TAG: ds_zstack.CHASSIS_ASSET_TAG + '\n', + } } } diff --git a/tools/ds-identify b/tools/ds-identify index e0d4865..daaa17b 100755 --- a/tools/ds-identify +++ b/tools/ds-identify @@ -124,7 +124,7 @@ DI_DSNAME="" # be searched if there is no setting found in config. DI_DSLIST_DEFAULT="MAAS ConfigDrive NoCloud AltCloud Azure Bigstep \ CloudSigma CloudStack DigitalOcean AliYun Ec2 GCE OpenNebula OpenStack \ -OVF SmartOS Scaleway Hetzner IBMCloud Oracle Exoscale" +OVF SmartOS Scaleway Hetzner IBMCloud Oracle Exoscale ZStack" DI_DSLIST="" DI_MODE="" DI_ON_FOUND="" @@ -1103,6 +1103,12 @@ dscheck_Oracle() { return ${DS_NOT_FOUND} } +dscheck_ZStack() { + local asset_tag="ZStack Vm" + dmi_chassis_asset_tag_matches "${asset_tag}" && return ${DS_FOUND} + return ${DS_NOT_FOUND} +} + is_ibm_provisioning() { local pcfg="${PATH_ROOT}/root/provisioningConfiguration.cfg" local logf="${PATH_ROOT}/root/swinstall.log"
_______________________________________________ Mailing list: https://launchpad.net/~cloud-init-dev Post to : cloud-init-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~cloud-init-dev More help : https://help.launchpad.net/ListHelp