Skip to content

Commit 539a63b

Browse files
committedJul 1, 2021
cosalib, ore: add ability to cross upload aarch64 AMIs
This adds the ability to specify an architecture to buildextend-aws so that we can upload an aarch64 AMI even if we're on x86_64. Also removes --board option from `ore aws upload` as that wasn't used for anything useful any longer.
1 parent 2b622cd commit 539a63b

File tree

8 files changed

+32
-18
lines changed

8 files changed

+32
-18
lines changed
 

‎mantle/cmd/ore/aws/upload.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ After a successful run, the final line of output will be a line of JSON describi
5050
uploadSourceObject string
5151
uploadBucket string
5252
uploadImageName string
53-
uploadBoard string
53+
uploadImageArchitecture string
5454
uploadFile string
5555
uploadDiskSizeGiB uint
5656
uploadDiskSizeInspect bool
@@ -70,7 +70,7 @@ func init() {
7070
cmdUpload.Flags().StringVar(&uploadSourceObject, "source-object", "", "'s3://' URI pointing to image data (default: same as upload)")
7171
cmdUpload.Flags().StringVar(&uploadBucket, "bucket", "", "s3://bucket/prefix/ (defaults to a regional bucket and prefix defaults to $USER/board/name)")
7272
cmdUpload.Flags().StringVar(&uploadImageName, "name", "", "name of uploaded image")
73-
cmdUpload.Flags().StringVar(&uploadBoard, "board", "amd64-usr", "board used for naming with default prefix only")
73+
cmdUpload.Flags().StringVar(&uploadImageArchitecture, "arch", "", "The target architecture for the AMI")
7474
cmdUpload.Flags().StringVar(&uploadFile, "file", "", "path to CoreOS image")
7575
cmdUpload.Flags().UintVarP(&uploadDiskSizeGiB, "disk-size-gib", "", aws.ContainerLinuxDiskSizeGiB, "AMI disk size in GiB")
7676
cmdUpload.Flags().BoolVar(&uploadDiskSizeInspect, "disk-size-inspect", false, "set AMI disk size to size of local file")
@@ -92,7 +92,7 @@ func defaultBucketNameForRegion(region string) string {
9292
// defaultBucketURL determines the location the tool should upload to.
9393
// The 'urlPrefix' parameter, if it contains a path, will override all other
9494
// arguments
95-
func defaultBucketURL(urlPrefix, imageName, board, file, region string) (*url.URL, error) {
95+
func defaultBucketURL(urlPrefix, file, region string) (*url.URL, error) {
9696
if urlPrefix == "" {
9797
urlPrefix = fmt.Sprintf("s3://%s", defaultBucketNameForRegion(region))
9898
}
@@ -108,9 +108,9 @@ func defaultBucketURL(urlPrefix, imageName, board, file, region string) (*url.UR
108108
return nil, fmt.Errorf("URL missing bucket name %v\n", urlPrefix)
109109
}
110110

111-
// if prefix not specified, default to /$USER/$BOARD/$VERSION
111+
// if prefix not specified, default to 'ami-import'
112112
if s3URL.Path == "" {
113-
s3URL.Path = fmt.Sprintf("/%s/%s/%s", os.Getenv("USER"), board, imageName)
113+
s3URL.Path = "/ami-import"
114114
}
115115

116116
if s3URL.Path[len(s3URL.Path)-1] != '/' {
@@ -171,7 +171,7 @@ func runUpload(cmd *cobra.Command, args []string) error {
171171
os.Exit(1)
172172
}
173173
} else {
174-
s3URL, err = defaultBucketURL(uploadBucket, uploadImageName, uploadBoard, uploadFile, region)
174+
s3URL, err = defaultBucketURL(uploadBucket, uploadFile, region)
175175
if err != nil {
176176
fmt.Fprintf(os.Stderr, "%v\n", err)
177177
os.Exit(1)
@@ -241,7 +241,7 @@ func runUpload(cmd *cobra.Command, args []string) error {
241241
}
242242

243243
// create AMIs and grant permissions
244-
amiID, err := API.CreateHVMImage(sourceSnapshot, uploadDiskSizeGiB, uploadAMIName, uploadAMIDescription)
244+
amiID, err := API.CreateHVMImage(sourceSnapshot, uploadDiskSizeGiB, uploadAMIName, uploadAMIDescription, uploadImageArchitecture)
245245
if err != nil {
246246
fmt.Fprintf(os.Stderr, "unable to create HVM image: %v\n", err)
247247
os.Exit(1)

‎mantle/cmd/plume/prerelease.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ func awsUploadToPartition(spec *channelSpec, part *awsPartitionSpec, imagePath s
462462

463463
plog.Printf("Creating AMIs from %v...", snapshot.SnapshotID)
464464

465-
imageID, err := api.CreateHVMImage(snapshot.SnapshotID, aws.ContainerLinuxDiskSizeGiB, imageName, imageDescription)
465+
imageID, err := api.CreateHVMImage(snapshot.SnapshotID, aws.ContainerLinuxDiskSizeGiB, imageName, imageDescription, "x86_64")
466466
if err != nil {
467467
return nil, fmt.Errorf("unable to create image: %v", err)
468468
}

‎mantle/platform/api/aws/images.go

+9-5
Original file line numberDiff line numberDiff line change
@@ -329,15 +329,18 @@ func (a *API) CreateImportRole(bucket string) error {
329329
return nil
330330
}
331331

332-
func (a *API) CreateHVMImage(snapshotID string, diskSizeGiB uint, name string, description string) (string, error) {
332+
func (a *API) CreateHVMImage(snapshotID string, diskSizeGiB uint, name string, description string, architecture string) (string, error) {
333333
var awsArch string
334-
switch runtime.GOARCH {
335-
case "amd64":
334+
if architecture == "" {
335+
architecture = runtime.GOARCH
336+
}
337+
switch architecture {
338+
case "amd64", "x86_64":
336339
awsArch = ec2.ArchitectureTypeX8664
337-
case "arm64":
340+
case "arm64", "aarch64":
338341
awsArch = ec2.ArchitectureTypeArm64
339342
default:
340-
return "", fmt.Errorf("unsupported ec2 architecture %q", runtime.GOARCH)
343+
return "", fmt.Errorf("unsupported ec2 architecture %q", architecture)
341344
}
342345

343346
return a.createImage(&ec2.RegisterImageInput{
@@ -431,6 +434,7 @@ func (a *API) createImage(params *ec2.RegisterImageInput) (string, error) {
431434
var imageID string
432435
if err == nil {
433436
imageID = *res.ImageId
437+
plog.Infof("created image %v", imageID)
434438
} else if awserr, ok := err.(awserr.Error); ok && awserr.Code() == "InvalidAMIName.Duplicate" {
435439
// The AMI already exists. Get its ID. Due to races, this
436440
// may take several attempts.

‎src/cmd-ore-wrapper

+1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ Each target has its own sub options. To access them us:
8888
help="Upload/replicate to specific regions",
8989
nargs='+')
9090
parser.add_argument("--source-region", help="Region to copy AMI from")
91+
parser.add_argument("--arch", dest="arch", help="Architecture to target")
9192

9293
parser.description = (
9394
f"'ore' interface for running ore commands for {target.upper()}"

‎src/cosalib/aws.py

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ def aws_run_ore(build, args):
125125
'--disk-size-inspect',
126126
'--delete-object'
127127
])
128+
if args.arch:
129+
ore_args.extend(['--arch', f"{args.arch}"])
128130
for user in args.grant_user:
129131
ore_args.extend(['--grant-user', user])
130132
for user in args.grant_user_snapshot:

‎src/cosalib/build.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,12 @@ def __init__(self, **kwargs):
8888
else:
8989
build = builds.get_latest()
9090

91+
self._basearch = kwargs.get("arch", None) or BASEARCH
92+
log.info("Targeting architecture: %s", self.basearch)
9193
log.info("Targeting build: %s", build)
9294
self._build_dir = builds.get_build_dir(
9395
build,
94-
basearch=kwargs.get("arch", BASEARCH)
96+
basearch=self.basearch
9597
)
9698

9799
# This is a bit subtle; but essentially, we want to verify that the
@@ -115,7 +117,8 @@ def __init__(self, **kwargs):
115117
"commit": None,
116118
"config": None,
117119
"image": None,
118-
"meta": Meta(self.workdir, build, schema=schema)
120+
"meta": Meta(self.workdir, build,
121+
basearch=self.basearch, schema=schema)
119122
}
120123

121124
os.environ['workdir'] = self._workdir
@@ -252,7 +255,8 @@ def refresh_meta(self):
252255

253256
@property
254257
def basearch(self):
255-
return self.meta.get("coreos-assembler.basearch", BASEARCH)
258+
""" get the target architecture """
259+
return self._basearch
256260

257261
def ensure_built(self):
258262
if not self.have_artifact:

‎src/cosalib/meta.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -260,15 +260,17 @@ class GenericBuildMeta(GenericMeta):
260260
"""
261261

262262
def __init__(self, workdir=None, build='latest',
263-
schema=SCHEMA_PATH):
263+
basearch=None, schema=SCHEMA_PATH):
264264
builds = Builds(workdir)
265265
if build != "latest":
266266
if not builds.has(build):
267267
raise Exception('Build was not found in builds.json')
268268
else:
269269
build = builds.get_latest()
270270

271-
self._build_dir = builds.get_build_dir(build)
271+
self._build_dir = \
272+
builds.get_build_dir(build,
273+
basearch=basearch)
272274
path = os.path.join(self._build_dir, 'meta.json')
273275
super().__init__(schema=schema, path=path)
274276

‎src/cosalib/qemuvariants.py

+1
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ def get_qemu_variant(variant, parser, kwargs={}):
132132
schema=parser.schema,
133133
variant=variant,
134134
force=parser.force,
135+
arch=parser.arch,
135136
**kwargs)
136137

137138

0 commit comments

Comments
 (0)
Please sign in to comment.