3 ##############################################################################
4 # Copyright (c) 2016 Daniel Farrell and Others. All rights reserved.
6 # This program and the accompanying materials are made available under the
7 # terms of the Eclipse Public License v1.0 which accompanies this distribution,
8 # and is available at http://www.eclipse.org/legal/epl-v10.html
9 ##############################################################################
16 from urllib2 import urlopen
19 from bs4 import BeautifulSoup
21 from requests.exceptions import HTTPError
24 sys.stderr.write("We recommend using our included Vagrant env.\n")
25 sys.stderr.write("Else, do `pip install -r requirements.txt` in a venv.\n")
29 def extract_version(url):
30 """Determine ODL version information from the ODL tarball build URL
32 :arg str url: URL of the ODL tarball build for building RPMs
35 # Version components will be added below. Patch version is always 0.
36 version = {"version_patch": "0"}
38 # Parse URL to find major and minor versions. Eg:
39 # https://nexus.opendaylight.org/content/repositories/public/org/
40 # opendaylight/integration/distribution-karaf/0.3.4-Lithium-SR4/
41 # distribution-karaf-0.3.4-Lithium-SR4.tar.gz
44 re_out = re.search(r'\d\.(\d)\.(\d)', url)
45 version["version_major"] = re_out.group(1)
46 version["version_minor"] = re_out.group(2)
48 # Add version components that need to be extracted based on type of build
49 if "autorelease" in url:
50 version = extract_autorelease_version(url, version)
51 elif "snapshot" in url:
52 version = extract_snapshot_version(url, version)
53 elif "public" or "opendaylight.release" in url:
54 version = extract_release_version(url, version)
56 raise ValueError("Unrecognized URL {}".format(url))
61 def extract_release_version(url, version):
62 """Extract package version components from release build URL
64 :arg str url: URL to release tarball
65 :arg dict version: Package version components for given distro
66 :return dict version: Version components, with additions
68 # If this version of ODL has a codename, parse it from URL. Eg:
69 # https://nexus.opendaylight.org/content/repositories/public/org/
70 # opendaylight/integration/distribution-karaf/0.3.4-Lithium-SR4/
71 # distribution-karaf-0.3.4-Lithium-SR4.tar.gz
72 # codename = Lithium-SR4
73 if int(version["version_major"]) < 7:
74 # ODL versions before Nitrogen use Karaf 3, have a codename
75 # Include "-" in codename to avoid hanging "-" when no codename
76 version["codename"] = "-" + re.search(r'0\.[0-9]+\.[0-9]+-(.*)\/',
79 # ODL versions Nitrogen and after use Karaf 4, don't have a codename
80 version["codename"] = ""
82 # Package version is assumed to be 1 for release builds
83 # TODO: Should be able to manually set this in case this is a rebuild
84 version["pkg_version"] = "1"
89 def extract_autorelease_version(url, version):
90 """Extract package version components from an autorelease build URL
92 :arg str url: URL to autorelease tarball
93 :arg dict version: Package version components for given distro
94 :return dict version: Version components, with additions
96 # If this version of ODL has a codename, parse it from URL. Eg:
97 # https://nexus.opendaylight.org/content/repositories/autorelease-1533/
98 # org/opendaylight/integration/distribution-karaf/0.4.4-Beryllium-SR4/
99 # codename = Beryllium-SR4
100 if int(version["version_major"]) < 7:
101 # ODL versions before Nitrogen use Karaf 3, have a codename
102 # Include "-" in codename to avoid hanging "-" when no codename
103 version["codename"] = "-" + re.search(r'0\.[0-9]+\.[0-9]+-(.*)\/',
106 # ODL versions Nitrogen and after use Karaf 4, don't have a codename
107 version["codename"] = ""
109 # Autorelease URLs don't include a date, parse HTML to find build date
110 # Strip distro zip/tarball archive part of URL, resulting in base URL
111 base_url = url.rpartition("/")[0]+url.rpartition("/")[1]
112 # Using bash subprocess to parse HTML and find date of build
113 # TODO: Do all of this with Python, don't spawn a bash process
114 # Set base_url as an environment var to pass it to subprocess
115 os.environ["base_url"] = base_url
116 raw_date = subprocess.Popen(
117 "curl -s $base_url | grep tar.gz -A1 | tail -n1 |"
118 "sed \"s/<td>//g\" | sed \"s/\\n//g\" | awk '{print $3,$2,$6}' ",
119 shell=True, stdout=subprocess.PIPE,
120 stdin=subprocess.PIPE).stdout.read().rstrip().strip("</td>")
121 build_date = datetime.datetime.strptime(raw_date, "%d %b %Y").strftime(
124 # Parse URL to find unique build ID. Eg:
125 # https://nexus.opendaylight.org/content/repositories/autorelease-1533/
126 # org/opendaylight/integration/distribution-karaf/0.4.4-Beryllium-SR4/
128 build_id = re.search(r'\/autorelease-([0-9]+)\/', url).group(1)
130 # Combine build date and build ID into pkg_version
131 version["pkg_version"] = "0.1." + build_date + "rel" + build_id
136 def extract_snapshot_version(url, version):
137 """Extract package version components from a snapshot build URL
139 :arg str url: URL to snapshot tarball
140 :arg dict version: Package version components for given distro
141 :return dict version: Version components, with additions
144 # All snapshot builds use SNAPSHOT codename
145 # Include "-" in codename to avoid hanging "-" when no codename
146 version["codename"] = "-SNAPSHOT"
148 # Parse URL to find build date and build ID. Eg:
149 # https://nexus.opendaylight.org/content/repositories/
150 # opendaylight.snapshot/org/opendaylight/integration/
151 # distribution-karaf/0.6.0-SNAPSHOT/
152 # distribution-karaf-0.6.0-20161201.031047-2242.tar.gz
153 # build_date = 20161201
155 re_out = re.search(r'0.[0-9]+\.[0-9]+-([0-9]+)\.[0-9]+-([0-9]+)\.', url)
156 build_date = re_out.group(1)
157 build_id = re_out.group(2)
159 # Combine build date and build ID into pkg_version
160 version["pkg_version"] = "0.1." + build_date + "snap" + build_id
165 def get_snap_url(version_major):
166 """Get the most recent snapshot build of the given ODL major version
168 :arg str version_major: ODL major version to get latest snapshot of
169 :return str snapshot_url: URL to latest snapshot tarball of ODL version
172 # Dir that contains all shapshot build dirs, varies based on Karaf 3/4
173 parent_dir_url = "https://nexus.opendaylight.org/content/repositories/" \
174 "opendaylight.snapshot/org/opendaylight/integration/{}/" \
175 .format(get_distro_name_prefix(version_major))
177 # Get HTML of dir that contains all shapshot dirs
178 parent_dir_html = urlopen(parent_dir_url).read().decode('utf-8')
180 # Get most recent minor version of the given major version
181 version_minor = max(re.findall(r'>\d\.{}\.(\d)-SNAPSHOT\/'.format(version_major),
184 # Dir that contains snapshot builds for the given major version
185 snapshot_dir_url = parent_dir_url + "0.{}.{}-SNAPSHOT/".format(
189 # Get HTML of dir that contains snapshot builds for given major version
190 snapshot_dir_html = urlopen(snapshot_dir_url).read().decode('utf-8')
192 # Find most recent URL to tarball, ie most recent snapshot build
193 return re.findall(r'href="(.*\.tar\.gz)"', snapshot_dir_html)[-1]
196 def get_sysd_commit():
197 """Get latest Int/Pack repo commit hash"""
199 int_pack_repo = "https://github.com/opendaylight/integration-packaging.git"
200 # Get the commit hash at the tip of the master branch
201 args_git = ['git', 'ls-remote', int_pack_repo, "HEAD"]
202 args_awk = ['awk', '{print $1}']
203 references = subprocess.Popen(args_git, stdout=subprocess.PIPE,
205 sysd_commit = subprocess.check_output(args_awk, stdin=references.stdout,
211 def get_java_version(version_major):
212 """Get the java_version dependency for ODL builds
214 :arg str version_major: OpenDaylight major version number
215 :return int java_version: Java version required by given ODL version
217 if int(version_major) < 5:
224 def get_changelog_date(pkg_type):
225 """Get the changelog datetime formatted for the given package type
227 :arg str pkg_type: Type of datetime formatting (rpm, deb)
228 :return str changelog_date: Date or datetime formatted for given pkg_type
230 if pkg_type == "rpm":
231 # RPMs require a date of the format "Day Month Date Year". For example:
233 return datetime.date.today().strftime("%a %b %d %Y")
234 elif pkg_type == "deb":
235 # Debs require both a date and time.
236 # Date must be of the format "Day, Date Month Year". For example:
238 date = datetime.date.today().strftime("%a, %d %b %Y")
239 # Time must be of the format "HH:MM:SS +HHMM". For example:
241 time = datetime.datetime.now(tzlocal.get_localzone()).\
242 strftime("%H:%M:%S %z")
243 return "{} {}".format(date, time)
245 raise ValueError("Unknown package type: {}".format(pkg_type))
248 def get_distro_name_prefix(version_major):
249 """Return Karaf 3 or 4-style distro name prefix based on ODL major version
251 :arg str major_version: OpenDaylight major version umber
252 :return str distro_name_style: Karaf 3 or 4-style distro name prefix
255 if int(version_major) < 7:
256 # ODL versions before Nitrogen use Karaf 3, distribution-karaf- names
257 return "distribution-karaf"
259 # ODL versions Nitrogen and after use Karaf 4, karaf- names