source: trunk/debathena/third/schroot/sbuild/sbuild-chroot-lvm-snapshot.cc @ 24167

Revision 24167, 7.2 KB checked in by broder, 15 years ago (diff)
Import schroot upstream into subversion.
Line 
1/* Copyright © 2005-2009  Roger Leigh <rleigh@debian.org>
2 *
3 * schroot is free software: you can redistribute it and/or modify it
4 * under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * schroot is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program.  If not, see
15 * <http://www.gnu.org/licenses/>.
16 *
17 *********************************************************************/
18
19#include <config.h>
20
21#include "sbuild-chroot-lvm-snapshot.h"
22#include "sbuild-chroot-block-device.h"
23#include "sbuild-chroot-facet-session-clonable.h"
24#include "sbuild-chroot-facet-source-clonable.h"
25#include "sbuild-chroot-facet-mountable.h"
26#include "sbuild-format-detail.h"
27#include "sbuild-lock.h"
28
29#include <cassert>
30#include <cerrno>
31
32#include <boost/format.hpp>
33
34using std::endl;
35using boost::format;
36using namespace sbuild;
37
38chroot_lvm_snapshot::chroot_lvm_snapshot ():
39  chroot_block_device_base(),
40  snapshot_device(),
41  snapshot_options()
42{
43  add_facet(sbuild::chroot_facet_source_clonable::create());
44}
45
46chroot_lvm_snapshot::chroot_lvm_snapshot (const chroot_lvm_snapshot& rhs):
47  chroot_block_device_base(rhs),
48  snapshot_device(rhs.snapshot_device),
49  snapshot_options(rhs.snapshot_options)
50{
51}
52
53chroot_lvm_snapshot::~chroot_lvm_snapshot ()
54{
55}
56
57sbuild::chroot::ptr
58chroot_lvm_snapshot::clone () const
59{
60  return ptr(new chroot_lvm_snapshot(*this));
61}
62
63sbuild::chroot::ptr
64chroot_lvm_snapshot::clone_session (std::string const& session_id,
65                                    std::string const& user,
66                                    bool               root) const
67{
68  chroot_facet_session_clonable::const_ptr psess
69    (get_facet<chroot_facet_session_clonable>());
70  assert(psess);
71
72  ptr session(new chroot_lvm_snapshot(*this));
73  psess->clone_session_setup(session, session_id, user, root);
74
75  return session;
76}
77
78sbuild::chroot::ptr
79chroot_lvm_snapshot::clone_source () const
80{
81  ptr clone(new chroot_block_device(*this));
82
83  chroot_facet_source_clonable::const_ptr psrc
84    (get_facet<chroot_facet_source_clonable>());
85  assert(psrc);
86
87  psrc->clone_source_setup(clone);
88
89  return clone;
90}
91
92std::string const&
93chroot_lvm_snapshot::get_snapshot_device () const
94{
95  return this->snapshot_device;
96}
97
98void
99chroot_lvm_snapshot::set_snapshot_device (std::string const& snapshot_device)
100{
101  if (!is_absname(snapshot_device))
102    throw error(snapshot_device, DEVICE_ABS);
103
104  this->snapshot_device = snapshot_device;
105
106  chroot_facet_mountable::ptr pmnt
107    (get_facet<chroot_facet_mountable>());
108  pmnt->set_mount_device(this->snapshot_device);
109}
110
111std::string const&
112chroot_lvm_snapshot::get_snapshot_options () const
113{
114  return this->snapshot_options;
115}
116
117void
118chroot_lvm_snapshot::set_snapshot_options (std::string const& snapshot_options)
119{
120  this->snapshot_options = snapshot_options;
121}
122
123std::string const&
124chroot_lvm_snapshot::get_chroot_type () const
125{
126  static const std::string type("lvm-snapshot");
127
128  return type;
129}
130
131void
132chroot_lvm_snapshot::setup_env (chroot const& chroot,
133                                environment&  env) const
134{
135  chroot_block_device_base::setup_env(chroot, env);
136
137  env.add("CHROOT_LVM_SNAPSHOT_NAME", sbuild::basename(get_snapshot_device()));
138  env.add("CHROOT_LVM_SNAPSHOT_DEVICE", get_snapshot_device());
139  env.add("CHROOT_LVM_SNAPSHOT_OPTIONS", get_snapshot_options());
140}
141
142void
143chroot_lvm_snapshot::setup_lock (chroot::setup_type type,
144                                 bool               lock,
145                                 int                status)
146{
147  std::string device;
148
149  /* Lock is removed by setup script on setup stop.  Unlocking here
150     would fail: the LVM snapshot device no longer exists. */
151  if (!(type == SETUP_STOP && lock == false))
152    {
153      if (type == SETUP_START)
154        device = get_device();
155      else
156        device = get_snapshot_device();
157
158      if (device.empty())
159        throw error(CHROOT_DEVICE);
160
161      try
162        {
163          stat file_status(device);
164          if (!file_status.is_block())
165            {
166              throw error(get_device(), DEVICE_NOTBLOCK);
167            }
168          else
169            {
170              /* Lock is preserved while running a command. */
171              if ((type == EXEC_START && lock == false) ||
172                  (type == EXEC_STOP && lock == true))
173                return;
174
175              sbuild::device_lock dlock(device);
176              if (lock)
177                {
178                  try
179                    {
180                      dlock.set_lock(lock::LOCK_EXCLUSIVE, 15);
181                    }
182                  catch (sbuild::lock::error const& e)
183                    {
184                      throw error(get_device(), DEVICE_LOCK, e);
185                    }
186                }
187              else
188                {
189                  try
190                    {
191                      dlock.unset_lock();
192                    }
193                  catch (sbuild::lock::error const& e)
194                    {
195                      throw error(get_device(), DEVICE_UNLOCK, e);
196                    }
197                }
198            }
199        }
200      catch (sbuild::stat::error const& e) // Failed to stat
201        {
202          // Don't throw if stopping a session and the device stat
203          // failed.  This is because the setup scripts shouldn't fail
204          // to be run if the LVM snapshot no longer exists, which
205          // would prevent the session from being ended.
206          if (type != SETUP_STOP)
207            throw;
208        }
209    }
210
211  /* Create or unlink session information. */
212  if ((type == SETUP_START && lock == true) ||
213      (type == SETUP_STOP && lock == false && status == 0))
214    {
215      bool start = (type == SETUP_START);
216      setup_session_info(start);
217    }
218}
219
220sbuild::chroot::session_flags
221chroot_lvm_snapshot::get_session_flags (chroot const& chroot) const
222{
223  session_flags flags = SESSION_NOFLAGS;
224
225  if (get_active())
226    flags = flags | SESSION_PURGE;
227
228  return flags;
229}
230
231void
232chroot_lvm_snapshot::get_details (chroot const& chroot,
233                                  format_detail& detail) const
234{
235  chroot_block_device_base::get_details(chroot, detail);
236
237  if (!this->snapshot_device.empty())
238    detail.add(_("LVM Snapshot Device"), get_snapshot_device());
239  if (!this->snapshot_options.empty())
240    detail.add(_("LVM Snapshot Options"), get_snapshot_options());
241}
242
243void
244chroot_lvm_snapshot::get_keyfile (chroot const& chroot,
245                                  keyfile& keyfile) const
246{
247  chroot_block_device_base::get_keyfile(chroot, keyfile);
248
249  if (get_active())
250    keyfile::set_object_value(*this,
251                              &chroot_lvm_snapshot::get_snapshot_device,
252                              keyfile, get_keyfile_name(),
253                              "lvm-snapshot-device");
254
255  if (!get_active())
256    keyfile::set_object_value(*this,
257                              &chroot_lvm_snapshot::get_snapshot_options,
258                              keyfile, get_keyfile_name(),
259                              "lvm-snapshot-options");
260}
261
262void
263chroot_lvm_snapshot::set_keyfile (chroot&        chroot,
264                                  keyfile const& keyfile,
265                                  string_list&   used_keys)
266{
267  chroot_block_device_base::set_keyfile(chroot, keyfile, used_keys);
268
269  keyfile::get_object_value(*this, &chroot_lvm_snapshot::set_snapshot_device,
270                            keyfile, get_keyfile_name(), "lvm-snapshot-device",
271                            get_active() ?
272                            keyfile::PRIORITY_REQUIRED :
273                            keyfile::PRIORITY_DISALLOWED);
274  used_keys.push_back("lvm-snapshot-device");
275
276  keyfile::get_object_value(*this, &chroot_lvm_snapshot::set_snapshot_options,
277                            keyfile, get_keyfile_name(), "lvm-snapshot-options",
278                            get_active() ?
279                            keyfile::PRIORITY_DEPRECATED :
280                            keyfile::PRIORITY_REQUIRED); // Only needed for creating snapshot, not using snapshot
281  used_keys.push_back("lvm-snapshot-options");
282}
Note: See TracBrowser for help on using the repository browser.