Merge pull request #1579 from MasterRoot24/gentoo-chroot

This commit is contained in:
Dr-Bean
2015-05-04 18:25:33 +02:00
32 changed files with 1582 additions and 0 deletions

View File

@ -0,0 +1,91 @@
SPK_NAME = gentoo-chroot
SPK_VERS = 13.0
SPK_REV = 1
SPK_ICON = src/gentoo.png
DSM_UI_DIR = app
DEPENDS =
WHEELS = pyextdirect==0.3.1 flask Werkzeug Jinja2 itsdangerous
SPK_DEPENDS = "python>=2.7.6-8"
MAINTAINER = "SynoCommunity"
DESCRIPTION = "Gentoo is a free operating system based on either Linux or FreeBSD that can be automatically optimized and customized for just about any application or need. Gentoo Chroot allows you to install the Gentoo OS inside your DiskStation, alongside DSM. This package is intended for advanced users only."
RELOAD_UI = yes
DISPLAY_NAME = "Gentoo Chroot"
CHANGELOG =
HOMEPAGE = "http://www.gentoo.org/"
LICENSE =
HELPURL = "3rdparty/gentoo-chroot/help/enu/index.html"
SUPPORTURL = "http://www.gentoo.org/main/en/support.xml"
INSTALLER_SCRIPT = src/installer.sh
SSS_SCRIPT = src/dsm-control.sh
INSTALL_PREFIX = /usr/local/$(SPK_NAME)
COPY_TARGET = nop
POST_STRIP_TARGET = gentoo-chroot_extra_install
GENTOO_ARCH =
ifeq ($(findstring $(ARCH),88f6281),$(ARCH))
GENTOO_CPU = arm
GENTOO_ARCH = armv7a
endif
ifeq ($(findstring $(ARCH),armada370 armadaxp armada375 alpine),$(ARCH))
GENTOO_CPU = arm
GENTOO_ARCH = armv7a_hardfp
endif
ifeq ($(findstring $(ARCH),bromolow cedarview evansport x86 avoton x64),$(ARCH))
GENTOO_CPU = x86
GENTOO_ARCH = i686
endif
ifeq ($(findstring $(ARCH),qoriq),$(ARCH))
GENTOO_CPU = ppc
GENTOO_ARCH = ppc
endif
ifeq ($(strip $(GENTOO_ARCH)),)
$(error Arch $(ARCH) not supported)
endif
GENTOO_STAGE3 := $(shell curl -s http://distfiles.gentoo.org/releases/$(GENTOO_CPU)/autobuilds/latest-stage3-$(GENTOO_ARCH).txt | sed '/^\#/d' | awk '{print $$1}')
GENTOO_STAGE3_URL := http://distfiles.gentoo.org/releases/$(GENTOO_CPU)/autobuilds/$(GENTOO_STAGE3)
GENTOO_STAGE3_FILE := $(shell basename $(GENTOO_STAGE3))
include ../../mk/spksrc.spk.mk
.PHONY: gentoo-chroot_extra_install
gentoo-chroot_extra_install:
install -m 755 -d ${STAGING_DIR}/share/wheelhouse
install -m 644 ${WORK_DIR}/wheelhouse/* ${STAGING_DIR}/share/wheelhouse/
wget -nv -c -O $(WORK_DIR)/$(GENTOO_STAGE3_FILE) $(GENTOO_STAGE3_URL)
install -m 755 -d $(STAGING_DIR)/var
install -m 755 -d $(STAGING_DIR)/var/chroottarget
tar xjpf $(WORK_DIR)/$(GENTOO_STAGE3_FILE) -C $(STAGING_DIR)/var/chroottarget --exclude './dev/*'
install -m 755 -d $(STAGING_DIR)/etc
install -m 644 src/mounts $(STAGING_DIR)/etc/mounts
install -m 755 -d $(STAGING_DIR)/app
install -m 755 -d $(STAGING_DIR)/app/help
install -m 755 -d $(STAGING_DIR)/app/help/enu
install -m 644 src/app/help/enu/index.html $(STAGING_DIR)/app/help/enu/index.html
install -m 644 src/app/config $(STAGING_DIR)/app/config
install -m 644 src/app/style.css $(STAGING_DIR)/app/style.css
install -m 644 src/app/gentoo-chroot.js $(STAGING_DIR)/app/gentoo-chroot.js
install -m 755 src/app/setup.py $(STAGING_DIR)/app/setup.py
install -m 755 src/app/start.py $(STAGING_DIR)/app/start.py
install -m 755 src/app/stop.py $(STAGING_DIR)/app/stop.py
install -m 755 src/app/gentoo-chroot.cgi.py $(STAGING_DIR)/app/gentoo-chroot.cgi
install -m 755 -d $(STAGING_DIR)/app/application
install -m 644 src/app/application/* $(STAGING_DIR)/app/application/
install -m 755 -d $(STAGING_DIR)/app/texts
for language in enu; do \
install -m 755 -d $(STAGING_DIR)/app/texts/$${language}; \
install -m 644 src/app/texts/$${language}/strings $(STAGING_DIR)/app/texts/$${language}/strings; \
done
install -m 755 -d $(STAGING_DIR)/app/images
install -m 644 src/app/images/*.png $(STAGING_DIR)/app/images/
for size in 16 24 32 48 72; do \
convert $(SPK_ICON) -thumbnail $${size}x$${size} \
$(STAGING_DIR)/app/images/$(SPK_NAME)-$${size}.png ; \
done

0
spk/gentoo-chroot/PLIST Normal file
View File

View File

@ -0,0 +1,66 @@
# -*- coding: utf-8 -*-
from collections import namedtuple
from flask import abort, request
from functools import wraps, partial
from subprocess import check_output
import grp
import os
import pwd
__all__ = ['authenticate', 'requires_auth']
def authenticate():
"""Authenticate a user using Synology's authenticate.cgi
If the user is authenticated, returns a nametuple with the
username and its groups, if not returns None. For example::
>>> authenticate()
User(name='admin', groups=['administrators'])
:rtype: namedtuple or None
"""
User = namedtuple('User', ['name', 'groups'])
with open(os.devnull, 'w') as devnull:
user = check_output(['/usr/syno/synoman/webman/modules/authenticate.cgi'], stderr=devnull).strip()
if not user:
return None
groups = [g.gr_name for g in grp.getgrall() if user in g.gr_mem]
groups.append(grp.getgrgid(pwd.getpwnam(user).pw_gid).gr_name)
return User(user, set(groups))
def requires_auth(f=None, groups=None, users=None):
"""Require a user to be authenticated. If he is not, this aborts
on 403.
The condition to be authorized is for the user to be authenticated
and in one of the listed groups (if any) or one of the listed users
(if any)
:param function f: the decorated function
:param list groups: groups whitelist
:param list users: users whitelist
"""
if f is None:
return partial(requires_auth, groups=groups, users=users)
@wraps(f)
def decorated(*args, **kwargs):
user = authenticate()
if user is None: # Not authenticated
abort(403)
# A user is authorized if he is in the groups whitelist or the users whitelist
authorized = False
if groups is not None and len(set(groups) & user.groups) > 0: # Authorized group
authorized = True
if users is not None and user.name in users: # Authorized user
authorized = True
if not authorized:
abort(403)
return f(*args, **kwargs)
return decorated

View File

@ -0,0 +1,5 @@
__all__ = ['env_path', 'chroottarget', 'installed']
env_path = '/usr/local/gentoo-chroot/bin:/usr/local/gentoo-chroot/env/bin:/usr/local/python/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/syno/sbin:/usr/syno/bin'
chroottarget = '/usr/local/gentoo-chroot/var/chroottarget/'
installed = '/usr/local/gentoo-chroot/var/installed'

View File

@ -0,0 +1,44 @@
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
from sqlalchemy.engine import create_engine
from sqlalchemy.orm.session import sessionmaker
import subprocess
import os
from config import *
__all__ = ['Base', 'engine', 'Session', 'Service', 'setup']
Base = declarative_base()
engine = create_engine('sqlite:////usr/local/gentoo-chroot/var/gentoo-chroot.db', echo=False)
Session = sessionmaker(bind=engine)
class Service(Base):
__tablename__ = 'services'
id = Column(Integer, primary_key=True)
name = Column(String)
launch_script = Column(String)
status_command = Column(String)
def start(self):
with open(os.devnull, 'w') as devnull:
status = not subprocess.call(['chroot', chroottarget, '/bin/bash', '-c', self.launch_script + ' start'], stdin=devnull, stdout=devnull, stderr=devnull, env={'PATH': env_path})
return status
def stop(self):
with open(os.devnull, 'w') as devnull:
status = not subprocess.call(['chroot', chroottarget, '/bin/bash', '-c', self.launch_script + ' stop'], stdin=devnull, stdout=devnull, stderr=devnull, env={'PATH': env_path})
return status
@property
def status(self):
with open(os.devnull, 'w') as devnull:
status = not subprocess.call(['chroot', chroottarget, '/bin/bash', '-c', self.status_command], stdin=devnull, stdout=devnull, stderr=devnull, env={'PATH': env_path})
return status
def setup():
Base.metadata.create_all(engine)

View File

@ -0,0 +1,117 @@
from pyextdirect.configuration import create_configuration, expose, LOAD, STORE_READ, STORE_CUD
from pyextdirect.router import Router
import os
import subprocess
from config import *
from db import *
__all__ = ['Base', 'Services', 'Overview']
Base = create_configuration()
class Services(Base):
def __init__(self):
self.session = Session()
@expose(kind=STORE_CUD)
def create(self, data):
results = []
for record in data:
service = Service(name=record['name'], launch_script=record['launch_script'], status_command=record['status_command'])
self.session.add(service)
self.session.commit()
results.append({'id': service.id, 'name': service.name, 'launch_script': service.launch_script,
'status_command': service.status_command, 'status': service.status})
return results
@expose(kind=STORE_READ)
def read(self):
results = []
for service in self.session.query(Service).all():
results.append({'id': service.id, 'name': service.name, 'launch_script': service.launch_script,
'status_command': service.status_command, 'status': service.status})
return results
@expose(kind=STORE_CUD)
def update(self, data):
results = []
for record in data:
service = self.session.query(Service).get(record['id'])
service.name = record['name']
service.launch_script = record['launch_script']
service.status_command = record['status_command']
results.append({'id': service.id, 'name': service.name, 'launch_script': service.launch_script,
'status_command': service.status_command, 'status': service.status})
self.session.commit()
return results
@expose(kind=STORE_CUD)
def destroy(self, data):
results = []
for service_id in data:
service = self.session.query(Service).get(service_id)
self.session.delete(service)
results.append({'id': service.id, 'name': service.name, 'launch_script': service.launch_script,
'status_command': service.status_command, 'status': service.status})
self.session.commit()
return [r['id'] for r in results]
@expose
def start(self, service_id):
service = self.session.query(Service).get(service_id)
return service.start()
@expose
def stop(self, service_id):
service = self.session.query(Service).get(service_id)
return service.stop()
def stop_all(self):
for service in self.session.query(Service).all():
if service.status:
service.stop()
def start_all(self):
for service in self.session.query(Service).all():
if not service.status:
service.start()
class Overview(Base):
def __init__(self):
self.session = Session()
@expose(kind=LOAD)
def load(self):
result = {'installed': 'installed' if self.is_installed() else 'installing',
'running_services': self.running_services(),
'updates': self.updates_count()}
return result
@expose
def updates_count(self):
with open(os.devnull, 'w') as devnull:
updates_count = int(subprocess.check_output(['chroot', chroottarget, '/bin/bash', '-c', 'emerge --update --deep @world --pretend --quiet | grep "U" | wc -l'], stdin=devnull, stderr=devnull, env={'PATH': env_path}))
return updates_count
@expose
def do_refresh(self):
with open(os.devnull, 'w') as devnull:
status = not subprocess.call(['chroot', chroottarget, '/bin/bash', '-c', 'emerge --sync --quiet'], stdin=devnull, stdout=devnull, stderr=devnull, env={'PATH': env_path})
if status:
return self.updates_count()
return status
@expose
def do_update(self):
with open(os.devnull, 'w') as devnull:
status = not subprocess.call(['chroot', chroottarget, '/bin/bash', '-c', 'emerge --update --deep @world --quiet'], stdin=devnull, stdout=devnull, stderr=devnull, env={'PATH': env_path})
return status
def is_installed(self):
return os.path.exists(installed)
def running_services(self):
return len([service for service in self.session.query(Service).all() if service.status == 1])

View File

@ -0,0 +1,31 @@
{
"gentoo-chroot.js": {
"SYNOCOMMUNITY.GentooChroot.AppInstance": {
"type": "app",
"title": "app:app_name",
"version": "0.1",
"icon": "images/gentoo-chroot-{0}.png",
"texts": "texts",
"allowMultiInstance": false,
"allUsers": false,
"appWindow": "SYNOCOMMUNITY.GentooChroot.AppWindow",
"depend": ["SYNOCOMMUNITY.GentooChroot.AppWindow"]
},
"SYNOCOMMUNITY.GentooChroot.AppWindow": {
"type": "lib",
"title": "app:app_name",
"icon": "images/gentoo-chroot-{0}.png",
"texts": "texts",
"depend": ["SYNOCOMMUNITY.GentooChroot.ListView", "SYNOCOMMUNITY.GentooChroot.MainCardPanel"]
},
"SYNOCOMMUNITY.GentooChroot.ListView": [],
"SYNOCOMMUNITY.GentooChroot.MainCardPanel": {
"depend": ["SYNOCOMMUNITY.GentooChroot.PanelOverview", "SYNOCOMMUNITY.GentooChroot.PanelServices"]
},
"SYNOCOMMUNITY.GentooChroot.PanelOverview": [],
"SYNOCOMMUNITY.GentooChroot.PanelServices": {
"depend": ["SYNOCOMMUNITY.GentooChroot.ServiceEditorWindow"]
},
"SYNOCOMMUNITY.GentooChroot.ServiceEditorWindow": []
}
}

View File

@ -0,0 +1,38 @@
#!/usr/local/gentoo-chroot/env/bin/python
from application.auth import requires_auth
from application.direct import Base, Overview
from flask import Flask, request, Response
from pyextdirect.api import create_api
from pyextdirect.router import Router
from wsgiref.handlers import CGIHandler
import json
app = Flask('gentoo-chroot')
@app.route('/direct/router', methods=['POST'])
@requires_auth(groups=['administrators'])
def route():
router = Router(Base)
return Response(router.route(request.json or dict((k, v[0] if len(v) == 1 else v) for k, v in request.form.to_dict(False).iteritems())), mimetype='application/json')
@app.route('/direct/poller', methods=['GET'])
@requires_auth(groups=['administrators'])
def poll():
overview = Overview()
event = {'type': 'event', 'name': 'status', 'data': {
'installed': 'installed' if overview.is_installed() else 'installing',
'running_services': overview.running_services()}}
return Response(json.dumps(event), mimetype='application/json')
@app.route('/direct/api')
@requires_auth(groups=['administrators'])
def api():
return create_api(Base)
if __name__ == '__main__':
CGIHandler().run(app)

View File

@ -0,0 +1,814 @@
// Namespace
Ext.ns("SYNOCOMMUNITY.GentooChroot");
// Translator
_V = function (category, element) {
return _TT("SYNOCOMMUNITY.GentooChroot.AppInstance", category, element)
}
// Direct API
Ext.Direct.addProvider({
"url": "3rdparty/gentoo-chroot/gentoo-chroot.cgi/direct/router",
"namespace": "SYNOCOMMUNITY.GentooChroot.Remote",
"type": "remoting",
"actions": {
"Overview": [{
"name": "load",
"len": 0
}, {
"name": "updates_count",
"len": 0
}, {
"name": "do_refresh",
"len": 0
}, {
"name": "do_update",
"len": 0
}],
"Services": [{
"name": "save",
"len": 5
}, {
"name": "read",
"len": 0
}, {
"name": "create",
"len": 1
}, {
"name": "update",
"len": 1
}, {
"name": "destroy",
"len": 1
}, {
"name": "start",
"len": 1
}, {
"name": "stop",
"len": 1
}]
}
});
SYNOCOMMUNITY.GentooChroot.Poller = new Ext.direct.PollingProvider({
'type': 'polling',
'url': '3rdparty/gentoo-chroot/gentoo-chroot.cgi/direct/poller',
'interval': 10000
});
Ext.Direct.addProvider(SYNOCOMMUNITY.GentooChroot.Poller);
SYNOCOMMUNITY.GentooChroot.Poller.disconnect();
// Const
SYNOCOMMUNITY.GentooChroot.DEFAULT_HEIGHT = 300;
SYNOCOMMUNITY.GentooChroot.MAIN_WIDTH = 800;
SYNOCOMMUNITY.GentooChroot.LIST_WIDTH = 210;
// Application
SYNOCOMMUNITY.GentooChroot.AppInstance = Ext.extend(SYNO.SDS.AppInstance, {
appWindowName: "SYNOCOMMUNITY.GentooChroot.AppWindow",
constructor: function () {
SYNOCOMMUNITY.GentooChroot.AppInstance.superclass.constructor.apply(this, arguments);
}
});
// Main window
SYNOCOMMUNITY.GentooChroot.AppWindow = Ext.extend(SYNO.SDS.AppWindow, {
appInstance: null,
mainPanel: null,
constructor: function (config) {
this.appInstance = config.appInstance;
this.mainPanel = new SYNOCOMMUNITY.GentooChroot.MainPanel({
owner: this
});
config = Ext.apply({
resizable: true,
maximizable: true,
minimizable: true,
width: SYNOCOMMUNITY.GentooChroot.MAIN_WIDTH,
height: SYNOCOMMUNITY.GentooChroot.DEFAULT_HEIGHT,
layout: "fit",
border: false,
cls: "synocommunity-gentoochroot",
items: [this.mainPanel]
}, config);
SYNOCOMMUNITY.GentooChroot.AppWindow.superclass.constructor.call(this, config);
},
onOpen: function (a) {
SYNOCOMMUNITY.GentooChroot.AppWindow.superclass.onOpen.call(this, a);
this.mainPanel.onActivate();
},
onRequest: function (a) {
SYNOCOMMUNITY.GentooChroot.AppWindow.superclass.onRequest.call(this, a);
},
onClose: function () {
if (SYNOCOMMUNITY.GentooChroot.AppWindow.superclass.onClose.apply(this, arguments)) {
this.doClose();
this.mainPanel.onDeactivate();
return true;
}
return false;
},
setStatus: function (status) {
status = status || {};
var toolbar = this.mainPanel.cardPanel.layout.activeItem.getFooterToolbar();
if (toolbar && Ext.isFunction(toolbar.setStatus)) {
toolbar.setStatus(status)
} else {
this.getMsgBox().alert("Message", status.text)
}
}
});
// Main panel
SYNOCOMMUNITY.GentooChroot.MainPanel = Ext.extend(Ext.Panel, {
listPanel: null,
cardPanel: null,
constructor: function (config) {
this.owner = config.owner;
var a = new SYNOCOMMUNITY.GentooChroot.ListView({
module: this
});
this.listPanel = new Ext.Panel({
region: "west",
width: SYNOCOMMUNITY.GentooChroot.LIST_WIDTH,
height: SYNOCOMMUNITY.GentooChroot.DEFAULT_HEIGHT,
cls: "synocommunity-gentoochroot-list",
items: [a],
listeners: {
scope: this,
activate: this.onActivate,
deactivate: this.onDeactivate
},
onActivate: function (panel) {
a.onActivate()
}
});
this.listView = a;
this.curHeight = SYNOCOMMUNITY.GentooChroot.DEFAULT_HEIGHT;
this.cardPanel = new SYNOCOMMUNITY.GentooChroot.MainCardPanel({
module: this,
owner: config.owner,
itemId: "grid",
region: "center"
});
this.id_panel = [
["overview", this.cardPanel.PanelOverview],
["services", this.cardPanel.PanelServices]
];
SYNOCOMMUNITY.GentooChroot.MainPanel.superclass.constructor.call(this, {
border: false,
layout: "border",
height: SYNOCOMMUNITY.GentooChroot.DEFAULT_HEIGHT,
monitorResize: true,
items: [this.listPanel, this.cardPanel]
});
},
onActivate: function (panel) {
if (!this.isVisible()) {
return
}
this.listPanel.onActivate(panel);
this.cardPanel.onActivate(panel);
},
onDeactivate: function (panel) {
if (!this.rendered) {
return
}
this.cardPanel.onDeactivate(panel);
},
doSwitchPanel: function (id_panel) {
var c = this.cardPanel.getLayout();
c.setActiveItem(id_panel);
var b;
for (b = 0; b < this.id_panel.length; b++) {
var a = this.id_panel[b][1];
if (id_panel === this.id_panel[b][0]) {
a.onActivate();
break
}
}
},
getPanelHeight: function (id_panel) {
return SYNOCOMMUNITY.GentooChroot.DEFAULT_HEIGHT
},
isPanelDirty: function (c) {
var b;
for (b = 0; b < this.id_panel.length; b++) {
if (c === this.id_panel[b][0]) {
var a = this.id_panel[b][1];
if ("undefined" === typeof a.checkDirty) {
return false
}
if (true == a.checkDirty()) {
return true
}
break
}
}
return false
},
panelDeactivate: function (c) {
for (var b = 0; b < this.id_panel.length; b++) {
if (c === this.id_panel[b][0]) {
var a = this.id_panel[b][1];
if ("undefined" === typeof a.onDeactivate) {
return
}
a.onDeactivate();
return
}
}
return
},
switchPanel: function (f) {
var c = this.cardPanel.getLayout();
var b = c.activeItem.itemId;
if (f === b) {
return
}
if (Ext.isIE) {
this.doSwitchPanel(f);
return
}
var a = this.getPanelHeight(f);
if (this.curHeight == a) {
this.doSwitchPanel(f);
return
}
this.owner.el.disableShadow();
var d = this.owner.body;
var e = function () {
d.clearOpacity();
this.owner.getEl().setHeight("auto");
d.setHeight("auto");
this.owner.setHeight(a);
this.owner.el.enableShadow();
this.owner.syncShadow();
this.doSwitchPanel(f)
};
d.shift({
height: a - 54,
duration: 0.3,
opacity: 0.1,
scope: this,
callback: e
});
this.curHeight = a
}
});
// List view
SYNOCOMMUNITY.GentooChroot.ListView = Ext.extend(Ext.list.ListView, {
constructor: function (config) {
var store = new Ext.data.JsonStore({
data: {
items: [{
title: _V("ui", "console"),
id: "console_title"
}, {
title: _V("ui", "overview"),
id: "overview"
}, {
title: _V("ui", "services"),
id: "services"
}]
},
autoLoad: true,
root: "items",
fields: ["title", "id"]
});
config = Ext.apply({
cls: "synocommunity-gentoochroot-list",
padding: 10,
split: false,
trackOver: false,
hideHeaders: true,
singleSelect: true,
store: store,
columns: [{
dataIndex: "title",
cls: "synocommunity-gentoochroot-list-column",
sortable: false,
tpl: '<div class="synocommunity-gentoochroot-list-{id}">{title}</div>'
}],
listeners: {
scope: this,
beforeclick: this.onBeforeClick,
selectionchange: this.onListSelect,
activate: this.onActivate,
mouseenter: {
fn: function (d, e, g) {
var f = Ext.get(g);
if (f.hasClass(this.selectedClass)) {
f.removeClass(this.overClass)
}
var h = d.getRecord(g).get("id");
if (h === "console_title") {
f.removeClass(this.overClass)
}
}
}
}
}, config);
this.addEvents("onbeforeclick");
SYNOCOMMUNITY.GentooChroot.ListView.superclass.constructor.call(this, config)
},
onBeforeClick: function (c, d, f, b) {
var g = c.getRecord(f);
var h = g.get("id");
if (h === "console_title") {
return false
}
if (false == this.fireEvent("onbeforeclick", this, d, f, b)) {
return false
}
var e = this.module.cardPanel.getLayout();
var a = e.activeItem.itemId;
if (h === a) {
return false
}
if (this.module.isPanelDirty(a)) {
this.module.cardPanel.owner.getMsgBox().confirm(_T("app", "app_name"), _T("common", "confirm_lostchange"), function (i) {
if ("yes" === i) {
this.module.panelDeactivate(a);
this.select(d)
}
}, this);
return false
}
this.module.panelDeactivate(a);
return true
},
onListSelect: function (b, a) {
var c = this.getRecord(a[0]);
this.module.switchPanel(c.get("id"))
},
onActivate: function (panel) {
var a = this.getSelectedRecords()[0];
if (!a) {
this.select(1)
}
}
});
// Card panel
SYNOCOMMUNITY.GentooChroot.MainCardPanel = Ext.extend(Ext.Panel, {
PanelOverview: null,
constructor: function (config) {
this.owner = config.owner;
this.module = config.module;
this.PanelOverview = new SYNOCOMMUNITY.GentooChroot.PanelOverview({
owner: this.owner
});
this.PanelServices = new SYNOCOMMUNITY.GentooChroot.PanelServices({
owner: this.owner
});
config = Ext.apply({
activeItem: 0,
layout: "card",
items: [this.PanelOverview, this.PanelServices],
border: false,
listeners: {
scope: this,
activate: this.onActivate,
deactivate: this.onDeactivate
}
}, config);
SYNOCOMMUNITY.GentooChroot.MainCardPanel.superclass.constructor.call(this, config)
},
onActivate: function (panel) {
if (this.PanelOverview) {
this.PanelOverview.onActivate();
}
},
onDeactivate: function (panel) {
this.PanelOverview.onDeactivate();
}
});
// FormPanel base
SYNOCOMMUNITY.GentooChroot.FormPanel = Ext.extend(Ext.FormPanel, {
constructor: function (config) {
config = Ext.apply({
owner: null,
items: [],
padding: "20px 30px 2px 30px",
border: false,
header: false,
trackResetOnLoad: true,
monitorValid: true,
fbar: {
xtype: "statusbar",
defaultText: "&nbsp;",
statusAlign: "left",
buttonAlign: "left",
hideMode: "visibility",
items: [{
text: _T("common", "commit"),
ctCls: "syno-sds-cp-btn",
scope: this,
handler: this.onApply
}, {
text: _T("common", "reset"),
ctCls: "syno-sds-cp-btn",
scope: this,
handler: this.onReset
}]
}
}, config);
SYNO.LayoutConfig.fill(config);
SYNOCOMMUNITY.GentooChroot.FormPanel.superclass.constructor.call(this, config);
if (!this.owner instanceof SYNO.SDS.BaseWindow) {
throw Error("please set the owner window of form");
}
},
onActivate: Ext.emptyFn,
onDeactivate: Ext.emptyFn,
onApply: function () {
if (!this.getForm().isDirty()) {
this.owner.setStatusError({
text: _T("error", "nochange_subject"),
clear: true
});
return;
}
if (!this.getForm().isValid()) {
this.owner.setStatusError({
text: _T("common", "forminvalid"),
clear: true
});
return;
}
return true;
},
onReset: function () {
if (!this.getForm().isDirty()) {
this.getForm().reset();
return;
}
this.owner.getMsgBox().confirm(this.title, _T("common", "confirm_lostchange"), function (response) {
if ("yes" === response) {
this.getForm().reset();
}
}, this);
}
});
// Overview panel
SYNOCOMMUNITY.GentooChroot.PanelOverview = Ext.extend(SYNOCOMMUNITY.GentooChroot.FormPanel, {
constructor: function (config) {
this.owner = config.owner;
this.loaded = false;
config = Ext.apply({
itemId: "overview",
fbar: {
xtype: "statusbar",
defaultText: "&nbsp;",
statusAlign: "left",
buttonAlign: "left",
hideMode: "visibility",
items: []
},
items: [{
xtype: "fieldset",
labelWidth: 130,
title: _V("ui", "information"),
defaultType: "displayfield",
items: [{
fieldLabel: _V("ui", "status"),
name: "install_status",
value: ""
}, {
fieldLabel: _V("ui", "running_services"),
name: "running_services",
value: ""
}]
}, {
xtype: "fieldset",
labelWidth: 130,
title: "Portage",
items: [{
xtype: "compositefield",
fieldLabel: _V("ui", "available_updates"),
items: [{
xtype: "displayfield",
name: "updates",
width: 60,
value: ""
}, {
xtype: "button",
id: "synocommunity-gentoochroot-do_refresh",
text: _V("ui", "do_refresh"),
handler: this.onClickRefreshUpdates,
scope: this
}, {
xtype: "button",
id: "synocommunity-gentoochroot-do_update",
text: _V("ui", "do_update"),
handler: this.onClickUpdate,
scope: this
}]
}]
}],
api: {
load: SYNOCOMMUNITY.GentooChroot.Remote.Overview.load
}
}, config);
SYNO.LayoutConfig.fill(config);
SYNOCOMMUNITY.GentooChroot.PanelOverview.superclass.constructor.call(this, config);
},
onClickRefreshUpdates: function (button, event) {
button.disable();
Ext.getCmp("synocommunity-gentoochroot-do_update").disable();
SYNOCOMMUNITY.GentooChroot.Remote.Overview.do_refresh(function (provider, response) {
if (response.result !== false) {
this.getForm().findField("updates").setValue(response.result);
this.owner.setStatusOK({
text: response.result + " " + _V("ui", "updates_available")
});
} else {
this.owner.setStatusError({
text: _V("ui", "cannot_update"),
clear: true
});
}
button.enable();
Ext.getCmp("synocommunity-gentoochroot-do_update").enable();
}, this);
},
onClickUpdate: function (button, event) {
button.disable();
Ext.getCmp("synocommunity-gentoochroot-do_refresh").disable();
SYNOCOMMUNITY.GentooChroot.Remote.Overview.do_update(function (provider, response) {
if (response.result) {
this.getForm().findField("updates").setValue(0);
this.owner.setStatusOK({
text: _V("ui", "update_successful")
});
} else {
this.owner.setStatusError({
text: _V("ui", "cannot_update"),
clear: true
});
}
button.enable();
Ext.getCmp("synocommunity-gentoochroot-do_refresh").enable();
}, this);
},
onStatus: function (response) {
this.getForm().findField("install_status").setValue(_V("ui", response.data.installed));
this.getForm().findField("running_services").setValue(response.data.running_services);
if (response.data.installed == "installing") {
Ext.getCmp("synocommunity-gentoochroot-do_refresh").disable();
Ext.getCmp("synocommunity-gentoochroot-do_update").disable();
} else {
Ext.getCmp("synocommunity-gentoochroot-do_refresh").enable();
Ext.getCmp("synocommunity-gentoochroot-do_update").enable();
}
},
onActivate: function () {
Ext.Direct.on("status", this.onStatus, this);
if (!this.loaded) {
this.loaded = true;
this.getEl().mask(_T("common", "loading"), "x-mask-loading");
this.load({
scope: this,
success: function (form, action) {
this.getForm().findField("install_status").setValue(_V("ui", action.result.data.installed));
if (action.result.data.updates > 0) {
this.owner.setStatusOK({
text: action.result.data.updates + " " + _V("ui", "updates_available")
});
}
if (action.result.data.installed == "installing") {
Ext.getCmp("synocommunity-gentoochroot-do_refresh").disable();
Ext.getCmp("synocommunity-gentoochroot-do_update").disable();
}
this.getEl().unmask();
SYNOCOMMUNITY.GentooChroot.Poller.connect();
}
});
} else {
SYNOCOMMUNITY.GentooChroot.Poller.connect();
}
},
onDeactivate: function () {
Ext.Direct.un("status", this.onStatus, this);
SYNOCOMMUNITY.GentooChroot.Poller.disconnect();
}
});
// Services panel
SYNOCOMMUNITY.GentooChroot.PanelServices = Ext.extend(Ext.grid.GridPanel, {
constructor: function (config) {
this.owner = config.owner;
this.loaded = false;
this.store = new Ext.data.DirectStore({
autoSave: false,
fields: ["id", "name", "launch_script", "status_command", "status"],
api: {
read: SYNOCOMMUNITY.GentooChroot.Remote.Services.read,
create: SYNOCOMMUNITY.GentooChroot.Remote.Services.create,
update: SYNOCOMMUNITY.GentooChroot.Remote.Services.update,
destroy: SYNOCOMMUNITY.GentooChroot.Remote.Services.destroy
},
idProperty: "id",
root: "data",
writer: new Ext.data.JsonWriter({
encode: false,
listful: true,
writeAllFields: true
})
});
config = Ext.apply({
itemId: "services",
border: false,
store: this.store,
loadMask: true,
tbar: {
items: [{
text: _V("ui", "add"),
itemId: "add",
scope: this,
handler: this.onClickAdd
}, {
text: _V("ui", "edit"),
itemId: "edit",
scope: this,
handler: this.onClickEdit
}, {
text: _V("ui", "delete"),
itemId: "delete",
scope: this,
handler: this.onClickDelete
}, {
text: _V("ui", "start"),
itemId: "start",
scope: this,
handler: this.onClickStart
}, {
text: _V("ui", "stop"),
itemId: "stop",
scope: this,
handler: this.onClickStop
}, {
text: _V("ui", "refresh"),
itemId: "refresh",
scope: this,
handler: this.onClickRefresh
}]
},
columns: [{
header: _V("ui", "name"),
sortable: true,
width: 35,
dataIndex: "name"
}, {
header: _V("ui", "launch_script"),
width: 45,
dataIndex: "launch_script"
}, {
header: _V("ui", "status_command"),
dataIndex: "status_command"
}, {
header: _V("ui", "status"),
width: 25,
dataIndex: "status",
renderer: function (value, metaData, record, rowIndex, colIndex, store) {
if (value) {
return _V("ui", "running");
}
return _V("ui", "not_running");
}
}]
}, config);
SYNOCOMMUNITY.GentooChroot.PanelServices.superclass.constructor.call(this, config);
},
onActivate: function () {
if (!this.loaded) {
this.store.load();
this.loaded = true;
}
},
onClickAdd: function () {
var editor = new SYNOCOMMUNITY.GentooChroot.ServiceEditorWindow({}, this.store);
editor.open()
},
onClickEdit: function () {
var editor = new SYNOCOMMUNITY.GentooChroot.ServiceEditorWindow({}, this.store, this.getSelectionModel().getSelected());
editor.open()
},
onClickDelete: function () {
var records = this.getSelectionModel().getSelections();
if (records.length != 0) {
this.store.remove(this.getSelectionModel().getSelections());
this.store.save();
}
},
onClickStart: function () {
this.getSelectionModel().each(function (record) {
SYNOCOMMUNITY.GentooChroot.Remote.Services.start(record.id, function (provider, response) {
if (response.result) {
record.set("status", true);
record.commit();
}
});
}, this);
},
onClickStop: function () {
this.getSelectionModel().each(function (record) {
SYNOCOMMUNITY.GentooChroot.Remote.Services.stop(record.id, function (provider, response) {
if (response.result) {
record.set("status", false);
record.commit();
}
});
}, this);
},
onClickRefresh: function () {
this.store.load();
}
});
// Service window
SYNOCOMMUNITY.GentooChroot.ServiceEditorWindow = Ext.extend(SYNO.SDS.ModalWindow, {
title: _V("ui", "service"),
constructor: function (config, store, record) {
this.store = store;
this.record = record;
this.panel = new SYNOCOMMUNITY.GentooChroot.PanelServiceEditor({}, record);
config = Ext.apply(config, {
width: 550,
height: 210,
resizable: false,
layout: "fit",
items: [this.panel],
buttons: [{
text: _T("common", "apply"),
scope: this,
handler: this.onClickApply
}, {
text: _T("common", "close"),
scope: this,
handler: this.onClickClose
}]
})
SYNOCOMMUNITY.GentooChroot.ServiceEditorWindow.superclass.constructor.call(this, config);
},
onClickApply: function () {
if (this.record === undefined) {
var record = new this.store.recordType({
name: this.panel.getForm().findField("name").getValue(),
launch_script: this.panel.getForm().findField("launch_script").getValue(),
status_command: this.panel.getForm().findField("status_command").getValue()
});
this.store.add(record);
} else {
this.record.beginEdit();
this.record.set("name", this.panel.getForm().findField("name").getValue());
this.record.set("launch_script", this.panel.getForm().findField("launch_script").getValue());
this.record.set("status_command", this.panel.getForm().findField("status_command").getValue());
this.record.endEdit();
}
this.store.save();
this.close();
},
onClickClose: function () {
this.close();
}
});
// Service panel
SYNOCOMMUNITY.GentooChroot.PanelServiceEditor = Ext.extend(SYNOCOMMUNITY.GentooChroot.FormPanel, {
constructor: function (config, record) {
this.record = record;
config = Ext.apply({
itemId: "service",
padding: "15px 15px 2px 15px",
defaultType: "textfield",
labelWidth: 130,
fbar: null,
defaults: {
anchor: "-20"
},
items: [{
fieldLabel: _V("ui", "name"),
name: "name"
}, {
fieldLabel: _V("ui", "launch_script"),
name: "launch_script"
}, {
fieldLabel: _V("ui", "status_command"),
name: "status_command"
}]
}, config);
SYNOCOMMUNITY.GentooChroot.PanelServiceEditor.superclass.constructor.call(this, config);
if (this.record !== undefined) {
this.loadRecord();
}
},
loadRecord: function () {
this.getForm().findField("name").setValue(this.record.data.name);
this.getForm().findField("launch_script").setValue(this.record.data.launch_script);
this.getForm().findField("status_command").setValue(this.record.data.status_command);
}
});

View File

@ -0,0 +1,47 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Help - Gentoo Chroot</title>
<link href="/webman/help/help.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h1>Gentoo Chroot</h1>
<p><a href="http://www.gentoo.org/">Gentoo</a> is a free operating system based on either Linux or FreeBSD that can be automatically optimized and customized for just about any application or need. Gentoo Chroot allows you to install the Gentoo OS inside your DiskStation, alongside DSM. <em>This package is intended for advanced users only</em>.</p>
<h2>Installation</h2>
<p>Once the <em>package</em> installation has finished in the Package Center, the installation of the <em>chroot environment</em> continues in the background. Open <b>Gentoo Chroot</b> from the <b>Main Menu</b> of DSM and you can see its status under <b>Overview</b> in the left pane. When the installation finishes, the status will automatically change to <b>Installed</b>.</p>
<h3>Initial Setup</h3>
<p>Due to the custom nature of Gentoo, this package installs a very minimal Gentoo installation to your DiskStation and leaves the setup and configuration up to you.</p>
<p>As soon as the status of the <em>chroot environment</em> is <b>Installed</b>, you can begin configuring your new installation of Gentoo. To do so, connect to the DiskStation through SSH (root user) and use the following commands:</p>
<ol>
<li><code>/var/packages/gentoo-chroot/scripts/start-stop-status start</code></li>
<li><code>/var/packages/gentoo-chroot/scripts/start-stop-status chroot</code></li>
<li><code>env-update</code></li>
<li><code>source /etc/profile</code></li>
<li><code>export PS1="(chroot) $PS1"</code></li>
</ol>
<p>Unless you know what you are doing, it is <em>strongly</em> recommended that you to continue the setup of your installation of Gentoo by following from the relevant section of the official Gentoo handbook: <a href="http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=1&chap=6#doc_chap2">here</a>.</p>
<h2>App Usage</h2>
<h3>Overview</h3>
<p>From the Gentoo Chroot app, you can monitor how many services are running, perform update operations and manage services.</p>
<h3>Updates</h3>
<p>Gentoo uses <a href="http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=2&chap=1">Portage</a> to handle package updates.</p>
<p>Again, due to the custom nature of Gentoo, usually it's best to perform package updates via the command-line interface to Portage: <code><a href="http://dev.gentoo.org/~zmedico/portage/doc/man/emerge.1.html">emerge</a></code>. As <code>emerge</code> generally provides a greater amount of control over the packages that are installed and updated in your installation of Gentoo, wherever possible it's advisable to update your Gentoo installation manually using via the command-line.</p>
<p>If you just want to quickly check for available updates for Gentoo, simply click <b>Update</b> and Portage will sync with the package tree, then inform you of how many updates are available.</p>
<p>Whilst it's generally better to update Gentoo via the command-line, you can perform a quick update by simply clicking <b>Update</b>.</p>
<h3>Services</h3>
<p>Gentoo Chroot allows you to manage the packages you installed in the chroot directly from DSM.</p>
<p>Under <b>Services</b> in the left pane, you can manage services that you manually installed previously in the chroot: start and stop them easily.</p>
<h4>Configuration</h4>
<ol>
<li>Manually install in the chroot the service you chose.</li>
<li>Configure it by editing the correct configuration files.</li>
<li>In the interface, click on <b>Add</b> and fill the form. The <b>Launch script</b> will be launched with the <code>start</code> argument to start the service and <code>stop</code> to stop it. The <b>Status command</b> should return exit code <code>0</code> (success) if the service is started, or <code>>0</code> (error) if it is stopped.</li>
</ol>
<h4>Example: SSH Server</h4>
<ol>
<li>Edit the configuration file: <code>/etc/ssh/sshd_config</code>.</li>
<li>Change the port number and other things if necessary.</li>
<li>Click on <b>Add</b> and put the name <code>SSHD</code>, the launch script <code>rc-service sshd</code> and the status command <code>rc-service sshd status</code>.</li>
</ol>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 715 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 718 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1,6 @@
#!/usr/local/gentoo-chroot/env/bin/python
from application.db import setup
if __name__ == '__main__':
setup()

View File

@ -0,0 +1,7 @@
#!/usr/local/gentoo-chroot/env/bin/python
from application.direct import Services
if __name__ == '__main__':
services = Services()
services.start_all()

View File

@ -0,0 +1,7 @@
#!/usr/local/gentoo-chroot/env/bin/python
from application.direct import Services
if __name__ == '__main__':
services = Services()
services.stop_all()

View File

@ -0,0 +1,60 @@
/* List view customized style */
.synocommunity-gentoochroot-list {
background-color: #E1ECFA !important;
}
.synocommunity-gentoochroot-list .x-list-selected {
background-image: url(images/list_item_active.png);
background-position: right top;
color: #FFF;
}
.synocommunity-gentoochroot-list .x-list-over {
background-image: url(images/list_item_hover.png);
background-position: right top;
color: #FFF;
}
.synocommunity-gentoochroot-list-column div {
background-repeat: no-repeat;
padding-left: 20px;
height: 16px;
line-height: 16px;
}
.synocommunity-gentoochroot .synocommunity-gentoochroot-list .x-panel-body {
background-color: #E1ECFA;
background-image: url(images/synocommunity.png);
background-position: center bottom;
background-repeat: no-repeat;
}
/* List view icons */
.synocommunity-gentoochroot-list-overview {
background-image: url(images/overview.png);
margin-left: 16px;
}
.synocommunity-gentoochroot-list-services {
background-image: url(images/services.png);
margin-left: 16px;
}
/* Titles */
.synocommunity-gentoochroot-list-column div.synocommunity-gentoochroot-list-console_title {
margin-top: 8px;
padding-left: 0;
color: #003C66 !important;
font-weight: bold;
}
.x-list-over .synocommunity-gentoochroot-list-column div.synocommunity-gentoochroot-list-console_title {
cursor: default;
}
.synocommunity-gentoochroot-compositefield-button {
left: auto;
right: 0;
}
.ext-ie8 .synocommunity-gentoochroot .x-toolbar-cell .x-form-field-trigger-wrap .x-form-trigger {
right: auto
}

View File

@ -0,0 +1,36 @@
[app]
app_name = "Gentoo Chroot"
description = "Management UI for Gentoo Chroot"
[help]
description = "SynoCommunity Gentoo Chroot"
[ui]
console = "Console"
overview = "Overview"
services = "Services"
service = "Service"
information = "Information"
status = "Status"
running_services = "Running services"
installed = "Installed"
installing = "Installing"
available_updates = "Available Update(s)"
do_refresh = "Refresh"
updates_available = "update(s) available"
cannot_refresh = "Error occurred whilst updating the Portage tree"
do_update = "Update"
cannot_update = "Error occurred during update"
update_successful = "Update successful"
name = "Name"
launch_script = "Launch script"
status_command = "Status command"
actions = "Actions"
start = "Start"
stop = "Stop"
add = "Add"
edit = "Edit"
delete = "Delete"
refresh = "Refresh"
running = "Started"
not_running = "Stopped"

View File

@ -0,0 +1,126 @@
#!/bin/sh
# Package
PACKAGE="gentoo-chroot"
DNAME="Gentoo Chroot"
# Others
INSTALL_DIR="/usr/local/${PACKAGE}"
PATH="${INSTALL_DIR}/bin:${PATH}"
CHROOTTARGET=`realpath ${INSTALL_DIR}/var/chroottarget`
start_daemon ()
{
# Mount if install is finished
if [ -f ${INSTALL_DIR}/var/installed ]; then
# Make sure we don't mount twice
grep -q "${CHROOTTARGET}/proc " /proc/mounts || mount -t proc proc ${CHROOTTARGET}/proc
grep -q "${CHROOTTARGET}/sys " /proc/mounts || mount -t sysfs sys ${CHROOTTARGET}/sys
grep -q "${CHROOTTARGET}/dev " /proc/mounts || mount -o bind /dev ${CHROOTTARGET}/dev
grep -q "${CHROOTTARGET}/dev/pts " /proc/mounts || mount -o bind /dev/pts ${CHROOTTARGET}/dev/pts
test -d "${CHROOTTARGET}/dev/fd" || ln -s '../proc/self/fd' ${CHROOTTARGET}/dev/fd
grep -q "${CHROOTTARGET}/tmp " /proc/mounts || mount -t tmpfs /tmp ${CHROOTTARGET}/tmp
# Mount user specified directories, if specified
if [ -f ${INSTALL_DIR}/etc/mounts ]; then
if [ `sed -e 's/#.*$//g' -e '/^$/d' ${INSTALL_DIR}/etc/mounts | wc -l` != 0 ]; then
sed -e 's/#.*$//g' -e '/^$/d' ${INSTALL_DIR}/etc/mounts | while read mount; do
SRC=$(echo $mount | awk '{ print $1 }')
DST=$(echo $mount | awk '{ print $2 }' | cut -c 2-)
grep -q "${CHROOTTARGET}/${DST} " /proc/mounts || mount -o bind $SRC ${CHROOTTARGET}/${DST}
done
fi
fi
# Start all services
${INSTALL_DIR}/app/start.py
fi
}
stop_daemon ()
{
# Stop running services
${INSTALL_DIR}/app/stop.py
# Unmount
test -L ${CHROOTTARGET}/dev/fd && rm ${CHROOTTARGET}/dev/fd
for mount in `grep ${CHROOTTARGET} /proc/mounts | awk '{ print $2 }'`; do umount -l $mount; done
}
daemon_status ()
{
`grep -q "${CHROOTTARGET}/proc " /proc/mounts` && `grep -q "${CHROOTTARGET}/sys " /proc/mounts` && `grep -q "${CHROOTTARGET}/dev " /proc/mounts` && `grep -q "${CHROOTTARGET}/dev/pts " /proc/mounts` && `grep -q "${CHROOTTARGET}/tmp " /proc/mounts` && `test -d "${CHROOTTARGET}/dev/fd"`
}
case $1 in
start)
if daemon_status; then
echo ${DNAME} is already running
exit 0
else
echo Starting ${DNAME} ...
start_daemon
exit $?
fi
;;
stop)
if daemon_status; then
echo Stopping ${DNAME} ...
stop_daemon
exit 0
else
echo ${DNAME} is not running
exit 0
fi
;;
restart)
if daemon_status; then
echo Stopping ${DNAME} ... && \
stop_daemon && \
echo Starting ${DNAME} ... && \
start_daemon && \
exit 0
else
echo ${DNAME} is not running
exit 1
fi
;;
status)
if daemon_status; then
echo ${DNAME} is running
exit 0
else
echo ${DNAME} is not running
exit 1
fi
;;
chroot)
if daemon_status; then
echo Entering chroot...
chroot ${CHROOTTARGET}/ /bin/bash
else
echo WARNING: ${DNAME} is not running
echo WARNING: The chroot environment will not have access to /proc, /dev, /sys or /tmp which could cause problems!
echo Entering chroot...
chroot ${CHROOTTARGET}/ /bin/bash
exit 1
fi
;;
log)
if [ -f ${CHROOTTARGET}/var/log/syslog ]; then
echo ${CHROOTTARGET}/var/log/syslog
exit 0
elif [ -f ${CHROOTTARGET}/var/log/messages ]; then
echo ${CHROOTTARGET}/var/log/messages
exit 0
else
exit 1
fi
;;
*)
echo "You must provide an argument to this script; either 'start', 'stop', 'restart', 'status' or 'chroot'"
exit 1
;;
esac

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@ -0,0 +1,82 @@
#!/bin/sh
# Package
PACKAGE="gentoo-chroot"
DNAME="Gentoo Chroot"
# Others
INSTALL_DIR="/usr/local/${PACKAGE}"
PYTHON_DIR="/usr/local/python"
CHROOTTARGET="${INSTALL_DIR}/var/chroottarget"
PATH="${INSTALL_DIR}/bin:${INSTALL_DIR}/env/bin:${PYTHON_DIR}/bin:${PATH}"
CHROOT_PATH="/usr/local/bin:/usr/bin:/bin"
VIRTUALENV="${PYTHON_DIR}/bin/virtualenv"
TMP_DIR="${SYNOPKG_PKGDEST}/../../@tmp"
preinst ()
{
exit 0
}
postinst ()
{
# Link
ln -s ${SYNOPKG_PKGDEST} ${INSTALL_DIR}
# Create a Python virtualenv
${VIRTUALENV} --system-site-packages ${INSTALL_DIR}/env > /dev/null
# Install the wheels/requirements
${INSTALL_DIR}/env/bin/pip install --use-wheel --no-deps --no-index -U --force-reinstall -f ${INSTALL_DIR}/share/wheelhouse -r ${INSTALL_DIR}/share/wheelhouse/requirements.txt > /dev/null 2>&1
# Setup the database
${INSTALL_DIR}/env/bin/python ${INSTALL_DIR}/app/setup.py
# Configure the chroot environment
if [ "${SYNOPKG_PKG_STATUS}" != "UPGRADE" ]; then
cp /etc/hosts /etc/resolv.conf ${CHROOTTARGET}/etc/
echo 'hostname="'`hostname -s`'"' > ${CHROOTTARGET}/etc/conf.d/hostname
touch ${CHROOTTARGET}/run/openrc/softlevel
touch ${CHROOTTARGET}/var/run/utmp
touch ${CHROOTTARGET}/var/log/wtmp
touch ${INSTALL_DIR}/var/installed
fi
exit 0
}
preuninst ()
{
exit 0
}
postuninst ()
{
# Remove link
rm -f ${INSTALL_DIR}
exit 0
}
preupgrade ()
{
# Save some stuff
rm -fr ${TMP_DIR}/${PACKAGE}
mkdir -p ${TMP_DIR}/${PACKAGE}
mv ${INSTALL_DIR}/etc ${TMP_DIR}/${PACKAGE}/
mv ${INSTALL_DIR}/var ${TMP_DIR}/${PACKAGE}/
exit 0
}
postupgrade ()
{
# Restore some stuff
rm -fr ${INSTALL_DIR}/etc
rm -fr ${INSTALL_DIR}/var
mv ${TMP_DIR}/${PACKAGE}/etc ${INSTALL_DIR}/
mv ${TMP_DIR}/${PACKAGE}/var ${INSTALL_DIR}/
rm -fr ${TMP_DIR}/${PACKAGE}
exit 0
}

View File

@ -0,0 +1,5 @@
# Enter any custom mounts below.
# Use the following format:
# /path/to/host/dir /path/inside/chroot