Merge ~smoser/cloud-init:aliyun-datasource into ~kaihuan-pkh/cloud-init:aliyun-datasource

Proposed by Scott Moser
Status: Merged
Approved by: lawrence peng
Approved revision: 1f73d4ed753d0310c4743d82f6666d427cf33ca6
Merge reported by: Scott Moser
Merged at revision: 1f73d4ed753d0310c4743d82f6666d427cf33ca6
Proposed branch: ~smoser/cloud-init:aliyun-datasource
Merge into: ~kaihuan-pkh/cloud-init:aliyun-datasource
Diff against target: 177 lines (+21/-78)
3 files modified
cloudinit/sources/DataSourceAliYun.py (+12/-67)
cloudinit/sources/DataSourceEc2.py (+8/-10)
tests/unittests/test_datasource/test_aliyun.py (+1/-1)
Reviewer Review Type Date Requested Status
lawrence peng Approve
Review via email: mp+309614@code.launchpad.net

Description of the change

Hi,

I've made some changes here locally, and they seem to work fine.

For a squashed commit message, i suggest:

   AliYun: Add new datasource for Ali-Cloud ECS

   Support AliYun(Ali-Cloud ECS). This datasource inherits from EC2,
   the main difference is the meta-server address is changed to
   100.100.100.200.

   The datasource behaves similarly to EC2 and relies on network polling.
   As such, it is not enabled by default.

To post a comment you must log in.
Revision history for this message
lawrence peng (kaihuan-pkh) :
review: Approve
Revision history for this message
lawrence peng (kaihuan-pkh) :
review: Approve
Revision history for this message
lawrence peng (kaihuan-pkh) wrote :

hi smoser,

I have reviewed your changes and run `make test` passed. but I have some questions:

1. how to make this request (https://code.launchpad.net/~smoser/cloud-init/+git/cloud-init/+merge/309614) merged to my branch automatically ? I found the only one thing I can do is just change the status from 'needs review' to 'approved' or others. If I change the status to 'merged' but nothing happend, so maybe it's not like github ? if I want to do the real merge to my code, what should I do ?

2. my merge request (https://code.launchpad.net/~kaihuan-pkh/cloud-init/+git/cloud-init/+merge/308483) is now status changed to merged, then I found the master commit is some different with my local branch changes, it added your work; but as question 1 said, my branch is not changed, how it happend ?

3. I found my code not enable DataSourceAliYun by default (it's a mistake), and I wish it could be used like other datasources, so I need add it to cloudinit/settings.py, if I add it to my local branch, should I merge your commit first ? and what sequence to put 'AliYun' insert into settings.py:datasource_list ?

Revision history for this message
Scott Moser (smoser) wrote :

On Wed, 2 Nov 2016, lawrence peng wrote:

> hi smoser,
>
>
> I have reviewed your changes and run `make test` passed. but I have some questions:
>
> 1. how to make this request (https://code.launchpad.net/~smoser/cloud-init/+git/cloud-init/+merge/309614) merged to my branch automatically ? I found the only one thing I can do is just change the status from 'needs review' to 'approved' or others. If I change the status to 'merged' but nothing happend, so maybe it's not like github ? if I want to do the real merge to my code, what should I do ?

launchpad doesn't have any push-button "merge" support. I marked both
branches as 'merged', and then rebased and "squashed" your change to go on
master and merged it. And then pushed to master.

Then, because the commit is different you have to also actually tell
launchpad what commit *was* the one that was merged. You don't have to do
this, but I often to just for completeness.

I generally prefer this method as I think it makes the history more
correct, and gives one sane commit message on the change. I could have
just done a 'git merge' from your branch and then launchpad would have
recognized the branch was merged, but all your intermediate commits would
show in 'git log'.

> 2. my merge request (https://code.launchpad.net/~kaihuan-pkh/cloud-init/+git/cloud-init/+merge/308483) is now status changed to merged, then I found the master commit is some different with my local branch changes, it added your work; but as question 1 said, my branch is not changed, how it happend ?

Yeah, you have to merge yourself and push, or do something and manually
mark as 'merged.

>
> 3. I found my code not enable DataSourceAliYun by default (it's a
> mistake), and I wish it could be used like other datasources, so I need
> add it to cloudinit/settings.py, if I add it to my local branch, should
> I merge your commit first ? and what sequence to put 'AliYun' insert
> into settings.py:datasource_list ?

Well, we can't really enable your datasource by default. This is
unfortunate, but polling on network locations is not really ideal.
Currently the only datasource that is enabled by default that does this is
EC2, and that is really only for legacy reasons.

In order to enable the datasource by default, we need to have a way to
identify without network that this instance is on AliYun. Many of the
other cloud providers provide a smbios identification, or some other way
that we definitively determine that we are on that cloud. Then, if we
don't see that we get out fast without the network polling.

Scott

Revision history for this message
lawrence peng (kaihuan-pkh) wrote :

> > 3. I found my code not enable DataSourceAliYun by default (it's a
> > mistake), and I wish it could be used like other datasources, so I need
> > add it to cloudinit/settings.py, if I add it to my local branch, should
> > I merge your commit first ? and what sequence to put 'AliYun' insert
> > into settings.py:datasource_list ?
>
> Well, we can't really enable your datasource by default. This is
> unfortunate, but polling on network locations is not really ideal.
> Currently the only datasource that is enabled by default that does this is
> EC2, and that is really only for legacy reasons.
>
> In order to enable the datasource by default, we need to have a way to
> identify without network that this instance is on AliYun. Many of the
> other cloud providers provide a smbios identification, or some other way
> that we definitively determine that we are on that cloud. Then, if we
> don't see that we get out fast without the network polling.
>
> Scott

so I think the primary reason is that cloud-init will block a long time when call datesource's get_data() method if it's use network ?

in our cloud platform, an instance vm could use an asm instructions `cpuid` (with eax setted to 0x40000100 ), it will returned our platform id keyword "AliYun" into register ebx and ecx, and if vm is not running on our environment, the value is others. so I guess this is a method to identify our platform ?

if I change DataSourceAliYun: get_date() method, first I use the method above to detect the evironment, if it is on AliYun, then I could call the super class (ec2) get_date() to fetch meta-date from our meta-server by network. do this ok ?

Revision history for this message
Scott Moser (smoser) wrote :

Yeah, that sounds great.
Please make sure it will work (or return without exception) on non Intel arch. And really don't want to pick up a dependency for this.

Thanks!

On November 3, 2016 4:24:25 AM EDT, lawrence peng <email address hidden> wrote:
>> > 3. I found my code not enable DataSourceAliYun by default (it's a
>> > mistake), and I wish it could be used like other datasources, so I
>need
>> > add it to cloudinit/settings.py, if I add it to my local branch,
>should
>> > I merge your commit first ? and what sequence to put 'AliYun'
>insert
>> > into settings.py:datasource_list ?
>>
>> Well, we can't really enable your datasource by default. This is
>> unfortunate, but polling on network locations is not really ideal.
>> Currently the only datasource that is enabled by default that does
>this is
>> EC2, and that is really only for legacy reasons.
>>
>> In order to enable the datasource by default, we need to have a way
>to
>> identify without network that this instance is on AliYun. Many of
>the
>> other cloud providers provide a smbios identification, or some other
>way
>> that we definitively determine that we are on that cloud. Then, if
>we
>> don't see that we get out fast without the network polling.
>>
>> Scott
>
>so I think the primary reason is that cloud-init will block a long time
>when call datesource's get_data() method if it's use network ?
>
>in our cloud platform, an instance vm could use an asm instructions
>`cpuid` (with eax setted to 0x40000100 ), it will returned our
>platform id keyword "AliYun" into register ebx and ecx, and if vm is
>not running on our environment, the value is others. so I guess this
>is a method to identify our platform ?
>
>if I change DataSourceAliYun: get_date() method, first I use the method
>above to detect the evironment, if it is on AliYun, then I could call
>the super class (ec2) get_date() to fetch meta-date from our
>meta-server by network. do this ok ?
>
>
>
>
>
>--
>https://code.launchpad.net/~smoser/cloud-init/+git/cloud-init/+merge/309614
>You are the owner of ~smoser/cloud-init:aliyun-datasource.

Revision history for this message
Scott Moser (smoser) wrote :

I opened bug 1638931 to track the enabling of the datasource.

Lets move any further conversation there.

Thanks Lawrence.

There was an error fetching revisions from git servers. Please try again in a few minutes. If the problem persists, contact Launchpad support.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/cloudinit/sources/DataSourceAliYun.py b/cloudinit/sources/DataSourceAliYun.py
2index 23a65b7..1995721 100644
3--- a/cloudinit/sources/DataSourceAliYun.py
4+++ b/cloudinit/sources/DataSourceAliYun.py
5@@ -1,75 +1,21 @@
6 # vi: ts=4 expandtab
7
8 import os
9-import time
10
11-from cloudinit import log as logging
12 from cloudinit import sources
13-from cloudinit import url_helper as uhelp
14-from cloudinit import util
15-
16 from cloudinit.sources import DataSourceEc2 as EC2
17
18-LOG = logging.getLogger(__name__)
19-
20-DEF_MD_URL = "http://100.100.100.200"
21-
22 DEF_MD_VERSION = "2016-01-01"
23
24-# Default metadata urls that will be used if none are provided
25-# They will be checked for 'resolveability' and some of the
26-# following may be discarded if they do not resolve
27-DEF_MD_URLS = [DEF_MD_URL, ]
28-
29
30 class DataSourceAliYun(EC2.DataSourceEc2):
31+ metadata_urls = ["http://100.100.100.200"]
32+
33 def __init__(self, sys_cfg, distro, paths):
34 super(DataSourceAliYun, self).__init__(sys_cfg, distro, paths)
35- self.metadata_address = DEF_MD_URL
36 self.seed_dir = os.path.join(paths.seed_dir, "AliYun")
37 self.api_ver = DEF_MD_VERSION
38
39- def wait_for_metadata_service(self):
40- mcfg = self.ds_cfg
41-
42- (max_wait, timeout) = self._get_url_settings()
43- if max_wait <= 0:
44- return False
45-
46- # Remove addresses from the list that wont resolve.
47- mdurls = mcfg.get("metadata_urls", DEF_MD_URLS)
48- filtered = [x for x in mdurls if util.is_resolvable_url(x)]
49-
50- if set(filtered) != set(mdurls):
51- LOG.debug("Removed the following from metadata urls: %s",
52- list((set(mdurls) - set(filtered))))
53-
54- if len(filtered):
55- mdurls = filtered
56- else:
57- LOG.warn("Empty metadata url list! using default list")
58- mdurls = DEF_MD_URLS
59-
60- urls = []
61- url2base = {}
62- for url in mdurls:
63- cur = "%s/%s/meta-data/instance-id" % (url, self.api_ver)
64- urls.append(cur)
65- url2base[cur] = url
66-
67- start_time = time.time()
68- url = uhelp.wait_for_url(urls=urls, max_wait=max_wait,
69- timeout=timeout, status_cb=LOG.warn)
70-
71- if url:
72- LOG.debug("Using metadata source: '%s'", url2base[url])
73- else:
74- LOG.critical("Giving up on md from %s after %s seconds",
75- urls, int(time.time() - start_time))
76-
77- self.metadata_address = url2base.get(url)
78- return bool(url)
79-
80 def get_hostname(self, fqdn=False, _resolve_ip=False):
81 return self.metadata.get('hostname', 'localhost.localdomain')
82
83@@ -77,17 +23,6 @@ class DataSourceAliYun(EC2.DataSourceEc2):
84 return parse_public_keys(self.metadata.get('public-keys', {}))
85
86
87-# Used to match classes to dependencies
88-datasources = [
89- (DataSourceAliYun, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
90-]
91-
92-
93-# Return a list of data sources that match this set of dependencies
94-def get_datasource_list(depends):
95- return sources.list_from_depends(depends, datasources)
96-
97-
98 def parse_public_keys(public_keys):
99 keys = []
100 for key_id, key_body in public_keys.items():
101@@ -102,3 +37,13 @@ def parse_public_keys(public_keys):
102 elif isinstance(key, list):
103 keys.extend(key)
104 return keys
105+
106+# Used to match classes to dependencies
107+datasources = [
108+ (DataSourceAliYun, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
109+]
110+
111+
112+# Return a list of data sources that match this set of dependencies
113+def get_datasource_list(depends):
114+ return sources.list_from_depends(depends, datasources)
115diff --git a/cloudinit/sources/DataSourceEc2.py b/cloudinit/sources/DataSourceEc2.py
116index 6fe2a0b..bc84ef5 100644
117--- a/cloudinit/sources/DataSourceEc2.py
118+++ b/cloudinit/sources/DataSourceEc2.py
119@@ -31,21 +31,19 @@ from cloudinit import util
120
121 LOG = logging.getLogger(__name__)
122
123-DEF_MD_URL = "http://169.254.169.254"
124-
125 # Which version we are requesting of the ec2 metadata apis
126 DEF_MD_VERSION = '2009-04-04'
127
128-# Default metadata urls that will be used if none are provided
129-# They will be checked for 'resolveability' and some of the
130-# following may be discarded if they do not resolve
131-DEF_MD_URLS = [DEF_MD_URL, "http://instance-data.:8773"]
132-
133
134 class DataSourceEc2(sources.DataSource):
135+ # Default metadata urls that will be used if none are provided
136+ # They will be checked for 'resolveability' and some of the
137+ # following may be discarded if they do not resolve
138+ metadata_urls = ["http://169.254.169.254", "http://instance-data.:8773"]
139+
140 def __init__(self, sys_cfg, distro, paths):
141 sources.DataSource.__init__(self, sys_cfg, distro, paths)
142- self.metadata_address = DEF_MD_URL
143+ self.metadata_address = None
144 self.seed_dir = os.path.join(paths.seed_dir, "ec2")
145 self.api_ver = DEF_MD_VERSION
146
147@@ -106,7 +104,7 @@ class DataSourceEc2(sources.DataSource):
148 return False
149
150 # Remove addresses from the list that wont resolve.
151- mdurls = mcfg.get("metadata_urls", DEF_MD_URLS)
152+ mdurls = mcfg.get("metadata_urls", self.metadata_urls)
153 filtered = [x for x in mdurls if util.is_resolvable_url(x)]
154
155 if set(filtered) != set(mdurls):
156@@ -117,7 +115,7 @@ class DataSourceEc2(sources.DataSource):
157 mdurls = filtered
158 else:
159 LOG.warn("Empty metadata url list! using default list")
160- mdurls = DEF_MD_URLS
161+ mdurls = self.metadata_urls
162
163 urls = []
164 url2base = {}
165diff --git a/tests/unittests/test_datasource/test_aliyun.py b/tests/unittests/test_datasource/test_aliyun.py
166index d7d4e99..6f1de07 100644
167--- a/tests/unittests/test_datasource/test_aliyun.py
168+++ b/tests/unittests/test_datasource/test_aliyun.py
169@@ -66,7 +66,7 @@ class TestAliYunDatasource(test_helpers.HttprettyTestCase):
170 distro = {}
171 paths = helpers.Paths({})
172 self.ds = ay.DataSourceAliYun(cfg, distro, paths)
173- self.metadata_address = self.ds.metadata_address
174+ self.metadata_address = self.ds.metadata_urls[0]
175 self.api_ver = self.ds.api_ver
176
177 @property

Subscribers

People subscribed via source and target branches

to all changes: