Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1349)

Unified Diff: state/machine.go

Issue 10447045: Add machine instance metadata to state (Closed)
Patch Set: Add machine instance metadata to state Created 11 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « state/export_test.go ('k') | state/machine_test.go » ('j') | state/state.go » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: state/machine.go
=== modified file 'state/machine.go'
--- state/machine.go 2013-06-25 21:36:47 +0000
+++ state/machine.go 2013-06-28 12:47:26 +0000
@@ -56,7 +56,6 @@
Nonce string
Series string
ContainerType string
- InstanceId instance.Id
Principals []string
Life Life
Tools *Tools `bson:",omitempty"`
@@ -64,6 +63,11 @@
Jobs []MachineJob
PasswordHash string
Clean bool
+ // Deprecated. InstanceId, now lives on instanceData.
+ // This attribute is retained so that data from existing machines can be read.
+ // SCHEMACHANGE
+ // TODO(wallyworld): remove this attribute when schema upgrades are possible.
+ InstanceId instance.Id
}
func newMachine(st *State, doc *machineDoc) *Machine {
@@ -104,6 +108,43 @@
return machineGlobalKey(m.doc.Id)
}
+// instanceData holds attributes relevant to a provisioned machine.
+type instanceData struct {
+ Id string `bson:"_id"`
+ InstanceId instance.Id `bson:"instanceid"`
+ Arch *string `bson:"arch,omitempty"`
+ Mem *uint64 `bson:"mem,omitempty"`
+ CpuCores *uint64 `bson:"cpucpores,omitempty"`
+ CpuPower *uint64 `bson:"cpupower,omitempty"`
+ TxnRevno int64 `bson:"txn-revno"`
+}
+
+// TODO(wallyworld): move this method to a service.
+func (m *Machine) HardwareCharacteristics() (*instance.HardwareCharacteristics, error) {
+ hc := &instance.HardwareCharacteristics{}
+ instData, err := getInstanceData(m.st, m.Id())
+ if err != nil {
+ return nil, err
+ }
+ hc.Arch = instData.Arch
+ hc.Mem = instData.Mem
+ hc.CpuCores = instData.CpuCores
+ hc.CpuPower = instData.CpuPower
+ return hc, nil
+}
+
+func getInstanceData(st *State, id string) (instanceData, error) {
+ var instData instanceData
+ err := st.instanceData.FindId(id).One(&instData)
+ if err == mgo.ErrNotFound {
+ return instanceData{}, errors.NotFoundf("instance data for machine %v", id)
+ }
+ if err != nil {
+ return instanceData{}, fmt.Errorf("cannot get instance data for machine %v: %v", id, err)
+ }
+ return instData, nil
+}
+
const machineTagPrefix = "machine-"
// MachineTag returns the tag for the
@@ -384,6 +425,11 @@
Assert: txn.DocExists,
Remove: true,
},
+ {
+ C: m.st.instanceData.Name,
+ Id: m.doc.Id,
+ Remove: true,
+ },
removeStatusOp(m.st, m.globalKey()),
removeConstraintsOp(m.st, m.globalKey()),
annotationRemoveOp(m.st, m.globalKey()),
@@ -449,8 +495,21 @@
// InstanceId returns the provider specific instance id for this machine
// and whether it has been set.
-func (m *Machine) InstanceId() (instance.Id, bool) {
- return m.doc.InstanceId, m.doc.InstanceId != ""
+func (m *Machine) InstanceId() (instance.Id, error) {
+ // SCHEMACHANGE
+ // TODO(wallyworld) - remove this backward compatibility code when schema upgrades are possible
+ // (we first check for InstanceId stored on the machineDoc)
+ if m.doc.InstanceId != "" {
+ return m.doc.InstanceId, nil
+ }
+ instData, err := getInstanceData(m.st, m.Id())
+ if (err == nil && instData.InstanceId == "") || (err != nil && errors.IsNotFoundError(err)) {
+ err = &NotProvisionedError{m.Id()}
+ }
+ if err != nil {
+ return "", err
+ }
+ return instData.InstanceId, nil
}
// Units returns all the units that have been assigned to the machine.
@@ -475,25 +534,49 @@
return units, nil
}
-// SetProvisioned sets the provider specific machine id and nonce for
+// SetProvisioned sets the provider specific machine id, nonce and also metadata for
// this machine. Once set, the instance id cannot be changed.
-func (m *Machine) SetProvisioned(id instance.Id, nonce string) (err error) {
- defer utils.ErrorContextf(&err, "cannot set instance id of machine %q", m)
+func (m *Machine) SetProvisioned(id instance.Id, nonce string, characteristics *instance.HardwareCharacteristics) (err error) {
+ defer utils.ErrorContextf(&err, "cannot set instance data for machine %q", m)
if id == "" || nonce == "" {
return fmt.Errorf("instance id and nonce cannot be empty")
}
+
+ if characteristics == nil {
+ characteristics = &instance.HardwareCharacteristics{}
+ }
+ hc := &instanceData{
+ Id: m.doc.Id,
+ InstanceId: id,
+ Arch: characteristics.Arch,
+ Mem: characteristics.Mem,
+ CpuCores: characteristics.CpuCores,
+ CpuPower: characteristics.CpuPower,
+ }
+ // SCHEMACHANGE
+ // TODO(wallyworld) - do not check instanceId on machineDoc after schema is upgraded
notSetYet := D{{"instanceid", ""}, {"nonce", ""}}
- ops := []txn.Op{{
- C: m.st.machines.Name,
- Id: m.doc.Id,
- Assert: append(isAliveDoc, notSetYet...),
- Update: D{{"$set", D{{"instanceid", id}, {"nonce", nonce}}}},
- }}
+ ops := []txn.Op{
+ {
+ C: m.st.machines.Name,
+ Id: m.doc.Id,
+ Assert: append(isAliveDoc, notSetYet...),
+ Update: D{{"$set", D{{"instanceid", id}, {"nonce", nonce}}}},
+ }, {
+ C: m.st.instanceData.Name,
+ Id: m.doc.Id,
+ Assert: txn.DocMissing,
+ Insert: hc,
+ },
+ }
if err = m.st.runTransaction(ops); err == nil {
+ m.doc.Nonce = nonce
+ // SCHEMACHANGE
+ // TODO(wallyworld) - remove this backward compatibility code when schema upgrades are possible
+ // (InstanceId is stored on the instanceData document but we duplicate the value on the machineDoc.
m.doc.InstanceId = id
- m.doc.Nonce = nonce
return nil
} else if err != txn.ErrAborted {
return err
@@ -505,10 +588,26 @@
return fmt.Errorf("already set")
}
-// CheckProvisioned returns true if the machine was provisioned with
-// the given nonce.
+// NotProvisionedError records an error when a machine is not provisioned.
+type NotProvisionedError struct {
+ machineId string
+}
+
+// IsNotProvisionedError returns true if err is a NotProvisionedError.
+func IsNotProvisionedError(err error) bool {
+ if _, ok := err.(*NotProvisionedError); ok {
+ return true
+ }
+ return false
+}
+
+func (e *NotProvisionedError) Error() string {
+ return fmt.Sprintf("machine %v is not provisioned", e.machineId)
+}
+
+// CheckProvisioned returns true if the machine was provisioned with the given nonce.
func (m *Machine) CheckProvisioned(nonce string) bool {
- return m.doc.Nonce == nonce && m.doc.InstanceId != ""
+ return m.doc.Nonce == nonce
fwereade 2013/06/28 13:08:58 hmm, sorry: maybe nonce == m.doc.Nonce && nonce !=
}
// String returns a unique description of this machine.
@@ -527,12 +626,12 @@
// is already provisioned.
func (m *Machine) SetConstraints(cons constraints.Value) (err error) {
defer utils.ErrorContextf(&err, "cannot set constraints")
- notProvisioned := D{{"instanceid", ""}}
+ notSetYet := D{{"nonce", ""}}
ops := []txn.Op{
{
C: m.st.machines.Name,
Id: m.doc.Id,
- Assert: append(isAliveDoc, notProvisioned...),
+ Assert: append(isAliveDoc, notSetYet...),
},
setConstraintsOp(m.st, m.globalKey(), cons),
}
@@ -545,8 +644,10 @@
if m.doc.Life != Alive {
return errNotAlive
}
- if m.doc.InstanceId != "" {
+ if _, err := m.InstanceId(); err == nil {
return fmt.Errorf("machine is already provisioned")
+ } else if !IsNotProvisionedError(err) {
+ return err
}
if err := m.st.runTransaction(ops); err != txn.ErrAborted {
return err
« no previous file with comments | « state/export_test.go ('k') | state/machine_test.go » ('j') | state/state.go » ('J')

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b