1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
import subprocess
from oe.package_manager import RpmPM
from oe.package_manager import OpkgPM
from oe.package_manager import DpkgPM
from oe.utils import format_pkg_list
from oe.rootfs import image_list_installed_packages
import oe.path
import swupd.path
import swupd.utils
def create_bundle_manifest(d, bundlename, dest=None):
"""
create a bundle subscription receipt
swupd-client expects a bundle subscription to exist for each
installed bundle. This is simply an empty file named for the
bundle in /usr/share/clear/bundles
d -- the bitbake datastore
bundlename -- the name of the bundle [and the receipt file name]
dest -- the effective root location in which to create the receipt
(default IMAGE_ROOTFS)
"""
tgtpath = '/usr/share/clear/bundles'
if dest:
bundledir = dest + tgtpath
else:
bundledir = d.expand('${IMAGE_ROOTFS}%s' % tgtpath)
bb.utils.mkdirhier(bundledir)
open(os.path.join(bundledir, bundlename), 'w+b').close()
def get_bundle_packages(d, bundle):
"""
Return a list of packages included in a bundle
d -- the bitbake datastore
bundle -- the name of the bundle for which we return a package list
"""
pkgs = (d.getVarFlag('BUNDLE_CONTENTS', bundle, True) or '').split()
return pkgs
def create_content_manifest(dir, outfile, blacklist):
"""
Iterate over the content of the directory, remove entries listed in the blacklist
(for example, /etc/machine-id), and write the full paths of the remaining
entries (without leading ./ or /) to the file named in outfile. All directories
are explicitly listed.
"""
bb.debug(3, 'Creating %s from directory %s, excluding %s' % (outfile, dir, blacklist))
cwd = os.getcwd()
try:
os.chdir(dir)
with open(outfile, 'w') as f:
for root, dirs, files in os.walk('.'):
for entry in dirs + files:
# strip the leading ./
fullpath = os.path.join(root, entry)[2:]
if not ('/' + fullpath) in blacklist:
f.write(fullpath + '\n')
finally:
os.chdir(cwd)
def copy_core_contents(d):
"""
Determine the os-core contents and copy the mega image to swupd's image directory.
d -- the bitbake datastore
"""
corefile = d.expand('${SWUPDIMAGEDIR}/${OS_VERSION}/os-core${SWUPD_ROOTFS_MANIFEST_SUFFIX}')
fullfile = d.expand('${SWUPDIMAGEDIR}/${OS_VERSION}/full${SWUPD_ROOTFS_MANIFEST_SUFFIX}')
bundledir = d.expand('${SWUPDIMAGEDIR}/${OS_VERSION}/full/')
rootfs = d.getVar('IMAGE_ROOTFS', True)
# Generate a manifest of the bundle content.
bb.utils.mkdirhier(bundledir)
unwanted_files = (d.getVar('SWUPD_FILE_BLACKLIST', True) or '').split()
create_content_manifest(rootfs, corefile, unwanted_files)
havebundles = (d.getVar('SWUPD_BUNDLES', True) or '') != ''
imgrootfs = d.getVar('MEGA_IMAGE_ROOTFS', True)
if not havebundles:
imgrootfs = rootfs
manifest_files = swupd.utils.manifest_to_file_list(corefile)
with open(fullfile, 'w') as f:
f.write('\n'.join(manifest_files))
else:
create_content_manifest(imgrootfs, fullfile, unwanted_files)
manifest_files = swupd.utils.manifest_to_file_list(fullfile)
bb.debug(1, "Copying from image (%s) to full bundle dir (%s)" % (imgrootfs, bundledir))
swupd.path.copyxattrfiles(d, manifest_files, imgrootfs, bundledir)
def stage_image_bundle_contents(d, bundle):
"""
Determine bundle contents which aren't part of os-core from the mega-image rootfs
For an image-based bundle, generate a list of files which exist in the
bundle but not os-core and stage those files from the mega image rootfs to
the swupd inputs directory
d -- the bitbake datastore
bundle -- the name of the bundle to be staged
"""
# Construct paths to manifest files and directories
pn = d.getVar('PN', True)
manifest_path = d.expand('${SWUPDIMAGEDIR}/${OS_VERSION}/')
base_manifest_name = d.expand('os-core${SWUPD_ROOTFS_MANIFEST_SUFFIX}')
image_manifest_name = base_manifest_name.replace('os-core', bundle, 1)
base_manifest = manifest_path + base_manifest_name
image_manifest = manifest_path + image_manifest_name
megarootfs = d.getVar('MEGA_IMAGE_ROOTFS', True)
imagesrc = megarootfs.replace('mega', bundle)
# Generate the manifest of the bundle image's file contents,
# excluding blacklisted files and the content of the os-core.
bb.debug(3, 'Writing bundle image file manifest %s' % image_manifest)
unwanted_files = set((d.getVar('SWUPD_FILE_BLACKLIST', True) or '').split())
unwanted_files.update(['/' + x for x in swupd.utils.manifest_to_file_list(base_manifest)])
create_content_manifest(imagesrc, image_manifest, unwanted_files)
def stage_empty_bundle(d, bundle):
"""
stage an empty bundle
d -- the bitbake datastore
bundle -- the name of the bundle to be staged
"""
bundledir = d.expand('${SWUPDIMAGEDIR}/${OS_VERSION}/%s' % bundle)
bb.utils.mkdirhier(bundledir)
create_bundle_manifest(d, bundle, bundledir)
def copy_bundle_contents(d):
"""
Stage bundle contents
Copy the contents of all bundles from the mega image rootfs to the swupd
inputs directory to ensure that any image postprocessing which modifies
files is reflected in os-core bundle
d -- the bitbake datastore
"""
bb.debug(1, 'Copying contents of bundles for %s from mega image rootfs' % d.getVar('PN', True))
bundles = (d.getVar('SWUPD_BUNDLES', True) or '').split()
for bndl in bundles:
stage_image_bundle_contents(d, bndl)
bundles = (d.getVar('SWUPD_EMPTY_BUNDLES', True) or '').split()
for bndl in bundles:
stage_empty_bundle(d, bndl)
|