diff --git a/amqp_job_queue.go b/amqp_job_queue.go index 8566095c8..ce3bc5dfb 100644 --- a/amqp_job_queue.go +++ b/amqp_job_queue.go @@ -216,6 +216,7 @@ func (q *AMQPJobQueue) Jobs(ctx gocontext.Context) (outChan <-chan Job, err erro buildJob.startAttributes.VMSize = buildJob.payload.VMSize buildJob.startAttributes.VMConfig = buildJob.payload.VMConfig buildJob.startAttributes.Warmer = buildJob.payload.Warmer + buildJob.startAttributes.TamToken = buildJob.payload.TamToken buildJob.startAttributes.SetDefaults(q.DefaultLanguage, q.DefaultDist, q.DefaultArch, q.DefaultGroup, q.DefaultOS, VMTypeDefault, VMConfigDefault) buildJob.conn = q.conn buildJob.stateCount = buildJob.payload.Meta.StateUpdateCount diff --git a/backend/lxd.go b/backend/lxd.go index a9a791da4..24672a83c 100644 --- a/backend/lxd.go +++ b/backend/lxd.go @@ -509,6 +509,19 @@ func (p *lxdProvider) Start(ctx gocontext.Context, startAttributes *StartAttribu // Select the image if startAttributes.ImageName != "" { imageName = startAttributes.ImageName + } else if startAttributes.OSCustom != "" { + imageName = startAttributes.OSCustom + + var imgManager *image.Manager + imgManager, err = image.NewManager(ctx, nil, p.imageBaseURL) + if err != nil { + return nil, err + } + err = imgManager.LoadCustom(imageName, startAttributes.TamToken) + + if err != nil { + return nil, err + } } else { imageArch := startAttributes.Arch if p.archOverride != "" { @@ -724,6 +737,10 @@ func (p *lxdProvider) Start(ctx gocontext.Context, startAttributes *StartAttribu container.Devices["eth0"]["ipv4.address"] = strings.Split(address, "/")[0] + if startAttributes.OSCustom != "" { + startAttributes.Dist = "" + } + var fileName, content string switch startAttributes.Dist { case "xenial": @@ -741,7 +758,7 @@ iface eth0 inet static mtu %s `, address, p.networkGateway, strings.Join(p.networkDNS, " "), p.networkMTU) default: - fileName = "/etc/netplan/50-cloud-init.yaml" + fileName = "/etc/netplan/51-cloud-init.yaml" content = fmt.Sprintf(`network: version: 2 ethernets: diff --git a/backend/start_attributes.go b/backend/start_attributes.go index 075efbdb9..040bc748e 100644 --- a/backend/start_attributes.go +++ b/backend/start_attributes.go @@ -20,6 +20,7 @@ type StartAttributes struct { Group string `json:"group"` OS string `json:"os"` ImageName string `json:"image_name"` + OSCustom string `json:"os_custom"` // The VMType isn't stored in the config directly, but in the top level of // the job payload, see the worker.JobPayload struct. @@ -29,12 +30,10 @@ type StartAttributes struct { // the job payload, see the worker.JobPayload struct. VMConfig VmConfig `json:"-"` - // The VMSize isn't stored in the config directly, but in the top level of // the job payload, see the worker.JobPayload struct. VMSize string `json:"-"` - // Warmer isn't stored in the config directly, but in the top level of // the job payload, see the worker.JobPayload struct. Warmer bool `json:"-"` @@ -46,6 +45,10 @@ type StartAttributes struct { // ProgressType isn't stored in the config directly, but is injected from // the processor ProgressType string `json:"-"` + + // TamToken isn't stored in the config directly, but in the top level of + // the job payload, see the worker.JobPayload struct. + TamToken string `json:"-"` } // SetDefaults sets any missing required attributes to the default values provided diff --git a/image/manager.go b/image/manager.go index b360227cd..0b14a4cd5 100644 --- a/image/manager.go +++ b/image/manager.go @@ -68,6 +68,31 @@ func (m *Manager) Load(imageName string) error { return m.importImage(imageName, imageURL) } +func (m *Manager) LoadCustom(imageName string, tamToken string) error { + ok, err := m.Exists(imageName) + if err != nil { + return err + } + + if ok { + m.logger.WithFields(logrus.Fields{ + "image_name": imageName, + "token": tamToken, + }).Info("image already present") + + return nil + } + + imageURL := m.customImageUrl(imageName, tamToken) + + m.logger.WithFields(logrus.Fields{ + "image_name": imageName, + "image_url": imageURL, + }).Info("importing image") + + return m.importImage(imageName, imageURL) +} + func (m *Manager) Exists(imageName string) (bool, error) { images, err := m.client.GetImages() if err != nil { @@ -206,3 +231,9 @@ func (m *Manager) imageUrl(name string) string { u.Path = fmt.Sprintf("/images/travis/%s", name) return u.String() } + +func (m *Manager) customImageUrl(name string, tamToken string) string { + u := *m.imagesServerURL + u.Path = fmt.Sprintf("/images/custom/%s/%s", url.QueryEscape(name), tamToken) + return u.String() +} diff --git a/job.go b/job.go index 00b4b79c7..e3dcae8e6 100644 --- a/job.go +++ b/job.go @@ -41,6 +41,7 @@ type JobPayload struct { Queue string `json:"queue"` Trace bool `json:"trace"` Warmer bool `json:"warmer"` + TamToken string `json:"tam_token"` } // JobMetaPayload contains meta information about the job.