summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShixin Ruan <matboy_80@aliyun.com>2019-09-18 13:15:25 +0000
committerServer Team CI Bot <josh.powers+server-team-bot@canonical.com>2019-09-18 13:15:25 +0000
commit571f7c36e89f67f4c2d1cacfd8f9269bf864d560 (patch)
treeca88604c5f74aef35455e250dc781a4c1fc62f5b
parent4df0065998961ad21a9b733fb23ae2ebd78b7380 (diff)
downloadvyos-cloud-init-571f7c36e89f67f4c2d1cacfd8f9269bf864d560.tar.gz
vyos-cloud-init-571f7c36e89f67f4c2d1cacfd8f9269bf864d560.zip
Add datasource for ZStack platform.
Zstack platform provides a AWS Ec2 metadata service, and identifies their platform to the guest by setting the 'chassis asset tag' to a string that ends with '.zstack.io'. LP: #1841181
-rw-r--r--cloudinit/apport.py1
-rw-r--r--cloudinit/sources/DataSourceEc2.py16
-rw-r--r--doc/rtd/topics/datasources.rst1
-rw-r--r--doc/rtd/topics/datasources/zstack.rst36
-rw-r--r--tests/unittests/test_datasource/test_ec2.py28
-rw-r--r--tests/unittests/test_ds_identify.py9
-rwxr-xr-xtools/ds-identify5
7 files changed, 94 insertions, 2 deletions
diff --git a/cloudinit/apport.py b/cloudinit/apport.py
index 003ff1ff..fde1f75b 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/sources/DataSourceEc2.py b/cloudinit/sources/DataSourceEc2.py
index 10107456..6c72ace2 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"
@@ -477,10 +478,16 @@ def identify_brightbox(data):
return CloudNames.BRIGHTBOX
+def identify_zstack(data):
+ if data['asset_tag'].endswith('.zstack.io'):
+ return CloudNames.ZSTACK
+
+
def identify_platform():
# identify the platform and return an entry in CloudNames.
data = _collect_platform_data()
- checks = (identify_aws, identify_brightbox, lambda x: CloudNames.UNKNOWN)
+ checks = (identify_aws, identify_brightbox, identify_zstack,
+ lambda x: CloudNames.UNKNOWN)
for checker in checks:
try:
result = checker(data)
@@ -498,6 +505,7 @@ def _collect_platform_data():
uuid: system-uuid from dmi or /sys/hypervisor
uuid_source: 'hypervisor' (/sys/hypervisor/uuid) or 'dmi'
serial: dmi 'system-serial-number' (/sys/.../product_serial)
+ asset_tag: 'dmidecode -s chassis-asset-tag'
On Ec2 instances experimentation is that product_serial is upper case,
and product_uuid is lower case. This returns lower case values for both.
@@ -520,6 +528,12 @@ def _collect_platform_data():
data['serial'] = serial.lower()
+ asset_tag = util.read_dmi_data('chassis-asset-tag')
+ if asset_tag is None:
+ asset_tag = ''
+
+ data['asset_tag'] = asset_tag.lower()
+
return data
diff --git a/doc/rtd/topics/datasources.rst b/doc/rtd/topics/datasources.rst
index 8e58be97..a337c08c 100644
--- a/doc/rtd/topics/datasources.rst
+++ b/doc/rtd/topics/datasources.rst
@@ -45,6 +45,7 @@ The following is a list of documents for each supported datasource:
datasources/oracle.rst
datasources/ovf.rst
datasources/smartos.rst
+ datasources/zstack.rst
Creation
diff --git a/doc/rtd/topics/datasources/zstack.rst b/doc/rtd/topics/datasources/zstack.rst
new file mode 100644
index 00000000..36e60ffb
--- /dev/null
+++ b/doc/rtd/topics/datasources/zstack.rst
@@ -0,0 +1,36 @@
+.. _datasource_zstack:
+
+ZStack
+======
+ZStack platform provides a AWS Ec2 metadata service, but with different datasource identity.
+More information about ZStack can be found at `ZStack <https://www.zstack.io>`__.
+
+Discovery
+---------
+To determine whether a vm running on ZStack platform, cloud-init checks DMI information
+by 'dmidecode -s chassis-asset-tag', if the output ends with '.zstack.io', it's running
+on ZStack platform:
+
+
+Metadata
+^^^^^^^^
+Same as EC2, instance metadata can be queried at
+
+::
+
+ GET http://169.254.169.254/2009-04-04/meta-data/
+ instance-id
+ local-hostname
+
+Userdata
+^^^^^^^^
+Same as EC2, instance userdata can be queried at
+
+::
+
+ GET http://169.254.169.254/2009-04-04/user-data/
+ meta_data.json
+ user_data
+ password
+
+.. vi: textwidth=78
diff --git a/tests/unittests/test_datasource/test_ec2.py b/tests/unittests/test_datasource/test_ec2.py
index 1ec8e009..6fabf258 100644
--- a/tests/unittests/test_datasource/test_ec2.py
+++ b/tests/unittests/test_datasource/test_ec2.py
@@ -662,4 +662,32 @@ class TestConvertEc2MetadataNetworkConfig(test_helpers.CiTestCase):
expected,
ec2.convert_ec2_metadata_network_config(self.network_metadata))
+
+class TesIdentifyPlatform(test_helpers.CiTestCase):
+
+ def collmock(self, **kwargs):
+ """return non-special _collect_platform_data updated with changes."""
+ unspecial = {
+ 'asset_tag': '3857-0037-2746-7462-1818-3997-77',
+ 'serial': 'H23-C4J3JV-R6',
+ 'uuid': '81c7e555-6471-4833-9551-1ab366c4cfd2',
+ 'uuid_source': 'dmi',
+ }
+ unspecial.update(**kwargs)
+ return unspecial
+
+ @mock.patch('cloudinit.sources.DataSourceEc2._collect_platform_data')
+ def test_identify_zstack(self, m_collect):
+ """zstack should be identified if cassis-asset-tag ends in .zstack.io
+ """
+ m_collect.return_value = self.collmock(asset_tag='123456.zstack.io')
+ self.assertEqual(ec2.CloudNames.ZSTACK, ec2.identify_platform())
+
+ @mock.patch('cloudinit.sources.DataSourceEc2._collect_platform_data')
+ def test_identify_zstack_full_domain_only(self, m_collect):
+ """zstack asset-tag matching should match only on full domain boundary.
+ """
+ m_collect.return_value = self.collmock(asset_tag='123456.buzzstack.io')
+ self.assertEqual(ec2.CloudNames.UNKNOWN, ec2.identify_platform())
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/test_ds_identify.py b/tests/unittests/test_ds_identify.py
index de87be29..7aeeb91c 100644
--- a/tests/unittests/test_ds_identify.py
+++ b/tests/unittests/test_ds_identify.py
@@ -609,6 +609,10 @@ class TestDsIdentify(DsIdentifyBase):
self.assertEqual(expected, [p for p in expected if p in toks],
"path did not have expected tokens")
+ def test_zstack_is_ec2(self):
+ """EC2: chassis asset tag ends with 'zstack.io'"""
+ self._test_ds_found('Ec2-ZStack')
+
class TestIsIBMProvisioning(DsIdentifyBase):
"""Test the is_ibm_provisioning method in ds-identify."""
@@ -971,8 +975,11 @@ VALID_CFG = {
{'name': 'blkid', 'ret': 2, 'out': ''},
],
'files': {ds_smartos.METADATA_SOCKFILE: 'would be a socket\n'},
+ },
+ 'Ec2-ZStack': {
+ 'ds': 'Ec2',
+ 'files': {P_CHASSIS_ASSET_TAG: '123456.zstack.io\n'},
}
-
}
# vi: ts=4 expandtab
diff --git a/tools/ds-identify b/tools/ds-identify
index 2447d14f..f76f2a6e 100755
--- a/tools/ds-identify
+++ b/tools/ds-identify
@@ -895,6 +895,11 @@ ec2_identify_platform() {
*.brightbox.com) _RET="Brightbox"; return 0;;
esac
+ local asset_tag="${DI_DMI_CHASSIS_ASSET_TAG}"
+ case "$asset_tag" in
+ *.zstack.io) _RET="ZStack"; return 0;;
+ esac
+
# AWS http://docs.aws.amazon.com/AWSEC2/
# latest/UserGuide/identify_ec2_instances.html
local uuid="" hvuuid="${PATH_SYS_HYPERVISOR}/uuid"