Index: trunk/LATMOS-Accounts/bin/la-sql-upgrade.in
===================================================================
--- trunk/LATMOS-Accounts/bin/la-sql-upgrade.in	(revision 1307)
+++ trunk/LATMOS-Accounts/bin/la-sql-upgrade.in	(revision 1308)
@@ -202,9 +202,4 @@
             ALTER TABLE revaliases ADD COLUMN description text;
             },
-        ],
-    },
-    {
-        ver => 7,
-        sql => [
             q{
             CREATE OR REPLACE FUNCTION group_sort_fields()
@@ -259,5 +254,263 @@
         ],
     },
-
+    {
+        ver => 8,
+        sql => [
+            q{
+            CREATE TABLE objectslogs
+            (
+              logkey SERIAL NOT NULL,
+              ikey bigint NOT NULL,
+              otype text NOT NULL,
+              name text NOT NULL,
+              changetype text NOT NULL,
+              username text NOT NULL,
+              message text NOT NULL,
+              logdate timestamp with time zone NOT NULL DEFAULT now(),
+              CONSTRAINT objectlogs_pkey PRIMARY KEY (logkey)
+            );},
+            q{
+            CREATE INDEX objectlogs_name_idx
+              ON objectslogs
+              USING btree
+              (name);
+            },
+            q{
+            CREATE INDEX objectslogs_ikey_idx
+              ON objectslogs
+              USING btree
+              (ikey);
+            },
+            q{
+            CREATE INDEX objectslogs_otype_idx
+              ON objectslogs
+              USING btree
+              (otype);
+            }
+        ],
+    },
+    {
+        ver => 9,
+        sql => [
+            q{
+            CREATE TABLE nethost_attributes_nethosts
+            (
+            CONSTRAINT nethost_attributes_nethosts_pkey PRIMARY KEY (attr_key),
+            CONSTRAINT nethost_attr_nethosts_fkey FOREIGN KEY (okey)
+            REFERENCES nethost (ikey) MATCH SIMPLE
+            ON UPDATE CASCADE ON DELETE CASCADE,
+            CONSTRAINT nethost_attr_nethosts_nethosts FOREIGN KEY ("value")
+            REFERENCES nethost (name) MATCH SIMPLE
+            ON UPDATE CASCADE ON DELETE CASCADE
+            )
+            INHERITS (nethost_attributes);
+
+            CREATE INDEX fki_nethost_attr_nethosts_fkey
+            ON nethost_attributes_nethosts
+            USING btree
+            (okey);
+
+            CREATE TRIGGER nethost_attr_nethosts_update
+            AFTER INSERT OR UPDATE OR DELETE
+            ON nethost_attributes_nethosts
+            FOR EACH ROW
+            EXECUTE PROCEDURE nethost_attr_update_ref();
+
+
+            CREATE OR REPLACE FUNCTION nethost_sort_fields()
+              RETURNS trigger AS
+              $BODY$BEGIN
+
+              IF (TG_OP='INSERT') then
+              IF (new.attr='ip') THEN
+              insert into nethost_attributes_ips VALUES (new.*);
+              RETURN NULL;
+              END IF;
+
+              IF (new.attr='macaddr') THEN
+              insert into nethost_attributes_macs VALUES (new.*);
+              RETURN NULL;
+              END IF;
+
+              IF (new.attr='owner') THEN
+              insert into nethost_attributes_users VALUES (new.*);
+              RETURN NULL;
+              END IF;
+
+              IF (new.attr='user') THEN
+              insert into nethost_attributes_users VALUES (new.*);
+              RETURN NULL;
+              END IF;
+
+              IF (new.attr='related') THEN
+              insert into nethost_attributes_nethosts VALUES (new.*);
+              RETURN NULL;
+              END IF;
+              end if;
+
+              if (TG_OP='DELETE') THEN
+              RETURN old;
+              else
+              RETURN new;
+              end if;
+              END;$BODY$
+              LANGUAGE plpgsql VOLATILE
+              COST 100;
+
+            }
+        ],
+    },
+    {
+        ver => 10,
+        sql => [
+            q{
+            CREATE OR REPLACE FUNCTION service_attr_update_ref()
+            RETURNS trigger AS
+            $BODY$begin
+
+            IF (TG_OP != 'INSERT') then
+            update "service" set date = now() where "service".ikey = old.okey;
+            end if;
+            IF (TG_OP != 'DELETE') then
+            update "service"  set date = now() where "service".ikey = new.okey;
+            end if;
+
+            IF (TG_OP = 'DELETE') then
+            return old;
+            ELSE
+            return new;
+            END IF;
+
+            END;$BODY$
+            LANGUAGE plpgsql VOLATILE
+            COST 100;
+            },
+            q{
+
+            CREATE TABLE service
+            (
+
+            CONSTRAINT service_pkey PRIMARY KEY (name),
+            CONSTRAINT service_ikey_uniq UNIQUE (ikey)
+            )
+            INHERITS (objects);
+            },
+            q{
+
+            CREATE TABLE service_attributes_list
+            (
+            ikey integer NOT NULL DEFAULT nextval('ikey_seq'::regclass),
+            canonical text NOT NULL,
+            description text,
+            CONSTRAINT service_attributes_list_pkey PRIMARY KEY (ikey),
+            CONSTRAINT g_attr_l_service_uniq UNIQUE (canonical)
+            )
+            INHERITS (revisions, attributes_list)
+            WITH (
+            OIDS=FALSE
+            );
+            ALTER TABLE service_attributes_list
+            OWNER TO latmos;
+
+            CREATE TABLE service_attributes
+            (
+            CONSTRAINT service_attributes_pkey PRIMARY KEY (attr_key),
+            CONSTRAINT service_attr_users_okey_fkey FOREIGN KEY (okey)
+            REFERENCES service (ikey) MATCH SIMPLE
+            ON UPDATE CASCADE ON DELETE CASCADE,
+            CONSTRAINT service_attributes_attr_fkey FOREIGN KEY (attr)
+            REFERENCES service_attributes_list (canonical) MATCH SIMPLE
+            ON UPDATE CASCADE ON DELETE NO ACTION
+            )
+            INHERITS (attributes)
+            WITH (
+            OIDS=FALSE
+            );
+            ALTER TABLE service_attributes
+            OWNER TO latmos;
+
+            CREATE INDEX fki_service_attributes_attr_fkey
+            ON nethost_attributes
+            USING btree
+            (attr);
+
+            CREATE INDEX service_attr_value_idx
+            ON nethost_attributes
+            USING btree
+            (value);
+
+            CREATE TRIGGER serivce_attr_update
+            AFTER INSERT OR UPDATE OR DELETE
+            ON service_attributes
+            FOR EACH ROW
+            EXECUTE PROCEDURE service_attr_update_ref();
+            },
+            q{
+            CREATE TABLE service_attributes_users
+            (
+            CONSTRAINT service_attributes_user_pkey PRIMARY KEY (attr_key),
+            CONSTRAINT service_attr_users_okey_fkey FOREIGN KEY (okey)
+            REFERENCES service (ikey) MATCH SIMPLE
+            ON UPDATE CASCADE ON DELETE CASCADE,
+            CONSTRAINT service_attributes_users_attr_fkey FOREIGN KEY (attr)
+            REFERENCES service_attributes_list (canonical) MATCH SIMPLE
+            ON UPDATE CASCADE ON DELETE NO ACTION,
+            CONSTRAINT service_attributes_users_user_fkey FOREIGN KEY (value)
+            REFERENCES "user" (name) MATCH SIMPLE
+            ON UPDATE CASCADE ON DELETE CASCADE,
+            CONSTRAINT service_attributes_users_uniq UNIQUE (okey, attr, value)
+            )
+            INHERITS (service_attributes);
+
+            CREATE INDEX fki_service_attr_users_okey_fkey
+            ON service_attributes_users
+            USING btree
+            (okey);
+
+            CREATE INDEX fki_service_attributes_users_attr_fkey
+            ON service_attributes_users
+            USING btree
+            (attr);
+
+            CREATE INDEX fki_service_attributes_users_user_fkey
+            ON service_attributes_users
+            USING btree
+            (value);
+
+            CREATE TRIGGER service_attributes_users_update_ref
+            AFTER INSERT OR UPDATE OR DELETE
+            ON service_attributes_users
+            FOR EACH ROW
+            EXECUTE PROCEDURE service_attr_update_ref();
+
+            CREATE OR REPLACE FUNCTION service_sort_fields()
+              RETURNS trigger AS
+              $BODY$BEGIN
+
+              if (TG_OP='INSERT' or TG_OP='UPDATE') THEN
+              IF (new.attr='manager') THEN
+              insert into service_attributes_users VALUES (new.*);
+              RETURN NULL;
+              END IF;
+              END IF;
+
+              if (TG_OP='DELETE') THEN
+              RETURN old;
+              else
+              RETURN new;
+              end if;
+              END;$BODY$
+              LANGUAGE plpgsql VOLATILE
+              COST 100;
+
+              CREATE TRIGGER service_sort_field_tg
+              BEFORE INSERT OR UPDATE OR DELETE
+              ON service_attributes
+              FOR EACH ROW
+              EXECUTE PROCEDURE service_sort_fields();
+
+            },
+        ],
+    },
 );
 
Index: trunk/LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql/objects.pm
===================================================================
--- trunk/LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql/objects.pm	(revision 1307)
+++ trunk/LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql/objects.pm	(revision 1308)
@@ -103,5 +103,5 @@
     $info->{exported}   = { inline => 1, formtype => 'CHECKBOX', hide => 1, monitored => 1 };
     $info->{unexported} = { inline => 1, formtype => 'CHECKBOX', };
-    $info->{services}   = { inline => 1, ro => 1, };
+    $info->{services}   = { inline => 1, multiple => 1, reference => 'service' };
 
     $info
@@ -320,4 +320,21 @@
     if (exists($data{exported})) {
         $data{exported} ||= 0;
+    }
+    if (exists($data{services})) {
+        my %old = map { $_ => 0 } $self->get_attributes('services');
+        foreach my $serv (grep { $_ } ref $data{services} ? @{ $data{services} } : $data{services}) {
+            if (!exists($old{$serv})) {
+                my $oserv = $self->base->get_object('service', $serv) or next;
+                $oserv->addAttributeValue('dependOn', $self->type . '.' . $self->id);
+            }
+            $old{$serv} = 1;
+        }
+        foreach my $serv (keys %old) {
+            if (!$old{$serv}) {
+                my $oserv = $self->base->get_object('service', $serv) or next;
+                $oserv->delAttributeValue('dependOn', $self->type . '.' . $self->id);
+            }
+        }
+        delete($data{services});
     }
     foreach my $field (keys %data) {
