1
0
mirror of https://gitlab.com/libvirt/libvirt-python.git synced 2024-10-26 16:25:10 +03:00
Commit Graph

184 Commits

Author SHA1 Message Date
Daniel P. Berrange
8bc78e12c1 generator: Remove string.lower(XXX) with XXX.lower()
In python3 the string.lower() method doesn't exist, the
lower() function can only be executed against a string
variable directly. Python2 supported both approaches so
this change is compatible

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-12-04 17:08:28 +00:00
Daniel P. Berrange
978ec4a4ec generator: Don't use 'list' as a variable name
In python3 if we use 'list' as a variable name it causes it
to hide the corresponding 'list()' function from the entire
function that holds the variable.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-12-04 17:08:19 +00:00
Daniel P. Berrange
9f1c4e3d94 Skip copying manually written python for C APIs which don't exist
If the libvirt-override-virXXXX.py file has methods which call
C APIs that don't exist in the version of libvirt built against
we need to skip copying their code.

eg for 0.9.13 libvirt we should not copy the 'listAllDomains'
method.

The way this works is that it breaks the override file into
individual methods by looking for ' def '. It then collects
the contents until the next method start, whereupon it looks
for a libvirtmod.XXXXXX API call. It checks if the XXXXX part
is present in the XML description we have, and if not, it
discards the entire method.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-11-28 11:54:02 +00:00
Daniel P. Berrange
590f338b23 Fix code for avoiding overrides of non-existant functions
When reading/writing a global variable from inside a method
it must be declared as a global, otherwise a local variable
by the same name will be used.

Special case the virConnectListDomainsID method which is
bizarrely renamed for no obvious reason.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-11-28 11:52:32 +00:00
Daniel P. Berrange
9f02373b5e Deal with old filenames for events/error functions
Older libvirt has files named 'events' and 'virterror'
rather than 'virevent' and 'virerror'. This is visible
in the API XML files. We must look for both names to
ensure we don't lose generation of methods with older
versions of libvirt.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-11-28 11:52:20 +00:00
Daniel P. Berrange
197153c67e Add missing binding of security model/label APIs
The virNodeGetSecurityModel, virDomainGetSecurityLabel and
virDomainGetSecurityLabelList methods were disabled in the
python binding for inexplicable reasons.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-11-27 11:11:23 +00:00
Daniel P. Berrange
9bc81a156d Avoid generating the methods in multiple classes
The python code generator tries to figure out what class a
method should be in by looking at the list of arguments for
any which are object types. Unfortunately missing break
statements meant that methods which have multiple object
arguments (eg migrate as a virDomainPtr followed by a
virConnectPtr) got added to multiple classes.

The following incorrect methods are removed by this change

   virStream.download       (dup of virStorageVol.download)
   virStream.screenshot     (dup of virDomain.screenshot)
   virStream.upload         (dup of virStorageVol.upload)
   virConnect.migrate       (dup of virDomain.migrate)
   virConnect.migrate2      (dup of virDomain.migrate2)
   virConnect.migrate3      (dup of virDomain.migrate3)
   virConnect.migrateToURI3 (dup of virDomain.migrateToURI3)

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-11-27 11:07:45 +00:00
Daniel P. Berrange
edb16fd5c1 Don't include virDomainSnapshotRef in python API
The reference counting API is for internal use only. Attempts
to use it from python application code will cause havoc.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-11-27 11:07:19 +00:00
Daniel P. Berrange
6f82518edc Ensure API overrides only used if API exists
Entries in the -overrides.xml files should only be recorded
if the API also exists in the main API XML file.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-11-22 15:59:43 +00:00
Doug Goldstein
3878fbd548 Break generator.py to be called per module
Since we don't always want to build all the modules, and there might be
more modules added in the future but we want to retain backwards
compatibility with older libvirts, change generator.py to be called once
per module instead of with all modules at once.
2013-11-22 15:58:06 +00:00
Daniel P. Berrange
19453b7836 Update generator for new code layout
Change the generator.py to

 - Take XML API file names on command line
 - Generate data in build/ directory instead of cwd
2013-11-22 15:58:05 +00:00
Doug Goldstein
45ac117cf6 python: remove virConnectGetCPUModelNames from globals
Commit de51dc9c9aed0e615c8b301cccb89f4859324eb0 primarily added
virConnectGetCPUModelNames as libvirt.getCPUModelNames(conn, arch)
instead of libvirt.virConnect.getCPUModelNames(arch) so revert the code
that does the former while leaving the code that does the later.

This is the rest of the patch that was ACK'd by Dan but I committed only
the partial patch in 6a8b8ae.
2013-11-21 14:20:45 -06:00
Doug Goldstein
4b6944d3c0 python: remove virConnectGetCPUModelNames from globals
Commit de51dc9c9aed0e615c8b301cccb89f4859324eb0 primarily added
virConnectGetCPUModelNames as libvirt.getCPUModelNames(conn, arch)
instead of libvirt.virConnect.getCPUModelNames(arch) so revert the code
that does the former while leaving the code that does the later.
2013-11-21 08:47:08 -06:00
Eric Blake
90461df0ca maint: avoid 'const fooPtr' in python bindings
'const fooPtr' is the same as 'foo * const' (the pointer won't
change, but it's contents can).  But in general, if an interface
is trying to be const-correct, it should be using 'const foo *'
(the pointer is to data that can't be changed).

Fix up offenders in the python bindings.

* python/generator.py (py_types): Drop useless conversions.
* python/libvirt-override.c (getPyVirTypedParameter)
(setPyVirTypedParameter): Use intended type.

Signed-off-by: Eric Blake <eblake@redhat.com>
2013-10-14 14:34:37 -06:00
Giuseppe Scrivano
357df252fb python: add bindings for virConnectGetCPUModelNames
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-09-23 16:59:39 -06:00
Giuseppe Scrivano
9d091faa7d libvirt: add new public API virConnectGetCPUModelNames
The new function virConnectGetCPUModelNames allows to retrieve the list
of CPU models known by the hypervisor for a specific architecture.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-09-23 15:41:50 -06:00
Oskari Saarenmaa
44dce1e00f docs, comments: minor typo fixes
Signed-off-by: Oskari Saarenmaa <os@ohmu.fi>
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-09-10 17:06:41 -06:00
Claudio Bley
1f01027098 python: simplify complicated conditional assignment 2013-08-23 10:54:58 +02:00
Claudio Bley
d101d3bce8 Test for object identity when checking for None in Python
Consistently use "is" or "is not" to compare variables to None,
because doing so is preferrable, as per PEP 8
(http://www.python.org/dev/peps/pep-0008/#programming-recommendations):

> Comparisons to singletons like None should always be done with is or
> is not, never the equality operators.
2013-08-23 08:12:26 +02:00
Daniel P. Berrange
03e7cacfa2 Introduce new domain create APIs to pass pre-opened FDs to LXC
With container based virt, it is useful to be able to pass
pre-opened file descriptors to the container init process.
This allows for containers to be auto-activated from incoming
socket connections, passing the active socket into the container.

To do this, introduce a pair of new APIs, virDomainCreateXMLWithFiles
and virDomainCreateWithFiles, which accept an array of file
descriptors. For the LXC driver, UNIX file descriptor passing
will be used to send them to libvirtd, which will them pass
them down to libvirt_lxc, which will then pass them to the container
init process.

This will only be implemented for LXC right now, but the design
is generic enough it could work with other hypervisors, hence
I suggest adding this to libvirt.so, rather than libvirt-lxc.so

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-18 11:01:14 +01:00
Jiri Denemark
1c94615878 Extensible migration APIs
This patch introduces two new APIs virDomainMigrate3 and
virDomainMigrateToURI3 that may be used in place of their older
variants. These new APIs take optional migration parameters (such as
bandwidth, domain XML, ...) in an array of virTypedParameters, which
makes adding new parameters easier as there's no need to introduce new
APIs whenever a new migration parameter needs to be added. Both APIs are
backward compatible and will automatically use older migration calls in
case the new calls are not supported as long as the typed parameters
array does not contain any parameter which was not supported by the
older calls.
2013-06-25 01:24:53 +02:00
Guannan Ren
109e7e30b2 python: set default value to optional arguments
When prefixing with string (optional) or optional in the description
of arguments to libvirt C APIs, in python, these arguments will be
set as optional arugments, for example:

 * virDomainSaveFlags:
 * @domain: a domain object
 * @to: path for the output file
 * @dxml: (optional) XML config for adjusting guest xml used on restore
 * @flags: bitwise-OR of virDomainSaveRestoreFlags

 the corresponding python APIs is
 restoreFlags(self, frm, dxml=None, flags=0)

The following python APIs are changed to:
 blockCommit(self, disk, base, top, bandwidth=0, flags=0)
 blockPull(self, disk, bandwidth=0, flags=0)
 blockRebase(self, disk, base, bandwidth=0, flags=0)
 migrate(self, dconn, flags=0, dname=None, uri=None, bandwidth=0)
 migrate2(self, dconn, dxml=None, flags=0, dname=None, uri=None, bandwidth=0)
 migrateToURI(self, duri, flags=0, dname=None, bandwidth=0)
 migrateToURI2(self, dconnuri=None, miguri=None, dxml=None, flags=0, \
               dname=None, bandwidth=0)
 saveFlags(self, to, dxml=None, flags=0)
 migrate(self, domain, flags=0, dname=None, uri=None, bandwidth=0)
 migrate2(self, domain, dxml=None, flags=0, dname=None, uri=None, bandwidth=0)
 restoreFlags(self, frm, dxml=None, flags=0)
2013-03-26 12:34:49 +08:00
Guannan Ren
36975201ff python:remove semicolon in python code
This breaked "make syntax-check" testing

Pushed under trivial rule
2013-03-22 12:08:20 +08:00
Guannan Ren
497a0ceecb python: treat flags as default argument with value 0
The following four functions have not changed because default arguments
have to come after positional arguments. Changing them will break the
the binding APIs.

migrate(self, dconn, flags, dname, uri, bandwidth):
migrate2(self, dconn, dxml, flags, dname, uri, bandwidth):
migrateToURI(self, duri, flags, dname, bandwidth):
migrateToURI2(self, dconnuri, miguri, dxml, flags, dname, bandwidth):
2013-03-22 11:50:09 +08:00
Peter Krempa
a5036ccfd6 python: Fix emulatorpin API bindings
The addition of emulator pinning APIs didn't think of doing the right
job with python APIs for them. The default generator produced unusable
code for this.

This patch switches to proper code as in the case of domain Vcpu pining.
This change can be classified as a python API-breaker but in the state
the code was before I doubt anyone was able to use it successfully.
2013-03-21 12:32:03 +01:00
Guannan Ren
48c23ca1f1 python: fix bindings that don't raise an exception
For example:
 >>> dom.memoryStats()
 libvir: QEMU Driver error : Requested operation is not valid:\
         domain is not running

There are six such python API functions like so.
The root reason is that generator.py script checks the type of return
value of a python stub function defined in libvirt-api.xml or
libvirt-override-api.xml to see whether to add the raise clause or not
in python wrapper code in libvirt.py.

The type of return value is supposed to be C types.
For those stub functions which return python non-integer data type like
string, list, tuple, dictionary, the existing type in functions varies
from each other which leads problem like this.

Currently, in generator.py, it maintains a buggy whitelist for stub functions
returning a list type. I think it is easy to forget adding new function name
in the whitelist.

This patch makes the value of type consistent with C type "char *"
in libvirt-override-api.xml. For python, any of types could be printed
as string, so I choose "char *" in this case. And the comment in xml
could explain it when adding new function definition.

      <function name='virNodeGetCPUStats' file='python'>
        ...
 -      <return type='virNodeCPUStats' info='...'/>
 +      <return type='char *' info='...'/>
        ...
      </function>
2013-03-21 11:24:49 +08:00
Daniel P. Berrange
2ccc4d0f7c Apply security label when entering LXC namespaces
Add a new virDomainLxcEnterSecurityLabel() function as a
counterpart to virDomainLxcEnterNamespaces(), which can
change the current calling process to have a new security
context. This call runs client side, not in libvirtd
so we can't use the security driver infrastructure.

When entering a namespace, the process spawned from virsh
will default to running with the security label of virsh.
The actual desired behaviour is to run with the security
label of the container most of the time. So this changes
virsh lxc-enter-namespace command to invoke the
virDomainLxcEnterSecurityLabel method.

The current behaviour is:

LABEL                             PID TTY          TIME CMD
system_u:system_r:svirt_lxc_net_t:s0:c0.c1023 1 pts/0 00:00:00 systemd
system_u:system_r:svirt_lxc_net_t:s0:c0.c1023 3 pts/1 00:00:00 sh
system_u:system_r:svirt_lxc_net_t:s0:c0.c1023 24 ? 00:00:00 systemd-journal
system_u:system_r:svirt_lxc_net_t:s0:c0.c1023 29 ? 00:00:00 dhclient
staff_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 47 ? 00:00:00 ps

Note the ps command is running as unconfined_t,  After this patch,

The new behaviour is this:

virsh -c lxc:/// lxc-enter-namespace dan -- /bin/ps -eZ
LABEL                             PID TTY          TIME CMD
system_u:system_r:svirt_lxc_net_t:s0:c0.c1023 1 pts/0 00:00:00 systemd
system_u:system_r:svirt_lxc_net_t:s0:c0.c1023 3 pts/1 00:00:00 sh
system_u:system_r:svirt_lxc_net_t:s0:c0.c1023 24 ? 00:00:00 systemd-journal
system_u:system_r:svirt_lxc_net_t:s0:c0.c1023 32 ? 00:00:00 dhclient
system_u:system_r:svirt_lxc_net_t:s0:c0.c1023 38 ? 00:00:00 ps

The '--noseclabel' flag can be used to skip security labelling.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-03-13 15:16:37 +00:00
Guannan Ren
71697db203 python: fix fd leak in generator.py 2013-03-01 15:49:07 +08:00
Guannan Ren
f88b551eeb python: fix typoes and repeated global vars references 2013-03-01 15:49:02 +08:00
Jiri Denemark
feae4e0524 Introduce virDomainMigrate*CompressionCache APIs
Introduce virDomainMigrateGetCompressionCache and
virDomainMigrateSetCompressionCache APIs.
2013-02-22 17:35:59 +01:00
Jiri Denemark
78975020eb Introduce virDomainGetJobStats API
This is an extensible version of virDomainGetJobInfo.
2013-02-22 17:35:58 +01:00
Guido Günther
728ca81bd6 Remove more trailing semicolons in Python files 2013-02-07 19:52:44 +01:00
Daniel P. Berrange
0f102b90f1 Fix missing error constants in libvirt python module
The previous change to the generator, changed too much - only
the functions are in 'virerror.c', the constants remained in
'virerror.h' which could not be renamed for API compat reasons.

Add a test case to sanity check the generated python bindings

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-02-05 15:40:20 +00:00
Serge Hallyn
9654aeb6ce complete virterror->virerror name change
Without these two string changes in generator.py, the
virGetLastError wrapper does not get created in
/usr/share/pyshared/libvirt.py.  Noticed when running
tests with virt-install.

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2013-01-31 08:39:53 -06:00
Jiri Denemark
a2e333640d python: Fix bindings for virDomainSnapshotGet{Domain,Connect}
https://bugzilla.redhat.com/show_bug.cgi?id=895882

virDomainSnapshot.getDomain() and virDomainSnapshot.getConnect()
wrappers around virDomainSnapshotGet{Domain,Connect} were not supposed
to be ever implemented. The class should contain proper domain() and
connect() accessors that fetch python objects stored internally within
the class. While domain() was already provided, connect() was missing.

This patch adds connect() method to virDomainSnapshot class and
reimplements getDomain() and getConnect() methods as aliases to domain()
and connect() for backward compatibility.
2013-01-24 21:24:30 +01:00
Daniel P. Berrange
d9a4428e44 Make python objects inherit from 'object' base class
As of python >= 2.2, it is recommended that all objects inherit
from the 'object' base class. We already require python >= 2.3
for libvirt for thread macro support, so we should follow this
best practice.

See also

  http://stackoverflow.com/questions/4015417/python-class-inherits-object

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-01-24 14:13:26 +00:00
Jiri Denemark
6d36e1dd94 Introduce virTypedParamsClear public API
The function is just a renamed public version of former
virTypedParameterArrayClear.
2013-01-18 15:04:00 +01:00
Jiri Denemark
adf784e70d Add virTypedParams* APIs
Working with virTypedParameters in clients written in C is ugly and
requires all clients to duplicate the same code. This set of APIs makes
this code for manipulating with virTypedParameters integral part of
libvirt so that all clients may benefit from it.
2013-01-18 15:03:58 +01:00
Daniel P. Berrange
5b18cc1d26 Fix build due to previous LXC patch
Mark virDomainLxcEnterNamespace as skipped in python binding
and remove reference to lxcDomainOpenNamespace which doesn't
arrive until a later patch
2013-01-14 16:35:40 +00:00
Daniel P. Berrange
d18147940f Introduce an LXC specific public API & library
This patch introduces support for LXC specific public APIs. In
common with what was done for QEMU, this creates a libvirt_lxc.so
library and libvirt/libvirt-lxc.h header file.

The actual APIs are

  int virDomainLxcOpenNamespace(virDomainPtr domain,
                                int **fdlist,
                                unsigned int flags);

  int virDomainLxcEnterNamespace(virDomainPtr domain,
                                 unsigned int nfdlist,
                                 int *fdlist,
                                 unsigned int *noldfdlist,
                                 int **oldfdlist,
                                 unsigned int flags);

which provide a way to use the setns() system call to move the
calling process into the container's namespace. It is not
practical to write in a generically applicable manner. The
nearest that we could get to such an API would be an API which
allows to pass a command + argv to be executed inside a
container. Even if we had such a generic API, this LXC specific
API is still useful, because it allows the caller to maintain
the current process context, in particular any I/O streams they
have open.

NB the virDomainLxcEnterNamespace() API is special in that it
runs client side, so does not involve the internal driver API.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-01-14 13:58:34 +00:00
Michal Privoznik
9ad1c7f711 python: Adapt to virevent rename
With our recent renames under src/util/* we forgot to adapt
python wrapper code generator. This results in some methods being
not exposed:

$ python examples/domain-events/events-python/event-test.py
Using uri:qemu:///system
Traceback (most recent call last):
  File "examples/domain-events/events-python/event-test.py", line 585, in <module>
    main()
  File "examples/domain-events/events-python/event-test.py", line 543, in main
    virEventLoopPureStart()
  File "examples/domain-events/events-python/event-test.py", line 416, in virEventLoopPureStart
    virEventLoopPureRegister()
  File "examples/domain-events/events-python/event-test.py", line 397, in virEventLoopPureRegister
    libvirt.virEventRegisterImpl(virEventAddHandleImpl,
AttributeError: 'module' object has no attribute 'virEventRegisterImpl'
2012-12-28 16:22:09 +01:00
Daniel P. Berrange
ac532dd37d Bind connection close callback APIs to python binding
Add code in the python binding to cope with the new APIs
virConnectRegisterCloseCallback and
virConnectUnregisterCloseCallback. Also demonstrate their
use in the python domain events demo

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-12-04 13:50:11 +00:00
Viktor Mihajlovski
2594a00750 virNodeGetCPUMap: Define public API.
Adding a new API to obtain information about the
host node's present, online and offline CPUs.

int virNodeGetCPUMap(virConnectPtr conn,
                     unsigned char **cpumap,
                     unsigned int *online,
                     unsigned int flags);

The function will return the number of CPUs present on the host
or -1 on failure;
If cpumap is non-NULL virNodeGetCPUMap will allocate an array
containing a bit map representation of the online CPUs. It's
the callers responsibility to deallocate cpumap using free().
If online is non-NULL, the variable pointed to will contain
the number of online host node CPUs.
The variable flags has been added to support future extensions
and must be set to 0.

Extend the driver structure by nodeGetCPUMap entry in support of the
new API virNodeGetCPUMap.
Added implementation of virNodeGetCPUMap to libvirt.c

Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
2012-10-23 18:46:47 -06:00
Guido Günther
c360b84ba0 Properly parse (unsigned) long long
This fixes problems on platforms where sizeof(long) != sizeof(long long)
like ia32.
2012-10-13 02:54:11 +02:00
Osier Yang
270cebde5a node_memory: Define the APIs to get/set memory parameters
* include/libvirt/libvirt.h.in: (Add macros for the param fields,
  declare the APIs).
* src/driver.h: (New methods for the driver struct)
* src/libvirt.c: (Implement the public APIs)
* src/libvirt_public.syms: (Export the public symbols)
2012-09-17 13:49:44 +08:00
Osier Yang
c29d337637 list: Define new API virConnectListAllSecrets
This is to list the secret objects. Supports to filter the secrets
by its storage location, and whether it's private or not.

include/libvirt/libvirt.h.in: Declare enum virConnectListAllSecretFlags
                              and virConnectListAllSecrets.
python/generator.py: Skip auto-generating
src/driver.h: (virDrvConnectListAllSecrets)
src/libvirt.c: Implement the public API
src/libvirt_public.syms: Export the symbol to public
2012-09-17 13:08:39 +08:00
Osier Yang
ff9990a39d list: Define new API virConnectListAllNWFilters
This is to list the network filter objects. No flags are supported

include/libvirt/libvirt.h.in: Declare enum virConnectListAllNWFilterFlags
                              and virConnectListAllNWFilters.
python/generator.py: Skip auto-generating
src/driver.h: (virDrvConnectListAllNWFilters)
src/libvirt.c: Implement the public API
src/libvirt_public.syms: Export the symbol to public
2012-09-17 12:35:15 +08:00
Osier Yang
cb41d86c6c list: Define new API virConnectListAllNodeDevices
This is to list the node device objects, supports to filter the results
by capability types.

include/libvirt/libvirt.h.in: Declare enum virConnectListAllNodeDeviceFlags
                              and virConnectListAllNodeDevices.
python/generator.py: Skip auto-generating
src/driver.h: (virDrvConnectListAllNodeDevices)
src/libvirt.c: Implement the public API
src/libvirt_public.syms: Export the symbol to public
2012-09-17 10:30:04 +08:00
Osier Yang
c3a037d412 list: Define new API virConnectListAllInterfaces
This is to list the interface objects, supported filtering flags
are: active|inactive.

include/libvirt/libvirt.h.in: Declare enum virConnectListAllInterfaceFlags
                              and virConnectListAllInterfaces.
python/generator.py: Skip auto-generating
src/driver.h: (virDrvConnectListAllInterfaces)
src/libvirt.c: Implement the public API
src/libvirt_public.syms: Export the symbol to public
2012-09-12 15:19:46 +08:00
Osier Yang
849f4b05c2 list: Define new API virConnectListAllNetworks
This is to list the network objects, supported filtering flags
are: active|inactive, persistent|transient, autostart|no-autostart.

include/libvirt/libvirt.h.in: Declare enum virConnectListAllNetworkFlags
                              and virConnectListAllNetworks.
python/generator.py: Skip auto-generating
src/driver.h: (virDrvConnectListAllNetworks)
src/libvirt.c: Implement the public API
src/libvirt_public.syms: Export the symbol to public
2012-09-11 16:58:16 +08:00