diff options
| author | Shixin Ruan <matboy_80@aliyun.com> | 2019-09-18 13:15:25 +0000 | 
|---|---|---|
| committer | Server Team CI Bot <josh.powers+server-team-bot@canonical.com> | 2019-09-18 13:15:25 +0000 | 
| commit | 571f7c36e89f67f4c2d1cacfd8f9269bf864d560 (patch) | |
| tree | ca88604c5f74aef35455e250dc781a4c1fc62f5b | |
| parent | 4df0065998961ad21a9b733fb23ae2ebd78b7380 (diff) | |
| download | vyos-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.py | 1 | ||||
| -rw-r--r-- | cloudinit/sources/DataSourceEc2.py | 16 | ||||
| -rw-r--r-- | doc/rtd/topics/datasources.rst | 1 | ||||
| -rw-r--r-- | doc/rtd/topics/datasources/zstack.rst | 36 | ||||
| -rw-r--r-- | tests/unittests/test_datasource/test_ec2.py | 28 | ||||
| -rw-r--r-- | tests/unittests/test_ds_identify.py | 9 | ||||
| -rwxr-xr-x | tools/ds-identify | 5 | 
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" | 
