~ci-train-bot/libertine/libertine-ubuntu-zesty-2129

« back to all changes in this revision

Viewing changes to liblibertine/libertined.cpp

  • Committer: Bileto Bot
  • Date: 2017-02-09 16:13:59 UTC
  • mfrom: (184.1.4 libertine.1.6-release)
  • Revision ID: ci-train-bot@canonical.com-20170209161359-qzl9r3xjtlny1q7v
* Get libertine-container-manager and libertine-launch working in a confined
  environment.
* Create a special desktop file to satisfy the snappy store.
* Update snap definition to include aliases, renamed commands, and internal
  desktop file.
* Ensure absolute path lxd bind-mounts have a valid name by using the full
  path as a backup.
* Refactor liblibertine as a client wrapper for libertined and bump version
  to 1.5.2.
* Protect against containers that aren't started when running commands.
* Migrate the list-apps subcommand to list application ids. (LP: #1657877)
* Run the libertined integration test with its own dbus sesison to prevent
  collisions with running service.
* Discover if a session is running and if so, use it's dbus session to start
  the container manager. (LP: #1657490)
* Replace all pylxd execute()'s with calls to 'lxc exec' as pylxd has
  performance issues in execute().
* Add ability to freeze and unfreeze LXC/LXD containers. This is disabled by
  default for now. (LP: #1654355)
* Add ability to enable and disable the freezing of LXC/LXD containers when
  not in use. (LP: #1654355)
* Deprecate the lx[cd] managers and use libertined for managing the containers
  and move the actual starting and stopping of containers to the respective
  backends. (LP: #1660685)
* Add a restart subcommand to libertine-container-manager. Also try to restart
  the container when adding/removing bind-mounts, if appropriate.
  (LP: #1654355)
* Enable Xmir '-rootless' mode by default and remove using Matchbox for the
  window manager. (LP: #1662555)
* Change when the libertine-xmir Upstart gets started to account for Unity 8
  now directly starting apps.
* Bump release version to 1.6.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2017 Canonical Ltd
 
3
 *
 
4
 * Libertine is free software: you can redistribute it and/or modify it under
 
5
 * the terms of the GNU General Public License, version 3, as published by the
 
6
 * Free Software Foundation.
 
7
 *
 
8
 * Libertine is distributed in the hope that it will be useful, but WITHOUT ANY
 
9
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 
10
 * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 
11
 *
 
12
 * You should have received a copy of the GNU General Public License
 
13
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
14
 */
 
15
 
 
16
 
 
17
#include "libertined.h"
 
18
 
 
19
#include <QDBusMessage>
 
20
#include <QDBusInterface>
 
21
#include <QDebug>
 
22
#include <thread>
 
23
#include <chrono>
 
24
#include <QJsonDocument>
 
25
#include <QJsonArray>
 
26
#include <QJsonObject>
 
27
 
 
28
namespace
 
29
{
 
30
static const auto SERVICE_INTERFACE = "com.canonical.libertine.Service";
 
31
static const auto PROGRESS_INTERFACE = "com.canonical.libertine.Service.Progress";
 
32
 
 
33
static QVariantList
 
34
dbusCall(QDBusConnection const& bus, QString const& iface, QString const& path,
 
35
         QString const& method, QVariantList const& args = QVariantList())
 
36
{
 
37
  auto message = QDBusMessage::createMethodCall(SERVICE_INTERFACE, path, iface, method);
 
38
  message.setArguments(args);
 
39
  auto response = bus.call(message);
 
40
  if (response.type() == QDBusMessage::ErrorMessage)
 
41
  {
 
42
    qWarning() << "error calling result" << response.errorMessage();
 
43
    return QVariantList();
 
44
  }
 
45
 
 
46
  return response.arguments();
 
47
}
 
48
 
 
49
static bool
 
50
isRunning(QDBusConnection const& bus, QString const& path)
 
51
{
 
52
  auto args = dbusCall(bus, PROGRESS_INTERFACE, path, "running", QVariantList());
 
53
 
 
54
  if (args.isEmpty())
 
55
  {
 
56
    qWarning() << "lastError - no arguments?";
 
57
    return false;
 
58
  }
 
59
 
 
60
  return args.first().toBool();
 
61
}
 
62
 
 
63
static QString
 
64
result(QDBusConnection const& bus, QString const& path)
 
65
{
 
66
  auto args = dbusCall(bus, PROGRESS_INTERFACE, path, "result");
 
67
 
 
68
  if (args.isEmpty())
 
69
  {
 
70
    qWarning() << "lastError - no arguments?";
 
71
    return "";
 
72
  }
 
73
 
 
74
  return args.first().toString();
 
75
}
 
76
 
 
77
static QString
 
78
lastError(QDBusConnection const& bus, QString const& path)
 
79
{
 
80
  auto args = dbusCall(bus, PROGRESS_INTERFACE, path, "last_error");
 
81
 
 
82
  if (args.isEmpty())
 
83
  {
 
84
    qWarning() << "lastError - no arguments?";
 
85
    return "";
 
86
  }
 
87
 
 
88
  return args.first().toString();
 
89
}
 
90
 
 
91
static QString
 
92
call(QDBusConnection const& bus, QString const& method, QVariantList const& args)
 
93
{
 
94
  auto results = dbusCall(bus, SERVICE_INTERFACE, "/Manager", method, args);
 
95
 
 
96
  if (results.isEmpty())
 
97
  {
 
98
    return QString();
 
99
  }
 
100
 
 
101
  return qvariant_cast<QDBusObjectPath>(results.first()).path();
 
102
}
 
103
 
 
104
static bool
 
105
waitForFinish(QDBusConnection const& bus, QString const& path)
 
106
{
 
107
  std::chrono::microseconds wait(500);
 
108
  for (auto i = 0; i < 2000; ++i)
 
109
  {
 
110
    if (!isRunning(bus, path))
 
111
    {
 
112
      return true;
 
113
    }
 
114
    std::this_thread::sleep_for(wait);
 
115
  }
 
116
  return !isRunning(bus, path);
 
117
}
 
118
 
 
119
QString
 
120
container_info(char const* container_id, QString const& key)
 
121
{
 
122
  auto bus = QDBusConnection::sessionBus();
 
123
  auto path = call(bus, "container_info", QVariantList{QVariant(container_id)});
 
124
 
 
125
  if (!waitForFinish(bus, path))
 
126
  {
 
127
    return QString();
 
128
  }
 
129
 
 
130
  auto error = lastError(bus, path);
 
131
  if (!error.isEmpty())
 
132
  {
 
133
    qWarning() << "error:" << error;
 
134
    return QString();
 
135
  }
 
136
 
 
137
  return QJsonDocument::fromJson(result(bus, path).toLatin1()).object().value(key).toString();
 
138
}
 
139
}
 
140
 
 
141
QJsonArray
 
142
libertined_list()
 
143
{
 
144
  auto bus = QDBusConnection::sessionBus();
 
145
  auto path = call(bus, "list", QVariantList());
 
146
 
 
147
  if (!waitForFinish(bus, path))
 
148
  {
 
149
    return QJsonArray();
 
150
  }
 
151
 
 
152
  auto error = lastError(bus, path);
 
153
  if (!error.isEmpty())
 
154
  {
 
155
    qWarning() << "error:" << error;
 
156
    return QJsonArray();
 
157
  }
 
158
 
 
159
  return QJsonDocument::fromJson(result(bus, path).toLatin1()).array();
 
160
}
 
161
 
 
162
QJsonArray
 
163
libertined_list_app_ids(char const* container_id)
 
164
{
 
165
  auto bus = QDBusConnection::sessionBus();
 
166
  auto path = call(bus, "list_app_ids", QVariantList{QVariant(container_id)});
 
167
 
 
168
  if (!waitForFinish(bus, path))
 
169
  {
 
170
    return QJsonArray();
 
171
  }
 
172
 
 
173
  auto error = lastError(bus, path);
 
174
  if (!error.isEmpty())
 
175
  {
 
176
    qWarning() << "error:" << error;
 
177
    return QJsonArray();
 
178
  }
 
179
 
 
180
  return QJsonDocument::fromJson(result(bus, path).toLatin1()).array();
 
181
}
 
182
 
 
183
QString
 
184
libertined_container_path(char const* container_id)
 
185
{
 
186
  return container_info(container_id, "root");
 
187
}
 
188
 
 
189
QString
 
190
libertined_container_home_path(char const* container_id)
 
191
{
 
192
  return container_info(container_id, "home");
 
193
}
 
194
 
 
195
QString
 
196
libertined_container_name(char const* container_id)
 
197
{
 
198
  return container_info(container_id, "name");
 
199
}