Merge lp:~kaihuan-pkh/cloud-init/cloud-init into lp:~cloud-init-dev/cloud-init/trunk

Proposed by lawrence peng
Status: Merged
Approved by: Scott Moser
Approved revision: 1162
Merge reported by: Scott Moser
Merged at revision: not available
Proposed branch: lp:~kaihuan-pkh/cloud-init/cloud-init
Merge into: lp:~cloud-init-dev/cloud-init/trunk
Diff against target: 148 lines (+119/-3)
3 files modified
cloudinit/distros/__init__.py (+1/-1)
cloudinit/sources/DataSourceAliYun.py (+112/-0)
cloudinit/user_data.py (+6/-2)
To merge this branch: bzr merge lp:~kaihuan-pkh/cloud-init/cloud-init
Reviewer Review Type Date Requested Status
cloud-init Commiters Pending
Review via email: mp+284627@code.launchpad.net

Description of the change

add the support for the AliCloud

To post a comment you must log in.
Revision history for this message
Scott Moser (smoser) wrote :

Lawrence,
Sorry for just seeing this now.

Over all comment, is that you will need to sign the contributors agreement at http://www.ubuntu.com/legal/contributors . Please feel free to ping me in IRC (freenode 'smoser') or in email if you have further questions.

Second, how does this differe from the EC2 MD ?
Is it only in the base_url ?

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

Hi, Scott :
I signed the contributors agreement.
the previous merging request (284627)  is just add one file ( cloudinit/sources/DataSourceAliYun.py ),which we copied from ec2 datasource and change the DEF_MD_URL to our testing environment.
from the day i push that commit to now, we have more changes on cloud-init (but have not yet push to launchpad site for now ) , the main changes including:
1.  add some new config modules in cloudinit/config/2.  add some distro support in cloudinit/distros/3.  change the aliyun datasource DEF_MD_URL again4.  some bug fix
now, our local devel branch is almostly complete, and we are in process of testing.  we will push a new merge request in later when it passed test.
by the way, we are design cloud-init self-upgrade plan, do you have some suggest ?
thx.

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

if the DataSourceAliYun datasource in fact is just a Ec2DataSource except with the DEF_MD_URL changed then can we just inherit from the Ec2 and change the things that are needed ?

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

Yes, I agree with you, so on the next commit i will change the code construction of the DataSourceAliYun.py,  it won't be too long.

1159. By kaihuan-pkh <email address hidden>

bug fix for user_data.py

in _do_include:

when one url requests timeout, it will raise a exception and break the execution of cloudinit

1160. By kaihuan-pkh <email address hidden>

bug fix for distro/__init__.py

in get_primary_arch:
 os.uname is a function

1161. By kaihuan-pkh <email address hidden>

1. change default metaserver address
2. make DataSourceAliYun inherit from EC2.DataSourceEc2

Revision history for this message
Joshua Harlow (harlowja) :
1162. By kaihuan-pkh <email address hidden>

simplify get_public_ssh_keys

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

hi,

I put some comments inline. I'd like to get this in.

We have moved development to git now. Information is available
https://git.launchpad.net/cloud-init/tree/HACKING.rst

If you want to continue on here, we can, but ultimately we'll have to get it into the git branch.

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'cloudinit/distros/__init__.py'
2--- cloudinit/distros/__init__.py 2016-07-14 02:10:22 +0000
3+++ cloudinit/distros/__init__.py 2016-07-25 04:31:42 +0000
4@@ -112,7 +112,7 @@
5 raise NotImplementedError()
6
7 def get_primary_arch(self):
8- arch = os.uname[4]
9+ arch = os.uname()[4]
10 if arch in ("i386", "i486", "i586", "i686"):
11 return "i386"
12 return arch
13
14=== added file 'cloudinit/sources/DataSourceAliYun.py'
15--- cloudinit/sources/DataSourceAliYun.py 1970-01-01 00:00:00 +0000
16+++ cloudinit/sources/DataSourceAliYun.py 2016-07-25 04:31:42 +0000
17@@ -0,0 +1,112 @@
18+# vi: ts=4 expandtab
19+#
20+# Copyright (C) 2009-2010 Canonical Ltd.
21+# Copyright (C) 2012 Hewlett-Packard Development Company, L.P.
22+# Copyright (C) 2012 Yahoo! Inc.
23+#
24+# Author: Scott Moser <scott.moser@canonical.com>
25+# Author: Juerg Hafliger <juerg.haefliger@hp.com>
26+# Author: Joshua Harlow <harlowja@yahoo-inc.com>
27+#
28+# This program is free software: you can redistribute it and/or modify
29+# it under the terms of the GNU General Public License version 3, as
30+# published by the Free Software Foundation.
31+#
32+# This program is distributed in the hope that it will be useful,
33+# but WITHOUT ANY WARRANTY; without even the implied warranty of
34+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35+# GNU General Public License for more details.
36+#
37+# You should have received a copy of the GNU General Public License
38+# along with this program. If not, see <http://www.gnu.org/licenses/>.
39+
40+import os
41+import time
42+from copy import deepcopy
43+
44+from cloudinit import ec2_utils as ec2
45+from cloudinit import log as logging
46+from cloudinit import sources
47+from cloudinit import url_helper as uhelp
48+from cloudinit import util
49+from cloudinit.sources import DataSourceEc2 as EC2
50+
51+LOG = logging.getLogger(__name__)
52+
53+DEF_MD_URL = "http://100.100.100.200"
54+
55+DEF_MD_VERSION = 'latest'
56+
57+# Default metadata urls that will be used if none are provided
58+# They will be checked for 'resolveability' and some of the
59+# following may be discarded if they do not resolve
60+DEF_MD_URLS = [DEF_MD_URL,]
61+
62+
63+class DataSourceAliYun(EC2.DataSourceEc2):
64+ EC2.DEF_MD_URL = DEF_MD_URL
65+ EC2.DEF_MD_URLS = DEF_MD_URLS
66+
67+ def __init__(self, sys_cfg, distro, paths):
68+ super(DataSourceAliYun, self).__init__(sys_cfg, distro, paths)
69+ self.metadata_address = DEF_MD_URL
70+ self.seed_dir = os.path.join(paths.seed_dir, "AliYun")
71+ self.api_ver = DEF_MD_VERSION
72+
73+ def get_instance_id(self):
74+ if not self.metadata:
75+ url = uhelp.combine_url(self.metadata_address, self.api_ver, 'meta-data/', 'instance-id')
76+ try:
77+ out = util.read_file_or_url(url=url, ssl_details=None, timeout=5, retries=5)
78+ except Exception as e:
79+ out = ''
80+ finally:
81+ return str(out).strip()
82+ else:
83+ return self.metadata.get('instance-id', '')
84+
85+ def get_hostname(self, fqdn=False, _resolve_ip=False):
86+ return self.metadata.get('hostname', 'localhost.localdomain')
87+
88+ def get_public_ssh_keys(self):
89+ if not self.metadata:
90+ return []
91+ public_keys = self.metadata.get('public-keys', {})
92+
93+ keys = []
94+ for key_id, key_body in public_keys.items():
95+ if isinstance(key_body, (str, basestring)):
96+ keys.append( key_body.strip() )
97+ elif isinstance(key_body, list):
98+ keys.extend( key_body )
99+ elif isinstance(key_body, dict):
100+ key = key_body.get('openssh-key', [])
101+ if isinstance(key, str):
102+ keys.append( key.strip() )
103+ elif isinstance(key, list):
104+ keys.extend(key)
105+ return keys
106+
107+ def get_ntp_conf(self):
108+ if not self.metadata:
109+ return {}
110+ return self.metadata.get('ntp-conf')
111+
112+ def get_source_address(self):
113+ if not self.metadata or not self.metadata.get('source-address'):
114+ return []
115+ source_address = self.metadata.get('source-address')
116+ if isinstance(source_address, str):
117+ source_address = [source_address]
118+ return source_address
119+
120+
121+# Used to match classes to dependencies
122+datasources = [
123+ (DataSourceAliYun, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
124+]
125+
126+
127+# Return a list of data sources that match this set of dependencies
128+def get_datasource_list(depends):
129+ return sources.list_from_depends(depends, datasources)
130
131=== modified file 'cloudinit/user_data.py'
132--- cloudinit/user_data.py 2016-06-21 20:27:02 +0000
133+++ cloudinit/user_data.py 2016-07-25 04:31:42 +0000
134@@ -233,8 +233,12 @@
135 if include_once_on and os.path.isfile(include_once_fn):
136 content = util.load_file(include_once_fn)
137 else:
138- resp = util.read_file_or_url(include_url,
139- ssl_details=self.ssl_details)
140+ try:
141+ resp = util.read_file_or_url(include_url,
142+ ssl_details=self.ssl_details)
143+ except Exception as e:
144+ LOG.warn("Fetching from %s resulted in exception happend" % include_url)
145+ continue
146 if include_once_on and resp.ok():
147 util.write_file(include_once_fn, resp.contents, mode=0o600)
148 if resp.ok():