h'dWc@sdZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl m Z m Z m Z mZmZmZddlmZmZddlmZddlmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*ddl+m,Z,m-Z-m.Z.m/Z0m1Z2m3Z4m5Z6m7Z7m8Z8m9Z:dZ;d d gZ<d d d ddgZ=defdYZ>dZ?e@dZAdS(s AI Server Interface iN(terrsvctApplicationDatatsystem_temp_pathtPopentCalledProcessErrort SetUIDasEUID(tINSTALL_LOGGER_NAMEtSCRIPT_LOGGER_NAME(t InstallEngine(t AIServerErrort ERROR_TYPEt IPv4AddresstServicetEventsGeneratortObjectChangedEventt CreatedEventt DeletedEventtClientStatusEventt LoggingEventtServerStatusEventt AUTH_NONEt CertificatetKeytFWtFW_KEYStmake_credentialt check_authst SERVICE_AUTHtDHCPAddressRange( tlogtloggertcachetservice_configtai_smf_servicetsecurityt utilitiest KNOWN_ARCHStdhcpt aiservices ai-serverssetup-webserver-files-dirs setup-webserver-secure-files-dirscreate-main-ports-files mount-alltremounts unmount-alls refresh-portstServerc BsKeZdZdeZeejdedZeejdedZ e dZ e ededZ e dZdZdedZdedededZe d Zd Zd Zd Zd Zdededededededededeeded ZedZedZdZdZdZdZdedZdedZ e dZ!e dZ"e dZ#e dZ$e dZ%dZ&eedZ'dZ(dedZ)d Z*d!Z+d"Z,ded#Z-ded$Z.d%Z/d&Z0d'Z1ed(Z2dedededededededededee3ed) Z4e d*Z5d+Z6d,Z7e8d-Z9e d.Z:e:j;d/Z:e d0Z<e d1Z=e d2Z>e d3Z?e d4Z@e d5ZAd6ZBe d7ZCe d8ZDd9ZEe d:ZFe d;ZGd<ZHe d=ZId>ZJe d?ZKd@ZLe dAZMedBZNe dCZOdDZPe dEZQe dFZRe dGZSe dHZTe dIZUe dJZVdKZWdLZXe dMZYe dNZZdedOZ[edPZ\dQZ]eedRZ^dedSZ_dTZ`dUZadVZbdWZce dXZdedYZee dZZfed[Zge d\Zhe d]Zie d^Zje d_Zkd`ZldaZme dbZnenj;dcZne ddZoRS(fsThe Server interface is the heart of the system, and is the means to access other interfaces on a given AI server machine, such as the Services, Clients, etc. There should only ever be one Server implementation instance per AI server in an application's address space, and this should be enforced by the implementation. The following event types are possible for a Server: - ObjectChangedEvent - CreatedEvent - DeletedEvent - ClientStatusEvent - ServerStatusEvent - LoggingEvent cCs'tjdkrtj|StjSdS(N(R(t _instancetNonetobjectt__new__(tclstapp_nametlogleveltdry_run((s server.pyR,Xs cCsP|dk r]t|dr]|j|kr]ttjtdi|jd6|d6q]ntjdk rpdS|t_t |_ t j dt dd|j |_|jtjtj|_?t>|_@t>|_At>|_Bt>|_Ct>|_Dt>|_Ed|_Fd|_Gt>|_Ht>|_It>|_Jt>|_Kt>|_Lt>|_Md|_NtO|_PtQjR|jStTt|jUtVtWtXtYtZt[gdS(sConstruct the single-instance of the Server API Parameters: app_name - The name of the application that is using the API, defaults to 'ai_server'. loglevel - logging level to set when instantiating InstallEngine dry_run - If set to True then will execute whole Server API in dry-run mode. t_dry_runsOAttempt to run Server with dry_run value being changed from %(pre)s to %(post)stpretpostNtprefixs-engine-tdirs %s-%d.logtwork_dirtlognames Logging to %ssRunning in dry-run modeitvalid(\R*thasattrR1R R t RUNTIME_ERRORt_R(R)Rt temp_pathttempfiletmkdtempt_DEFAULT_APPNAMEtengine_temp_dirtostenvironRt TMP_CACHE_ENVtgetpidRt _app_dataR7tlog_pathR/t_enginet_loggertenginetloggingtDEBUGtlog_exception_leveltPREP_MSGtFalset_suppress_log_eventstdata_object_cachetdoct_setup_log_eventst persistenttinsert_childrenRtdebugtinfot_Server__next_task_numt error_infotlistt_smf_actions_requiredt_smf_post_actionsRtCachet _servicest_default_imagepath_basedirt _http_portt_secure_http_portt_exclude_networkst _networkst _enable_webuit_wizard_saves_to_servert_http_files_dirt_https_files_dirt _manage_dhcpt _dhcp_configt _bootserverRt_keyt_certt _ca_certst_signing_ca_certt_deleted_certst_aest_sha1t _is_enabledt_has_credentialst_default_client_keyt_default_client_certt_default_client_ca_certst_default_client_deleted_certst_default_client_aest_default_client_sha1t_default_client_has_credentialstTruetcleanup_at_exittatexittregistert_Server__atexit_cleanup_servertsupert__init__RRRRRR(tselfR.R/R0tlog_name((s server.pyR`s  !                                               cCsR|jdkrKttjjjkrKt|jd|j dt |_qKn|jS(s3Returns engine instance if required for this ServerR/t stop_on_errorN( RGR*RRJtLoggertmanagert loggerDictRRFR/Rz(R((s server.pyRIs   cCs1|jdkr*td|d||_n|jS(sReturns the Server singletonR.R0N(R)R*R((R-R.R0((s server.pyt get_instancescCsU|jdkrNttjjjkr9tjt|_qNtjt|_n|jS(sReturn server loggerN( RHR*RRJRRRt getLoggerR(R((s server.pyRs cCs`|jr\tjj|jr1tj|jntjj|jr\tj|jq\ndS(s'Cleanup after the server has completed.N( R{RAtpathtexistsRFtunlinkR@tshutiltrmtree(R((s server.pyt__atexit_cleanup_servers  cCs;|jd7_|dkr&d|jSd|j|fSdS(s&Returns the next task name in sequenceistask-%ds task-%d-%sN(RWR*(Rtsuffix((s server.pyt__next_task_name$s  cCs|j|}y/d|_|jj|||d|d|Wnjtk r}tdt||_|jj |j|jj t j t t j|jnX|S(sAdd a new task to the AI Server's execution queue It's not expected that this would be used as part of any public API. Parameters class_path: String Path to the class file containing the method to execute class_name: String The task method that will be executed by this checkpoint task_name: String The task name that will be executed by this checkpoint args: List List of arguments required by the task_name method kwargs: Dict Dictionary with extra arguments for the task_name method Return Value String Name of the newly created AI server engine task. Errors / Exceptions AIServerError The following error types can be raised by this method: - InsufficientArguments The list of arguments passed does not match what the task_name method is expecting targstkwargss=An exception occurred while registering a new checkpoint: %sN(t_Server__next_task_nameR*RXRItregister_checkpointt ExceptionR;tstrRRUt tracebackt format_excR R tINSUFFICIENT_ARGUMENTS(Rt class_patht class_namet task_nameRRt new_task_nametex((s server.pytappend_to_queue,s#     cCsRt|jjdd}|dkr;|jjdtS|jjd|tS(s"Evaluate if execute queue is emptyis'No checkpoints in queue to be executed.s'%d checkpoints in queue to be executed.N(tlenRIt get_exec_listR*RRURzRN(Rt len_queue((s server.pytexecute_queue_is_empty`s  cCsX|jjdd}t}x3|D]+}|js%|jt|jjq%q%W|S(s6Get a list of the tasks in the queue pending executionN( RIRR*RYt completedtappendRtcp_infotcp_name(Rt checkpointst task_namestckpt((s server.pytget_queue_tasksks     c Csu|jr dSd|_|jy>tj|jjddddd|jdd\}}WnKt k r}|j|j j t j ttjt|nX|tjkr:tddg}xU|D]M}tj|d}t|jtj}|jd ||jdqWd j||_n|j|jrZ|jn|tjkrmtStSdS( sExecutes any tasks on the queueNt start_fromt pause_beforeR0tcallbacksThe following errors occurred:tis s (RR*RXt flush_cacheRtclear_error_listRItexecute_checkpointsR0RRRURRR R R:RRt EXEC_SUCCESSR;tget_errors_by_mod_idt error_datatES_DATA_EXCEPTIONRtjointsmf_actions_requiredtsmf_service_actionsRzRN(Rtstatustfailed_checkpointsRterr_strst failed_cpterr_datat err_string((s server.pyt execute_queuevs8          cCs|jj|jtS(sClears the execution queue(RItclear_checkpointsRRz(R((s server.pyt clear_queues  cCst|j_d|_d|_d|_d|_d|_d|_ d|_ d|_ d|_ d|_ t|_t|_t|_t|_t|_t|_t|_d|_d|_t|_t|_t|_t|_t|_t|_d|_dS(sClears the cache and all values from memory, forcing the next access to any property to go to disk to retrieve the information. N(RNR]R8R*R^R_R`RaRbRcRdReRfRgRRjRkRlRnRmRoRpRrRqRsRtRuRvRwRxRy(R((s server.pyRs6                          c CsVtttjd|d|d|d|d|d|d|d|d | d | d | S( sThis method creates a new Service object, and initializes it with the parameters provided, some parameters are optional depending on the intention. Parameters See the Service object's implementation for more information. Return Value Returns a tuple with: String Name of the newly created AI server engine task. Service: Reference to the new service Errors / Exceptions AIServerError The following error types can be raised by this method: - InsufficientArguments Insufficient arguments are provided to be able to complete the method successfully. - InvalidValue This signifies that an invalid value was passed as a parameter. tnametalias_oftarcht ips_settingstsourcet dhcp_ip_ranget boot_argstboot_file_servert image_pathtdefer_source_validationtdefault_manifest_content(RRR t_create_on_disk( RRRRRRRRRRRR((s server.pytcreate_services     cCs$tt|j||j|S(sThis method removes any service on the client that matches the provided Service reference. Parameters service: Service This is a Service reference that matches an existing service on the AI server. autoremove: Bool Optional: If set to True, any clients assigned to this service, and any services aliased to this service, are also removed. Return Value String Name of the newly created AI server engine task. Errors / Exceptions AIServerError The following error types can be raised by this method: - NoMatches The Service object provided doesn't match any existing service. - InvalidValue The service cannot be removed because it has assigned clients or aliases and autoremove is set to False (RRt_validate_service_existstdelete(Rtservicet autoremove((s server.pytdelete_services  cCs&tt|j|}|j|S(sThis method removes any service on the AI server that matches the given name. Parameters name: String This specifies the name of a service to remove. Return Value String Name of the newly created AI server engine task. Errors / Exceptions AIServerError The following error types can be raised by this method: - NoMatches The name provided doesn't match any existing service. - InvalidValue The service cannot be removed because it has assigned clients or aliases and autoremove is set to False. (RRt_get_service_by_nameR(RRRR((s server.pytdelete_service_by_name"s cCs$tt|j||j|S(snThis method renames any service on the AI server that matches the provided service reference. Parameters service: Service This is a Service reference that matches an existing service on the AI server. newname: String The new name for the service. Return Value String Name of the newly created AI server engine task. Errors / Exceptions AIServerError The following error types can be raised by this method: - NoMatches The Service object provided doesn't match any existing service. - InvalidValue The service cannot be removed because it has assigned clients or aliases and autoremove is set to False (RRRtrename(RRtnewname((s server.pytrename_service;s  cCs&tt|j|}|j|S(sThis method renames any service on the AI server that matches the given name. Parameters name: String This specifies the name of the service to be renamed. newname: String The new name for the service. Return Value String Name of the newly created AI server engine task. Errors / Exceptions AIServerError The following error types can be raised by this method: - NoMatches The name provided doesn't match any existing service. - InvalidValue A service already exists with the new name (RRRR(RRRR((s server.pytrename_service_by_nameXs cCsot|ts4ttjtdt|n|jd|jskttj td|jndS(sXValidates that the given service exists and that it is associated to this serversArgument is not a service: '%s'tfilter_by_namesService not found: '%s'N( t isinstanceR R R t INVALID_VALUER;Rt get_servicesRt NO_MATCHES(RR((s server.pyRrs   cCsl|jd|}|s7ttjtd|nt|dkrdttjtdn|dS(sZValidates that a service with the given name exists and returns the service objectRsUnknown service: '%s'is!More than one service was matchedi(RR R RR;RR(RRtservices((s server.pyR~s  cCs|jjst|j_tj}xY|D]Q}||}|r+tj|kr+tj||}|jj|j |q+q+Wx\|D]Q}||}|rtj|krtj||}|jj|j |qqWn|jj d|S(sThis method will fetch a list of services that match the value in filter_by_name. Parameters filter_by_name: String Optional: This string is the name of a service to match. It is possible to match sub-strings using the '*' character, e.g. 'test*' will match all service names that start with the word 'test'. Omitting the parameter will return all known services. Return Value Service[] Returns a list of services. Should there be no matches, an empty list will be returned. Errors / Exceptions None. t filter_by_key( R]R8Rztconfigtget_all_service_propst PROP_ALIAS_OFR t_construct_from_service_propstaddRtget(RRRRt service_propst new_service((s server.pyRs           cCs:t}x*|jD]}|j|j|qW|S(sThis method will fetch a list of clients that match the value in filter_by_value. Parameters filter_by_value: String Optional: This string is the MAC address, of a client to match. It is possible to match sub-strings using the '*' character, e.g. '08:4c:*' will match all client MAC addresses that start with the characters '08:4c:' - case will be ignored for matching. Omitting the parameter will return all known clients. Return Value Clients[] Returns a list of clients. Should there be no matches, an empty list will be returned. Errors / Exceptions None. (RYRtextendt get_clients(Rtfilter_by_valuetclientsR((s server.pyRs cCs5tt|jdkr.|jj|_n|jS(sdBoolean defining whether the default client has any security credentials or not. N(RRRyR*R"tclient_has_credentials(R((s server.pytdefault_client_has_credentialss cCsktt|jtkrd|jj}|dk rX|\}}tt|||_qdd|_n|jS(sNReturns default client's key. Returns: a Key object or None. N( RRRsRR"tget_client_keyR*RR(Rt client_keyt key_sourcet key_contents((s server.pytdefault_client_security_keys     cCsktt|jtkrd|jj}|dk rX|\}}tt|||_qdd|_n|jS(s^Returns default client's certificate. Returns: a Certificate object or None. N( RRRtRR"tget_client_certR*RR(Rt client_certt cert_sourcet cert_contents((s server.pytdefault_client_security_certs    cCsttt}|jtkr|jj}|dk r|\}}t|tsd|g}nx*|D]}|j t t ||qkWn||_n|jS(skGets the CA certificates for the client. Returns a list, possibly empty, of Certificates. N( RRRYRuRR"tget_client_cacrtR*RRRR(Rtca_certst server_cat ca_sourcet ca_contentst ca_content((s server.pytdefault_client_ca_certs s       cCsttd}}|jtkrt|jjtj}|dk rh|\}}t t |||_qtd|_n|j tkr|jjtj }|dk r|\}}t t |||_ qd|_ nt |j|j S(suGet the default client's FW key. Returns: a tuple of two (ENCR_AES & HMAC_SHA1) Certificate objects N(RRR*RwRR"tget_client_fw_keytsectENCR_AESRRRxt HMAC_SHA1R(Rt aes_contentst sha1_contentst server_aest aes_sourcet server_sha1t sha1_source((s server.pytdefault_client_fw_key s"          c Csttt}t}d |dThis is a list of network subnets to be served by the AI server in CIDR format (e.g. 192.168.56.0/24). How the contents of this list is interpreted depends upon the value of the exclude_networks property (see above). This value can be updated using the update_networks method. N(RbR*RPt get_networks(R((s server.pyR8fs cCs.|jdkr'ttj|_n|jS(sContains the network port being used for the AI web server for unsecured connections. The default value is port 5555. N(R_R*tintRPt get_http_port(R((s server.pyRGtscCsyt|}Wn-tk r?ttjtd|nX|dkrkttjtd|n|jd|}||_|S(s+Sets the network port being used for the AI web server for unsecured connections. Parameters value: Integer The value of the http port. Return Value String Name of the newly created AI server engine task. Errors / Exceptions AIServerError The following error types can be raised by this method: - InvalidValue This signifies that an invalid value was passed as a parameter s%HTTP port '%s' is not a valid integerisHTTP port '%s' is invalidRG(R}R&R R RR;R=R_(RRqRGR((s server.pytupdate_http_ports      cCs tjS(s"The security object for the server(Rt AISecurity(R((s server.pyR"scCs.|jdkr'ttj|_n|jS(sContains the network port being used for the AI web server for secured connections. The default value is port 5556. N(R`R*R}RPtget_secure_http_port(R((s server.pytsecure_http_portscCsyt|}Wn-tk r?ttjtd|nX|dkrkttjtd|n|jd|}||_|S(s#Sets the network port being used for the AI web server for secured connections. Parameters value: Integer The value of the secure http port. Return Value String Name of the newly created AI server engine task. Raises AIServerError The following error types can be raised by this method: - InvalidValue This signifies that an invalid value was passed as a parameter s,Secure HTTP port '%s' is not a valid integeris Secure HTTP port '%s' is invalidRH(R}R&R R RR;R=R`(RRqRR((s server.pytupdate_secure_http_ports      cCs(|jdkr!tj|_n|jS(sThis value is the default location for new images when a service is first created. Changing this value will change the base directory used for all new services. It defaults to: /export/auto_installN(R^R*RPt get_imagedir(R((s server.pytdefault_imagepath_basedirscCsftjj|s1ttjtd|ntjj|rbttjtd|ntS(sUValidates the default location for new images, which is used when a service is first created. Parameters basedir: String The value of the default imagepath basedir. Return Value Boolean True if the directory can be used as default imagepath base dir Errors / Exceptions AIServerError The following error types can be raised by this method: - InvalidValue This signifies that an invalid value was passed as a parameter sCA full pathname is required for the default imagepath basedir: '%s's7The default imagepath basedir cannot be a symlink: '%s'( RARtisabsR R RR;tislinkRz(R-RI((s server.pytvalidate_def_imagepath_basedirs      cCs,|j||jd|}||_|S(suUpdates the default location for new images, which is used when a service is first created. Parameters basedir: String The value of the default imagepath basedir. Return Value String Name of the newly created AI server engine task. Errors / Exceptions AIServerError The following error types will be raised by the call to validate_def_imagepath_basedir(): - InvalidValue This signifies that an invalid value was passed as a parameter RI(RR=R^(RRIR((s server.pyt update_default_imagepath_basedirs  cCs(|jdkr!tj|_n|jS(sContains the webserver files directory used for the AI web server. The default value is /var/ai/ai-webserver. N(ReR*RPt get_files_dir(R((s server.pyRTscCsPtjj|s1ttjtd|n|jd|}||_|S(sSets the files directory to be used by the AI web server. Parameters value: String The value of webserver files directory. Return Value String Name of the newly created AI server engine task. Errors / Exceptions AIServerError The following error types can be raised by this method: - InvalidValue This signifies that an invalid value was passed as a parameter s,Webserver files dir '%s' is not a valid pathRT( RARtisdirR R RR;R=Re(RRR((s server.pytupdate_http_files_dir$s    cCs(|jdkr!tj|_n|jS(sContains the webserver secure files directory used for the AI web server. The default value is /var/ai/ai-webserver. N(RfR*RPtget_secure_files_dir(R((s server.pyRU?scCsPtjj|s1ttjtd|n|jd|}||_|S(sSets the files directory to be used by the AI web server. Parameters value: String The value of webserver secure files directory. Return Value String Name of the newly created AI server engine task. Errors / Exceptions AIServerError The following error types can be raised by this method: - InvalidValue This signifies that an invalid value was passed as a parameter s3Webserver secure files dir '%s' is not a valid pathRU( RARRR R RR;R=Rf(RRR((s server.pytupdate_https_files_dirKs    cCs`tj}t}xD|jD]9}x0|jD]%\}}|jt|d|q/WqW|S(s*Get a list with the current DHCP IP rangest ip_finish(R%t DHCPServerRYt_subnetstrangesRR(Rt dhcp_serverRR>tip_startR((s server.pyRfs   !c Csrttt|ts8ttjtd|n| rd|j rdttjtdn|r|j rttjtdnyt j |j |j Wn(t jk r}ttj|nXt}t}d|d<|j |d<|j |d<||d((s server.pytbootfile_servers    c CsE|js$ttjtdn|jsHttjtdnt|tsvttjtd|nytj |j Wn(tj k r}ttj|nXt }t }d|dtt|jdkr.|jj|_n|jo=|jS(sReturns booleanN(RRRqR*R"tis_db_state_enabledthas_credentials(R((s server.pytis_security_enableds cCs5tt|jdkr.|jj|_n|jS(sSBoolean signifying whether the AI Server has security credentials. N(RRRrR*R"tserver_has_credentials(R((s server.pyR s c Cs|jd kr|d krtStjdddt\}}|d k rx1|D]&}tj||tj|dqSWnx$|jD]}tj||jqWtj |tjdddt\}}tj||tj |dt j ||f}zwyGt j |jdt jdt j}|jjd d krQtSWn)tk r}ttjtd nXWd tjj|rtj|ntjj|rtj|nXtS( sWVerify the given certificate against the CAs. Parameters cert: String A string containing contents of cert file ca_certs: List of Strings A list of strings containing additional CA certificate contents Return Value Boolean True on success, otherwise False. Errors / Exceptions AIServerError The following error types can be raised by this method: - RuntimeError Openssl returned error while trying to verify the cert R4tcacrt_R5s tcrt_s%s verify -CAfile %s %ststdouttstderrtOKisopenssl error verifying certN(RR*RNR=tmkstempRRAtwritetcontentstcloseRtOPENSSLRt check_calltsplittSTORERtfindRzRR R R:R;RRtremove( RRRtfdescRRt cert_pathtcmd_strtprocess((s server.pyt verify_cert s>        c Cstt|j r9|j r9ttjtdn| rn|j rn|jrnttjtdnt }t }d |dAssigns a CA certificate for the Server. Parameters ca_cert_contents A list of strings containing contents of user-specified files. Return Value String The task name that will be executed by this checkpoint. Errors / Exceptions AIServerError The following error types can be raised by this method: - DuplicateEntry The cert has already been removed or it's scheduled to be removed in the current queue. R Rs/solaris_install/ai/server/internal/set_securityRsupdate-server-ca-certificateRRRN( RRRYRRRRRRR*RRl( RRRRRRRRRR((s server.pytupdate_ca_cert s"          c Cs~tt|jtk rG||jkrGttjtd|nt}t }d |d<||dtipt prefix_lentval_errtipv4_err((s server.pyR:S s  "  N(pt__name__t __module__t__doc__R*R)R?RJRKR,RtpropertyRIt classmethodRRR~RRRRRRRRzRRRRRRRRRRRRRR RRRRR"R#R1R2R4R6R?R@RFRNR=RROR]RYRR0tsetterRtRRyR{R8RGRR"RRRRRRTRRURRRRRRRRRRRRRRRRRRRRRRRRRRRKRRRBRDRCRRRRR:(((s server.pyR(Cs      3 2 )    %      1   ,- + 9 - + ,    E  + Q ! N   # "     G 9 P (  6 3 (+ 7 + > 5 .     cCsytt|dkrHtj}t|j|}WdQX|S|dkrtj}t8|j|dt}|j|j|j WdQX|St t j t d|Wn%tk r}t t j|nXdS(sUtility method to configure AI Webserver files directory Parameters opt: String Option indicating action to perform path: String Path to webserver files directory Return Value Integer 0 - Webserver files configuration has changed 1 - Webserver files configuration has not changed Errors / Exceptions The following error types can be raised by this method: - InvalidValue This signifies that an invalid value was passed as a parameter - RuntimeError The action could not be performed ssetup-webserver-files-dirNs setup-webserver-secure-files-dirtsecures"Error: Unrecognized subcommand: %s(RRRRRtsetup_webserver_files_dirRztgen_ai_httpd_ssl_conftconfigure_docroott build_netbootR R RR;RR:(toptRRtretR.((s server.pytperform_securityu s&          cCsytt|dkrM|d kr@ttjtdntj|S|dkrct j S|dkrt j dt S|dkrt j S|dkrt j d|Sttjtd|Wn%tk r}ttj|nXd S( s&Utility method to access internal AI or SMF Service related functions without exposing the entire aiservice internals module Parameters opt: String option indicating action to perform create-main-ports-file: Create the listen address:ports file for the apache webserver services. mount-all: Mounts all services that are configured as enabled. remount: Remounts all services that are configured as enabled. unmount-all: Unmounts all services refresh-ports: Refresh the ports within the services port: String SMF Webserver port or options AI Service port to refresh Return Value Depends on action being performed: create-main-ports-file: 0 - New LISTEN_ADDRESSES file has been put into place. 1 - Existing LISTEN_ADDRESSES file was not touched. mount-all: 0 - Success # - Refer to documentation in aiservice.py:AIService.mount_enabled_services for a list of return codes remount: 0 - Success # - Refer to documentation in aiservice.py:AIService.mount_enabled_services for a list of return codes unmount-all: 0 - Success # - Refer to documentation in aiservice.py:AIService.unmount_all for a list of return codes refresh-ports: True if service config has been updated otherwise False Errors / Exceptions The following error types can be raised by this method: - InvalidValue An invalid option was passed - InsufficientArguments Missing required port argument when requesting the create-main-ports-file option - RuntimeError The operation failed to execute screate-main-ports-files*Error: SMF Webserver port must be provideds mount-allR's unmount-alls refresh-portstports"Error: Unrecognized subcommand: %sN(RRR*R R RR;Rtcreate_main_ports_filetaisvctmount_enabled_servicesRzt unmount_allt refresh_portsRRR:(RRR.((s server.pytperform_ai_service_config s(@           (BRR|R[RJRARuRRrR=Rtsolaris_installRRRRRRtsolaris_install.loggerRRtsolaris_install.engineRtsolaris_install.ai.serverR R R R R RRRRRRRRRRRRRRRt"solaris_install.ai.server.internalRRRR RR!RPR"RR#R;R$R%R&RR?t SECURITY_OPTSt SERVICE_OPTSR(RR*R(((s server.pytsH         .F  = 3