func setServerConfig(d *Daemon, key string, value string) error { tx, err := shared.DbBegin(d.db) if err != nil { return err } _, err = tx.Exec("DELETE FROM config WHERE key=?", key) if err != nil { tx.Rollback() return err } if value != "" { str := `INSERT INTO config (key, value) VALUES (?, ?);` stmt, err := tx.Prepare(str) if err != nil { tx.Rollback() return err } defer stmt.Close() _, err = stmt.Exec(key, value) if err != nil { tx.Rollback() return err } } err = shared.TxCommit(tx) if err != nil { return err } return nil }
func dbInsertImage(d *Daemon, fp string, fname string, sz int64, public int, arch int, properties map[string]string) error { tx, err := shared.DbBegin(d.db) if err != nil { return err } stmt, err := tx.Prepare(`INSERT INTO images (fingerprint, filename, size, public, architecture, upload_date) VALUES (?, ?, ?, ?, ?, strftime("%s"))`) if err != nil { tx.Rollback() return err } defer stmt.Close() result, err := stmt.Exec(fp, fname, sz, public, arch) if err != nil { tx.Rollback() return err } if len(properties) > 0 { id64, err := result.LastInsertId() if err != nil { tx.Rollback() return err } id := int(id64) pstmt, err := tx.Prepare(`INSERT INTO images_properties (image_id, type, key, value) VALUES (?, 0, ?, ?)`) if err != nil { tx.Rollback() return err } defer pstmt.Close() for k, v := range properties { // we can assume, that there is just one // value per key _, err = pstmt.Exec(id, k, v) if err != nil { tx.Rollback() return err } } } if err := shared.TxCommit(tx); err != nil { return err } return nil }
func containerReplaceConfig(d *Daemon, ct *lxdContainer, name string, newConfig containerConfigReq) error { /* check to see that the config actually applies to the container * successfully before saving it. in particular, raw.lxc and * raw.apparmor need to be parsed once to make sure they make sense. */ if err := ct.applyConfig(newConfig.Config, false); err != nil { return err } tx, err := shared.DbBegin(d.db) if err != nil { return err } /* Update config or profiles */ if err = dbClearContainerConfig(tx, ct.id); err != nil { shared.Debugf("Error clearing configuration for container %s\n", name) tx.Rollback() return err } if err = dbInsertContainerConfig(tx, ct.id, newConfig.Config); err != nil { shared.Debugf("Error inserting configuration for container %s\n", name) tx.Rollback() return err } /* handle profiles */ if emptyProfile(newConfig.Profiles) { _, err := tx.Exec("DELETE from containers_profiles where container_id=?", ct.id) if err != nil { tx.Rollback() return err } } else { if err := dbInsertProfiles(tx, ct.id, newConfig.Profiles); err != nil { tx.Rollback() return err } } err = AddDevices(tx, "container", ct.id, newConfig.Devices) if err != nil { tx.Rollback() return err } return shared.TxCommit(tx) }
func imageDelete(d *Daemon, r *http.Request) Response { fingerprint := mux.Vars(r)["fingerprint"] imgInfo, err := dbImageGet(d.db, fingerprint, false) if err != nil { return SmartError(err) } fname := shared.VarPath("images", imgInfo.Fingerprint) err = os.Remove(fname) if err != nil { shared.Debugf("Error deleting image file %s: %s\n", fname, err) } vgname, vgnameIsSet, err := getServerConfigValue(d, "core.lvm_vg_name") if err != nil { return InternalError(fmt.Errorf("Error checking server config: %v", err)) } if vgnameIsSet { err = shared.LVMRemoveLV(vgname, imgInfo.Fingerprint) if err != nil { return InternalError(fmt.Errorf("Failed to remove deleted image LV: %v", err)) } lvsymlink := fmt.Sprintf("%s.lv", fname) err = os.Remove(lvsymlink) if err != nil { return InternalError(fmt.Errorf("Failed to remove symlink to deleted image LV: '%s': %v", lvsymlink, err)) } } else if d.BackingFs == "btrfs" { subvol := fmt.Sprintf("%s.btrfs", fname) exec.Command("btrfs", "subvolume", "delete", subvol).Run() } tx, err := shared.DbBegin(d.db) if err != nil { return InternalError(err) } _, _ = tx.Exec("DELETE FROM images_aliases WHERE image_id=?", imgInfo.Id) _, _ = tx.Exec("DELETE FROM images_properties WHERE image_id?", imgInfo.Id) _, _ = tx.Exec("DELETE FROM images WHERE id=?", imgInfo.Id) if err := shared.TxCommit(tx); err != nil { return InternalError(err) } return EmptySyncResponse }
func dbProfileDelete(db *sql.DB, name string) error { tx, err := shared.DbBegin(db) if err != nil { return err } _, err = tx.Exec("DELETE FROM profiles WHERE name=?", name) if err != nil { tx.Rollback() return err } err = shared.TxCommit(tx) return err }
func profilesPost(d *Daemon, r *http.Request) Response { req := profilesPostReq{} if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return BadRequest(err) } if req.Name == "" { return BadRequest(fmt.Errorf("No name provided")) } name := req.Name tx, err := shared.DbBegin(d.db) if err != nil { return InternalError(err) } result, err := tx.Exec("INSERT INTO profiles (name) VALUES (?)", name) if err != nil { tx.Rollback() return SmartError(err) } id64, err := result.LastInsertId() if err != nil { tx.Rollback() return InternalError(fmt.Errorf("Error inserting %s into database", name)) } id := int(id64) err = addProfileConfig(tx, id, req.Config) if err != nil { tx.Rollback() return SmartError(err) } err = AddDevices(tx, "profile", id, req.Devices) if err != nil { tx.Rollback() return SmartError(err) } err = shared.TxCommit(tx) if err != nil { return InternalError(err) } return EmptySyncResponse }
func saveCert(d *Daemon, host string, cert *x509.Certificate) error { tx, err := shared.DbBegin(d.db) if err != nil { return err } fingerprint := shared.GenerateFingerprint(cert) stmt, err := tx.Prepare("INSERT INTO certificates (fingerprint,type,name,certificate) VALUES (?, ?, ?, ?)") if err != nil { tx.Rollback() return err } defer stmt.Close() _, err = stmt.Exec(fingerprint, 1, host, pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})) if err != nil { tx.Rollback() return err } return shared.TxCommit(tx) }
func imagePut(d *Daemon, r *http.Request) Response { fingerprint := mux.Vars(r)["fingerprint"] imageRaw := imagePutReq{} if err := json.NewDecoder(r.Body).Decode(&imageRaw); err != nil { return BadRequest(err) } imgInfo, err := dbImageGet(d.db, fingerprint, false) if err != nil { return SmartError(err) } tx, err := shared.DbBegin(d.db) if err != nil { return InternalError(err) } _, err = tx.Exec(`DELETE FROM images_properties WHERE image_id=?`, imgInfo.Id) stmt, err := tx.Prepare(`INSERT INTO images_properties (image_id, type, key, value) VALUES (?, ?, ?, ?)`) if err != nil { tx.Rollback() return InternalError(err) } for key, value := range imageRaw.Properties { _, err = stmt.Exec(imgInfo.Id, 0, key, value) if err != nil { tx.Rollback() return InternalError(err) } } if err := shared.TxCommit(tx); err != nil { return InternalError(err) } return EmptySyncResponse }
func createDefaultProfile(db *sql.DB) error { rows, err := shared.DbQuery(db, "SELECT id FROM profiles WHERE name=?", "default") if err != nil { return err } defer rows.Close() id := -1 for rows.Next() { var xId int rows.Scan(&xId) id = xId } if id != -1 { // default profile already exists return nil } tx, err := shared.DbBegin(db) if err != nil { return err } result, err := tx.Exec("INSERT INTO profiles (name) VALUES (?)", "default") if err != nil { tx.Rollback() return err } id64, err := result.LastInsertId() if err != nil { tx.Rollback() return err } id = int(id64) result, err = tx.Exec(`INSERT INTO profiles_devices (profile_id, name, type) VALUES (?, ?, ?)`, id, "eth0", "nic") if err != nil { tx.Rollback() return err } id64, err = result.LastInsertId() if err != nil { tx.Rollback() return err } devId := int(id64) _, err = tx.Exec(`INSERT INTO profiles_devices_config (profile_device_id, key, value) VALUES (?, ?, ?)`, devId, "nictype", "bridged") if err != nil { tx.Rollback() return err } /* TODO - analyze system to choose a bridge */ _, err = tx.Exec(`INSERT INTO profiles_devices_config (profile_device_id, key, value) VALUES (?, ?, ?)`, devId, "parent", "lxcbr0") if err != nil { tx.Rollback() return err } if err := tx.Commit(); err != nil { return err } return nil }
func profilePut(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] req := profilesPostReq{} if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return BadRequest(err) } tx, err := shared.DbBegin(d.db) if err != nil { return InternalError(err) } rows, err := tx.Query("SELECT id FROM profiles WHERE name=?", name) if err != nil { tx.Rollback() return SmartError(err) } var id int for rows.Next() { var i int err = rows.Scan(&i) if err != nil { shared.Debugf("DBERR: profilePut: scan returned error %q\n", err) tx.Rollback() return InternalError(err) } id = i } rows.Close() err = rows.Err() if err != nil { shared.Debugf("DBERR: profilePut: Err returned an error %q\n", err) tx.Rollback() return InternalError(err) } err = dbClearProfileConfig(tx, id) if err != nil { tx.Rollback() return InternalError(err) } err = addProfileConfig(tx, id, req.Config) if err != nil { tx.Rollback() return SmartError(err) } err = AddDevices(tx, "profile", id, req.Devices) if err != nil { tx.Rollback() return SmartError(err) } err = shared.TxCommit(tx) if err != nil { return InternalError(err) } return EmptySyncResponse }